Merge "arm/dt: msm9625: add IPA host mode pipes"
diff --git a/Documentation/ABI/testing/sysfs-bus-msm_subsys b/Documentation/ABI/testing/sysfs-bus-msm_subsys
index fcfb1d4..f915a46 100644
--- a/Documentation/ABI/testing/sysfs-bus-msm_subsys
+++ b/Documentation/ABI/testing/sysfs-bus-msm_subsys
@@ -16,3 +16,16 @@
 
 		This file supports poll(3) to detect when a subsystem changes
 		state. Use POLLPRI to detect state changes.
+
+What:		/sys/bus/msm_subsys/devices/.../restart_level
+Date:		December 2012
+Contact:	Stephen Boyd <sboyd@codeaurora.org>
+Description:
+		Shows the restart level of a subsystem. The level is taken into
+		account when the subsystem is restarted via
+		subsystem_restart{_dev}(). Current supported states are:
+
+			SYSTEM	- reset the entire system
+			RELATED	- reset this subsystem and the other subsystems
+				  related to this one. Having no other
+				  subsystems related to this subsystem is valid.
diff --git a/Documentation/devicetree/bindings/arm/msm/qcom-wdog-debug.txt b/Documentation/devicetree/bindings/arm/msm/qcom-wdog-debug.txt
deleted file mode 100644
index e5fd1b2..0000000
--- a/Documentation/devicetree/bindings/arm/msm/qcom-wdog-debug.txt
+++ /dev/null
@@ -1,16 +0,0 @@
-* Qualcomm's Watchdog Debug Image Controller
-
-The Qualcomm's Watchdog debug image controller is used for enabling/disabling of
-watchdog debug image feature.
-
-Required properties:
-- compatible : should be "qcom,msm-wdog-debug"
-- reg : base page aligned physical base address of the controller and length of
-	memory mapped region.
-
-Example:
-
-	qcom,msm-wdog-debug@fc401000 {
-		compatible = "qcom,msm-wdogi-debug";
-		reg = <0xfc401000 0x1000>;
-	};
diff --git a/Documentation/devicetree/bindings/fb/mdss-dsi-ctrl.txt b/Documentation/devicetree/bindings/fb/mdss-dsi-ctrl.txt
index 7d19c03..5c426f2 100644
--- a/Documentation/devicetree/bindings/fb/mdss-dsi-ctrl.txt
+++ b/Documentation/devicetree/bindings/fb/mdss-dsi-ctrl.txt
@@ -8,22 +8,45 @@
 - cell-index:				Specifies the controller used among the two controllers.
 - reg:					offset and length of the register set for the device.
 - vdd-supply:				Phandle for vdd regulator device node.
-- vdd-io-supply:			Phandle for vdd-io regulator device node.
-- vreg-supply:				Phandle for vreg regulator device node.
+- vddio-supply:				Phandle for vdd-io regulator device node.
+- vdda-supply:				Phandle for vreg regulator device node.
 - qcom,mdss-fb-map:			pHandle that specifies the framebuffer to which the
 					interface is mapped.
 
 Optional properties:
 - label:		        	A string used to describe the controller used.
+- qcom,supply-names:			A list of strings that lists the names of the
+					regulator supplies.
+- qcom,supply-type:			A list of strings that list the type of supply(ies)
+					mentioned above. This list maps in the order of
+					the supply names listed above.
+					  regulator = supply with controlled output
+					  switch = supply without controlled output. i.e.
+					  voltage switch
+- qcom,supply-min-voltage-level:	A list that specifies minimum voltage level
+					of supply(ies) mentioned above. This list maps
+					in the order of the supply names listed above.
+- qcom,supply-max-voltage-level:	A list that specifies maximum voltage level of
+					supply(ies) mentioned above. This list maps in
+					the order of the supply names listed above.
+- qcom,supply-peak-current:		A list that specifies the peak current that will
+					be drawn from the supply(ies) mentioned above. This
+					list maps in the order of the supply names listed above.
+
 
 Example:
         mdss_dsi0: qcom,mdss_dsi@fd922800 {
-                compatible = "qcom,mdss-dsi-ctrl";
-                label = "MDSS DSI CTRL->0";
-                cell-index = <0>;
-                reg = <0xfd922800 0x600>;
-                vdd-supply = <&pm8941_l22>;
-                vdd_io-supply = <&pm8941_l12>;
-                vreg-supply = <&pm8941_l2>;
+		compatible = "qcom,mdss-dsi-ctrl";
+		label = "MDSS DSI CTRL->0";
+		cell-index = <0>;
+		reg = <0xfd922800 0x600>;
+		vdd-supply = <&pm8226_l15>;
+		vddio-supply = <&pm8226_l8>;
+		vdda-supply = <&pm8226_l4>;
+		qcom,supply-names = "vdd", "vddio", "vdda";
+		qcom,supply-type = "regulator", "regulator", "regulator";
+		qcom,supply-min-voltage-level = <2800000 1800000 1200000>;
+		qcom,supply-max-voltage-level = <2800000 1800000 1200000>;
+		qcom,supply-peak-current = <150000 100000 100000>;
 		qcom,mdss-fb-map = <&mdss_fb0>;
         };
diff --git a/Documentation/devicetree/bindings/power/qpnp-bms.txt b/Documentation/devicetree/bindings/power/qpnp-bms.txt
index 708ada1..5b22752 100644
--- a/Documentation/devicetree/bindings/power/qpnp-bms.txt
+++ b/Documentation/devicetree/bindings/power/qpnp-bms.txt
@@ -40,13 +40,16 @@
 			The bms will not accept new ocvs between these
 			thresholds.
 - qcom,low-soc-calculate-soc-threshold : The SoC threshold for when
-			the period calculate_soc work speeds up. This ensures
+			the periodic calculate_soc work speeds up. This ensures
 			SoC is updated in userspace constantly when we are near
 			shutdown.
+- qcom,low-voltage-threshold : The battery voltage threshold in micro-volts for
+			when the BMS tries to wake up and hold a wakelock to
+			ensure a clean shutdown.
 - qcom,low-soc-calculate-soc-ms : The time period between subsequent
-
 			SoC recalculations when the current SoC is below
-			qcom,low-soc-calculate-soc-threshold.
+			qcom,low-soc-calculate-soc-threshold or when battery
+			voltage is below qcom,low-voltage-threshold.
 - qcom,soc-calculate-soc-ms : The time period between subsequent SoC
 			recalculations when the current SoC is above or equal
 			qcom,low-soc-calculate-soc-threshold.
@@ -107,6 +110,7 @@
 	qcom,adjust-soc-low-threshold = <25>;
 	qcom,adjust-soc-high-threshold = <45>;
 	qcom,low-soc-calculate-soc-threshold = <15>;
+	qcom,low-voltage-threshold = <3420000>;
 	qcom,low-soc-calculate-soc-ms = <5000>;
 	qcom,calculate-soc-ms = <20000>;
 	qcom,chg-term-ua = <100000>;
diff --git a/Documentation/devicetree/bindings/sound/qcom-audio-dev.txt b/Documentation/devicetree/bindings/sound/qcom-audio-dev.txt
index 4cd9f99..a4c05d4 100644
--- a/Documentation/devicetree/bindings/sound/qcom-audio-dev.txt
+++ b/Documentation/devicetree/bindings/sound/qcom-audio-dev.txt
@@ -96,6 +96,12 @@
    is 8, which indicates the rx path used for audio playback
    on HDMI device.
 
+* msm-lsm-client
+
+Required properties:
+
+ - compatible : "qcom,msm-lsm-client"
+
 * msm-dai-q6
 
 [First Level Nodes]
diff --git a/Documentation/devicetree/bindings/thermal/tsens.txt b/Documentation/devicetree/bindings/thermal/tsens.txt
index 67a986b..1388b7d 100644
--- a/Documentation/devicetree/bindings/thermal/tsens.txt
+++ b/Documentation/devicetree/bindings/thermal/tsens.txt
@@ -38,7 +38,11 @@
 Optional properties:
 - qcom,calibration-less-mode : If present the pre-characterized data for offsets
 		are used else it defaults to use calibration data from QFPROM.
-
+- qcom,tsens-local-init : If the flag is present the TSENS control registers are
+		initialized. If the boot configures the control register there is
+		no need to re-initialize them. The control registers are also
+		under a secure domain which can prevent them from being initialized
+		locally.
 Example:
 
 tsens@fc4a8000 {
diff --git a/Documentation/devicetree/bindings/usb/msm-ehci-hsic.txt b/Documentation/devicetree/bindings/usb/msm-ehci-hsic.txt
index 1885e8a..9f8bbd9 100644
--- a/Documentation/devicetree/bindings/usb/msm-ehci-hsic.txt
+++ b/Documentation/devicetree/bindings/usb/msm-ehci-hsic.txt
@@ -15,7 +15,10 @@
 	"wakeup" : Wakeup interrupt from HSIC during suspend (or XO shutdown).
 - hsic,<gpio-name>-gpio : handle to the GPIO node, see "gpios property"
   in Documentation/devicetree/bindings/gpio/gpio.txt.
-  Optional "gpio-name" can be "strobe" and "data".
+  Optional "gpio-name" can be "strobe", "data" and "resume".
+- hsic,resume-gpio : if present then periperal connected to hsic controller
+  cannot wakeup from XO shutdown using in-band hsic resume. Use resume
+  gpio to wakeup peripheral
 - hsic,ignore-cal-pad-config : If present then HSIC CAL PAD configuration
   using TLMM is not performed.
 - hsic,strobe-pad-offset : Offset of TLMM register for configuring HSIC
diff --git a/arch/arm/boot/dts/msm-pm8110.dtsi b/arch/arm/boot/dts/msm-pm8110.dtsi
index 2f58185..c488ab1 100644
--- a/arch/arm/boot/dts/msm-pm8110.dtsi
+++ b/arch/arm/boot/dts/msm-pm8110.dtsi
@@ -21,6 +21,73 @@
 		reg = <0x0>;
 		#address-cells = <1>;
 		#size-cells = <1>;
+
+		pm8110_vadc: vadc@3100 {
+			compatible = "qcom,qpnp-vadc";
+			reg = <0x3100 0x100>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			interrupts = <0x0 0x31 0x0>;
+			interrupt-names = "eoc-int-en-set";
+			qcom,adc-bit-resolution = <15>;
+			qcom,adc-vdd-reference = <1800>;
+
+			chan@8 {
+				label = "die_temp";
+				reg = <8>;
+				qcom,decimation = <0>;
+				qcom,pre-div-channel-scaling = <0>;
+				qcom,calibration-type = "absolute";
+				qcom,scale-function = <3>;
+				qcom,hw-settle-time = <0>;
+				qcom,fast-avg-setup = <0>;
+			};
+
+			chan@9 {
+				label = "ref_625mv";
+				reg = <9>;
+				qcom,decimation = <0>;
+				qcom,pre-div-channel-scaling = <0>;
+				qcom,calibration-type = "absolute";
+				qcom,scale-function = <0>;
+				qcom,hw-settle-time = <0>;
+				qcom,fast-avg-setup = <0>;
+			};
+
+			chan@a {
+				label = "ref_1250v";
+				reg = <0xa>;
+				qcom,decimation = <0>;
+				qcom,pre-div-channel-scaling = <0>;
+				qcom,calibration-type = "absolute";
+				qcom,scale-function = <0>;
+				qcom,hw-settle-time = <0>;
+				qcom,fast-avg-setup = <0>;
+			};
+		};
+
+		iadc@3600 {
+			compatible = "qcom,qpnp-iadc";
+			reg = <0x3600 0x100>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			interrupts = <0x0 0x36 0x0>;
+			interrupt-names = "eoc-int-en-set";
+			qcom,adc-bit-resolution = <16>;
+			qcom,adc-vdd-reference = <1800>;
+			qcom,rsense = <1500>;
+
+			chan@0 {
+				label = "internal_rsense";
+				reg = <0>;
+				qcom,decimation = <0>;
+				qcom,pre-div-channel-scaling = <1>;
+				qcom,calibration-type = "absolute";
+				qcom,scale-function = <0>;
+				qcom,hw-settle-time = <0>;
+				qcom,fast-avg-setup = <0>;
+			};
+		};
 	};
 
 	qcom,pm8110@1 {
diff --git a/arch/arm/boot/dts/msm-pm8941.dtsi b/arch/arm/boot/dts/msm-pm8941.dtsi
index d456303..320c3e4a 100644
--- a/arch/arm/boot/dts/msm-pm8941.dtsi
+++ b/arch/arm/boot/dts/msm-pm8941.dtsi
@@ -111,6 +111,7 @@
 			qcom,calculate-soc-ms = <20000>;
 			qcom,chg-term-ua = <100000>;
 			qcom,batt-type = <0>;
+			qcom,low-voltage-threshold = <3420000>;
 
 			qcom,bms-iadc@3800 {
 				reg = <0x3800 0x100>;
diff --git a/arch/arm/boot/dts/msm8226-cdp.dts b/arch/arm/boot/dts/msm8226-cdp.dts
index ec4b464b..fa77c35 100644
--- a/arch/arm/boot/dts/msm8226-cdp.dts
+++ b/arch/arm/boot/dts/msm8226-cdp.dts
@@ -87,6 +87,10 @@
 			vdd-phy-supply = <&pm8226_lvs1>;
 		};
 	};
+
+	sound {
+		qcom,cdc-mclk-gpios = <&pm8226_gpios 1 0>;
+	};
 };
 
 &sdcc1 {
@@ -178,6 +182,14 @@
 
 &pm8226_gpios {
 	gpio@c000 { /* GPIO 1 */
+		/* XO_PMIC_CDC_MCLK enable for tapan codec */
+		qcom,mode = <1>;		/* Digital output */
+		qcom,output-type = <0>;	/* CMOS logic */
+		qcom,pull = <5>;		/* QPNP_PIN_PULL_NO*/
+		qcom,vin-sel = <2>;		/* QPNP_PIN_VIN2 */
+		qcom,out-strength = <3>;/* QPNP_PIN_OUT_STRENGTH_HIGH */
+		qcom,src-sel = <2>;		/* QPNP_PIN_SEL_FUNC_1 */
+		qcom,master-en = <1>;	/* Enable GPIO */
 	};
 
 	gpio@c100 { /* GPIO 2 */
@@ -227,3 +239,8 @@
 	mpp@a700 { /* MPP 8 */
 	};
 };
+
+&pm8226_chg {
+	qcom,chg-charging-disabled;
+	qcom,chg-use-default-batt-values;
+};
diff --git a/arch/arm/boot/dts/msm8226-coresight.dtsi b/arch/arm/boot/dts/msm8226-coresight.dtsi
index 8d5d23c..30d79df 100644
--- a/arch/arm/boot/dts/msm8226-coresight.dtsi
+++ b/arch/arm/boot/dts/msm8226-coresight.dtsi
@@ -142,12 +142,72 @@
 		coresight-child-ports = <7>;
 	};
 
+	etm0: etm@fc33c000 {
+		compatible = "arm,coresight-etm";
+		reg = <0xfc33c000 0x1000>;
+		reg-names = "etm0-base";
+
+		coresight-id = <10>;
+		coresight-name = "coresight-etm0";
+		coresight-nr-inports = <0>;
+		coresight-outports = <0>;
+		coresight-child-list = <&funnel_a7ss>;
+		coresight-child-ports = <0>;
+
+		qcom,round-robin;
+	};
+
+	etm1: etm@fc33d000 {
+		compatible = "arm,coresight-etm";
+		reg = <0xfc33d000 0x1000>;
+		reg-names = "etm1-base";
+
+		coresight-id = <11>;
+		coresight-name = "coresight-etm1";
+		coresight-nr-inports = <0>;
+		coresight-outports = <0>;
+		coresight-child-list = <&funnel_a7ss>;
+		coresight-child-ports = <1>;
+
+		qcom,round-robin;
+	};
+
+	etm2: etm@fc33e000 {
+		compatible = "arm,coresight-etm";
+		reg = <0xfc33e000 0x1000>;
+		reg-names = "etm2-base";
+
+		coresight-id = <12>;
+		coresight-name = "coresight-etm2";
+		coresight-nr-inports = <0>;
+		coresight-outports = <0>;
+		coresight-child-list = <&funnel_a7ss>;
+		coresight-child-ports = <2>;
+
+		qcom,round-robin;
+	};
+
+	etm3: etm@fc33f000 {
+		compatible = "arm,coresight-etm";
+		reg = <0xfc33f000 0x1000>;
+		reg-names = "etm3-base";
+
+		coresight-id = <13>;
+		coresight-name = "coresight-etm3";
+		coresight-nr-inports = <0>;
+		coresight-outports = <0>;
+		coresight-child-list = <&funnel_a7ss>;
+		coresight-child-ports = <3>;
+
+		qcom,round-robin;
+	};
+
 	csr: csr@fc302000 {
 		compatible = "qcom,coresight-csr";
 		reg = <0xfc302000 0x1000>;
 		reg-names = "csr-base";
 
-		coresight-id = <10>;
+		coresight-id = <14>;
 		coresight-name = "coresight-csr";
 		coresight-nr-inports = <0>;
 
diff --git a/arch/arm/boot/dts/msm8226-mdss.dtsi b/arch/arm/boot/dts/msm8226-mdss.dtsi
index 30a89ef..21ed66a 100644
--- a/arch/arm/boot/dts/msm8226-mdss.dtsi
+++ b/arch/arm/boot/dts/msm8226-mdss.dtsi
@@ -59,8 +59,13 @@
 		cell-index = <0>;
 		reg = <0xfd922800 0x600>;
 		vdd-supply = <&pm8226_l15>;
-		vdd_io-supply = <&pm8226_l8>;
-		vreg-supply = <&pm8226_l4>;
+		vddio-supply = <&pm8226_l8>;
+		vdda-supply = <&pm8226_l4>;
+		qcom,supply-names = "vdd", "vddio", "vdda";
+		qcom,supply-type = "regulator", "regulator", "regulator";
+		qcom,supply-min-voltage-level = <2800000 1800000 1200000>;
+		qcom,supply-max-voltage-level = <2800000 1800000 1200000>;
+		qcom,supply-peak-current = <150000 100000 100000>;
 		qcom,mdss-fb-map = <&mdss_fb0>;
 	};
 
diff --git a/arch/arm/boot/dts/msm8226-mtp.dts b/arch/arm/boot/dts/msm8226-mtp.dts
index 57fb4b5..e747cb5 100644
--- a/arch/arm/boot/dts/msm8226-mtp.dts
+++ b/arch/arm/boot/dts/msm8226-mtp.dts
@@ -87,6 +87,10 @@
 			vdd-phy-supply = <&pm8226_lvs1>;
 		};
 	};
+
+	sound {
+		qcom,cdc-mclk-gpios = <&pm8226_gpios 1 0>;
+	};
 };
 
 &sdcc1 {
@@ -175,6 +179,14 @@
 
 &pm8226_gpios {
 	gpio@c000 { /* GPIO 1 */
+		/* XO_PMIC_CDC_MCLK enable for tapan codec */
+		qcom,mode = <1>;		/* Digital output */
+		qcom,output-type = <0>;	/* CMOS logic */
+		qcom,pull = <5>;		/* QPNP_PIN_PULL_NO*/
+		qcom,vin-sel = <2>;		/* QPNP_PIN_VIN2 */
+		qcom,out-strength = <3>;/* QPNP_PIN_OUT_STRENGTH_HIGH */
+		qcom,src-sel = <2>;		/* QPNP_PIN_SEL_FUNC_1 */
+		qcom,master-en = <1>;	/* Enable GPIO */
 	};
 
 	gpio@c100 { /* GPIO 2 */
diff --git a/arch/arm/boot/dts/msm8226-pm.dtsi b/arch/arm/boot/dts/msm8226-pm.dtsi
index 686ffb7..34283e8 100644
--- a/arch/arm/boot/dts/msm8226-pm.dtsi
+++ b/arch/arm/boot/dts/msm8226-pm.dtsi
@@ -22,7 +22,7 @@
 		qcom,saw2-ver-reg = <0xfd0>;
 		qcom,saw2-cfg = <0x01>;
 		qcom,saw2-spm-dly= <0x3c102800>;
-		qcom,saw2-spm-ctl = <0x1>;
+		qcom,saw2-spm-ctl = <0x0>;
 		qcom,saw2-spm-cmd-wfi = [60 03 60 0b 0f];
 		qcom,saw2-spm-cmd-spc = [00 20 10 80 30 90 5b 60 03 60 3b 76 76
 				0b 94 5b 80 10 2b 06 26 30 0f];
@@ -39,7 +39,7 @@
 		qcom,saw2-ver-reg = <0xfd0>;
 		qcom,saw2-cfg = <0x01>;
 		qcom,saw2-spm-dly= <0x3c102800>;
-		qcom,saw2-spm-ctl = <0x1>;
+		qcom,saw2-spm-ctl = <0x0>;
 		qcom,saw2-spm-cmd-wfi = [60 03 60 0b 0f];
 		qcom,saw2-spm-cmd-spc = [00 20 10 80 30 90 5b 60 03 60 3b 76 76
 				0b 94 5b 80 10 2b 06 26 30 0f];
@@ -56,7 +56,7 @@
 		qcom,saw2-ver-reg = <0xfd0>;
 		qcom,saw2-cfg = <0x01>;
 		qcom,saw2-spm-dly= <0x3c102800>;
-		qcom,saw2-spm-ctl = <0x1>;
+		qcom,saw2-spm-ctl = <0x0>;
 		qcom,saw2-spm-cmd-wfi = [60 03 60 76 76 0b 0f];
 		qcom,saw2-spm-cmd-spc = [00 20 10 80 30 90 5b 60 03 60 3b 76 76
 				0b 94 5b 80 10 2b 06 26 30 0f];
@@ -73,7 +73,7 @@
 		qcom,saw2-ver-reg = <0xfd0>;
 		qcom,saw2-cfg = <0x01>;
 		qcom,saw2-spm-dly= <0x3c102800>;
-		qcom,saw2-spm-ctl = <0x1>;
+		qcom,saw2-spm-ctl = <0x0>;
 		qcom,saw2-spm-cmd-wfi = [60 03 60 76 76 0b 0f];
 		qcom,saw2-spm-cmd-spc = [00 20 10 80 30 90 5b 60 03 60 3b 76 76
 				0b 94 5b 80 10 2b 06 26 30 0f];
@@ -90,7 +90,7 @@
 		qcom,saw2-ver-reg = <0xfd0>;
 		qcom,saw2-cfg = <0x14>;
 		qcom,saw2-spm-dly= <0x3c102800>;
-		qcom,saw2-spm-ctl = <0x1>;
+		qcom,saw2-spm-ctl = <0x0>;
 		qcom,saw2-pmic-data0 = <0x0400009c>;
 		qcom,saw2-pmic-data1 = <0x0000001c>;
 		qcom,vctl-timeout-us = <50>;
@@ -114,8 +114,8 @@
 		qcom,lpm-resources@0 {
 			reg = <0x0>;
 			qcom,name = "vdd-dig";
-			qcom,type = <0x62706d73>;	/* "smpb" */
-			qcom,id = <0x02>;
+			qcom,type = <0x61706d73>;	/* "smpa" */
+			qcom,id = <0x01>;
 			qcom,key = <0x6e726f63>;	/* "corn" */
 			qcom,init-value = <5>;		/* Super Turbo */
 		};
@@ -123,8 +123,8 @@
 		qcom,lpm-resources@1 {
 			reg = <0x1>;
 			qcom,name = "vdd-mem";
-			qcom,type = <0x62706d73>;	/* "smpb" */
-			qcom,id = <0x01>;
+			qcom,type = <0x616F646C>;	/* "ldoa" */
+			qcom,id = <0x03>;
 			qcom,key = <0x7675>;		/* "uv" */
 			qcom,init-value = <1050000>;	/* Super Turbo */
 		};
diff --git a/arch/arm/boot/dts/msm8226-qrd.dts b/arch/arm/boot/dts/msm8226-qrd.dts
index 09b2d0b..acc4597 100644
--- a/arch/arm/boot/dts/msm8226-qrd.dts
+++ b/arch/arm/boot/dts/msm8226-qrd.dts
@@ -87,6 +87,10 @@
 			vdd-phy-supply = <&pm8226_lvs1>;
 		};
 	};
+
+	sound {
+		qcom,cdc-mclk-gpios = <&pm8226_gpios 1 0>;
+	};
 };
 
 &sdcc1 {
@@ -178,6 +182,14 @@
 
 &pm8226_gpios {
 	gpio@c000 { /* GPIO 1 */
+		/* XO_PMIC_CDC_MCLK enable for tapan codec */
+		qcom,mode = <1>;		/* Digital output */
+		qcom,output-type = <0>;	/* CMOS logic */
+		qcom,pull = <5>;		/* QPNP_PIN_PULL_NO*/
+		qcom,vin-sel = <2>;		/* QPNP_PIN_VIN2 */
+		qcom,out-strength = <3>;/* QPNP_PIN_OUT_STRENGTH_HIGH */
+		qcom,src-sel = <2>;		/* QPNP_PIN_SEL_FUNC_1 */
+		qcom,master-en = <1>;	/* Enable GPIO */
 	};
 
 	gpio@c100 { /* GPIO 2 */
diff --git a/arch/arm/boot/dts/msm8226.dtsi b/arch/arm/boot/dts/msm8226.dtsi
index 17de157..3cf7a6a 100644
--- a/arch/arm/boot/dts/msm8226.dtsi
+++ b/arch/arm/boot/dts/msm8226.dtsi
@@ -215,6 +215,12 @@
 		compatible = "qcom,msm-pcm-routing";
 	};
 
+	qcom,msm-pcm-low-latency {
+		compatible = "qcom,msm-pcm-dsp";
+		qcom,msm-pcm-dsp-id = <1>;
+		qcom,msm-pcm-low-latency;
+	};
+
 	qcom,msm-pcm-lpa {
 		compatible = "qcom,msm-pcm-lpa";
 	};
@@ -459,7 +465,6 @@
 		/* 190,ee0_krait_hlos_spmi_periph_irq */
 		/* 187,channel_0_krait_hlos_trans_done_irq */
 		interrupts = <0 190 0>, <0 187 0>;
-		qcom,not-wakeup;
 		qcom,pmic-arb-ee = <0>;
 		qcom,pmic-arb-channel = <0>;
 	};
@@ -770,9 +775,6 @@
 &pm8226_chg {
 	status = "ok";
 
-	qcom,chg-charging-disabled;
-	qcom,chg-use-default-batt-values;
-
 	qcom,chg-chgr@1000 {
 		status = "ok";
 	};
@@ -781,6 +783,10 @@
 		status = "ok";
 	};
 
+	qcom,chg-bat-if@1200 {
+		status = "ok";
+	};
+
 	qcom,chg-usb-chgpth@1300 {
 		status = "ok";
 	};
diff --git a/arch/arm/boot/dts/msm8610-coresight.dtsi b/arch/arm/boot/dts/msm8610-coresight.dtsi
new file mode 100644
index 0000000..298cb68
--- /dev/null
+++ b/arch/arm/boot/dts/msm8610-coresight.dtsi
@@ -0,0 +1,142 @@
+/* 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.
+ */
+
+/ {
+	tmc_etr: tmc@fc326000 {
+		compatible = "arm,coresight-tmc";
+		reg = <0xfc326000 0x1000>,
+		      <0xfc37c000 0x3000>;
+		reg-names = "tmc-etr-base", "tmc-etr-bam-base";
+
+		qcom,memory-reservation-type = "EBI1";
+		qcom,memory-reservation-size = <0x100000>; /* 1M EBI1 buffer */
+
+		coresight-id = <0>;
+		coresight-name = "coresight-tmc-etr";
+		coresight-nr-inports = <1>;
+	};
+
+	tpiu: tpiu@fc320000 {
+		compatible = "arm,coresight-tpiu";
+		reg = <0xfc320000 0x1000>;
+		reg-names = "tpiu-base";
+
+		coresight-id = <1>;
+		coresight-name = "coresight-tpiu";
+		coresight-nr-inports = <1>;
+	};
+
+	replicator: replicator@fc324000 {
+		compatible = "qcom,coresight-replicator";
+		reg = <0xfc324000 0x1000>;
+		reg-names = "replicator-base";
+
+		coresight-id = <2>;
+		coresight-name = "coresight-replicator";
+		coresight-nr-inports = <1>;
+		coresight-outports = <0 1>;
+		coresight-child-list = <&tmc_etr &tpiu>;
+		coresight-child-ports = <0 0>;
+	};
+
+	tmc_etf: tmc@fc325000 {
+		compatible = "arm,coresight-tmc";
+		reg = <0xfc325000 0x1000>;
+		reg-names = "tmc-etf-base";
+
+		coresight-id = <3>;
+		coresight-name = "coresight-tmc-etf";
+		coresight-nr-inports = <1>;
+		coresight-outports = <0>;
+		coresight-child-list = <&replicator>;
+		coresight-child-ports = <0>;
+		coresight-default-sink;
+	};
+
+	funnel_merg: funnel@fc323000 {
+		compatible = "arm,coresight-funnel";
+		reg = <0xfc323000 0x1000>;
+		reg-names = "funnel-merg-base";
+
+		coresight-id = <4>;
+		coresight-name = "coresight-funnel-merg";
+		coresight-nr-inports = <2>;
+		coresight-outports = <0>;
+		coresight-child-list = <&tmc_etf>;
+		coresight-child-ports = <0>;
+	};
+
+	funnel_in0: funnel@fc321000 {
+		compatible = "arm,coresight-funnel";
+		reg = <0xfc321000 0x1000>;
+		reg-names = "funnel-in0-base";
+
+		coresight-id = <5>;
+		coresight-name = "coresight-funnel-in0";
+		coresight-nr-inports = <8>;
+		coresight-outports = <0>;
+		coresight-child-list = <&funnel_merg>;
+		coresight-child-ports = <0>;
+	};
+
+	funnel_in1: funnel@fc322000 {
+		compatible = "arm,coresight-funnel";
+		reg = <0xfc322000 0x1000>;
+		reg-names = "funnel-in1-base";
+
+		coresight-id = <6>;
+		coresight-name = "coresight-funnel-in1";
+		coresight-nr-inports = <8>;
+		coresight-outports = <0>;
+		coresight-child-list = <&funnel_merg>;
+		coresight-child-ports = <1>;
+	};
+
+	funnel_a7ss: funnel@fc355000 {
+		compatible = "arm,coresight-funnel";
+		reg = <0xfc355000 0x1000>;
+		reg-names = "funnel-a7ss-base";
+
+		coresight-id = <7>;
+		coresight-name = "coresight-funnel-a7ss";
+		coresight-nr-inports = <4>;
+		coresight-outports = <0>;
+		coresight-child-list = <&funnel_in1>;
+		coresight-child-ports = <5>;
+	};
+
+	stm: stm@fc302000 {
+		compatible = "arm,coresight-stm";
+		reg = <0xfc302000 0x1000>,
+		      <0xfa280000 0x180000>;
+		reg-names = "stm-base", "stm-data-base";
+
+		coresight-id = <8>;
+		coresight-name = "coresight-stm";
+		coresight-nr-inports = <0>;
+		coresight-outports = <0>;
+		coresight-child-list = <&funnel_in1>;
+		coresight-child-ports = <7>;
+	};
+
+	csr: csr@fc301000 {
+		compatible = "qcom,coresight-csr";
+		reg = <0xfc301000 0x1000>;
+		reg-names = "csr-base";
+
+		coresight-id = <9>;
+		coresight-name = "coresight-csr";
+		coresight-nr-inports = <0>;
+
+		qcom,blk-size = <3>;
+	};
+};
diff --git a/arch/arm/boot/dts/msm8610.dtsi b/arch/arm/boot/dts/msm8610.dtsi
index fe0ebf9..b258506 100644
--- a/arch/arm/boot/dts/msm8610.dtsi
+++ b/arch/arm/boot/dts/msm8610.dtsi
@@ -14,6 +14,7 @@
 /include/ "msm-iommu-v0.dtsi"
 /include/ "msm8610-ion.dtsi"
 /include/ "msm-gdsc.dtsi"
+/include/ "msm8610-coresight.dtsi"
 /include/ "msm8610-pm.dtsi"
 
 / {
@@ -448,6 +449,7 @@
 		qcom,slope = <2901 2846>;
 		qcom,calib-mode = "fuse_map2";
 		qcom,calibration-less-mode;
+		qcom,tsens-local-init;
 	};
 
 };
@@ -488,3 +490,95 @@
 
 /include/ "msm8610-regulator.dtsi"
 /include/ "msm-pm8110.dtsi"
+
+&pm8110_vadc {
+	chan@0 {
+		label = "usb_in";
+		reg = <0>;
+		qcom,decimation = <0>;
+		qcom,pre-div-channel-scaling = <4>;
+		qcom,calibration-type = "absolute";
+		qcom,scale-function = <0>;
+		qcom,hw-settle-time = <0>;
+		qcom,fast-avg-setup = <0>;
+	};
+
+	chan@2 {
+		label = "vchg_sns";
+		reg = <2>;
+		qcom,decimation = <0>;
+		qcom,pre-div-channel-scaling = <3>;
+		qcom,calibration-type = "absolute";
+		qcom,scale-function = <0>;
+		qcom,hw-settle-time = <0>;
+		qcom,fast-avg-setup = <0>;
+	};
+
+	chan@5 {
+		label = "vcoin";
+		reg = <5>;
+		qcom,decimation = <0>;
+		qcom,pre-div-channel-scaling = <1>;
+		qcom,calibration-type = "absolute";
+		qcom,scale-function = <0>;
+		qcom,hw-settle-time = <0>;
+		qcom,fast-avg-setup = <0>;
+	};
+
+	chan@6 {
+		label = "vbat_sns";
+		reg = <6>;
+		qcom,decimation = <0>;
+		qcom,pre-div-channel-scaling = <1>;
+		qcom,calibration-type = "absolute";
+		qcom,scale-function = <0>;
+		qcom,hw-settle-time = <0>;
+		qcom,fast-avg-setup = <0>;
+	};
+
+	chan@7 {
+		label = "vph_pwr";
+		reg = <7>;
+		qcom,decimation = <0>;
+		qcom,pre-div-channel-scaling = <1>;
+		qcom,calibration-type = "absolute";
+		qcom,scale-function = <0>;
+		qcom,hw-settle-time = <0>;
+		qcom,fast-avg-setup = <0>;
+	};
+
+	chan@30 {
+		label = "batt_therm";
+		reg = <0x30>;
+		qcom,decimation = <0>;
+		qcom,pre-div-channel-scaling = <0>;
+		qcom,calibration-type = "ratiometric";
+		qcom,scale-function = <1>;
+		qcom,hw-settle-time = <2>;
+		qcom,fast-avg-setup = <0>;
+	};
+
+	chan@31 {
+		label = "batt_id";
+		reg = <0x31>;
+		qcom,decimation = <0>;
+		qcom,pre-div-channel-scaling = <0>;
+		qcom,calibration-type = "ratiometric";
+		qcom,scale-function = <0>;
+		qcom,hw-settle-time = <2>;
+		qcom,fast-avg-setup = <0>;
+	};
+
+	chan@b2 {
+		label = "xo_therm_pu2";
+		reg = <0xb2>;
+		qcom,decimation = <0>;
+		qcom,pre-div-channel-scaling = <0>;
+		qcom,calibration-type = "ratiometric";
+		qcom,scale-function = <4>;
+		qcom,hw-settle-time = <2>;
+		qcom,fast-avg-setup = <0>;
+	};
+};
+
+
diff --git a/arch/arm/boot/dts/msm8974-cdp.dtsi b/arch/arm/boot/dts/msm8974-cdp.dtsi
index 2b1cbb5..45cbc89 100644
--- a/arch/arm/boot/dts/msm8974-cdp.dtsi
+++ b/arch/arm/boot/dts/msm8974-cdp.dtsi
@@ -213,6 +213,7 @@
                 HSIC_GDSC-supply = <&gdsc_usb_hsic>;
                 hsic,strobe-gpio = <&msmgpio 144 0x00>;
                 hsic,data-gpio = <&msmgpio 145 0x00>;
+                hsic,resume-gpio = <&msmgpio 80 0x00>;
                 hsic,ignore-cal-pad-config;
                 hsic,strobe-pad-offset = <0x2050>;
                 hsic,data-pad-offset = <0x2054>;
diff --git a/arch/arm/boot/dts/msm8974-liquid.dtsi b/arch/arm/boot/dts/msm8974-liquid.dtsi
index 985b307..a35b9d2 100644
--- a/arch/arm/boot/dts/msm8974-liquid.dtsi
+++ b/arch/arm/boot/dts/msm8974-liquid.dtsi
@@ -370,6 +370,14 @@
 			hsic,ignore-cal-pad-config;
 			hsic,strobe-pad-offset = <0x2050>;
 			hsic,data-pad-offset = <0x2054>;
+
+			qcom,msm-bus,name = "hsic";
+			qcom,msm-bus,num-cases = <2>;
+			qcom,msm-bus,active-only = <0>;
+			qcom,msm-bus,num-paths = <1>;
+			qcom,msm-bus,vectors-KBps =
+					<85 512 0 0>,
+					<85 512 40000 160000>;
 		};
 	};
 };
diff --git a/arch/arm/boot/dts/msm8974-mdss.dtsi b/arch/arm/boot/dts/msm8974-mdss.dtsi
index f382c3e..2f9adbb 100644
--- a/arch/arm/boot/dts/msm8974-mdss.dtsi
+++ b/arch/arm/boot/dts/msm8974-mdss.dtsi
@@ -75,8 +75,8 @@
 		cell-index = <0>;
 		reg = <0xfd922800 0x600>;
 		vdd-supply = <&pm8941_l22>;
-		vdd_io-supply = <&pm8941_l12>;
-		vreg-supply = <&pm8941_l2>;
+		vddio-supply = <&pm8941_l12>;
+		vdda-supply = <&pm8941_l2>;
 		qcom,mdss-fb-map = <&mdss_fb0>;
 	};
 
@@ -86,8 +86,8 @@
 		cell-index = <1>;
 		reg = <0xfd922e00 0x600>;
 		vdd-supply = <&pm8941_l22>;
-		vdd_io-supply = <&pm8941_l12>;
-		vreg-supply = <&pm8941_l2>;
+		vddio-supply = <&pm8941_l12>;
+		vdda-supply = <&pm8941_l2>;
 		qcom,mdss-fb-map = <&mdss_fb0>;
 	};
 
diff --git a/arch/arm/boot/dts/msm8974-v2-pm.dtsi b/arch/arm/boot/dts/msm8974-v2-pm.dtsi
index ad8e5a3..e020fa4 100644
--- a/arch/arm/boot/dts/msm8974-v2-pm.dtsi
+++ b/arch/arm/boot/dts/msm8974-v2-pm.dtsi
@@ -15,8 +15,8 @@
 / {
 	qcom,spm@f9089000 {
 		compatible = "qcom,spm-v2";
-		#address-cells = <1>;
-		#size-cells = <1>;
+	#address-cells = <1>;
+	#size-cells = <1>;
 		reg = <0xf9089000 0x1000>;
 		qcom,core-id = <0>;
 		qcom,saw2-ver-reg = <0xfd0>;
@@ -29,10 +29,10 @@
 		qcom,saw2-spm-ctl = <0x1>;
 		qcom,saw2-spm-cmd-wfi = [03 0b 0f];
 		qcom,saw2-spm-cmd-ret = [42 1b 00 d0 03 d4 5b 0b 00 42 1b 0f];
-		qcom,saw2-spm-cmd-spc = [00 20 50 80 60 70 10 E0 03 6E 70 3B
-				E4 5B 82 3F 50 10 0B 30 06 26 30 0F];
+		qcom,saw2-spm-cmd-spc = [00 20 80 10 E0 03 3B E4 5B 82 10 0B
+			30 06 26 30 0F];
 		qcom,saw2-spm-cmd-pc = [00 20 50 80 60 70 10 E0 07 6E 70 3B
-				E4 5B 82 3F 50 10 0B 30 06 26 30 0F];
+			E4 5B 82 3F 50 10 0B 30 06 26 30 0F];
 	};
 
 	qcom,spm@f9099000 {
@@ -51,8 +51,8 @@
 		qcom,saw2-spm-ctl = <0x1>;
 		qcom,saw2-spm-cmd-wfi = [03 0b 0f];
 		qcom,saw2-spm-cmd-ret = [42 1b 00 d0 03 d4 5b 0b 00 42 1b 0f];
-		qcom,saw2-spm-cmd-spc = [00 20 50 80 60 70 10 E0 03 6E 70 3B
-				E4 5B 82 3F 50 10 0B 30 06 26 30 0F];
+		qcom,saw2-spm-cmd-spc = [00 20 80 10 E0 03 3B E4 5B 82 10 0B
+			30 06 26 30 0F];
 		qcom,saw2-spm-cmd-pc = [00 20 50 80 60 70 10 E0 07 6E 70 3B
 				E4 5B 82 3F 50 10 0B 30 06 26 30 0F];
 	};
@@ -73,8 +73,8 @@
 		qcom,saw2-spm-ctl = <0x1>;
 		qcom,saw2-spm-cmd-wfi = [03 0b 0f];
 		qcom,saw2-spm-cmd-ret = [42 1b 00 d0 03 d4 5b 0b 00 42 1b 0f];
-		qcom,saw2-spm-cmd-spc = [00 20 50 80 60 70 10 E0 03 6E 70 3B
-				E4 5B 82 3F 50 10 0B 30 06 26 30 0F];
+		qcom,saw2-spm-cmd-spc = [00 20 80 10 E0 03 3B E4 5B 82 10 0B
+			30 06 26 30 0F];
 		qcom,saw2-spm-cmd-pc = [00 20 50 80 60 70 10 E0 07 6E 70 3B
 				E4 5B 82 3F 50 10 0B 30 06 26 30 0F];
 	};
@@ -95,8 +95,8 @@
 		qcom,saw2-spm-ctl = <0x1>;
 		qcom,saw2-spm-cmd-wfi = [03 0b 0f];
 		qcom,saw2-spm-cmd-ret = [42 1b 00 d0 03 d4 5b 0b 00 42 1b 0f];
-		qcom,saw2-spm-cmd-spc = [00 20 50 80 60 70 10 E0 03 6E 70 3B
-				E4 5B 82 3F 50 10 0B 30 06 26 30 0F];
+		qcom,saw2-spm-cmd-spc = [00 20 80 10 E0 03 3B E4 5B 82 10 0B
+			30 06 26 30 0F];
 		qcom,saw2-spm-cmd-pc = [00 20 50 80 60 70 10 E0 07 6E 70 3B
 				E4 5B 82 3F 50 10 0B 30 06 26 30 0F];
 	};
diff --git a/arch/arm/boot/dts/msm8974.dtsi b/arch/arm/boot/dts/msm8974.dtsi
index 0377dca..ba03f79 100644
--- a/arch/arm/boot/dts/msm8974.dtsi
+++ b/arch/arm/boot/dts/msm8974.dtsi
@@ -36,13 +36,13 @@
 
 	memory {
 
-		secure_mem: region@0 {
+		secure_mem: secure_region {
 			linux,contiguous-region;
 			reg = <0 0x7800000>;
 			label = "secure_mem";
 		};
 
-		adsp_mem: region@0 {
+		adsp_mem: adsp_region {
 			linux,contiguous-region;
 			reg = <0 0x2000000>;
 			label = "adsp_mem";
@@ -590,6 +590,7 @@
 		qcom,audio-routing =
 			"RX_BIAS", "MCLK",
 			"LDO_H", "MCLK",
+			"AIF4 MAD", "MCLK",
 			"AMIC1", "MIC BIAS1 Internal1",
 			"MIC BIAS1 Internal1", "Handset Mic",
 			"AMIC2", "MIC BIAS2 External",
@@ -800,6 +801,10 @@
 		qcom,msm-dai-q6-dev-id = <8>;
 	};
 
+	qcom,msm-lsm-client {
+		compatible = "qcom,msm-lsm-client";
+	};
+
 	qcom,msm-dai-q6 {
 		compatible = "qcom,msm-dai-q6";
 		qcom,msm-dai-q6-sb-0-rx {
@@ -852,6 +857,11 @@
 			qcom,msm-dai-q6-dev-id = <16393>;
 		};
 
+		qcom,msm-dai-q6-sb-5-tx {
+			compatible = "qcom,msm-dai-q6-dev";
+			qcom,msm-dai-q6-dev-id = <16395>;
+		};
+
 		qcom,msm-dai-q6-bt-sco-rx {
 			compatible = "qcom,msm-dai-q6-dev";
 			qcom,msm-dai-q6-dev-id = <12288>;
@@ -1242,10 +1252,6 @@
 		interrupts = <0 29 1>;
 	};
 
-        qcom,msm-wdog-debug@fc401000 {
-               compatible = "qcom,msm-wdog-debug";
-               reg = <0xfc401000 0x1000>;
-        };
         qcom,msm-mem-hole {
                 compatible = "qcom,msm-mem-hole";
                 qcom,memblock-remove = <0x7f00000 0x8000000>; /* Address and Size of Hole */
diff --git a/arch/arm/boot/dts/msm9625-v2-cdp.dts b/arch/arm/boot/dts/msm9625-v2-cdp.dts
index 244556d..09a89ab 100644
--- a/arch/arm/boot/dts/msm9625-v2-cdp.dts
+++ b/arch/arm/boot/dts/msm9625-v2-cdp.dts
@@ -42,7 +42,7 @@
 
 	wlan0: qca,wlan {
 		cell-index = <0>;
-		compatible = "qca,ar6004-sdio";
+		compatible = "qca,ar6004-hsic";
 		qca,chip-pwd-l-gpios = <&msmgpio 62 0>;
 		qca,pm-enable-gpios = <&pm8019_gpios 3 0x0>;
 		qca,ar6004-vdd-io-supply = <&pm8019_l11>;
diff --git a/arch/arm/boot/dts/msm9625-v2-mtp.dts b/arch/arm/boot/dts/msm9625-v2-mtp.dts
index bf0f539..7949080 100644
--- a/arch/arm/boot/dts/msm9625-v2-mtp.dts
+++ b/arch/arm/boot/dts/msm9625-v2-mtp.dts
@@ -42,7 +42,7 @@
 
 	wlan0: qca,wlan {
 		cell-index = <0>;
-		compatible = "qca,ar6004-sdio";
+		compatible = "qca,ar6004-hsic";
 		qca,chip-pwd-l-gpios = <&msmgpio 62 0>;
 		qca,pm-enable-gpios = <&pm8019_gpios 3 0x0>;
 		qca,ar6004-vdd-io-supply = <&pm8019_l11>;
diff --git a/arch/arm/boot/dts/msm9625.dtsi b/arch/arm/boot/dts/msm9625.dtsi
index eb990d4..9172029 100644
--- a/arch/arm/boot/dts/msm9625.dtsi
+++ b/arch/arm/boot/dts/msm9625.dtsi
@@ -784,8 +784,8 @@
 
 	sfpb_spinlock: qcom,ipc-spinlock@fd484000 {
 		compatible = "qcom,ipc-spinlock-sfpb";
-		reg = <0xfd484000 0x1000>;
-		qcom,num-locks = <32>;
+		reg = <0xfd484000 0x400>;
+		qcom,num-locks = <8>;
 	};
 
 	ldrex_spinlock: qcom,ipc-spinlock@fa00000 {
diff --git a/arch/arm/boot/dts/msmzinc-sim.dts b/arch/arm/boot/dts/msmzinc-sim.dts
new file mode 100644
index 0000000..48d7ef1
--- /dev/null
+++ b/arch/arm/boot/dts/msmzinc-sim.dts
@@ -0,0 +1,29 @@
+/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+/dts-v1/;
+
+/include/ "msmzinc.dtsi"
+
+/ {
+	model = "Qualcomm MSM ZINC Simulator";
+	compatible = "qcom,msmzinc-sim", "qcom,msmzinc";
+	qcom,msm-id = <178 0 0>;
+
+	aliases {
+		serial0 = &uart0;
+	};
+
+	uart0: serial@f991f000 {
+		status = "ok";
+	};
+};
diff --git a/arch/arm/boot/dts/msmzinc.dtsi b/arch/arm/boot/dts/msmzinc.dtsi
new file mode 100644
index 0000000..8905962
--- /dev/null
+++ b/arch/arm/boot/dts/msmzinc.dtsi
@@ -0,0 +1,83 @@
+/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+/include/ "skeleton.dtsi"
+
+/ {
+	model = "Qualcomm MSM ZINC";
+	compatible = "qcom,msmzinc";
+	interrupt-parent = <&intc>;
+
+	intc: interrupt-controller@f9000000 {
+		compatible = "qcom,msm-qgic2";
+		interrupt-controller;
+		#interrupt-cells = <3>;
+		reg = <0xF9000000 0x1000>,
+		      <0xF9002000 0x1000>;
+	};
+
+	msmgpio: gpio@fd510000 {
+		compatible = "qcom,msm-gpio";
+		gpio-controller;
+		#gpio-cells = <2>;
+		interrupt-controller;
+		#interrupt-cells = <2>;
+		reg = <0xfd510000 0x4000>;
+		ngpio = <146>;
+		interrupts = <0 208 0>;
+		qcom,direct-connect-irqs = <8>;
+	};
+
+	timer {
+		compatible = "arm,armv7-timer";
+		interrupts = <1 2 0 1 3 0>;
+		clock-frequency = <19200000>;
+	};
+
+	serial@f991f000 {
+		compatible = "qcom,msm-lsuart-v14";
+		reg = <0xf991f000 0x1000>;
+		interrupts = <0 109 0>;
+		status = "disabled";
+	};
+
+	qcom,cache_erp {
+		compatible = "qcom,cache_erp";
+		interrupts = <1 9 0>, <0 2 0>;
+		interrupt-names = "l1_irq", "l2_irq";
+	};
+
+	qcom,cache_dump {
+		compatible = "qcom,cache_dump";
+		qcom,l1-dump-size = <0x100000>;
+		qcom,l2-dump-size = <0x500000>;
+		qcom,memory-reservation-type = "EBI1";
+		qcom,memory-reservation-size = <0x600000>; /* 6M EBI1 buffer */
+	};
+
+	rpm_bus: qcom,rpm-smd {
+		compatible = "qcom,rpm-smd";
+		rpm-channel-name = "rpm_requests";
+		rpm-channel-type = <15>; /* SMD_APPS_RPM */
+		rpm-standalone;
+	};
+
+	qcom,ion {
+		compatible = "qcom,msm-ion";
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		qcom,ion-heap@30 { /* SYSTEM HEAP */
+			reg = <30>;
+		};
+	};
+};
diff --git a/arch/arm/configs/msm8610_defconfig b/arch/arm/configs/msm8610_defconfig
index 216fe99..dc73f4d 100644
--- a/arch/arm/configs/msm8610_defconfig
+++ b/arch/arm/configs/msm8610_defconfig
@@ -182,6 +182,7 @@
 CONFIG_NET_CLS_FW=y
 CONFIG_SYNC=y
 CONFIG_SW_SYNC=y
+CONFIG_CMA=y
 CONFIG_BLK_DEV_LOOP=y
 CONFIG_BLK_DEV_RAM=y
 CONFIG_MD=y
@@ -324,6 +325,7 @@
 CONFIG_THERMAL=y
 CONFIG_THERMAL_TSENS8974=y
 CONFIG_THERMAL_MONITOR=y
+CONFIG_THERMAL_QPNP_ADC_TM=y
 CONFIG_MSM_RTB=y
 CONFIG_MSM_RTB_SEPARATE_CPUS=y
 CONFIG_CORESIGHT=y
diff --git a/arch/arm/configs/msm8974-perf_defconfig b/arch/arm/configs/msm8974-perf_defconfig
index ea10007..224df83 100644
--- a/arch/arm/configs/msm8974-perf_defconfig
+++ b/arch/arm/configs/msm8974-perf_defconfig
@@ -474,3 +474,4 @@
 CONFIG_PM_WAKELOCKS_LIMIT=0
 CONFIG_PM_AUTOSLEEP=y
 # CONFIG_PM_WAKELOCKS_GC is not set
+CONFIG_MSM_BOOT_STATS=y
diff --git a/arch/arm/configs/msm8974_defconfig b/arch/arm/configs/msm8974_defconfig
index 077c7a6..e42aa77 100644
--- a/arch/arm/configs/msm8974_defconfig
+++ b/arch/arm/configs/msm8974_defconfig
@@ -499,3 +499,4 @@
 CONFIG_PM_WAKELOCKS_LIMIT=0
 CONFIG_PM_AUTOSLEEP=y
 # CONFIG_PM_WAKELOCKS_GC is not set
+CONFIG_MSM_BOOT_STATS=y
diff --git a/arch/arm/configs/msm9625-perf_defconfig b/arch/arm/configs/msm9625-perf_defconfig
index 1a10e66..6e8fe3e 100644
--- a/arch/arm/configs/msm9625-perf_defconfig
+++ b/arch/arm/configs/msm9625-perf_defconfig
@@ -325,3 +325,4 @@
 CONFIG_MSM_MEMORY_DUMP=y
 CONFIG_PM_AUTOSLEEP=y
 # CONFIG_PM_WAKELOCKS_GC is not set
+CONFIG_MSM_BOOT_STATS=y
diff --git a/arch/arm/configs/msm9625_defconfig b/arch/arm/configs/msm9625_defconfig
index 4b9b805..9a32239 100644
--- a/arch/arm/configs/msm9625_defconfig
+++ b/arch/arm/configs/msm9625_defconfig
@@ -326,3 +326,4 @@
 CONFIG_MSM_MEMORY_DUMP=y
 CONFIG_PM_AUTOSLEEP=y
 # CONFIG_PM_WAKELOCKS_GC is not set
+CONFIG_MSM_BOOT_STATS=y
diff --git a/arch/arm/configs/msmzinc_defconfig b/arch/arm/configs/msmzinc_defconfig
new file mode 100644
index 0000000..b74b204
--- /dev/null
+++ b/arch/arm/configs/msmzinc_defconfig
@@ -0,0 +1,383 @@
+# CONFIG_ARM_PATCH_PHYS_VIRT is not set
+CONFIG_EXPERIMENTAL=y
+CONFIG_SYSVIPC=y
+CONFIG_RCU_FAST_NO_HZ=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_CGROUPS=y
+CONFIG_CGROUP_DEBUG=y
+CONFIG_CGROUP_FREEZER=y
+CONFIG_CGROUP_CPUACCT=y
+CONFIG_RESOURCE_COUNTERS=y
+CONFIG_CGROUP_SCHED=y
+CONFIG_RT_GROUP_SCHED=y
+CONFIG_NAMESPACES=y
+# CONFIG_UTS_NS is not set
+# CONFIG_IPC_NS is not set
+# CONFIG_PID_NS is not set
+CONFIG_RELAY=y
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_RD_BZIP2=y
+CONFIG_RD_LZMA=y
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_PANIC_TIMEOUT=5
+CONFIG_KALLSYMS_ALL=y
+CONFIG_ASHMEM=y
+CONFIG_EMBEDDED=y
+CONFIG_PROFILING=y
+CONFIG_KPROBES=y
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODULE_FORCE_UNLOAD=y
+CONFIG_MODVERSIONS=y
+CONFIG_PARTITION_ADVANCED=y
+CONFIG_EFI_PARTITION=y
+CONFIG_IOSCHED_TEST=y
+CONFIG_ARCH_MSM=y
+CONFIG_ARCH_MSMZINC=y
+CONFIG_MSM_KRAIT_TBB_ABORT_HANDLER=y
+CONFIG_MSM_RPM_SMD=y
+# CONFIG_MSM_STACKED_MEMORY is not set
+CONFIG_CPU_HAS_L2_PMU=y
+# CONFIG_MSM_FIQ_SUPPORT is not set
+# CONFIG_MSM_PROC_COMM is not set
+CONFIG_MSM_SMD=y
+CONFIG_MSM_SMD_PKG4=y
+CONFIG_MSM_IPC_LOGGING=y
+CONFIG_MSM_IPC_ROUTER=y
+CONFIG_MSM_IPC_ROUTER_SMD_XPRT=y
+CONFIG_MSM_IPC_ROUTER_SECURITY=y
+# CONFIG_MSM_HW3D is not set
+CONFIG_MSM_RPM_REGULATOR_SMD=y
+CONFIG_MSM_SUBSYSTEM_RESTART=y
+CONFIG_MSM_SYSMON_COMM=y
+CONFIG_MSM_DIRECT_SCLK_ACCESS=y
+CONFIG_MSM_WATCHDOG_V2=y
+CONFIG_MSM_MEMORY_DUMP=y
+CONFIG_MSM_DLOAD_MODE=y
+CONFIG_MSM_RUN_QUEUE_STATS=y
+CONFIG_MSM_SPM_V2=y
+CONFIG_MSM_L2_SPM=y
+CONFIG_MSM_MULTIMEDIA_USE_ION=y
+CONFIG_MSM_OCMEM=y
+CONFIG_MSM_OCMEM_LOCAL_POWER_CTRL=y
+CONFIG_MSM_OCMEM_DEBUG=y
+CONFIG_MSM_OCMEM_NONSECURE=y
+CONFIG_SENSORS_ADSP=y
+CONFIG_MSM_RTB=y
+CONFIG_MSM_RTB_SEPARATE_CPUS=y
+CONFIG_MSM_CACHE_ERP=y
+CONFIG_MSM_L1_ERR_PANIC=y
+CONFIG_MSM_L1_RECOV_ERR_PANIC=y
+CONFIG_MSM_L1_ERR_LOG=y
+CONFIG_MSM_L2_ERP_PRINT_ACCESS_ERRORS=y
+CONFIG_MSM_L2_ERP_PORT_PANIC=y
+CONFIG_MSM_L2_ERP_1BIT_PANIC=y
+CONFIG_MSM_L2_ERP_2BIT_PANIC=y
+CONFIG_MSM_CACHE_DUMP=y
+CONFIG_MSM_CACHE_DUMP_ON_PANIC=y
+CONFIG_MSM_ENABLE_WDOG_DEBUG_CONTROL=y
+CONFIG_ARM_LPAE=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_SMP=y
+# CONFIG_SMP_ON_UP is not set
+CONFIG_SCHED_MC=y
+CONFIG_ARM_ARCH_TIMER=y
+CONFIG_PREEMPT=y
+CONFIG_AEABI=y
+CONFIG_HIGHMEM=y
+CONFIG_VMALLOC_RESERVE=0x19000000
+CONFIG_CC_STACKPROTECTOR=y
+CONFIG_CP_ACCESS=y
+CONFIG_USE_OF=y
+CONFIG_CPU_FREQ=y
+CONFIG_CPU_FREQ_GOV_POWERSAVE=y
+CONFIG_CPU_FREQ_GOV_USERSPACE=y
+CONFIG_CPU_FREQ_GOV_ONDEMAND=y
+CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y
+CONFIG_CPU_IDLE=y
+CONFIG_VFP=y
+CONFIG_NEON=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+CONFIG_WAKELOCK=y
+CONFIG_PM_RUNTIME=y
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_INET=y
+CONFIG_IP_ADVANCED_ROUTER=y
+CONFIG_IP_MULTIPLE_TABLES=y
+CONFIG_IP_ROUTE_VERBOSE=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
+# CONFIG_INET_XFRM_MODE_TUNNEL is not set
+# CONFIG_INET_XFRM_MODE_BEET is not set
+# CONFIG_INET_LRO is not set
+CONFIG_IPV6=y
+CONFIG_IPV6_PRIVACY=y
+CONFIG_IPV6_ROUTER_PREF=y
+CONFIG_IPV6_ROUTE_INFO=y
+CONFIG_IPV6_OPTIMISTIC_DAD=y
+CONFIG_INET6_AH=y
+CONFIG_INET6_ESP=y
+CONFIG_INET6_IPCOMP=y
+CONFIG_IPV6_MIP6=y
+CONFIG_IPV6_MULTIPLE_TABLES=y
+CONFIG_IPV6_SUBTREES=y
+CONFIG_NETFILTER=y
+CONFIG_NETFILTER_NETLINK_LOG=y
+CONFIG_NF_CONNTRACK=y
+CONFIG_NF_CONNTRACK_EVENTS=y
+CONFIG_NF_CT_PROTO_DCCP=y
+CONFIG_NF_CT_PROTO_SCTP=y
+CONFIG_NF_CT_PROTO_UDPLITE=y
+CONFIG_NF_CONNTRACK_AMANDA=y
+CONFIG_NF_CONNTRACK_FTP=y
+CONFIG_NF_CONNTRACK_H323=y
+CONFIG_NF_CONNTRACK_IRC=y
+CONFIG_NF_CONNTRACK_NETBIOS_NS=y
+CONFIG_NF_CONNTRACK_PPTP=y
+CONFIG_NF_CONNTRACK_SANE=y
+CONFIG_NF_CONNTRACK_SIP=y
+CONFIG_NF_CONNTRACK_TFTP=y
+CONFIG_NF_CT_NETLINK=y
+CONFIG_NETFILTER_TPROXY=y
+CONFIG_NETFILTER_XT_TARGET_CLASSIFY=y
+CONFIG_NETFILTER_XT_TARGET_CONNMARK=y
+CONFIG_NETFILTER_XT_TARGET_LOG=y
+CONFIG_NETFILTER_XT_TARGET_MARK=y
+CONFIG_NETFILTER_XT_TARGET_NFQUEUE=y
+CONFIG_NETFILTER_XT_MATCH_COMMENT=y
+CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=y
+CONFIG_NETFILTER_XT_MATCH_CONNMARK=y
+CONFIG_NETFILTER_XT_MATCH_CONNTRACK=y
+CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=y
+CONFIG_NETFILTER_XT_MATCH_HELPER=y
+CONFIG_NETFILTER_XT_MATCH_IPRANGE=y
+CONFIG_NETFILTER_XT_MATCH_LENGTH=y
+CONFIG_NETFILTER_XT_MATCH_LIMIT=y
+CONFIG_NETFILTER_XT_MATCH_MAC=y
+CONFIG_NETFILTER_XT_MATCH_MARK=y
+CONFIG_NETFILTER_XT_MATCH_MULTIPORT=y
+CONFIG_NETFILTER_XT_MATCH_POLICY=y
+CONFIG_NETFILTER_XT_MATCH_PKTTYPE=y
+CONFIG_NETFILTER_XT_MATCH_QTAGUID=y
+CONFIG_NETFILTER_XT_MATCH_QUOTA=y
+CONFIG_NETFILTER_XT_MATCH_QUOTA2=y
+CONFIG_NETFILTER_XT_MATCH_QUOTA2_LOG=y
+CONFIG_NETFILTER_XT_MATCH_SOCKET=y
+CONFIG_NETFILTER_XT_MATCH_STATE=y
+CONFIG_NETFILTER_XT_MATCH_STATISTIC=y
+CONFIG_NETFILTER_XT_MATCH_STRING=y
+CONFIG_NETFILTER_XT_MATCH_TIME=y
+CONFIG_NETFILTER_XT_MATCH_U32=y
+CONFIG_NF_CONNTRACK_IPV4=y
+CONFIG_IP_NF_IPTABLES=y
+CONFIG_IP_NF_MATCH_AH=y
+CONFIG_IP_NF_MATCH_ECN=y
+CONFIG_IP_NF_MATCH_TTL=y
+CONFIG_IP_NF_FILTER=y
+CONFIG_IP_NF_TARGET_REJECT=y
+CONFIG_IP_NF_MANGLE=y
+CONFIG_IP_NF_RAW=y
+CONFIG_IP_NF_ARPTABLES=y
+CONFIG_IP_NF_ARPFILTER=y
+CONFIG_IP_NF_ARP_MANGLE=y
+CONFIG_NF_CONNTRACK_IPV6=y
+CONFIG_IP6_NF_IPTABLES=y
+CONFIG_IP6_NF_FILTER=y
+CONFIG_IP6_NF_TARGET_REJECT=y
+CONFIG_IP6_NF_MANGLE=y
+CONFIG_IP6_NF_RAW=y
+CONFIG_NET_SCHED=y
+CONFIG_NET_SCH_HTB=y
+CONFIG_NET_SCH_PRIO=y
+CONFIG_NET_CLS_FW=y
+CONFIG_NET_CLS_U32=y
+CONFIG_CLS_U32_MARK=y
+CONFIG_NET_CLS_FLOW=y
+CONFIG_NET_EMATCH=y
+CONFIG_NET_EMATCH_CMP=y
+CONFIG_NET_EMATCH_NBYTE=y
+CONFIG_NET_EMATCH_U32=y
+CONFIG_NET_EMATCH_META=y
+CONFIG_NET_EMATCH_TEXT=y
+CONFIG_NET_CLS_ACT=y
+CONFIG_CFG80211=y
+CONFIG_RFKILL=y
+CONFIG_GENLOCK=y
+CONFIG_GENLOCK_MISCDEVICE=y
+CONFIG_SYNC=y
+CONFIG_SW_SYNC=y
+CONFIG_BLK_DEV_LOOP=y
+CONFIG_BLK_DEV_RAM=y
+CONFIG_HAPTIC_ISA1200=y
+CONFIG_USB_HSIC_SMSC_HUB=y
+CONFIG_TI_DRV2667=y
+CONFIG_SCSI=y
+CONFIG_SCSI_TGT=y
+CONFIG_BLK_DEV_SD=y
+CONFIG_CHR_DEV_SG=y
+CONFIG_CHR_DEV_SCH=y
+CONFIG_SCSI_MULTI_LUN=y
+CONFIG_SCSI_CONSTANTS=y
+CONFIG_SCSI_LOGGING=y
+CONFIG_SCSI_SCAN_ASYNC=y
+CONFIG_MD=y
+CONFIG_BLK_DEV_DM=y
+CONFIG_DM_CRYPT=y
+CONFIG_NETDEVICES=y
+CONFIG_DUMMY=y
+CONFIG_TUN=y
+CONFIG_KS8851=m
+# CONFIG_MSM_RMNET is not set
+CONFIG_SLIP=y
+CONFIG_SLIP_COMPRESSED=y
+CONFIG_SLIP_MODE_SLIP6=y
+CONFIG_USB_USBNET=y
+CONFIG_INPUT_EVDEV=y
+CONFIG_INPUT_EVBUG=m
+CONFIG_KEYBOARD_GPIO=y
+CONFIG_INPUT_JOYSTICK=y
+CONFIG_INPUT_TOUCHSCREEN=y
+CONFIG_TOUCHSCREEN_ATMEL_MXT=y
+CONFIG_INPUT_MISC=y
+CONFIG_INPUT_UINPUT=y
+CONFIG_SERIAL_MSM_HSL=y
+CONFIG_SERIAL_MSM_HSL_CONSOLE=y
+CONFIG_HW_RANDOM=y
+CONFIG_HW_RANDOM_MSM=y
+CONFIG_I2C=y
+CONFIG_I2C_CHARDEV=y
+CONFIG_I2C_QUP=y
+CONFIG_SPI=y
+CONFIG_SPI_SPIDEV=m
+CONFIG_SPMI=y
+CONFIG_SPMI_MSM_PMIC_ARB=y
+CONFIG_MSM_QPNP_INT=y
+CONFIG_DEBUG_GPIO=y
+CONFIG_GPIO_SYSFS=y
+CONFIG_GPIO_QPNP_PIN=y
+CONFIG_GPIO_QPNP_PIN_DEBUG=y
+CONFIG_POWER_SUPPLY=y
+CONFIG_SMB350_CHARGER=y
+CONFIG_BATTERY_BQ28400=y
+CONFIG_QPNP_CHARGER=y
+CONFIG_BATTERY_BCL=y
+CONFIG_SENSORS_EPM_ADC=y
+CONFIG_SENSORS_QPNP_ADC_VOLTAGE=y
+CONFIG_SENSORS_QPNP_ADC_CURRENT=y
+CONFIG_THERMAL=y
+CONFIG_THERMAL_TSENS8974=y
+CONFIG_THERMAL_MONITOR=y
+CONFIG_THERMAL_QPNP=y
+CONFIG_THERMAL_QPNP_ADC_TM=y
+CONFIG_REGULATOR_FIXED_VOLTAGE=y
+CONFIG_REGULATOR_STUB=y
+CONFIG_REGULATOR_QPNP=y
+CONFIG_MEDIA_SUPPORT=y
+CONFIG_MEDIA_CONTROLLER=y
+CONFIG_ION=y
+CONFIG_ION_MSM=y
+CONFIG_MSM_KGSL=y
+CONFIG_FB=y
+CONFIG_FB_MSM=y
+# CONFIG_FB_MSM_BACKLIGHT is not set
+CONFIG_FB_MSM_MDSS=y
+CONFIG_FB_MSM_MDSS_WRITEBACK=y
+CONFIG_FB_MSM_MDSS_HDMI_PANEL=y
+CONFIG_FB_MSM_MDSS_HDMI_MHL_SII8334=y
+CONFIG_BACKLIGHT_LCD_SUPPORT=y
+# CONFIG_LCD_CLASS_DEVICE is not set
+CONFIG_BACKLIGHT_CLASS_DEVICE=y
+# CONFIG_BACKLIGHT_GENERIC is not set
+CONFIG_USB=y
+CONFIG_USB_SUSPEND=y
+CONFIG_USB_EHCI_HCD=y
+CONFIG_USB_EHCI_MSM=y
+CONFIG_USB_EHCI_MSM_HSIC=y
+CONFIG_USB_ACM=y
+CONFIG_USB_STORAGE=y
+CONFIG_USB_STORAGE_DATAFAB=y
+CONFIG_USB_STORAGE_FREECOM=y
+CONFIG_USB_STORAGE_ISD200=y
+CONFIG_USB_STORAGE_USBAT=y
+CONFIG_USB_STORAGE_SDDR09=y
+CONFIG_USB_STORAGE_SDDR55=y
+CONFIG_USB_STORAGE_JUMPSHOT=y
+CONFIG_USB_STORAGE_ALAUDA=y
+CONFIG_USB_STORAGE_ONETOUCH=y
+CONFIG_USB_STORAGE_KARMA=y
+CONFIG_USB_STORAGE_CYPRESS_ATACB=y
+CONFIG_USB_STORAGE_ENE_UB6250=y
+CONFIG_LEDS_QPNP=y
+CONFIG_LEDS_TRIGGERS=y
+CONFIG_LEDS_TRIGGER_BACKLIGHT=y
+CONFIG_LEDS_TRIGGER_DEFAULT_ON=y
+CONFIG_SWITCH=y
+CONFIG_RTC_CLASS=y
+# CONFIG_RTC_DRV_MSM is not set
+CONFIG_RTC_DRV_QPNP=y
+CONFIG_STAGING=y
+CONFIG_ANDROID=y
+CONFIG_ANDROID_BINDER_IPC=y
+CONFIG_ANDROID_LOGGER=y
+CONFIG_ANDROID_TIMED_GPIO=y
+CONFIG_ANDROID_LOW_MEMORY_KILLER=y
+CONFIG_MSM_SSBI=y
+CONFIG_SPS=y
+CONFIG_SPS_SUPPORT_BAMDMA=y
+CONFIG_SPS_SUPPORT_NDP_BAM=y
+CONFIG_QPNP_PWM=y
+CONFIG_QPNP_POWER_ON=y
+CONFIG_QPNP_CLKDIV=y
+CONFIG_MSM_IOMMU=y
+CONFIG_EXT2_FS=y
+CONFIG_EXT2_FS_XATTR=y
+CONFIG_EXT3_FS=y
+# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
+CONFIG_EXT4_FS=y
+CONFIG_FUSE_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_TMPFS=y
+CONFIG_PSTORE=y
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_ASCII=y
+CONFIG_NLS_ISO8859_1=y
+CONFIG_PRINTK_TIME=y
+CONFIG_MAGIC_SYSRQ=y
+CONFIG_LOCKUP_DETECTOR=y
+# CONFIG_DETECT_HUNG_TASK is not set
+CONFIG_SCHEDSTATS=y
+CONFIG_TIMER_STATS=y
+CONFIG_DEBUG_KMEMLEAK=y
+CONFIG_DEBUG_KMEMLEAK_DEFAULT_OFF=y
+CONFIG_DEBUG_SPINLOCK=y
+CONFIG_DEBUG_MUTEXES=y
+CONFIG_DEBUG_ATOMIC_SLEEP=y
+CONFIG_DEBUG_STACK_USAGE=y
+CONFIG_DEBUG_INFO=y
+CONFIG_DEBUG_MEMORY_INIT=y
+CONFIG_DEBUG_LIST=y
+CONFIG_FAULT_INJECTION=y
+CONFIG_FAIL_PAGE_ALLOC=y
+CONFIG_FAULT_INJECTION_DEBUG_FS=y
+CONFIG_FAULT_INJECTION_STACKTRACE_FILTER=y
+CONFIG_DEBUG_PAGEALLOC=y
+CONFIG_CPU_FREQ_SWITCH_PROFILER=y
+CONFIG_DYNAMIC_DEBUG=y
+CONFIG_DEBUG_USER=y
+CONFIG_DEBUG_LL=y
+CONFIG_EARLY_PRINTK=y
+CONFIG_PID_IN_CONTEXTIDR=y
+CONFIG_KEYS=y
+CONFIG_CRYPTO_MD4=y
+CONFIG_CRYPTO_SHA256=y
+CONFIG_CRYPTO_ARC4=y
+CONFIG_CRYPTO_TWOFISH=y
+CONFIG_CRYPTO_DEV_QCRYPTO=m
+CONFIG_CRYPTO_DEV_QCE=m
+CONFIG_CRYPTO_DEV_QCEDEV=m
+CONFIG_CRC_CCITT=y
diff --git a/arch/arm/mach-msm/Kconfig b/arch/arm/mach-msm/Kconfig
index ce557b1..b65016a 100644
--- a/arch/arm/mach-msm/Kconfig
+++ b/arch/arm/mach-msm/Kconfig
@@ -286,6 +286,24 @@
 	select MSM_LPM_TEST
 	select MSM_RPM_LOG
 
+config ARCH_MSMZINC
+	bool "MSMZINC"
+	select ARCH_MSM_KRAITMP
+	select GPIO_MSM_V3
+	select ARM_GIC
+	select CPU_V7
+	select MSM_SCM if SMP
+	select MSM_GPIOMUX
+	select MULTI_IRQ_HANDLER
+	select MSM_NATIVE_RESTART
+	select MSM_RESTART_V2
+	select MSM_PM8X60 if PM
+	select MAY_HAVE_SPARSE_IRQ
+	select SPARSE_IRQ
+	select REGULATOR
+	select ARM_HAS_SG_CHAIN
+	select ARCH_DMA_ADDR_T_64BIT if ARM_LPAE
+
 config ARCH_MPQ8092
 	bool "MPQ8092"
 	select ARCH_MSM_KRAITMP
@@ -1043,6 +1061,7 @@
 	default "0x80200000" if ARCH_MSM8960
 	default "0x80200000" if ARCH_MSM8930
 	default "0x00000000" if ARCH_MSM8974
+	default "0x00000000" if ARCH_MSMZINC
 	default "0x00000000" if ARCH_MPQ8092
 	default "0x00000000" if ARCH_MSM8226
 	default "0x00000000" if ARCH_MSM8610
@@ -1193,6 +1212,14 @@
                 help
                   Say Y here if you want the debug print routines to direct
                   their output to the serial port on MPQ8092 devices.
+
+	config DEBUG_MSMZINC_UART
+                bool "Kernel low-level debugging messages via MSMZINC UART"
+                depends on ARCH_MSMZINC
+                select MSM_HAS_DEBUG_UART_HS_V14
+                help
+                  Say Y here if you want the debug print routines to direct
+                  their output to the serial port on MSMZINC devices.
 endchoice
 
 choice
@@ -2817,12 +2844,12 @@
 	 does not have a direct access to the PMIC.
 
 config MSM_ENABLE_WDOG_DEBUG_CONTROL
-	bool "MSM Watchdog driver to disable debug Image"
+	bool "Enable control of watchdog debug and boot partition select"
 	help
-	 This driver supports the configuration of the GCC_WDOG_DEBUG register
-	 used to control debug image.
-	 This support is currently required for MSM8974 to disable debug image
-	 on PS HOLD reset
+	  Enables support for controlling watchdog debug and boot partition
+	  select. This is currently used to bypass debug image for PS_HOLD reset
+	  by disabling watchdog debug and boot partition select. This allows
+	  for a clean MSM reset for reboot scenarios.
 
 config MSM_FIQ
 	bool "Enable FIQ for debugging"
diff --git a/arch/arm/mach-msm/Makefile b/arch/arm/mach-msm/Makefile
index fb7e4e3..161ee3d 100644
--- a/arch/arm/mach-msm/Makefile
+++ b/arch/arm/mach-msm/Makefile
@@ -118,6 +118,7 @@
 ifndef CONFIG_ARCH_MSM9625
 ifndef CONFIG_ARCH_MPQ8092
 ifndef CONFIG_ARCH_MSM8610
+ifndef CONFIG_ARCH_MSMZINC
 	obj-y += nand_partitions.o
 endif
 endif
@@ -127,6 +128,7 @@
 endif
 endif
 endif
+endif
 obj-$(CONFIG_MSM_SDIO_TTY) += sdio_tty.o
 obj-$(CONFIG_MSM_SMD_TTY) += smd_tty.o
 obj-$(CONFIG_MSM_SMD_QMI) += smd_qmi.o
@@ -290,6 +292,7 @@
 obj-$(CONFIG_MACH_MPQ8064_DTV) += board-8064-all.o board-8064-regulator.o
 obj-$(CONFIG_ARCH_MSM9615) += board-9615.o devices-9615.o board-9615-regulator.o board-9615-gpiomux.o board-9615-storage.o board-9615-display.o
 obj-$(CONFIG_ARCH_MSM9615) += clock-local.o clock-9615.o acpuclock-9615.o clock-rpm.o clock-pll.o
+obj-$(CONFIG_ARCH_MSMZINC) += board-zinc.o board-zinc-gpiomux.o
 obj-$(CONFIG_ARCH_MSM8974) += board-8974.o board-8974-gpiomux.o
 obj-$(CONFIG_ARCH_MSM8974) += acpuclock-8974.o
 obj-$(CONFIG_ARCH_MSM8974) += clock-local2.o clock-pll.o clock-8974.o clock-rpm.o clock-voter.o clock-mdss-8974.o
@@ -365,6 +368,7 @@
 obj-$(CONFIG_ARCH_MPQ8092) += gpiomux-v2.o gpiomux.o
 obj-$(CONFIG_ARCH_MSM8226) += gpiomux-v2.o gpiomux.o
 obj-$(CONFIG_ARCH_MSM8610) += gpiomux-v2.o gpiomux.o
+obj-$(CONFIG_ARCH_MSMZINC) += gpiomux-v2.o gpiomux.o
 
 obj-$(CONFIG_MSM_SLEEP_STATS_DEVICE) += idle_stats_device.o
 obj-$(CONFIG_MSM_DCVS) += msm_dcvs_scm.o msm_dcvs.o msm_mpdecision.o
diff --git a/arch/arm/mach-msm/Makefile.boot b/arch/arm/mach-msm/Makefile.boot
index 02d0b46..e3b8d73 100644
--- a/arch/arm/mach-msm/Makefile.boot
+++ b/arch/arm/mach-msm/Makefile.boot
@@ -58,6 +58,11 @@
         dtb-$(CONFIG_ARCH_MSM8974)	+= msm8974-v2-liquid.dtb
         dtb-$(CONFIG_ARCH_MSM8974)	+= msm8974-v2-mtp.dtb
 
+# MSMZINC
+   zreladdr-$(CONFIG_ARCH_MSMZINC)	:= 0x00008000
+        dtb-$(CONFIG_ARCH_MSMZINC)	+= msmzinc-sim.dtb
+
+
 # MSM9615
    zreladdr-$(CONFIG_ARCH_MSM9615)	:= 0x40808000
 
diff --git a/arch/arm/mach-msm/bam_dmux.c b/arch/arm/mach-msm/bam_dmux.c
index 833b213..20c461d 100644
--- a/arch/arm/mach-msm/bam_dmux.c
+++ b/arch/arm/mach-msm/bam_dmux.c
@@ -1577,8 +1577,6 @@
 {
 	DMUX_LOG_KERR("%s: modem timeout: BAM DMUX disabled\n", __func__);
 	in_global_reset = 1;
-	if (get_restart_level() <= RESET_SOC)
-		DMUX_LOG_KERR("%s: ssrestart not enabled\n", __func__);
 	return 1;
 }
 
diff --git a/arch/arm/mach-msm/board-8226-gpiomux.c b/arch/arm/mach-msm/board-8226-gpiomux.c
index 41263f8..e8e75df 100644
--- a/arch/arm/mach-msm/board-8226-gpiomux.c
+++ b/arch/arm/mach-msm/board-8226-gpiomux.c
@@ -17,7 +17,7 @@
 #include <mach/gpio.h>
 #include <mach/gpiomux.h>
 
-#define KS8851_IRQ_GPIO 75
+#define KS8851_IRQ_GPIO 115
 
 #if defined(CONFIG_KS8851) || defined(CONFIG_KS8851_MODULE)
 static struct gpiomux_setting gpio_eth_config = {
@@ -84,6 +84,12 @@
 	.pull = GPIOMUX_PULL_DOWN,
 };
 
+static struct gpiomux_setting gpio_spi_cs_eth_config = {
+	.func = GPIOMUX_FUNC_4,
+	.drv = GPIOMUX_DRV_6MA,
+	.pull = GPIOMUX_PULL_DOWN,
+};
+
 static struct gpiomux_setting gpio_i2c_config = {
 	.func = GPIOMUX_FUNC_3,
 	.drv = GPIOMUX_DRV_2MA,
@@ -186,6 +192,12 @@
 			[GPIOMUX_SUSPENDED] = &gpio_i2c_config,
 		},
 	},
+	{
+		.gpio      = 22,		/* BLSP1 QUP1 SPI_CS_ETH */
+		.settings = {
+			[GPIOMUX_SUSPENDED] = &gpio_spi_cs_eth_config,
+		},
+	},
 };
 
 static struct msm_gpiomux_config msm_synaptics_configs[] __initdata = {
diff --git a/arch/arm/mach-msm/board-8960.c b/arch/arm/mach-msm/board-8960.c
index 78e3ca6..7ef6fed 100644
--- a/arch/arm/mach-msm/board-8960.c
+++ b/arch/arm/mach-msm/board-8960.c
@@ -652,29 +652,6 @@
 #endif
 }
 
-static void ion_adjust_secure_allocation(void)
-{
-	int i;
-
-	for (i = 0; i < msm8960_ion_pdata.nr; i++) {
-		struct ion_platform_heap *heap =
-			&(msm8960_ion_pdata.heaps[i]);
-
-
-		if (heap->extra_data) {
-			switch ((int) heap->type) {
-			case ION_HEAP_TYPE_CP:
-				if (cpu_is_msm8960()) {
-					((struct ion_cp_heap_pdata *)
-					heap->extra_data)->allow_nonsecure_alloc
-						= 1;
-				}
-
-			}
-		}
-	}
-}
-
 static void __init reserve_mdp_memory(void)
 {
 	msm8960_mdp_writeback(msm8960_reserve_table);
@@ -3394,7 +3371,6 @@
 		mdm_sglte_device.dev.platform_data = &sglte_platform_data;
 		platform_device_register(&mdm_sglte_device);
 	}
-	ion_adjust_secure_allocation();
 }
 
 MACHINE_START(MSM8960_CDP, "QCT MSM8960 CDP")
diff --git a/arch/arm/mach-msm/board-8974-gpiomux.c b/arch/arm/mach-msm/board-8974-gpiomux.c
index d8a9c3e..688c6f7 100644
--- a/arch/arm/mach-msm/board-8974-gpiomux.c
+++ b/arch/arm/mach-msm/board-8974-gpiomux.c
@@ -203,7 +203,6 @@
 	.func = GPIOMUX_FUNC_GPIO,
 	.drv = GPIOMUX_DRV_2MA,
 	.pull = GPIOMUX_PULL_DOWN,
-	.dir = GPIOMUX_OUT_LOW,
 };
 
 static struct gpiomux_setting hsic_act_cfg = {
@@ -219,6 +218,19 @@
 	.dir = GPIOMUX_IN,
 };
 
+static struct gpiomux_setting hsic_resume_act_cfg = {
+	.func = GPIOMUX_FUNC_GPIO,
+	.drv = GPIOMUX_DRV_2MA,
+	.pull = GPIOMUX_PULL_DOWN,
+	.dir = GPIOMUX_OUT_LOW,
+};
+
+static struct gpiomux_setting hsic_resume_susp_cfg = {
+	.func = GPIOMUX_FUNC_GPIO,
+	.drv = GPIOMUX_DRV_2MA,
+	.pull = GPIOMUX_PULL_NONE,
+};
+
 static struct msm_gpiomux_config msm_hsic_configs[] = {
 	{
 		.gpio = 144,               /*HSIC_STROBE */
@@ -234,6 +246,13 @@
 			[GPIOMUX_SUSPENDED] = &hsic_sus_cfg,
 		},
 	},
+	{
+		.gpio = 80,
+		.settings = {
+			[GPIOMUX_ACTIVE] = &hsic_resume_act_cfg,
+			[GPIOMUX_SUSPENDED] = &hsic_resume_susp_cfg,
+		},
+	},
 };
 
 static struct msm_gpiomux_config msm_hsic_hub_configs[] = {
diff --git a/arch/arm/mach-msm/board-zinc-gpiomux.c b/arch/arm/mach-msm/board-zinc-gpiomux.c
new file mode 100644
index 0000000..ac4daa8
--- /dev/null
+++ b/arch/arm/mach-msm/board-zinc-gpiomux.c
@@ -0,0 +1,29 @@
+/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/gpio.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <mach/board.h>
+#include <mach/gpiomux.h>
+
+void __init msmzinc_init_gpiomux(void)
+{
+	int rc;
+
+	rc = msm_gpiomux_init_dt();
+	if (rc) {
+		pr_err("%s failed %d\n", __func__, rc);
+		return;
+	}
+}
diff --git a/arch/arm/mach-msm/board-zinc.c b/arch/arm/mach-msm/board-zinc.c
new file mode 100644
index 0000000..fa19e39
--- /dev/null
+++ b/arch/arm/mach-msm/board-zinc.c
@@ -0,0 +1,127 @@
+/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/err.h>
+#include <linux/kernel.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_platform.h>
+#include <linux/memory.h>
+#include <asm/hardware/gic.h>
+#include <asm/mach/map.h>
+#include <asm/mach/arch.h>
+#include <mach/board.h>
+#include <mach/gpiomux.h>
+#include <mach/msm_iomap.h>
+#include <mach/msm_memtypes.h>
+#include <mach/msm_smd.h>
+#include <mach/restart.h>
+#include <mach/socinfo.h>
+#include <mach/clk-provider.h>
+#include "board-dt.h"
+#include "clock.h"
+#include "devices.h"
+#include "platsmp.h"
+
+static struct memtype_reserve msmzinc_reserve_table[] __initdata = {
+	[MEMTYPE_SMI] = {
+	},
+	[MEMTYPE_EBI0] = {
+		.flags  =       MEMTYPE_FLAGS_1M_ALIGN,
+	},
+	[MEMTYPE_EBI1] = {
+		.flags  =       MEMTYPE_FLAGS_1M_ALIGN,
+	},
+};
+
+static int msmzinc_paddr_to_memtype(unsigned int paddr)
+{
+	return MEMTYPE_EBI1;
+}
+
+static struct reserve_info msmzinc_reserve_info __initdata = {
+	.memtype_reserve_table = msmzinc_reserve_table,
+	.paddr_to_memtype = msmzinc_paddr_to_memtype,
+};
+
+void __init msmzinc_reserve(void)
+{
+	reserve_info = &msmzinc_reserve_info;
+	of_scan_flat_dt(dt_scan_for_memory_reserve, msmzinc_reserve_table);
+	msm_reserve();
+}
+
+static void __init msmzinc_early_memory(void)
+{
+	reserve_info = &msmzinc_reserve_info;
+	of_scan_flat_dt(dt_scan_for_memory_hole, msmzinc_reserve_table);
+}
+
+static struct clk_lookup msm_clocks_dummy[] = {
+	CLK_DUMMY("core_clk",   BLSP1_UART_CLK, "f991f000.serial", OFF),
+	CLK_DUMMY("iface_clk",  BLSP1_UART_CLK, "f991f000.serial", OFF),
+};
+
+static struct clock_init_data msm_dummy_clock_init_data __initdata = {
+	.table = msm_clocks_dummy,
+	.size = ARRAY_SIZE(msm_clocks_dummy),
+};
+
+/*
+ * Used to satisfy dependencies for devices that need to be
+ * run early or in a particular order. Most likely your device doesn't fall
+ * into this category, and thus the driver should not be added here. The
+ * EPROBE_DEFER can satisfy most dependency problems.
+ */
+void __init msmzinc_add_drivers(void)
+{
+	msm_smd_init();
+	msm_clock_init(&msm_dummy_clock_init_data);
+}
+
+static void __init msmzinc_map_io(void)
+{
+	msm_map_zinc_io();
+}
+
+void __init msmzinc_init(void)
+{
+	if (socinfo_init() < 0)
+		pr_err("%s: socinfo_init() failed\n", __func__);
+
+	msmzinc_init_gpiomux();
+	of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
+	msmzinc_add_drivers();
+}
+
+void __init msmzinc_init_very_early(void)
+{
+	msmzinc_early_memory();
+}
+
+static const char *msmzinc_dt_match[] __initconst = {
+	"qcom,msmzinc",
+	NULL
+};
+
+DT_MACHINE_START(MSMZINC_DT, "Qualcomm MSM ZINC (Flattened Device Tree)")
+	.map_io = msmzinc_map_io,
+	.init_irq = msm_dt_init_irq,
+	.init_machine = msmzinc_init,
+	.handle_irq = gic_handle_irq,
+	.timer = &msm_dt_timer,
+	.dt_compat = msmzinc_dt_match,
+	.reserve = msmzinc_reserve,
+	.init_very_early = msmzinc_init_very_early,
+	.restart = msm_restart,
+	.smp = &msm8974_smp_ops,
+MACHINE_END
diff --git a/arch/arm/mach-msm/clock-8226.c b/arch/arm/mach-msm/clock-8226.c
index 813b210..2899d93 100644
--- a/arch/arm/mach-msm/clock-8226.c
+++ b/arch/arm/mach-msm/clock-8226.c
@@ -3094,6 +3094,10 @@
 	CLK_LOOKUP("core_clk", qdss_clk.c, "fc33d000.etm"),
 	CLK_LOOKUP("core_clk", qdss_clk.c, "fc33e000.etm"),
 	CLK_LOOKUP("core_clk", qdss_clk.c, "fc33f000.etm"),
+	CLK_LOOKUP("core_clk", qdss_clk.c, "fc33c000.jtagmm"),
+	CLK_LOOKUP("core_clk", qdss_clk.c, "fc33d000.jtagmm"),
+	CLK_LOOKUP("core_clk", qdss_clk.c, "fc33e000.jtagmm"),
+	CLK_LOOKUP("core_clk", qdss_clk.c, "fc33f000.jtagmm"),
 
 	CLK_LOOKUP("core_a_clk", qdss_a_clk.c, "fc322000.tmc"),
 	CLK_LOOKUP("core_a_clk", qdss_a_clk.c, "fc318000.tpiu"),
@@ -3109,6 +3113,10 @@
 	CLK_LOOKUP("core_a_clk", qdss_a_clk.c, "fc33d000.etm"),
 	CLK_LOOKUP("core_a_clk", qdss_a_clk.c, "fc33e000.etm"),
 	CLK_LOOKUP("core_a_clk", qdss_a_clk.c, "fc33f000.etm"),
+	CLK_LOOKUP("core_a_clk", qdss_clk.c, "fc33c000.jtagmm"),
+	CLK_LOOKUP("core_a_clk", qdss_clk.c, "fc33d000.jtagmm"),
+	CLK_LOOKUP("core_a_clk", qdss_clk.c, "fc33e000.jtagmm"),
+	CLK_LOOKUP("core_a_clk", qdss_clk.c, "fc33f000.jtagmm"),
 
 	/* HSUSB-OTG Clocks */
 	CLK_LOOKUP("xo",                          xo.c, "f9a55000.usb"),
@@ -3350,6 +3358,15 @@
 	CLK_LOOKUP("", mmss_mmssnoc_bto_ahb_clk.c, ""),
 	CLK_LOOKUP("", mmss_mmssnoc_axi_clk.c, ""),
 	CLK_LOOKUP("", mmss_s0_axi_clk.c, ""),
+
+	/* Audio clocks */
+	CLK_LOOKUP("osr_clk", div_clk1.c, "msm-dai-q6-dev.224"),
+	CLK_LOOKUP("osr_clk", div_clk1.c, "msm-dai-q6-dev.4106"),
+	CLK_LOOKUP("osr_clk", div_clk1.c, "msm-dai-q6-dev.16384"),
+	CLK_LOOKUP("osr_clk", div_clk1.c, "msm-dai-q6-dev.16386"),
+	CLK_LOOKUP("osr_clk", div_clk1.c, "msm-dai-q6-dev.16390"),
+	CLK_LOOKUP("osr_clk", div_clk1.c, "msm-dai-q6-dev.16391"),
+
 };
 
 static struct clk_lookup msm_clocks_8226_rumi[] = {
diff --git a/arch/arm/mach-msm/clock-8610.c b/arch/arm/mach-msm/clock-8610.c
index 5690730..0aee878 100644
--- a/arch/arm/mach-msm/clock-8610.c
+++ b/arch/arm/mach-msm/clock-8610.c
@@ -3047,35 +3047,65 @@
 	CLK_LOOKUP("mem_a_clk",	bimc_msmbus_a_clk.c,	"msm_bimc"),
 	CLK_LOOKUP("mem_clk",	bimc_acpu_a_clk.c,	""),
 
-	CLK_LOOKUP("core_clk", qdss_clk.c, "coresight-tmc-etr"),
-	CLK_LOOKUP("core_clk", qdss_clk.c, "coresight-tpiu"),
-	CLK_LOOKUP("core_clk", qdss_clk.c, "coresight-replicator"),
-	CLK_LOOKUP("core_clk", qdss_clk.c, "coresight-tmc-etf"),
-	CLK_LOOKUP("core_clk", qdss_clk.c, "coresight-funnel-merg"),
-	CLK_LOOKUP("core_clk", qdss_clk.c, "coresight-funnel-in0"),
-	CLK_LOOKUP("core_clk", qdss_clk.c, "coresight-funnel-in1"),
-	CLK_LOOKUP("core_clk", qdss_clk.c, "coresight-funnel-kpss"),
-	CLK_LOOKUP("core_clk", qdss_clk.c, "coresight-funnel-mmss"),
-	CLK_LOOKUP("core_clk", qdss_clk.c, "coresight-stm"),
-	CLK_LOOKUP("core_clk", qdss_clk.c, "coresight-etm0"),
-	CLK_LOOKUP("core_clk", qdss_clk.c, "coresight-etm1"),
-	CLK_LOOKUP("core_clk", qdss_clk.c, "coresight-etm2"),
-	CLK_LOOKUP("core_clk", qdss_clk.c, "coresight-etm3"),
+	/* CoreSight clocks */
+	CLK_LOOKUP("core_clk", qdss_clk.c, "fc326000.tmc"),
+	CLK_LOOKUP("core_clk", qdss_clk.c, "fc320000.tpiu"),
+	CLK_LOOKUP("core_clk", qdss_clk.c, "fc324000.replicator"),
+	CLK_LOOKUP("core_clk", qdss_clk.c, "fc325000.tmc"),
+	CLK_LOOKUP("core_clk", qdss_clk.c, "fc323000.funnel"),
+	CLK_LOOKUP("core_clk", qdss_clk.c, "fc321000.funnel"),
+	CLK_LOOKUP("core_clk", qdss_clk.c, "fc322000.funnel"),
+	CLK_LOOKUP("core_clk", qdss_clk.c, "fc355000.funnel"),
+	CLK_LOOKUP("core_clk", qdss_clk.c, "fc302000.stm"),
+	CLK_LOOKUP("core_clk", qdss_clk.c, "fc34c000.etm"),
+	CLK_LOOKUP("core_clk", qdss_clk.c, "fc34d000.etm"),
+	CLK_LOOKUP("core_clk", qdss_clk.c, "fc34e000.etm"),
+	CLK_LOOKUP("core_clk", qdss_clk.c, "fc34f000.etm"),
+	CLK_LOOKUP("core_clk", qdss_clk.c, "fc301000.csr"),
+	CLK_LOOKUP("core_clk", qdss_clk.c, "fc310000.cti"),
+	CLK_LOOKUP("core_clk", qdss_clk.c, "fc311000.cti"),
+	CLK_LOOKUP("core_clk", qdss_clk.c, "fc312000.cti"),
+	CLK_LOOKUP("core_clk", qdss_clk.c, "fc313000.cti"),
+	CLK_LOOKUP("core_clk", qdss_clk.c, "fc314000.cti"),
+	CLK_LOOKUP("core_clk", qdss_clk.c, "fc315000.cti"),
+	CLK_LOOKUP("core_clk", qdss_clk.c, "fc316000.cti"),
+	CLK_LOOKUP("core_clk", qdss_clk.c, "fc317000.cti"),
+	CLK_LOOKUP("core_clk", qdss_clk.c, "fc318000.cti"),
+	CLK_LOOKUP("core_clk", qdss_clk.c, "fc351000.cti"),
+	CLK_LOOKUP("core_clk", qdss_clk.c, "fc352000.cti"),
+	CLK_LOOKUP("core_clk", qdss_clk.c, "fc353000.cti"),
+	CLK_LOOKUP("core_clk", qdss_clk.c, "fc354000.cti"),
 
-	CLK_LOOKUP("core_a_clk", qdss_a_clk.c, "coresight-tmc-etr"),
-	CLK_LOOKUP("core_a_clk", qdss_a_clk.c, "coresight-tpiu"),
-	CLK_LOOKUP("core_a_clk", qdss_a_clk.c, "coresight-replicator"),
-	CLK_LOOKUP("core_a_clk", qdss_a_clk.c, "coresight-tmc-etf"),
-	CLK_LOOKUP("core_a_clk", qdss_a_clk.c, "coresight-funnel-merg"),
-	CLK_LOOKUP("core_a_clk", qdss_a_clk.c, "coresight-funnel-in0"),
-	CLK_LOOKUP("core_a_clk", qdss_a_clk.c, "coresight-funnel-in1"),
-	CLK_LOOKUP("core_a_clk", qdss_a_clk.c, "coresight-funnel-kpss"),
-	CLK_LOOKUP("core_a_clk", qdss_a_clk.c, "coresight-funnel-mmss"),
-	CLK_LOOKUP("core_a_clk", qdss_a_clk.c, "coresight-stm"),
-	CLK_LOOKUP("core_a_clk", qdss_a_clk.c, "coresight-etm0"),
-	CLK_LOOKUP("core_a_clk", qdss_a_clk.c, "coresight-etm1"),
-	CLK_LOOKUP("core_a_clk", qdss_a_clk.c, "coresight-etm2"),
-	CLK_LOOKUP("core_a_clk", qdss_a_clk.c, "coresight-etm3"),
+
+	CLK_LOOKUP("core_a_clk", qdss_a_clk.c, "fc326000.tmc"),
+	CLK_LOOKUP("core_a_clk", qdss_a_clk.c, "fc320000.tpiu"),
+	CLK_LOOKUP("core_a_clk", qdss_a_clk.c, "fc324000.replicator"),
+	CLK_LOOKUP("core_a_clk", qdss_a_clk.c, "fc325000.tmc"),
+	CLK_LOOKUP("core_a_clk", qdss_a_clk.c, "fc323000.funnel"),
+	CLK_LOOKUP("core_a_clk", qdss_a_clk.c, "fc321000.funnel"),
+	CLK_LOOKUP("core_a_clk", qdss_a_clk.c, "fc322000.funnel"),
+	CLK_LOOKUP("core_a_clk", qdss_a_clk.c, "fc355000.funnel"),
+	CLK_LOOKUP("core_a_clk", qdss_a_clk.c, "fc302000.stm"),
+	CLK_LOOKUP("core_a_clk", qdss_a_clk.c, "fc34c000.etm"),
+	CLK_LOOKUP("core_a_clk", qdss_a_clk.c, "fc34d000.etm"),
+	CLK_LOOKUP("core_a_clk", qdss_a_clk.c, "fc34e000.etm"),
+	CLK_LOOKUP("core_a_clk", qdss_a_clk.c, "fc34f000.etm"),
+	CLK_LOOKUP("core_a_clk", qdss_a_clk.c, "fc301000.csr"),
+	CLK_LOOKUP("core_a_clk", qdss_a_clk.c, "fc310000.cti"),
+	CLK_LOOKUP("core_a_clk", qdss_a_clk.c, "fc311000.cti"),
+	CLK_LOOKUP("core_a_clk", qdss_a_clk.c, "fc312000.cti"),
+	CLK_LOOKUP("core_a_clk", qdss_a_clk.c, "fc313000.cti"),
+	CLK_LOOKUP("core_a_clk", qdss_a_clk.c, "fc314000.cti"),
+	CLK_LOOKUP("core_a_clk", qdss_a_clk.c, "fc315000.cti"),
+	CLK_LOOKUP("core_a_clk", qdss_a_clk.c, "fc316000.cti"),
+	CLK_LOOKUP("core_a_clk", qdss_a_clk.c, "fc317000.cti"),
+	CLK_LOOKUP("core_a_clk", qdss_a_clk.c, "fc318000.cti"),
+	CLK_LOOKUP("core_a_clk", qdss_a_clk.c, "fc351000.cti"),
+	CLK_LOOKUP("core_a_clk", qdss_a_clk.c, "fc352000.cti"),
+	CLK_LOOKUP("core_a_clk", qdss_a_clk.c, "fc353000.cti"),
+	CLK_LOOKUP("core_a_clk", qdss_a_clk.c, "fc354000.cti"),
+
+
 
 	CLK_LOOKUP("core_clk_src", blsp1_qup1_spi_apps_clk_src.c, ""),
 	CLK_LOOKUP("core_clk_src", blsp1_qup2_spi_apps_clk_src.c, ""),
diff --git a/arch/arm/mach-msm/clock-8974.c b/arch/arm/mach-msm/clock-8974.c
index 78e3259..0657c21 100644
--- a/arch/arm/mach-msm/clock-8974.c
+++ b/arch/arm/mach-msm/clock-8974.c
@@ -4851,6 +4851,7 @@
 	CLK_LOOKUP("phy_clk", gcc_usb_hsic_clk.c,	  "msm_hsic_host"),
 	CLK_LOOKUP("cal_clk", gcc_usb_hsic_io_cal_clk.c,  "msm_hsic_host"),
 	CLK_LOOKUP("core_clk", gcc_usb_hsic_system_clk.c, "msm_hsic_host"),
+	CLK_LOOKUP("osr_clk", div_clk1.c, "msm-dai-q6-dev.16384"),
 	CLK_LOOKUP("ref_clk", div_clk2.c, "msm_smsc_hub"),
 	CLK_LOOKUP("iface_clk", gcc_usb_hs_ahb_clk.c,     "msm_ehci_host"),
 	CLK_LOOKUP("core_clk", gcc_usb_hs_system_clk.c,   "msm_ehci_host"),
diff --git a/arch/arm/mach-msm/cpufreq.c b/arch/arm/mach-msm/cpufreq.c
index 46af77d..d02ab66 100644
--- a/arch/arm/mach-msm/cpufreq.c
+++ b/arch/arm/mach-msm/cpufreq.c
@@ -32,6 +32,17 @@
 
 #include "acpuclock.h"
 
+struct cpufreq_work_struct {
+	struct work_struct work;
+	struct cpufreq_policy *policy;
+	struct completion complete;
+	int frequency;
+	int status;
+};
+
+static DEFINE_PER_CPU(struct cpufreq_work_struct, cpufreq_work);
+static struct workqueue_struct *msm_cpufreq_wq;
+
 struct cpufreq_suspend_t {
 	struct mutex suspend_mutex;
 	int device_suspended;
@@ -99,6 +110,15 @@
 	return ret;
 }
 
+static void set_cpu_work(struct work_struct *work)
+{
+	struct cpufreq_work_struct *cpu_work =
+		container_of(work, struct cpufreq_work_struct, work);
+
+	cpu_work->status = set_cpu_freq(cpu_work->policy, cpu_work->frequency);
+	complete(&cpu_work->complete);
+}
+
 static int msm_cpufreq_target(struct cpufreq_policy *policy,
 				unsigned int target_freq,
 				unsigned int relation)
@@ -107,11 +127,17 @@
 	int index;
 	struct cpufreq_frequency_table *table;
 
+	struct cpufreq_work_struct *cpu_work = NULL;
+	cpumask_var_t mask;
+
 	if (!cpu_active(policy->cpu)) {
 		pr_info("cpufreq: cpu %d is not active.\n", policy->cpu);
 		return -ENODEV;
 	}
 
+	if (!alloc_cpumask_var(&mask, GFP_KERNEL))
+		return -ENOMEM;
+
 	mutex_lock(&per_cpu(cpufreq_suspend, policy->cpu).suspend_mutex);
 
 	if (per_cpu(cpufreq_suspend, policy->cpu).device_suspended) {
@@ -133,9 +159,27 @@
 		policy->cpu, target_freq, relation,
 		policy->min, policy->max, table[index].frequency);
 
-	ret = set_cpu_freq(policy, table[index].frequency);
+	cpu_work = &per_cpu(cpufreq_work, policy->cpu);
+	cpu_work->policy = policy;
+	cpu_work->frequency = table[index].frequency;
+	cpu_work->status = -ENODEV;
+
+	cpumask_clear(mask);
+	cpumask_set_cpu(policy->cpu, mask);
+	if (cpumask_equal(mask, &current->cpus_allowed)) {
+		ret = set_cpu_freq(cpu_work->policy, cpu_work->frequency);
+		goto done;
+	} else {
+		cancel_work_sync(&cpu_work->work);
+		INIT_COMPLETION(cpu_work->complete);
+		queue_work_on(policy->cpu, msm_cpufreq_wq, &cpu_work->work);
+		wait_for_completion(&cpu_work->complete);
+	}
+
+	ret = cpu_work->status;
 
 done:
+	free_cpumask_var(mask);
 	mutex_unlock(&per_cpu(cpufreq_suspend, policy->cpu).suspend_mutex);
 	return ret;
 }
@@ -218,6 +262,7 @@
 	int cur_freq;
 	int index;
 	struct cpufreq_frequency_table *table;
+	struct cpufreq_work_struct *cpu_work = NULL;
 
 	table = cpufreq_frequency_get_table(policy->cpu);
 	if (table == NULL)
@@ -247,7 +292,7 @@
 	    CPUFREQ_RELATION_H, &index) &&
 	    cpufreq_frequency_table_target(policy, table, cur_freq,
 	    CPUFREQ_RELATION_L, &index)) {
-		pr_info("%s: cpu%d at invalid freq: %d\n", __func__,
+		pr_info("cpufreq: cpu%d at invalid freq: %d\n",
 				policy->cpu, cur_freq);
 		return -EINVAL;
 	}
@@ -268,6 +313,10 @@
 	policy->cpuinfo.transition_latency =
 		acpuclk_get_switch_time() * NSEC_PER_USEC;
 
+	cpu_work = &per_cpu(cpufreq_work, policy->cpu);
+	INIT_WORK(&cpu_work->work, set_cpu_work);
+	init_completion(&cpu_work->complete);
+
 	return 0;
 }
 
@@ -355,6 +404,7 @@
 		per_cpu(cpufreq_suspend, cpu).device_suspended = 0;
 	}
 
+	msm_cpufreq_wq = create_workqueue("msm-cpufreq");
 	register_hotcpu_notifier(&msm_cpufreq_cpu_notifier);
 
 	return cpufreq_register_driver(&msm_cpufreq_driver);
diff --git a/arch/arm/mach-msm/include/mach/board.h b/arch/arm/mach-msm/include/mach/board.h
index 327212e..3fa2d5e 100644
--- a/arch/arm/mach-msm/include/mach/board.h
+++ b/arch/arm/mach-msm/include/mach/board.h
@@ -598,6 +598,7 @@
 void msm_map_msm7x30_io(void);
 void msm_map_fsm9xxx_io(void);
 void msm_map_8974_io(void);
+void msm_map_zinc_io(void);
 void msm_map_msm8625_io(void);
 void msm_map_msm9625_io(void);
 void msm_init_irq(void);
@@ -606,6 +607,7 @@
 void msm_8974_reserve(void);
 void msm_8974_very_early(void);
 void msm_8974_init_gpiomux(void);
+void msmzinc_init_gpiomux(void);
 void msm9625_init_gpiomux(void);
 void msm_map_mpq8092_io(void);
 void mpq8092_init_gpiomux(void);
diff --git a/arch/arm/mach-msm/include/mach/iommu_domains.h b/arch/arm/mach-msm/include/mach/iommu_domains.h
index a104a42..d908a65 100644
--- a/arch/arm/mach-msm/include/mach/iommu_domains.h
+++ b/arch/arm/mach-msm/include/mach/iommu_domains.h
@@ -94,7 +94,7 @@
 
 extern int msm_iommu_map_extra(struct iommu_domain *domain,
 						unsigned long start_iova,
-						unsigned long phys_addr,
+						phys_addr_t phys_addr,
 						unsigned long size,
 						unsigned long page_size,
 						int cached);
@@ -104,7 +104,7 @@
 						unsigned long size,
 						unsigned long page_size);
 
-extern int msm_iommu_map_contig_buffer(unsigned long phys,
+extern int msm_iommu_map_contig_buffer(phys_addr_t phys,
 				unsigned int domain_no,
 				unsigned int partition_no,
 				unsigned long size,
@@ -148,7 +148,7 @@
 
 static inline int msm_iommu_map_extra(struct iommu_domain *domain,
 						unsigned long start_iova,
-						unsigned long phys_addr,
+						phys_addr_t phys_addr,
 						unsigned long size,
 						unsigned long page_size,
 						int cached)
@@ -163,7 +163,7 @@
 {
 }
 
-static inline int msm_iommu_map_contig_buffer(unsigned long phys,
+static inline int msm_iommu_map_contig_buffer(phys_addr_t phys,
 				unsigned int domain_no,
 				unsigned int partition_no,
 				unsigned long size,
diff --git a/arch/arm/mach-msm/include/mach/memory.h b/arch/arm/mach-msm/include/mach/memory.h
index 8c53ea5..fff7fa4 100644
--- a/arch/arm/mach-msm/include/mach/memory.h
+++ b/arch/arm/mach-msm/include/mach/memory.h
@@ -1,7 +1,7 @@
 /* arch/arm/mach-msm/include/mach/memory.h
  *
  * Copyright (C) 2007 Google, Inc.
- * Copyright (c) 2009-2012, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2009-2013, The Linux Foundation. All rights reserved.
  *
  * This software is licensed under the terms of the GNU General Public
  * License version 2, as published by the Free Software Foundation, and
@@ -96,11 +96,15 @@
 extern unsigned long memory_hole_offset;
 extern unsigned long memory_hole_start;
 extern unsigned long memory_hole_end;
+extern unsigned long memory_hole_align;
+extern unsigned long virtual_hole_start;
+extern unsigned long virtual_hole_end;
 #ifdef CONFIG_DONT_MAP_HOLE_AFTER_MEMBANK0
 void find_memory_hole(void);
 
 #define MEM_HOLE_END_PHYS_OFFSET (memory_hole_end)
-#define MEM_HOLE_PAGE_OFFSET (PAGE_OFFSET + memory_hole_offset)
+#define MEM_HOLE_PAGE_OFFSET (PAGE_OFFSET + memory_hole_offset + \
+				memory_hole_align)
 
 #define __phys_to_virt(phys)				\
 	((MEM_HOLE_END_PHYS_OFFSET && ((phys) >= MEM_HOLE_END_PHYS_OFFSET)) ? \
diff --git a/arch/arm/mach-msm/include/mach/msm_iomap-zinc.h b/arch/arm/mach-msm/include/mach/msm_iomap-zinc.h
new file mode 100644
index 0000000..8456445
--- /dev/null
+++ b/arch/arm/mach-msm/include/mach/msm_iomap-zinc.h
@@ -0,0 +1,45 @@
+/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+
+#ifndef __ASM_ARCH_MSM_IOMAP_zinc_H
+#define __ASM_ARCH_MSM_IOMAP_zinc_H
+
+/* Physical base address and size of peripherals.
+ * Ordered by the virtual base addresses they will be mapped at.
+ *
+ * If you add or remove entries here, you'll want to edit the
+ * io desc array in arch/arm/mach-msm/io.c to reflect your
+ * changes.
+ *
+ */
+
+#define MSMZINC_SHARED_RAM_PHYS     0x0FA00000
+
+#define MSMZINC_QGIC_DIST_PHYS	0xF9000000
+#define MSMZINC_QGIC_DIST_SIZE	SZ_4K
+
+#define MSMZINC_QGIC_CPU_PHYS	0xF9002000
+#define MSMZINC_QGIC_CPU_SIZE	SZ_4K
+
+#define MSMZINC_TLMM_PHYS	0xFD510000
+#define MSMZINC_TLMM_SIZE	SZ_16K
+
+#define MSMZINC_IMEM_PHYS       0xFC42B000
+#define MSMZINC_IMEM_SIZE       SZ_4K
+
+#ifdef CONFIG_DEBUG_MSMZINC_UART
+#define MSM_DEBUG_UART_BASE	IOMEM(0xFA71E000)
+#define MSM_DEBUG_UART_PHYS	0xF991E000
+#endif
+
+#endif
diff --git a/arch/arm/mach-msm/include/mach/msm_iomap.h b/arch/arm/mach-msm/include/mach/msm_iomap.h
index ebb096e..9cf9517 100644
--- a/arch/arm/mach-msm/include/mach/msm_iomap.h
+++ b/arch/arm/mach-msm/include/mach/msm_iomap.h
@@ -54,7 +54,8 @@
 	defined(CONFIG_ARCH_MSM7X25) || defined(CONFIG_ARCH_MSM7X01A) || \
 	defined(CONFIG_ARCH_MSM8625) || defined(CONFIG_ARCH_MSM7X30) || \
 	defined(CONFIG_ARCH_MSM9625) || defined(CONFIG_ARCH_MPQ8092) || \
-	defined(CONFIG_ARCH_MSM8226) || defined(CONFIG_ARCH_MSM8610)
+	defined(CONFIG_ARCH_MSM8226) || defined(CONFIG_ARCH_MSM8610) || \
+	defined(CONFIG_ARCH_MSMZINC)
 
 /* Unified iomap */
 
@@ -129,6 +130,7 @@
 #include "msm_iomap-8064.h"
 #include "msm_iomap-9615.h"
 #include "msm_iomap-8974.h"
+#include "msm_iomap-zinc.h"
 #include "msm_iomap-9625.h"
 #include "msm_iomap-8092.h"
 #include "msm_iomap-8226.h"
diff --git a/arch/arm/mach-msm/include/mach/qdsp6v2/apr.h b/arch/arm/mach-msm/include/mach/qdsp6v2/apr.h
index 59908e6..c21f6e5 100644
--- a/arch/arm/mach-msm/include/mach/qdsp6v2/apr.h
+++ b/arch/arm/mach-msm/include/mach/qdsp6v2/apr.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2010-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -82,6 +82,7 @@
 #define APR_SVC_ADSP_CVS	0x0A
 #define APR_SVC_ADSP_CVP	0x0B
 #define APR_SVC_USM		0x0C
+#define APR_SVC_LSM		0x0D
 #define APR_SVC_VIDC		0x16
 #define APR_SVC_MAX		0x17
 
diff --git a/arch/arm/mach-msm/include/mach/subsystem_restart.h b/arch/arm/mach-msm/include/mach/subsystem_restart.h
index 1f6ca66..67f643e 100644
--- a/arch/arm/mach-msm/include/mach/subsystem_restart.h
+++ b/arch/arm/mach-msm/include/mach/subsystem_restart.h
@@ -21,9 +21,8 @@
 struct subsys_device;
 
 enum {
-	RESET_SOC = 1,
+	RESET_SOC = 0,
 	RESET_SUBSYS_COUPLED,
-	RESET_SUBSYS_INDEPENDENT,
 	RESET_LEVEL_MAX
 };
 
@@ -60,7 +59,7 @@
 
 #if defined(CONFIG_MSM_SUBSYSTEM_RESTART)
 
-extern int get_restart_level(void);
+extern int subsys_get_restart_level(struct subsys_device *dev);
 extern int subsystem_restart_dev(struct subsys_device *dev);
 extern int subsystem_restart(const char *name);
 extern int subsystem_crashed(const char *name);
@@ -75,7 +74,7 @@
 
 #else
 
-static inline int get_restart_level(void)
+static inline int subsys_get_restart_level(struct subsys_device *dev)
 {
 	return 0;
 }
diff --git a/arch/arm/mach-msm/io.c b/arch/arm/mach-msm/io.c
index fd096ec..c7b47a5 100644
--- a/arch/arm/mach-msm/io.c
+++ b/arch/arm/mach-msm/io.c
@@ -323,6 +323,29 @@
 }
 #endif /* CONFIG_ARCH_MSM8974 */
 
+#ifdef CONFIG_ARCH_MSMZINC
+static struct map_desc msm_zinc_io_desc[] __initdata = {
+	MSM_CHIP_DEVICE(QGIC_DIST, MSMZINC),
+	MSM_CHIP_DEVICE(QGIC_CPU, MSMZINC),
+	MSM_CHIP_DEVICE(TLMM, MSMZINC),
+	MSM_CHIP_DEVICE(IMEM, MSMZINC),
+	{
+		.virtual =  (unsigned long) MSM_SHARED_RAM_BASE,
+		.length =   MSM_SHARED_RAM_SIZE,
+		.type =     MT_DEVICE,
+	},
+#ifdef CONFIG_DEBUG_MSMZINC_UART
+	MSM_DEVICE(DEBUG_UART),
+#endif
+};
+
+void __init msm_map_zinc_io(void)
+{
+	msm_shared_ram_phys = MSMZINC_SHARED_RAM_PHYS;
+	msm_map_io(msm_zinc_io_desc, ARRAY_SIZE(msm_zinc_io_desc));
+}
+#endif /* CONFIG_ARCH_MSMZINC */
+
 #ifdef CONFIG_ARCH_MSM7X30
 static struct map_desc msm7x30_io_desc[] __initdata = {
 	MSM_CHIP_DEVICE(VIC, MSM7X30),
diff --git a/arch/arm/mach-msm/iommu_domains.c b/arch/arm/mach-msm/iommu_domains.c
index f24dc87..5228abc 100644
--- a/arch/arm/mach-msm/iommu_domains.c
+++ b/arch/arm/mach-msm/iommu_domains.c
@@ -55,7 +55,7 @@
 
 int msm_iommu_map_extra(struct iommu_domain *domain,
 				unsigned long start_iova,
-				unsigned long phy_addr,
+				phys_addr_t phy_addr,
 				unsigned long size,
 				unsigned long page_size,
 				int prot)
@@ -135,7 +135,7 @@
 
 static int msm_iommu_map_iova_phys(struct iommu_domain *domain,
 				unsigned long iova,
-				unsigned long phys,
+				phys_addr_t phys,
 				unsigned long size,
 				int cached)
 {
@@ -167,7 +167,7 @@
 
 }
 
-int msm_iommu_map_contig_buffer(unsigned long phys,
+int msm_iommu_map_contig_buffer(phys_addr_t phys,
 				unsigned int domain_no,
 				unsigned int partition_no,
 				unsigned long size,
diff --git a/arch/arm/mach-msm/krait-regulator.c b/arch/arm/mach-msm/krait-regulator.c
index 8fe69d9..953f941d 100644
--- a/arch/arm/mach-msm/krait-regulator.c
+++ b/arch/arm/mach-msm/krait-regulator.c
@@ -28,6 +28,7 @@
 #include <linux/regulator/of_regulator.h>
 #include <linux/regulator/krait-regulator.h>
 #include <linux/debugfs.h>
+#include <linux/syscore_ops.h>
 #include <mach/msm_iomap.h>
 
 #include "spm.h"
@@ -292,27 +293,6 @@
 	return 0;
 }
 
-int krait_power_mdd_enable(int cpu_num, bool on)
-{
-	/*
-	 * Expected to be called when the cpu goes to retention mode as a part
-	 * of idle power collapse. IT is guaranteed that cpu won't be put in
-	 * retention while being hotplugged out
-	 */
-	struct krait_power_vreg *kvreg = per_cpu(krait_vregs, cpu_num);
-
-	if (!on && kvreg->mode == LDO_MODE) {
-		pr_debug("%s using LDO - cannot turn off MDD\n", kvreg->name);
-		return -EINVAL;
-	}
-
-	if (on && kvreg->mode == LDO_MODE)
-		return 0;
-
-	__krait_power_mdd_enable(kvreg, on);
-	return 0;
-}
-
 static int switch_to_using_hs(struct krait_power_vreg *kvreg)
 {
 	if (kvreg->mode == HS_MODE)
@@ -342,8 +322,6 @@
 	krait_masked_write(kvreg, APC_PWR_GATE_CTL,
 				LDO_PWR_DWN_MASK, LDO_PWR_DWN_MASK);
 
-	/* turn off MDD since LDO is not used */
-	__krait_power_mdd_enable(kvreg, false);
 	kvreg->mode = HS_MODE;
 	pr_debug("%s using BHS\n", kvreg->name);
 	return 0;
@@ -362,9 +340,6 @@
 	if (kvreg->mode == LDO_MODE)
 		switch_to_using_hs(kvreg);
 
-	/* turn on MDD since LDO is being turned on */
-	__krait_power_mdd_enable(kvreg, true);
-
 	set_krait_ldo_uv(kvreg, kvreg->uV - kvreg->ldo_delta_uV);
 
 	/*
@@ -792,8 +767,7 @@
 	int rc;
 
 	mutex_lock(&pvreg->krait_power_vregs_lock);
-	if (kvreg->mode == LDO_MODE)
-		__krait_power_mdd_enable(kvreg, true);
+	__krait_power_mdd_enable(kvreg, true);
 	kvreg->online = true;
 	rc = _get_optimum_mode(rdev, kvreg->uV, kvreg->uV, kvreg->load_uA);
 	if (rc < 0)
@@ -823,8 +797,7 @@
 		goto dis_err;
 
 	rc = _set_voltage(rdev, kvreg->uV, kvreg->uV);
-	if (kvreg->mode == LDO_MODE)
-		__krait_power_mdd_enable(kvreg, false);
+	__krait_power_mdd_enable(kvreg, false);
 dis_err:
 	mutex_unlock(&pvreg->krait_power_vregs_lock);
 	return rc;
@@ -889,6 +862,8 @@
 
 	/* setup the bandgap that configures the reference to the LDO */
 	writel_relaxed(0x00000190, kvreg->mdd_base + MDD_CONFIG_CTL);
+	/* Enable MDD */
+	writel_relaxed(0x00000002, kvreg->mdd_base + MDD_MODE);
 	mb();
 }
 
@@ -1112,6 +1087,26 @@
 	{}
 };
 
+static int boot_cpu_mdd_off(void)
+{
+	struct krait_power_vreg *kvreg = per_cpu(krait_vregs, 0);
+
+	__krait_power_mdd_enable(kvreg, false);
+	return 0;
+}
+
+static void boot_cpu_mdd_on(void)
+{
+	struct krait_power_vreg *kvreg = per_cpu(krait_vregs, 0);
+
+	__krait_power_mdd_enable(kvreg, true);
+}
+
+static struct syscore_ops boot_cpu_mdd_ops = {
+	.suspend	= boot_cpu_mdd_off,
+	.resume		= boot_cpu_mdd_on,
+};
+
 static int __devinit krait_pdn_probe(struct platform_device *pdev)
 {
 	int rc;
@@ -1172,6 +1167,7 @@
 	dent = debugfs_create_dir(KRAIT_REGULATOR_DRIVER_NAME, NULL);
 	debugfs_create_file("retention_uV",
 			0644, dent, the_gang, &retention_fops);
+	register_syscore_ops(&boot_cpu_mdd_ops);
 	return 0;
 }
 
diff --git a/arch/arm/mach-msm/mdm.c b/arch/arm/mach-msm/mdm.c
index fd8c878..7474215 100644
--- a/arch/arm/mach-msm/mdm.c
+++ b/arch/arm/mach-msm/mdm.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2010-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -119,7 +119,7 @@
 
 	CHARM_DBG("%s: setting AP2MDM_ERRFATAL high for a non graceful reset\n",
 			 __func__);
-	if (get_restart_level() == RESET_SOC)
+	if (subsys_get_restart_level(charm_subsys) == RESET_SOC)
 		pm8xxx_stay_on();
 
 	charm_disable_irqs();
@@ -237,7 +237,7 @@
 static void charm_fatal_fn(struct work_struct *work)
 {
 	pr_info("Reseting the charm due to an errfatal\n");
-	if (get_restart_level() == RESET_SOC)
+	if (subsys_get_restart_level(charm_subsys) == RESET_SOC)
 		pm8xxx_stay_on();
 	subsystem_restart_dev(charm_subsys);
 }
diff --git a/arch/arm/mach-msm/msm_rq_stats.c b/arch/arm/mach-msm/msm_rq_stats.c
index d1538dd..1589623 100644
--- a/arch/arm/mach-msm/msm_rq_stats.c
+++ b/arch/arm/mach-msm/msm_rq_stats.c
@@ -31,6 +31,7 @@
 #include <linux/tick.h>
 #include <asm/smp_plat.h>
 #include "acpuclock.h"
+#include <linux/suspend.h>
 
 #define MAX_LONG_SIZE 24
 #define DEFAULT_RQ_POLL_JIFFIES 1
@@ -206,6 +207,34 @@
 	return NOTIFY_OK;
 }
 
+static int system_suspend_handler(struct notifier_block *nb,
+				unsigned long val, void *data)
+{
+	switch (val) {
+	case PM_POST_HIBERNATION:
+	case PM_POST_SUSPEND:
+		rq_info.hotplug_disabled = 0;
+	case PM_HIBERNATION_PREPARE:
+	case PM_SUSPEND_PREPARE:
+		rq_info.hotplug_disabled = 1;
+		break;
+	default:
+		return NOTIFY_DONE;
+	}
+	return NOTIFY_OK;
+}
+
+
+static ssize_t hotplug_disable_show(struct kobject *kobj,
+		struct kobj_attribute *attr, char *buf)
+{
+	unsigned int val = 0;
+	val = rq_info.hotplug_disabled;
+	return snprintf(buf, MAX_LONG_SIZE, "%d\n", val);
+}
+
+static struct kobj_attribute hotplug_disabled_attr = __ATTR_RO(hotplug_disable);
+
 static void def_work_fn(struct work_struct *work)
 {
 	int64_t diff;
@@ -310,6 +339,7 @@
 	&def_timer_ms_attr.attr,
 	&run_queue_avg_attr.attr,
 	&run_queue_poll_ms_attr.attr,
+	&hotplug_disabled_attr.attr,
 	NULL,
 };
 
@@ -358,6 +388,7 @@
 	rq_info.def_timer_jiffies = DEFAULT_DEF_TIMER_JIFFIES;
 	rq_info.rq_poll_last_jiffy = 0;
 	rq_info.def_timer_last_jiffy = 0;
+	rq_info.hotplug_disabled = 0;
 	ret = init_rq_attribs();
 
 	rq_info.init = 1;
@@ -380,3 +411,16 @@
 	return ret;
 }
 late_initcall(msm_rq_stats_init);
+
+static int __init msm_rq_stats_early_init(void)
+{
+	/* Bail out if this is not an SMP Target */
+	if (!is_smp()) {
+		rq_info.init = 0;
+		return -ENOSYS;
+	}
+
+	pm_notifier(system_suspend_handler, 0);
+	return 0;
+}
+core_initcall(msm_rq_stats_early_init);
diff --git a/arch/arm/mach-msm/msm_rtb.c b/arch/arm/mach-msm/msm_rtb.c
index e797e2e..fdf39be 100644
--- a/arch/arm/mach-msm/msm_rtb.c
+++ b/arch/arm/mach-msm/msm_rtb.c
@@ -55,7 +55,7 @@
 
 struct msm_rtb_state {
 	struct msm_rtb_layout *rtb;
-	unsigned long phys;
+	phys_addr_t phys;
 	int nentries;
 	int size;
 	int enabled;
diff --git a/arch/arm/mach-msm/pil-dsps.c b/arch/arm/mach-msm/pil-dsps.c
index 0630e6a..65d60d6 100644
--- a/arch/arm/mach-msm/pil-dsps.c
+++ b/arch/arm/mach-msm/pil-dsps.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
@@ -142,9 +142,6 @@
 
 static void dsps_restart_handler(struct dsps_data *drv)
 {
-	pr_debug("%s: Restart lvl %d\n",
-		__func__, get_restart_level());
-
 	if (atomic_add_return(1, &drv->crash_in_progress) > 1) {
 		pr_err("%s: DSPS already resetting. Count %d\n", __func__,
 		       atomic_read(&drv->crash_in_progress));
diff --git a/arch/arm/mach-msm/platsmp.c b/arch/arm/mach-msm/platsmp.c
index e7b4cea..bc40130 100644
--- a/arch/arm/mach-msm/platsmp.c
+++ b/arch/arm/mach-msm/platsmp.c
@@ -284,7 +284,8 @@
 	if (per_cpu(cold_boot_done, cpu) == false) {
 		if (machine_is_msm8974_sim() || machine_is_mpq8092_sim())
 			release_secondary_sim(0xf9088000, cpu);
-		else if (!machine_is_msm8974_rumi())
+		else if (!machine_is_msm8974_rumi() &&
+			 !machine_is_msmzinc_sim())
 			msm8974_release_secondary(0xf9088000, cpu);
 
 		per_cpu(cold_boot_done, cpu) = true;
diff --git a/arch/arm/mach-msm/pm-8x60.c b/arch/arm/mach-msm/pm-8x60.c
index 8f6c242..a22d664 100644
--- a/arch/arm/mach-msm/pm-8x60.c
+++ b/arch/arm/mach-msm/pm-8x60.c
@@ -394,12 +394,10 @@
 
 	ret = msm_spm_set_low_power_mode(MSM_SPM_MODE_CLOCK_GATING, false);
 	WARN_ON(ret);
-	krait_power_mdd_enable(smp_processor_id(), false);
 }
 
 static void msm_pm_config_hw_before_retention(void)
 {
-	krait_power_mdd_enable(smp_processor_id(), true);
 	return;
 }
 
@@ -1001,10 +999,15 @@
 	 * up as they enter the deepest sleep mode, namely RPM assited power
 	 * collapse
 	 */
-	if (!enable)
+	if (!enable) {
+		preempt_disable();
 		smp_call_function_many(cpu_online_mask,
 				msm_pm_ack_retention_disable,
 				NULL, true);
+		preempt_enable();
+
+
+	}
 }
 EXPORT_SYMBOL(msm_pm_enable_retention);
 
diff --git a/arch/arm/mach-msm/qdsp6v2/apr.c b/arch/arm/mach-msm/qdsp6v2/apr.c
index 4c106c5..6e60db1 100644
--- a/arch/arm/mach-msm/qdsp6v2/apr.c
+++ b/arch/arm/mach-msm/qdsp6v2/apr.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2010-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -26,6 +26,7 @@
 #include <linux/sysfs.h>
 #include <linux/device.h>
 #include <linux/slab.h>
+#include <sound/apr_audio-v2.h>
 #include <asm/mach-types.h>
 #include <mach/subsystem_restart.h>
 #include <mach/msm_smd.h>
@@ -114,6 +115,11 @@
 		.name = "VIDC",
 		.idx = 9,
 		.id = APR_SVC_VIDC,
+	},
+	{
+		.name = "LSM",
+		.idx = 9,
+		.id = APR_SVC_LSM,
 		.client_id = APR_CLIENT_AUDIO,
 	},
 };
@@ -280,7 +286,6 @@
 		return -ENETRESET;
 	}
 
-
 	spin_lock_irqsave(&svc->w_lock, flags);
 	dest_id = svc->dest_id;
 	client_id = svc->client_id;
@@ -391,7 +396,8 @@
 		    svc == APR_SVC_ADM || svc == APR_SVC_ADSP_CORE ||
 		    svc == APR_SVC_USM ||
 		    svc == APR_SVC_TEST_CLIENT || svc == APR_SVC_ADSP_MVM ||
-		    svc == APR_SVC_ADSP_CVS || svc == APR_SVC_ADSP_CVP)
+		    svc == APR_SVC_ADSP_CVS || svc == APR_SVC_ADSP_CVP ||
+		    svc == APR_SVC_LSM)
 			clnt = APR_CLIENT_AUDIO;
 		else if (svc == APR_SVC_VIDC)
 			clnt = APR_CLIENT_AUDIO;
diff --git a/arch/arm/mach-msm/ramdump.h b/arch/arm/mach-msm/ramdump.h
index e43ca12..3a960a1 100644
--- a/arch/arm/mach-msm/ramdump.h
+++ b/arch/arm/mach-msm/ramdump.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011-2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2011-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -20,6 +20,7 @@
 	unsigned long size;
 };
 
+#ifdef CONFIG_MSM_SUBSYSTEM_RESTART
 void *create_ramdump_device(const char *dev_name, struct device *parent);
 void destroy_ramdump_device(void *dev);
 int do_ramdump(void *handle, struct ramdump_segment *segments,
@@ -27,4 +28,28 @@
 int do_elf_ramdump(void *handle, struct ramdump_segment *segments,
 		int nsegments);
 
+#else
+static inline void *create_ramdump_device(const char *dev_name,
+		struct device *parent)
+{
+	return NULL;
+}
+
+static inline void destroy_ramdump_device(void *dev)
+{
+}
+
+static inline int do_ramdump(void *handle, struct ramdump_segment *segments,
+		int nsegments)
+{
+	return -ENODEV;
+}
+
+static inline int do_elf_ramdump(void *handle, struct ramdump_segment *segments,
+		int nsegments)
+{
+	return -ENODEV;
+}
+#endif /* CONFIG_MSM_SUBSYSTEM_RESTART */
+
 #endif
diff --git a/arch/arm/mach-msm/restart.c b/arch/arm/mach-msm/restart.c
index a67af45..d95f979 100644
--- a/arch/arm/mach-msm/restart.c
+++ b/arch/arm/mach-msm/restart.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2010-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -253,7 +253,7 @@
 		__raw_writel(0x31F3, msm_tmr0_base + WDT0_BITE_TIME);
 		__raw_writel(1, msm_tmr0_base + WDT0_EN);
 	} else {
-		/* Needed for 8974: Reset GCC_WDOG_DEBUG register */
+		/* Needed to bypass debug image on some chips */
 		msm_disable_wdog_debug();
 		__raw_writel(0, MSM_MPM2_PSHOLD_BASE);
 	}
diff --git a/arch/arm/mach-msm/smd.c b/arch/arm/mach-msm/smd.c
index cffb211..40ef20e 100644
--- a/arch/arm/mach-msm/smd.c
+++ b/arch/arm/mach-msm/smd.c
@@ -49,6 +49,7 @@
 
 #include "smd_private.h"
 #include "modem_notifier.h"
+#include "ramdump.h"
 
 #if defined(CONFIG_ARCH_QSD8X50) || defined(CONFIG_ARCH_MSM8X60) \
 	|| defined(CONFIG_ARCH_MSM8960) || defined(CONFIG_ARCH_FSM9XXX) \
@@ -178,7 +179,10 @@
 };
 static uint32_t num_smem_areas;
 static struct smem_area *smem_areas;
+static struct ramdump_segment *smem_ramdump_segments;
+static void *smem_ramdump_dev;
 static void *smem_range_check(phys_addr_t base, unsigned offset);
+static void *smd_dev;
 
 struct interrupt_stat interrupt_stats[NUM_SMD_SUBSYSTEMS];
 
@@ -977,10 +981,6 @@
 
 	SMx_POWER_INFO("%s: starting reset\n", __func__);
 
-	/* release any held spinlocks */
-	remote_spin_release(&remote_spinlock, restart_pid);
-	remote_spin_release_all(restart_pid);
-
 	shared = smem_find(ID_CH_ALLOC_TBL, sizeof(*shared) * 64);
 	if (!shared) {
 		pr_err("%s: allocation table not initialized\n", __func__);
@@ -3720,6 +3720,7 @@
 	struct device_node *node;
 	int ret;
 	const char *compatible;
+	struct ramdump_segment *ramdump_segments_tmp;
 	int subnode_num = 0;
 	resource_size_t irq_out_size;
 
@@ -3757,13 +3758,33 @@
 		}
 	}
 
+	/* initialize SSR ramdump regions */
+	key = "smem";
+	r = platform_get_resource_byname(pdev, IORESOURCE_MEM, key);
+	if (!r) {
+		pr_err("%s: missing '%s'\n", __func__, key);
+		return -ENODEV;
+	}
+	ramdump_segments_tmp = kmalloc_array(num_smem_areas + 1,
+			sizeof(struct ramdump_segment), GFP_KERNEL);
+
+	if (!ramdump_segments_tmp) {
+		pr_err("%s: ramdump segment kmalloc failed\n", __func__);
+		ret = -ENOMEM;
+		goto free_smem_areas;
+	}
+	ramdump_segments_tmp[0].address = r->start;
+	ramdump_segments_tmp[0].size = resource_size(r);
+
 	if (num_smem_areas) {
+
 		smem_areas = kmalloc(sizeof(struct smem_area) * num_smem_areas,
 					GFP_KERNEL);
+
 		if (!smem_areas) {
 			pr_err("%s: smem areas kmalloc failed\n", __func__);
-			num_smem_areas = 0;
-			return -ENOMEM;
+			ret = -ENOMEM;
+			goto free_smem_areas;
 		}
 		count = 1;
 		while (1) {
@@ -3775,6 +3796,16 @@
 				break;
 			aux_mem_base = r->start;
 			aux_mem_size = resource_size(r);
+
+			/*
+			 * Add to ram-dumps segments.
+			 * ramdump_segments_tmp[0] is the main SMEM region,
+			 * so auxiliary segments are indexed by count
+			 * instead of count - 1.
+			 */
+			ramdump_segments_tmp[count].address = aux_mem_base;
+			ramdump_segments_tmp[count].size = aux_mem_size;
+
 			SMD_DBG("%s: %s = %pa %pa", __func__, temp_string,
 					&aux_mem_base, &aux_mem_size);
 			smem_areas[count - 1].phys_addr = aux_mem_base;
@@ -3822,6 +3853,7 @@
 		++subnode_num;
 	}
 
+	smem_ramdump_segments = ramdump_segments_tmp;
 	return 0;
 
 rollback_subnodes:
@@ -3838,6 +3870,7 @@
 	}
 free_smem_areas:
 	num_smem_areas = 0;
+	kfree(ramdump_segments_tmp);
 	kfree(smem_areas);
 	smem_areas = NULL;
 	return ret;
@@ -3869,6 +3902,7 @@
 								__func__);
 				return ret;
 			}
+			smd_dev = &pdev->dev;
 		} else if (pdev->dev.platform_data) {
 			ret = smd_core_platform_init(pdev);
 			if (ret) {
@@ -3928,6 +3962,26 @@
 				__func__, notifier->processor,
 				notifier->name);
 
+		remote_spin_release(&remote_spinlock, notifier->processor);
+		remote_spin_release_all(notifier->processor);
+
+		if (smem_ramdump_dev) {
+			int ret;
+
+			SMD_INFO("%s: saving ramdump\n", __func__);
+			/*
+			 * XPU protection does not currently allow the
+			 * auxiliary memory regions to be dumped.  If this
+			 * changes, then num_smem_areas + 1 should be passed
+			 * into do_elf_ramdump() to dump all regions.
+			 */
+			ret = do_elf_ramdump(smem_ramdump_dev,
+					smem_ramdump_segments, 1);
+			if (ret < 0)
+				pr_err("%s: unable to dump smem %d\n", __func__,
+						ret);
+		}
+
 		smd_channel_reset(notifier->processor);
 	}
 
@@ -3940,12 +3994,20 @@
 	void *handle;
 	struct restart_notifier_block *nb;
 
+	smem_ramdump_dev = create_ramdump_device("smem-smd", smd_dev);
+	if (IS_ERR_OR_NULL(smem_ramdump_dev)) {
+		pr_err("%s: Unable to create smem ramdump device.\n",
+			__func__);
+		smem_ramdump_dev = NULL;
+	}
+
 	for (i = 0; i < ARRAY_SIZE(restart_notifiers); i++) {
 		nb = &restart_notifiers[i];
 		handle = subsys_notif_register_notifier(nb->name, &nb->nb);
 		SMD_DBG("%s: registering notif for '%s', handle=%p\n",
 				__func__, nb->name, handle);
 	}
+
 	return 0;
 }
 late_initcall(modem_restart_late_init);
diff --git a/arch/arm/mach-msm/smd_pkt.c b/arch/arm/mach-msm/smd_pkt.c
index eb7aa8a..7eb9ead 100644
--- a/arch/arm/mach-msm/smd_pkt.c
+++ b/arch/arm/mach-msm/smd_pkt.c
@@ -645,8 +645,9 @@
 	struct smd_pkt_dev *smd_pkt_devp = priv;
 
 	if (smd_pkt_devp->ch == 0) {
-		pr_err("%s on a closed smd_pkt_dev id:%d\n",
-			__func__, smd_pkt_devp->i);
+		if (event != SMD_EVENT_CLOSE)
+			pr_err("%s on a closed smd_pkt_dev id:%d\n",
+					__func__, smd_pkt_devp->i);
 		return;
 	}
 
diff --git a/arch/arm/mach-msm/subsystem_restart.c b/arch/arm/mach-msm/subsystem_restart.c
index 29481d3..5fe7a29 100644
--- a/arch/arm/mach-msm/subsystem_restart.c
+++ b/arch/arm/mach-msm/subsystem_restart.c
@@ -72,6 +72,11 @@
 	[SUBSYS_ONLINE] = "ONLINE",
 };
 
+static const char * const restart_levels[] = {
+	[RESET_SOC] = "SYSTEM",
+	[RESET_SUBSYS_COUPLED] = "RELATED",
+};
+
 /**
  * struct subsys_tracking - track state of a subsystem or restart order
  * @p_state: private state of subsystem/order
@@ -123,6 +128,7 @@
  * @owner: module that provides @desc
  * @count: reference count of subsystem_get()/subsystem_put()
  * @id: ida
+ * @restart_level: restart level (0 - panic, 1 - related, 2 - independent, etc.)
  * @restart_order: order of other devices this devices restarts with
  * @dentry: debugfs directory for this device
  * @do_ramdump_on_put: ramdump on subsystem_put() if true
@@ -140,6 +146,7 @@
 	struct module *owner;
 	int count;
 	int id;
+	int restart_level;
 	struct subsys_soc_restart_order *restart_order;
 #ifdef CONFIG_DEBUG_FS
 	struct dentry *dentry;
@@ -167,6 +174,38 @@
 	return snprintf(buf, PAGE_SIZE, "%s\n", subsys_states[state]);
 }
 
+static ssize_t
+restart_level_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	int level = to_subsys(dev)->restart_level;
+	return snprintf(buf, PAGE_SIZE, "%s\n", restart_levels[level]);
+}
+
+static ssize_t restart_level_store(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t count)
+{
+	struct subsys_device *subsys = to_subsys(dev);
+	int i;
+	const char *p;
+
+	p = memchr(buf, '\n', count);
+	if (p)
+		count = p - buf;
+
+	for (i = 0; i < ARRAY_SIZE(restart_levels); i++)
+		if (!strncasecmp(buf, restart_levels[i], count)) {
+			subsys->restart_level = i;
+			return count;
+		}
+	return -EPERM;
+}
+
+int subsys_get_restart_level(struct subsys_device *dev)
+{
+	return dev->restart_level;
+}
+EXPORT_SYMBOL(subsys_get_restart_level);
+
 static void subsys_set_state(struct subsys_device *subsys,
 			     enum subsys_state state)
 {
@@ -199,6 +238,7 @@
 static struct device_attribute subsys_attrs[] = {
 	__ATTR_RO(name),
 	__ATTR_RO(state),
+	__ATTR(restart_level, 0644, restart_level_show, restart_level_store),
 	__ATTR_NULL,
 };
 
@@ -259,48 +299,6 @@
 static struct subsys_soc_restart_order **restart_orders;
 static int n_restart_orders;
 
-static int restart_level = RESET_SOC;
-
-int get_restart_level()
-{
-	return restart_level;
-}
-EXPORT_SYMBOL(get_restart_level);
-
-static int restart_level_set(const char *val, struct kernel_param *kp)
-{
-	int ret;
-	int old_val = restart_level;
-
-	if (cpu_is_msm9615()) {
-		pr_err("Only Phase 1 subsystem restart is supported\n");
-		return -EINVAL;
-	}
-
-	ret = param_set_int(val, kp);
-	if (ret)
-		return ret;
-
-	switch (restart_level) {
-	case RESET_SUBSYS_INDEPENDENT:
-		if (socinfo_get_platform_subtype() == PLATFORM_SUBTYPE_SGLTE) {
-			pr_info("Phase 3 is currently unsupported. Using phase 2 instead.\n");
-			restart_level = RESET_SUBSYS_COUPLED;
-		}
-	case RESET_SUBSYS_COUPLED:
-	case RESET_SOC:
-		pr_info("Phase %d behavior activated.\n", restart_level);
-		break;
-	default:
-		restart_level = old_val;
-		return -EINVAL;
-	}
-	return 0;
-}
-
-module_param_call(restart_level, restart_level_set, param_get_int,
-			&restart_level, 0644);
-
 static struct subsys_soc_restart_order *
 update_restart_order(struct subsys_device *dev)
 {
@@ -484,7 +482,7 @@
 {
 	struct subsys_soc_restart_order *order = subsys->restart_order;
 
-	if (restart_level != RESET_SUBSYS_INDEPENDENT && order)
+	if (order)
 		return &order->track;
 	else
 		return &subsys->track;
@@ -603,7 +601,7 @@
 	 * This is because the subsystem list inside the relevant
 	 * restart order is not being traversed.
 	 */
-	if (restart_level != RESET_SUBSYS_INDEPENDENT && order) {
+	if (order) {
 		list = order->subsys_ptrs;
 		count = order->count;
 		track = &order->track;
@@ -662,7 +660,8 @@
 	struct subsys_tracking *track;
 	unsigned long flags;
 
-	pr_debug("Restarting %s [level=%d]!\n", desc->name, restart_level);
+	pr_debug("Restarting %s [level=%s]!\n", desc->name,
+			restart_levels[dev->restart_level]);
 
 	track = subsys_get_track(dev);
 	/*
@@ -708,13 +707,12 @@
 		return -EBUSY;
 	}
 
-	pr_info("Restart sequence requested for %s, restart_level = %d.\n",
-		name, restart_level);
+	pr_info("Restart sequence requested for %s, restart_level = %s.\n",
+		name, restart_levels[dev->restart_level]);
 
-	switch (restart_level) {
+	switch (dev->restart_level) {
 
 	case RESET_SUBSYS_COUPLED:
-	case RESET_SUBSYS_INDEPENDENT:
 		__subsystem_restart_dev(dev);
 		break;
 	case RESET_SOC:
diff --git a/arch/arm/mach-msm/timer.c b/arch/arm/mach-msm/timer.c
index f410e7f..3144113 100644
--- a/arch/arm/mach-msm/timer.c
+++ b/arch/arm/mach-msm/timer.c
@@ -1,6 +1,6 @@
 /*
  * Copyright (C) 2007 Google, Inc.
- * Copyright (c) 2009-2012, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2009-2013, The Linux Foundation. All rights reserved.
  *
  * This software is licensed under the terms of the GNU General Public
  * License version 2, as published by the Free Software Foundation, and
@@ -1082,9 +1082,11 @@
 		__raw_writel(DGT_CLK_CTL_DIV_4, MSM_TMR_BASE + DGT_CLK_CTL);
 		gpt->status_mask = BIT(10);
 		dgt->status_mask = BIT(2);
-		gpt->freq = 32765;
-		gpt_hz = 32765;
-		sclk_hz = 32765;
+		if (!soc_class_is_apq8064()) {
+			gpt->freq = 32765;
+			gpt_hz = 32765;
+			sclk_hz = 32765;
+		}
 		if (!soc_class_is_msm8930() && !cpu_is_msm8960ab()) {
 			gpt->flags |= MSM_CLOCK_FLAGS_UNSTABLE_COUNT;
 			dgt->flags |= MSM_CLOCK_FLAGS_UNSTABLE_COUNT;
diff --git a/arch/arm/mach-msm/wdog_debug.c b/arch/arm/mach-msm/wdog_debug.c
index 8b39d26..cccca26 100644
--- a/arch/arm/mach-msm/wdog_debug.c
+++ b/arch/arm/mach-msm/wdog_debug.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
@@ -10,144 +10,31 @@
  * GNU General Public License for more details.
  */
 
-#include <linux/module.h>
 #include <linux/kernel.h>
-#include <linux/io.h>
-#include <linux/delay.h>
-#include <linux/mutex.h>
-#include <linux/sched.h>
-#include <linux/of.h>
-#include <linux/platform_device.h>
+#include <linux/module.h>
 #include <mach/scm.h>
-#include <linux/slab.h>
 
-#define MODULE_NAME "wdog_debug"
-#define WDOG_DEBUG_EN 17
-#define GCC_WDOG_DEBUG_OFFSET 0x780
-
-struct msm_wdog_debug_data {
-	unsigned int __iomem phys_base;
-	size_t size;
-	void __iomem *base;
-	struct device *dev;
-};
-
-static struct msm_wdog_debug_data *wdog_data;
-
-void msm_disable_wdog_debug(void)
-{
-	unsigned long int value;
-
-	if (wdog_data == NULL)
-		return;
-	value = readl_relaxed(wdog_data->base + GCC_WDOG_DEBUG_OFFSET);
-	value &= ~BIT(WDOG_DEBUG_EN);
-	writel_relaxed(value, wdog_data->base + GCC_WDOG_DEBUG_OFFSET);
-
-	/* Ensure the WDOG_DEBUG_EN status has changed */
-	while (readl_relaxed(wdog_data->base + GCC_WDOG_DEBUG_OFFSET) &
-		BIT(WDOG_DEBUG_EN))
-			;
-}
-EXPORT_SYMBOL(msm_disable_wdog_debug);
+#define SCM_WDOG_DEBUG_BOOT_PART	0x9
+#define BOOT_PART_EN_VAL		0x5D1
 
 void msm_enable_wdog_debug(void)
 {
-	unsigned long int value;
+	int ret;
 
-	if (wdog_data == NULL)
-		return;
-	value = readl_relaxed(wdog_data->base + GCC_WDOG_DEBUG_OFFSET);
-	value |= BIT(WDOG_DEBUG_EN);
-	writel_relaxed(value, wdog_data->base + GCC_WDOG_DEBUG_OFFSET);
+	ret = scm_call_atomic2(SCM_SVC_BOOT,
+			       SCM_WDOG_DEBUG_BOOT_PART, 0, BOOT_PART_EN_VAL);
+	if (ret)
+		pr_err("failed to enable wdog debug\n");
 }
 EXPORT_SYMBOL(msm_enable_wdog_debug);
 
-static int __devexit msm_wdog_debug_remove(struct platform_device *pdev)
-{
-	kfree(wdog_data);
-	wdog_data = NULL;
-	pr_info("MSM wdog_debug Exit - Deactivated\n");
-	return 0;
-}
-
-static int __devinit msm_wdog_debug_dt_to_pdata(struct platform_device *pdev,
-					struct msm_wdog_debug_data *pdata)
-{
-	struct resource *wdog_resource;
-
-	wdog_resource = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (!wdog_resource) {
-		dev_err(&pdev->dev, \
-		"%s cannot allocate resource for wdog_debug\n", \
-		 __func__);
-		return -ENXIO;
-	}
-	pdata->size = resource_size(wdog_resource);
-	pdata->phys_base = wdog_resource->start;
-	if (unlikely(!(devm_request_region(&pdev->dev, pdata->phys_base,
-					pdata->size, "msm-wdog-debug")))) {
-		dev_err(&pdev->dev, "%s cannot reserve wdog_debug region\n",
-								__func__);
-		return -ENXIO;
-	}
-	pdata->base  = devm_ioremap(&pdev->dev, pdata->phys_base,
-							pdata->size);
-	if (!pdata->base) {
-		dev_err(&pdev->dev, "%s cannot map wdog register space\n",
-				__func__);
-		return -ENXIO;
-	}
-
-	return 0;
-}
-
-static int __devinit msm_wdog_debug_probe(struct platform_device *pdev)
+void msm_disable_wdog_debug(void)
 {
 	int ret;
-	if (!pdev->dev.of_node)
-		return -ENODEV;
-	wdog_data = kzalloc(sizeof(struct msm_wdog_debug_data), GFP_KERNEL);
-	if (!wdog_data)
-		return -ENOMEM;
-	ret = msm_wdog_debug_dt_to_pdata(pdev, wdog_data);
+
+	ret = scm_call_atomic2(SCM_SVC_BOOT,
+			       SCM_WDOG_DEBUG_BOOT_PART, 1, 0);
 	if (ret)
-		goto err;
-	wdog_data->dev = &pdev->dev;
-	platform_set_drvdata(pdev, wdog_data);
-	return 0;
-err:
-	kzfree(wdog_data);
-	wdog_data = NULL;
-	return ret;
+		pr_err("failed to disable wdog debug\n");
 }
-
-static struct of_device_id msm_wdog_debug_match_table[] = {
-	{ .compatible = "qcom,msm-wdog-debug" },
-	{}
-};
-
-static struct platform_driver msm_wdog_debug_driver = {
-	.probe = msm_wdog_debug_probe,
-	.remove = msm_wdog_debug_remove,
-	.driver = {
-		.name = MODULE_NAME,
-		.owner = THIS_MODULE,
-		.of_match_table = msm_wdog_debug_match_table,
-	},
-};
-
-static int __devinit wdog_debug_init(void)
-{
-	return platform_driver_register(&msm_wdog_debug_driver);
-}
-module_init(wdog_debug_init);
-
-static void __exit wdog_debug_exit(void)
-{
-	platform_driver_unregister(&msm_wdog_debug_driver);
-}
-module_exit(wdog_debug_exit);
-
-MODULE_DESCRIPTION("MSM Driver to disable debug Image");
-MODULE_LICENSE("GPL v2");
+EXPORT_SYMBOL(msm_disable_wdog_debug);
diff --git a/arch/arm/mm/init.c b/arch/arm/mm/init.c
index 38da432..f16f700 100644
--- a/arch/arm/mm/init.c
+++ b/arch/arm/mm/init.c
@@ -381,6 +381,10 @@
 EXPORT_SYMBOL(memory_hole_start);
 unsigned long memory_hole_end;
 EXPORT_SYMBOL(memory_hole_end);
+unsigned long memory_hole_align;
+EXPORT_SYMBOL(memory_hole_align);
+unsigned long virtual_hole_start;
+unsigned long virtual_hole_end;
 
 #ifdef CONFIG_DONT_MAP_HOLE_AFTER_MEMBANK0
 void find_memory_hole(void)
@@ -388,6 +392,7 @@
 	int i;
 	unsigned long hole_start;
 	unsigned long hole_size;
+	unsigned long hole_end_virt;
 
 	/*
 	 * Find the start and end of the hole, using meminfo
@@ -420,7 +425,32 @@
 			}
 		}
 	}
+
 	memory_hole_offset = memory_hole_start - PHYS_OFFSET;
+	if (!IS_ALIGNED(memory_hole_start, SECTION_SIZE)) {
+		pr_err("memory_hole_start %lx is not aligned to %lx\n",
+			memory_hole_start, SECTION_SIZE);
+		BUG();
+	}
+	if (!IS_ALIGNED(memory_hole_end, SECTION_SIZE)) {
+		pr_err("memory_hole_end %lx is not aligned to %lx\n",
+			memory_hole_end, SECTION_SIZE);
+		BUG();
+	}
+
+	hole_end_virt = __phys_to_virt(memory_hole_end);
+
+	if ((!IS_ALIGNED(hole_end_virt, PMD_SIZE) &&
+	     IS_ALIGNED(memory_hole_end, PMD_SIZE)) ||
+	     (IS_ALIGNED(hole_end_virt, PMD_SIZE) &&
+	      !IS_ALIGNED(memory_hole_end, PMD_SIZE))) {
+		memory_hole_align = max(hole_end_virt & ~PMD_MASK,
+					memory_hole_end & ~PMD_MASK);
+		virtual_hole_start = hole_end_virt;
+		virtual_hole_end = hole_end_virt + memory_hole_align;
+		pr_info("Physical memory hole is not aligned. There will be a virtual memory hole from %lx to %lx\n",
+			virtual_hole_start, virtual_hole_end);
+	}
 }
 
 #endif
diff --git a/drivers/base/dma-contiguous.c b/drivers/base/dma-contiguous.c
index 3a8bbc5..ed91480 100644
--- a/drivers/base/dma-contiguous.c
+++ b/drivers/base/dma-contiguous.c
@@ -213,8 +213,7 @@
 	__be32 *prop;
 	char *name;
 
-	if (strncmp(uname, "region@", 7) != 0 || depth != 2 ||
-	    !of_get_flat_dt_prop(node, "linux,contiguous-region", NULL))
+	if (!of_get_flat_dt_prop(node, "linux,contiguous-region", NULL))
 		return 0;
 
 	prop = of_get_flat_dt_prop(node, "reg", &len);
diff --git a/drivers/char/adsprpc.c b/drivers/char/adsprpc.c
index 73fe5d6..0f4d613 100644
--- a/drivers/char/adsprpc.c
+++ b/drivers/char/adsprpc.c
@@ -89,7 +89,7 @@
 	int n = -1, err = 0;
 
 	VERIFY(err, 0 != access_ok(access ? VERIFY_WRITE : VERIFY_READ,
-			      (void __user *)start, len));
+					(void __user *)start, len));
 	if (err)
 		goto bail;
 	VERIFY(err, 0 != (vma = find_vma(current->mm, start)));
@@ -611,27 +611,28 @@
 static int get_dev(struct fastrpc_apps *me, struct fastrpc_device **rdev)
 {
 	struct hlist_head *head;
-	struct fastrpc_device *dev = 0;
-	struct hlist_node *n;
+	struct fastrpc_device *dev = 0, *devfree = 0;
+	struct hlist_node *pos, *n;
 	uint32_t h = hash_32(current->tgid, RPC_HASH_BITS);
 	int err = 0;
 
 	spin_lock(&me->hlock);
 	head = &me->htbl[h];
-	hlist_for_each_entry(dev, n, head, hn) {
+	hlist_for_each_entry_safe(dev, pos, n, head, hn) {
 		if (dev->tgid == current->tgid) {
 			hlist_del(&dev->hn);
+			devfree = dev;
 			break;
 		}
 	}
 	spin_unlock(&me->hlock);
-	VERIFY(err, dev != 0);
+	VERIFY(err, devfree != 0);
 	if (err)
 		goto bail;
-	*rdev = dev;
+	*rdev = devfree;
  bail:
 	if (err) {
-		free_dev(dev);
+		free_dev(devfree);
 		err = alloc_dev(rdev);
 	}
 	return err;
@@ -756,22 +757,23 @@
 	struct fastrpc_apps *me = &gfa;
 	uint32_t h = hash_32(current->tgid, RPC_HASH_BITS);
 	struct hlist_head *head;
-	struct hlist_node *pos;
-	struct fastrpc_device *dev;
+	struct hlist_node *pos, *n;
+	struct fastrpc_device *dev, *devfree;
 
  rnext:
-	dev = 0;
+	devfree = dev = 0;
 	spin_lock(&me->hlock);
 	head = &me->htbl[h];
-	hlist_for_each_entry(dev, pos, head, hn) {
+	hlist_for_each_entry_safe(dev, pos, n, head, hn) {
 		if (dev->tgid == current->tgid) {
 			hlist_del(&dev->hn);
+			devfree = dev;
 			break;
 		}
 	}
 	spin_unlock(&me->hlock);
-	if (dev) {
-		free_dev(dev);
+	if (devfree) {
+		free_dev(devfree);
 		goto rnext;
 	}
 	return;
diff --git a/drivers/char/diag/diag_dci.c b/drivers/char/diag/diag_dci.c
index 6ae5d03..6d28042 100644
--- a/drivers/char/diag/diag_dci.c
+++ b/drivers/char/diag/diag_dci.c
@@ -37,6 +37,7 @@
 unsigned char dci_cumulative_event_mask[DCI_EVENT_MASK_SIZE];
 struct mutex dci_log_mask_mutex;
 struct mutex dci_event_mask_mutex;
+struct mutex dci_health_mutex;
 
 #define DCI_CHK_CAPACITY(entry, new_data_len)				\
 ((entry->data_len + new_data_len > entry->total_capacity) ? 1 : 0)	\
@@ -211,6 +212,7 @@
 				entry = &(driver->dci_client_tbl[i]);
 				event_mask_ptr = entry->dci_event_mask +
 								 byte_index;
+				mutex_lock(&dci_health_mutex);
 				if (*event_mask_ptr & byte_mask) {
 					/* copy to client buffer */
 					if (DCI_CHK_CAPACITY(entry,
@@ -218,7 +220,9 @@
 						pr_err("diag: DCI event drop\n");
 						driver->dci_client_tbl[i].
 							dropped_events++;
-						return;
+						mutex_unlock(
+							&dci_health_mutex);
+						break;
 					}
 					driver->dci_client_tbl[i].
 							received_events++;
@@ -230,6 +234,7 @@
 						, total_event_len);
 					entry->data_len += 4 + total_event_len;
 				}
+				mutex_unlock(&dci_health_mutex);
 			}
 		}
 		temp_len += 2 + timestamp_len + payload_len_field + payload_len;
@@ -264,6 +269,7 @@
 			if (!log_mask_ptr)
 				return;
 			log_mask_ptr = log_mask_ptr + byte_offset;
+			mutex_lock(&dci_health_mutex);
 			if (*log_mask_ptr & byte_mask) {
 				pr_debug("\t log code %x needed by client %d",
 					 log_code, entry->client->tgid);
@@ -273,6 +279,8 @@
 						pr_err("diag: DCI log drop\n");
 						driver->dci_client_tbl[i].
 								dropped_logs++;
+						mutex_unlock(
+							&dci_health_mutex);
 						return;
 				}
 				driver->dci_client_tbl[i].received_logs++;
@@ -282,6 +290,7 @@
 					    buf + 4, *(uint16_t *)(buf + 2));
 				entry->data_len += 4 + *(uint16_t *)(buf + 2);
 			}
+			mutex_unlock(&dci_health_mutex);
 		}
 	}
 }
@@ -1028,6 +1037,8 @@
 	mutex_init(&driver->dci_mutex);
 	mutex_init(&dci_log_mask_mutex);
 	mutex_init(&dci_event_mask_mutex);
+	mutex_init(&dci_health_mutex);
+
 	for (i = 0; i < NUM_SMD_DCI_CHANNELS; i++) {
 		success = diag_smd_constructor(&driver->smd_dci[i],
 					i, SMD_DCI_TYPE);
@@ -1082,5 +1093,118 @@
 	kfree(driver->req_tracking_tbl);
 	kfree(driver->dci_client_tbl);
 	kfree(driver->apps_dci_buf);
+	mutex_destroy(&driver->dci_mutex);
+	mutex_destroy(&dci_log_mask_mutex);
+	mutex_destroy(&dci_event_mask_mutex);
+	mutex_destroy(&dci_health_mutex);
 	destroy_workqueue(driver->diag_dci_wq);
 }
+
+int diag_dci_clear_log_mask()
+{
+	int i, j, k, err = DIAG_DCI_NO_ERROR;
+	uint8_t *log_mask_ptr, *update_ptr;
+
+	i = diag_dci_find_client_index(current->tgid);
+	if (i == DCI_CLIENT_INDEX_INVALID)
+		return DIAG_DCI_TABLE_ERR;
+
+	mutex_lock(&dci_log_mask_mutex);
+	create_dci_log_mask_tbl(
+			driver->dci_client_tbl[i].dci_log_mask);
+	memset(dci_cumulative_log_mask,
+				0x0, DCI_LOG_MASK_SIZE);
+	for (i = 0; i < MAX_DCI_CLIENTS; i++) {
+		update_ptr = dci_cumulative_log_mask;
+		if (driver->dci_client_tbl[i].client) {
+			log_mask_ptr =
+				driver->dci_client_tbl[i].dci_log_mask;
+			for (j = 0; j < 16; j++) {
+				*update_ptr = j;
+				*(update_ptr + 1) = 1;
+				update_ptr += 2;
+				log_mask_ptr += 2;
+				for (k = 0; k < 513; k++) {
+					*update_ptr |= *log_mask_ptr;
+					update_ptr++;
+					log_mask_ptr++;
+				}
+			}
+		}
+	}
+	mutex_unlock(&dci_log_mask_mutex);
+	err = diag_send_dci_log_mask(driver->smd_cntl[MODEM_DATA].ch);
+	return err;
+}
+
+int diag_dci_clear_event_mask()
+{
+	int i, j, err = DIAG_DCI_NO_ERROR;
+	uint8_t *event_mask_ptr, *update_ptr;
+
+	i = diag_dci_find_client_index(current->tgid);
+	if (i == DCI_CLIENT_INDEX_INVALID)
+		return DIAG_DCI_TABLE_ERR;
+
+	mutex_lock(&dci_event_mask_mutex);
+	memset(driver->dci_client_tbl[i].dci_event_mask,
+			0x0, DCI_EVENT_MASK_SIZE);
+	memset(dci_cumulative_event_mask,
+			0x0, DCI_EVENT_MASK_SIZE);
+	update_ptr = dci_cumulative_event_mask;
+	for (i = 0; i < MAX_DCI_CLIENTS; i++) {
+		event_mask_ptr =
+			driver->dci_client_tbl[i].dci_event_mask;
+		for (j = 0; j < DCI_EVENT_MASK_SIZE; j++)
+			*(update_ptr + j) |= *(event_mask_ptr + j);
+	}
+	mutex_unlock(&dci_event_mask_mutex);
+	err = diag_send_dci_event_mask(driver->smd_cntl[MODEM_DATA].ch);
+	return err;
+}
+
+int diag_dci_query_log_mask(uint16_t log_code)
+{
+	uint16_t item_num;
+	uint8_t equip_id, *log_mask_ptr, byte_mask;
+	int i, byte_index, offset;
+
+	equip_id = LOG_GET_EQUIP_ID(log_code);
+	item_num = LOG_GET_ITEM_NUM(log_code);
+	byte_index = item_num/8 + 2;
+	byte_mask = 0x01 << (item_num % 8);
+	offset = equip_id * 514;
+
+	i = diag_dci_find_client_index(current->tgid);
+	if (i != DCI_CLIENT_INDEX_INVALID) {
+		log_mask_ptr = driver->dci_client_tbl[i].dci_log_mask;
+		log_mask_ptr = log_mask_ptr + offset + byte_index;
+		return ((*log_mask_ptr & byte_mask) == byte_mask) ?
+								1 : 0;
+	}
+	return 0;
+}
+
+
+int diag_dci_query_event_mask(uint16_t event_id)
+{
+	uint8_t *event_mask_ptr, byte_mask;
+	int i, byte_index, bit_index;
+	byte_index = event_id/8;
+	bit_index = event_id % 8;
+	byte_mask = 0x1 << bit_index;
+
+	i = diag_dci_find_client_index(current->tgid);
+	if (i != DCI_CLIENT_INDEX_INVALID) {
+		event_mask_ptr =
+		driver->dci_client_tbl[i].dci_event_mask;
+		event_mask_ptr = event_mask_ptr + byte_index;
+		if ((*event_mask_ptr & byte_mask) == byte_mask)
+			return 1;
+		else
+			return 0;
+	}
+	return 0;
+}
+
+
diff --git a/drivers/char/diag/diag_dci.h b/drivers/char/diag/diag_dci.h
index 9187516..260cdf3 100644
--- a/drivers/char/diag/diag_dci.h
+++ b/drivers/char/diag/diag_dci.h
@@ -37,6 +37,7 @@
 
 extern unsigned int dci_max_reg;
 extern unsigned int dci_max_clients;
+extern struct mutex dci_health_mutex;
 
 struct dci_pkt_req_tracking_tbl {
 	int pid;
@@ -68,6 +69,13 @@
 	int reset_status;
 };
 
+/* This is used for querying DCI Log
+   or Event Mask */
+struct diag_log_event_stats {
+	uint16_t code;
+	int is_set;
+};
+
 enum {
 	DIAG_DCI_NO_ERROR = 1001,	/* No error */
 	DIAG_DCI_NO_REG,		/* Could not register */
@@ -96,10 +104,14 @@
 void clear_client_dci_cumulative_log_mask(int client_index);
 int diag_send_dci_log_mask(smd_channel_t *ch);
 void extract_dci_log(unsigned char *buf);
+int diag_dci_clear_log_mask(void);
+int diag_dci_query_log_mask(uint16_t log_code);
 /* DCI event streaming functions */
 void update_dci_cumulative_event_mask(int offset, uint8_t byte_mask);
 void clear_client_dci_cumulative_event_mask(int client_index);
 int diag_send_dci_event_mask(smd_channel_t *ch);
 void extract_dci_events(unsigned char *buf);
 void create_dci_event_mask_tbl(unsigned char *tbl_buf);
+int diag_dci_clear_event_mask(void);
+int diag_dci_query_event_mask(uint16_t event_id);
 #endif
diff --git a/drivers/char/diag/diagchar.h b/drivers/char/diag/diagchar.h
index df28dab..a4eea54 100644
--- a/drivers/char/diag/diagchar.h
+++ b/drivers/char/diag/diagchar.h
@@ -30,7 +30,6 @@
 #define IN_BUF_SIZE		16384
 #define MAX_IN_BUF_SIZE	32768
 #define MAX_SYNC_OBJ_NAME_SIZE	32
-#define UINT32_MAX	UINT_MAX
 /* Size of the buffer used for deframing a packet
   reveived from the PC tool*/
 #define HDLC_MAX 4096
@@ -86,8 +85,8 @@
 #define SMD_DCI_TYPE 2
 
 /* Maximum number of pkt reg supported at initialization*/
-extern unsigned int diag_max_reg;
-extern unsigned int diag_threshold_reg;
+extern int diag_max_reg;
+extern int diag_threshold_reg;
 
 #define APPEND_DEBUG(ch) \
 do {							\
@@ -292,6 +291,7 @@
 	struct diag_request *write_ptr_mdm;
 #endif
 #ifdef CONFIG_DIAGFWD_BRIDGE_CODE
+	spinlock_t hsic_ready_spinlock;
 	/* common for all bridges */
 	struct work_struct diag_disconnect_work;
 	/* SGLTE variables */
diff --git a/drivers/char/diag/diagchar_core.c b/drivers/char/diag/diagchar_core.c
index 3e3d8fd..65fc89f 100644
--- a/drivers/char/diag/diagchar_core.c
+++ b/drivers/char/diag/diagchar_core.c
@@ -66,8 +66,8 @@
 static unsigned int max_clients = 15;
 static unsigned int threshold_client_limit = 30;
 /* This is the maximum number of pkt registrations supported at initialization*/
-unsigned int diag_max_reg = 600;
-unsigned int diag_threshold_reg = 750;
+int diag_max_reg = 600;
+int diag_threshold_reg = 750;
 
 /* Timer variables */
 static struct timer_list drain_timer;
@@ -516,149 +516,379 @@
 	*pnum_data = num_data;
 	return exit_stat;
 }
+
+static void diag_update_data_ready(int index)
+{
+	int clear_bit = 1;
+	unsigned long hsic_lock_flags;
+	unsigned long ready_lock_flags;
+	int i;
+
+	/*
+	 * Determine whether the data_ready USER_SPACE_DATA_TYPE bit
+	 * should be updated/cleared or not. There is a race condition that
+	 * can occur when in MEMORY_DEVICE_MODE with the hsic data.
+	 * When new hsic data arrives we prepare the data so it can
+	 * later be copied to userspace.  We set the USER_SPACE_DATA_TYPE
+	 * bit in data ready at that time. We later copy the hsic data
+	 * to userspace and clear the USER_SPACE_DATA_TYPE bit in
+	 * data ready. The race condition occurs if new data arrives (bit set)
+	 * while we are processing the current data and sending
+	 * it to userspace (bit clear).  The clearing of the bit can
+	 * overwrite the setting of the bit.
+	 */
+
+	spin_lock_irqsave(&driver->hsic_ready_spinlock, ready_lock_flags);
+	for (i = 0; i < MAX_HSIC_CH; i++) {
+		if (diag_hsic[i].hsic_inited) {
+			spin_lock_irqsave(&diag_hsic[i].hsic_spinlock,
+							hsic_lock_flags);
+			if ((diag_hsic[i].num_hsic_buf_tbl_entries > 0) &&
+				diag_hsic[i].hsic_device_enabled &&
+				diag_hsic[i].hsic_ch) {
+				/* New data do not clear the bit */
+				clear_bit = 0;
+			}
+			spin_unlock_irqrestore(&diag_hsic[i].hsic_spinlock,
+							hsic_lock_flags);
+			if (!clear_bit)
+				break;
+		}
+	}
+
+	if (clear_bit)
+		driver->data_ready[index] ^= USER_SPACE_DATA_TYPE;
+
+	spin_unlock_irqrestore(&driver->hsic_ready_spinlock, ready_lock_flags);
+}
 #else
 inline uint16_t diag_get_remote_device_mask(void) { return 0; }
 inline int diag_copy_remote(char __user *buf, size_t count, int *pret,
 			    int *pnum_data) { return 0; }
+static void diag_update_data_ready(int index)
+{
+	driver->data_ready[index] ^= USER_SPACE_DATA_TYPE;
+}
 #endif
 
-long diagchar_ioctl(struct file *filp,
-			   unsigned int iocmd, unsigned long ioarg)
+int diag_command_reg(unsigned long ioarg)
 {
-	int i, j, temp, success = -1, status, index = -1;
-	unsigned int count_entries = 0, interim_count = 0;
+	int i = 0, success = -EINVAL, j;
 	void *temp_buf;
-	uint16_t support_list = 0;
-	struct diag_dci_client_tbl *dci_params;
-	struct diag_dci_health_stats stats;
-
-	if (iocmd == DIAG_IOCTL_COMMAND_REG) {
-		struct bindpkt_params_per_process pkt_params;
-		struct bindpkt_params *params;
-		struct bindpkt_params *head_params;
-		if (copy_from_user(&pkt_params, (void *)ioarg,
-			   sizeof(struct bindpkt_params_per_process))) {
-			return -EFAULT;
-		}
-		if ((UINT32_MAX/sizeof(struct bindpkt_params)) <
-							 pkt_params.count) {
-			pr_warning("diag: integer overflow while multiply\n");
-			return -EFAULT;
-		}
-		params = kzalloc(pkt_params.count*sizeof(
-			struct bindpkt_params), GFP_KERNEL);
-		if (!params) {
-			pr_err("diag: unable to alloc memory\n");
-			return -ENOMEM;
-		} else
-			head_params = params;
-
-		if (copy_from_user(params, pkt_params.params,
-			   pkt_params.count*sizeof(struct bindpkt_params))) {
-			kfree(head_params);
-			return -EFAULT;
-		}
-		mutex_lock(&driver->diagchar_mutex);
-		for (i = 0; i < diag_max_reg; i++) {
-			if (driver->table[i].process_id == 0) {
-				diag_add_reg(i, params, &success,
-							 &count_entries);
-				if (pkt_params.count > count_entries) {
-					params++;
-				} else {
-					mutex_unlock(&driver->diagchar_mutex);
-					kfree(head_params);
-					return success;
-				}
+	unsigned int count_entries = 0, interim_count = 0;
+	struct bindpkt_params_per_process pkt_params;
+	struct bindpkt_params *params;
+	struct bindpkt_params *head_params;
+	if (copy_from_user(&pkt_params, (void *)ioarg,
+		   sizeof(struct bindpkt_params_per_process))) {
+		return -EFAULT;
+	}
+	if ((UINT_MAX/sizeof(struct bindpkt_params)) <
+						 pkt_params.count) {
+		pr_warn("diag: integer overflow while multiply\n");
+		return -EFAULT;
+	}
+	head_params = kzalloc(pkt_params.count*sizeof(
+		struct bindpkt_params), GFP_KERNEL);
+	if (!head_params) {
+		pr_err("diag: unable to alloc memory\n");
+		return -ENOMEM;
+	} else
+		params = head_params;
+	if (copy_from_user(params, pkt_params.params,
+		   pkt_params.count*sizeof(struct bindpkt_params))) {
+		kfree(head_params);
+		return -EFAULT;
+	}
+	mutex_lock(&driver->diagchar_mutex);
+	for (i = 0; i < diag_max_reg; i++) {
+		if (driver->table[i].process_id == 0) {
+			diag_add_reg(i, params, &success,
+						 &count_entries);
+			if (pkt_params.count > count_entries) {
+				params++;
+			} else {
+				kfree(head_params);
+				mutex_unlock(&driver->diagchar_mutex);
+				return success;
 			}
 		}
-		if (i < diag_threshold_reg) {
-			/* Increase table size by amount required */
+	}
+	if (i < diag_threshold_reg) {
+		/* Increase table size by amount required */
+		if (pkt_params.count >= count_entries) {
+			interim_count = pkt_params.count -
+						 count_entries;
+		} else {
+			pr_warn("diag: error in params count\n");
+			kfree(head_params);
+			mutex_unlock(&driver->diagchar_mutex);
+			return -EFAULT;
+		}
+		if (UINT_MAX - diag_max_reg >=
+						interim_count) {
+			diag_max_reg += interim_count;
+		} else {
+			pr_warn("diag: Integer overflow\n");
+			kfree(head_params);
+			mutex_unlock(&driver->diagchar_mutex);
+			return -EFAULT;
+		}
+		/* Make sure size doesnt go beyond threshold */
+		if (diag_max_reg > diag_threshold_reg) {
+			diag_max_reg = diag_threshold_reg;
+			pr_err("diag: best case memory allocation\n");
+		}
+		if (UINT_MAX/sizeof(struct diag_master_table) <
+							 diag_max_reg) {
+			pr_warn("diag: integer overflow\n");
+			kfree(head_params);
+			mutex_unlock(&driver->diagchar_mutex);
+			return -EFAULT;
+		}
+		temp_buf = krealloc(driver->table,
+				 diag_max_reg*sizeof(struct
+				 diag_master_table), GFP_KERNEL);
+		if (!temp_buf) {
+			pr_err("diag: Insufficient memory for reg.\n");
+
 			if (pkt_params.count >= count_entries) {
 				interim_count = pkt_params.count -
 							 count_entries;
 			} else {
-				pr_warning("diag: error in params count\n");
+				pr_warn("diag: params count error\n");
 				kfree(head_params);
 				mutex_unlock(&driver->diagchar_mutex);
 				return -EFAULT;
 			}
-			if (UINT32_MAX - diag_max_reg >=
-							interim_count) {
-				diag_max_reg += interim_count;
+			if (diag_max_reg >= interim_count) {
+				diag_max_reg -= interim_count;
 			} else {
-				pr_warning("diag: Integer overflow\n");
+				pr_warn("diag: Integer underflow\n");
 				kfree(head_params);
 				mutex_unlock(&driver->diagchar_mutex);
 				return -EFAULT;
 			}
-			/* Make sure size doesnt go beyond threshold */
-			if (diag_max_reg > diag_threshold_reg) {
-				diag_max_reg = diag_threshold_reg;
-				pr_info("diag: best case memory allocation\n");
-			}
-			if (UINT32_MAX/sizeof(struct diag_master_table) <
-								 diag_max_reg) {
-				pr_warning("diag: integer overflow\n");
-				kfree(head_params);
-				mutex_unlock(&driver->diagchar_mutex);
-				return -EFAULT;
-			}
-			temp_buf = krealloc(driver->table,
-					 diag_max_reg*sizeof(struct
-					 diag_master_table), GFP_KERNEL);
-			if (!temp_buf) {
-				pr_alert("diag: Insufficient memory for reg.\n");
-				mutex_unlock(&driver->diagchar_mutex);
-
-				if (pkt_params.count >= count_entries) {
-					interim_count = pkt_params.count -
-								 count_entries;
-				} else {
-					pr_warning("diag: params count error\n");
-					mutex_unlock(&driver->diagchar_mutex);
-					kfree(head_params);
-					return -EFAULT;
-				}
-				if (diag_max_reg >= interim_count) {
-					diag_max_reg -= interim_count;
-				} else {
-					pr_warning("diag: Integer underflow\n");
-					mutex_unlock(&driver->diagchar_mutex);
-					kfree(head_params);
-					return -EFAULT;
-				}
-				kfree(head_params);
-				return 0;
-			} else {
-				driver->table = temp_buf;
-			}
-			for (j = i; j < diag_max_reg; j++) {
-				diag_add_reg(j, params, &success,
-							 &count_entries);
-				if (pkt_params.count > count_entries) {
-					params++;
-				} else {
-					mutex_unlock(&driver->diagchar_mutex);
-					kfree(head_params);
-					return success;
-				}
-			}
 			kfree(head_params);
 			mutex_unlock(&driver->diagchar_mutex);
+			return 0;
 		} else {
-			mutex_unlock(&driver->diagchar_mutex);
-			kfree(head_params);
-			pr_err("Max size reached, Pkt Registration failed for"
-						" Process %d", current->tgid);
+			driver->table = temp_buf;
 		}
-		success = 0;
-	} else if (iocmd == DIAG_IOCTL_GET_DELAYED_RSP_ID) {
-		struct diagpkt_delay_params delay_params;
-		uint16_t interim_rsp_id;
-		int interim_size;
+		for (j = i; j < diag_max_reg; j++) {
+			diag_add_reg(j, params, &success,
+						 &count_entries);
+			if (pkt_params.count > count_entries) {
+				params++;
+			} else {
+				kfree(head_params);
+				mutex_unlock(&driver->diagchar_mutex);
+				return success;
+			}
+		}
+		kfree(head_params);
+		mutex_unlock(&driver->diagchar_mutex);
+	} else {
+		kfree(head_params);
+		mutex_unlock(&driver->diagchar_mutex);
+		pr_err("Max size reached, Pkt Registration failed for Process %d",
+					current->tgid);
+	}
+	success = 0;
+	return success;
+}
+
+#ifdef CONFIG_DIAGFWD_BRIDGE_CODE
+void diag_cmp_logging_modes_diagfwd_bridge(int old_mode, int new_mode)
+{
+	if (old_mode == MEMORY_DEVICE_MODE && new_mode
+					== NO_LOGGING_MODE) {
+		diagfwd_disconnect_bridge(0);
+		diag_clear_hsic_tbl();
+	} else if (old_mode == NO_LOGGING_MODE && new_mode
+					== MEMORY_DEVICE_MODE) {
+		diagfwd_connect_bridge(0);
+	} else if (old_mode == USB_MODE && new_mode
+					 == NO_LOGGING_MODE) {
+		diagfwd_disconnect_bridge(0);
+	} else if (old_mode == NO_LOGGING_MODE && new_mode
+					== USB_MODE) {
+		diagfwd_connect_bridge(0);
+	} else if (old_mode == USB_MODE && new_mode
+					== MEMORY_DEVICE_MODE) {
+		diagfwd_cancel_hsic();
+		diagfwd_connect_bridge(0);
+	} else if (old_mode == MEMORY_DEVICE_MODE && new_mode
+					== USB_MODE) {
+		diag_clear_hsic_tbl();
+		diagfwd_cancel_hsic();
+		diagfwd_connect_bridge(0);
+	}
+}
+#else
+void diag_cmp_logging_modes_diagfwd_bridge(int old_mode, int new_mode)
+{
+
+}
+#endif
+
+#ifdef CONFIG_DIAG_SDIO_PIPE
+void diag_cmp_logging_modes_sdio_pipe(int old_mode, int new_mode)
+{
+	if (old_mode == MEMORY_DEVICE_MODE && new_mode
+					== NO_LOGGING_MODE) {
+		mutex_lock(&driver->diagchar_mutex);
+		driver->in_busy_sdio = 1;
+		mutex_unlock(&driver->diagchar_mutex);
+	} else if (old_mode == NO_LOGGING_MODE && new_mode
+					== MEMORY_DEVICE_MODE) {
+		mutex_lock(&driver->diagchar_mutex);
+		driver->in_busy_sdio = 0;
+		mutex_unlock(&driver->diagchar_mutex);
+		/* Poll SDIO channel to check for data */
+		if (driver->sdio_ch)
+			queue_work(driver->diag_sdio_wq,
+				&(driver->diag_read_sdio_work));
+	} else if (old_mode == USB_MODE && new_mode
+					== MEMORY_DEVICE_MODE) {
+		mutex_lock(&driver->diagchar_mutex);
+		driver->in_busy_sdio = 0;
+		mutex_unlock(&driver->diagchar_mutex);
+		/* Poll SDIO channel to check for data */
+		if (driver->sdio_ch)
+			queue_work(driver->diag_sdio_wq,
+				&(driver->diag_read_sdio_work));
+	}
+}
+#else
+void diag_cmp_logging_modes_sdio_pipe(int old_mode, int new_mode)
+{
+
+}
+#endif
+
+int diag_switch_logging(unsigned long ioarg)
+{
+	int i, temp, success = -EINVAL, status;
+	mutex_lock(&driver->diagchar_mutex);
+	temp = driver->logging_mode;
+	driver->logging_mode = (int)ioarg;
+	if (temp == driver->logging_mode) {
+		mutex_unlock(&driver->diagchar_mutex);
+		pr_err("diag: forbidden logging change requested\n");
+		return 0;
+	}
+
+	if (driver->logging_mode == MEMORY_DEVICE_MODE) {
+		diag_clear_hsic_tbl();
+		driver->mask_check = 1;
+		if (driver->socket_process) {
+			/*
+			 * Notify the socket logging process that we
+			 * are switching to MEMORY_DEVICE_MODE
+			 */
+			status = send_sig(SIGCONT,
+				 driver->socket_process, 0);
+			if (status) {
+				pr_err("diag: %s, Error notifying ",
+					__func__);
+				pr_err("socket process, status: %d\n",
+					status);
+			}
+		}
+	} else if (driver->logging_mode == SOCKET_MODE) {
+		driver->socket_process = current;
+	} else if (driver->logging_mode == CALLBACK_MODE) {
+		driver->callback_process = current;
+	}
+
+	if (driver->logging_mode == UART_MODE ||
+				driver->logging_mode == SOCKET_MODE ||
+				driver->logging_mode == CALLBACK_MODE) {
+		diag_clear_hsic_tbl();
+		driver->mask_check = 0;
+		driver->logging_mode = MEMORY_DEVICE_MODE;
+	}
+
+	driver->logging_process_id = current->tgid;
+	mutex_unlock(&driver->diagchar_mutex);
+
+	if (temp == MEMORY_DEVICE_MODE && driver->logging_mode
+						== NO_LOGGING_MODE) {
+		for (i = 0; i < NUM_SMD_DATA_CHANNELS; i++) {
+			driver->smd_data[i].in_busy_1 = 0;
+			driver->smd_data[i].in_busy_2 = 0;
+		}
+		diag_cmp_logging_modes_sdio_pipe(temp, driver->logging_mode);
+		diag_cmp_logging_modes_diagfwd_bridge(temp,
+							driver->logging_mode);
+	} else if (temp == NO_LOGGING_MODE && driver->logging_mode
+						== MEMORY_DEVICE_MODE) {
+		for (i = 0; i < NUM_SMD_DATA_CHANNELS; i++) {
+			driver->smd_data[i].in_busy_1 = 0;
+			driver->smd_data[i].in_busy_2 = 0;
+			/* Poll SMD channels to check for data*/
+			if (driver->smd_data[i].ch)
+				queue_work(driver->diag_wq,
+					&(driver->smd_data[i].
+						diag_read_smd_work));
+		}
+		diag_cmp_logging_modes_sdio_pipe(temp,
+						driver->logging_mode);
+		diag_cmp_logging_modes_diagfwd_bridge(temp,
+						driver->logging_mode);
+	} else if (temp == USB_MODE && driver->logging_mode
+						 == NO_LOGGING_MODE) {
+		diagfwd_disconnect();
+		diag_cmp_logging_modes_diagfwd_bridge(temp,
+						driver->logging_mode);
+	} else if (temp == NO_LOGGING_MODE && driver->logging_mode
+							== USB_MODE) {
+		diagfwd_connect();
+		diag_cmp_logging_modes_diagfwd_bridge(temp,
+						driver->logging_mode);
+	} else if (temp == USB_MODE && driver->logging_mode
+						== MEMORY_DEVICE_MODE) {
+		diagfwd_disconnect();
+		for (i = 0; i < NUM_SMD_DATA_CHANNELS; i++) {
+			driver->smd_data[i].in_busy_1 = 0;
+			driver->smd_data[i].in_busy_2 = 0;
+			/* Poll SMD channels to check for data*/
+			if (driver->smd_data[i].ch)
+				queue_work(driver->diag_wq,
+					&(driver->smd_data[i].
+						diag_read_smd_work));
+		}
+		diag_cmp_logging_modes_sdio_pipe(temp, driver->logging_mode);
+		diag_cmp_logging_modes_diagfwd_bridge(temp,
+						driver->logging_mode);
+	} else if (temp == MEMORY_DEVICE_MODE &&
+			 driver->logging_mode == USB_MODE) {
+		diagfwd_connect();
+		diag_cmp_logging_modes_diagfwd_bridge(temp,
+						driver->logging_mode);
+	}
+	success = 1;
+	return success;
+}
+
+long diagchar_ioctl(struct file *filp,
+			   unsigned int iocmd, unsigned long ioarg)
+{
+	int i, result = -EINVAL, interim_size = 0, client_id = 0;
+	uint16_t support_list = 0, interim_rsp_id, remote_dev;
+	struct diag_dci_client_tbl *dci_params;
+	struct diag_dci_health_stats stats;
+	struct diag_log_event_stats le_stats;
+	struct diagpkt_delay_params delay_params;
+
+	switch (iocmd) {
+	case DIAG_IOCTL_COMMAND_REG:
+		result = diag_command_reg(ioarg);
+		break;
+	case DIAG_IOCTL_GET_DELAYED_RSP_ID:
 		if (copy_from_user(&delay_params, (void *)ioarg,
-					   sizeof(struct diagpkt_delay_params)))
+					sizeof(struct diagpkt_delay_params)))
 			return -EFAULT;
 		if ((delay_params.rsp_ptr) &&
 		 (delay_params.size == sizeof(delayed_rsp_id)) &&
@@ -672,9 +902,10 @@
 			if (copy_to_user((void *)delay_params.num_bytes_ptr,
 						 &interim_size, sizeof(int)))
 				return -EFAULT;
-			success = 0;
+			result = 0;
 		}
-	} else if (iocmd == DIAG_IOCTL_DCI_REG) {
+		break;
+	case DIAG_IOCTL_DCI_REG:
 		if (driver->dci_state == DIAG_DCI_NO_REG)
 			return DIAG_DCI_NO_REG;
 		if (driver->num_dci_client >= MAX_DCI_CLIENTS)
@@ -723,49 +954,47 @@
 		}
 		kfree(dci_params);
 		mutex_unlock(&driver->dci_mutex);
-		return driver->dci_client_id;
-	} else if (iocmd == DIAG_IOCTL_DCI_DEINIT) {
-		success = -1;
-		/*
-		* Clear log/event masks and send updated
-		* masks to peripherals
-		*/
+		result = driver->dci_client_id;
+		break;
+	case DIAG_IOCTL_DCI_DEINIT:
+		result = -EIO;
+		/* Delete this process from DCI table */
 		mutex_lock(&driver->dci_mutex);
-		index = diag_dci_find_client_index(current->tgid);
-		if (index != DCI_CLIENT_INDEX_INVALID) {
+		i = diag_dci_find_client_index(current->tgid);
+		if (i == DCI_CLIENT_INDEX_INVALID) {
+			result = DIAG_DCI_NOT_SUPPORTED;
+		} else {
 			/* clear respective cumulative log masks */
-			clear_client_dci_cumulative_log_mask(index);
+			clear_client_dci_cumulative_log_mask(i);
 			/* send updated log mask to peripherals */
-			success =
+			result =
 			diag_send_dci_log_mask(driver->smd_cntl[MODEM_DATA].ch);
-			if (success != DIAG_DCI_NO_ERROR) {
+			if (result != DIAG_DCI_NO_ERROR) {
 				mutex_unlock(&driver->dci_mutex);
-				return success;
+				return result;
 			}
 			/* clear respective cumulative event masks */
-			clear_client_dci_cumulative_event_mask(index);
+			clear_client_dci_cumulative_event_mask(i);
 			/* send updated event mask to peripherals */
-			success =
+			result =
 			diag_send_dci_event_mask(
 				driver->smd_cntl[MODEM_DATA].ch);
-			if (success != DIAG_DCI_NO_ERROR) {
+			if (result != DIAG_DCI_NO_ERROR) {
 				mutex_unlock(&driver->dci_mutex);
-				return success;
+				return result;
 			}
-		}
-		/* Delete this process from DCI table */
-		for (i = 0; i < dci_max_reg; i++)
-			if (driver->req_tracking_tbl[i].pid == current->tgid)
-				driver->req_tracking_tbl[i].pid = 0;
-		if (index != DCI_CLIENT_INDEX_INVALID) {
-			driver->dci_client_tbl[index].client = NULL;
-			success = index;
-		}
-		if (success >= 0)
+			result = i;
+			/* Delete this process from DCI table */
+			for (i = 0; i < dci_max_reg; i++)
+				if (driver->req_tracking_tbl[i].pid ==
+					 current->tgid)
+					driver->req_tracking_tbl[i].pid = 0;
+			driver->dci_client_tbl[result].client = NULL;
 			driver->num_dci_client--;
+		}
 		mutex_unlock(&driver->dci_mutex);
-		return success;
-	} else if (iocmd == DIAG_IOCTL_DCI_SUPPORT) {
+		break;
+	case DIAG_IOCTL_DCI_SUPPORT:
 		for (i = 0; i < NUM_SMD_DCI_CHANNELS; i++) {
 			if (driver->smd_dci[i].ch)
 				support_list |=
@@ -774,35 +1003,69 @@
 		if (copy_to_user((void *)ioarg, &support_list,
 							 sizeof(uint16_t)))
 			return -EFAULT;
-		return DIAG_DCI_NO_ERROR;
-	} else if (iocmd == DIAG_IOCTL_DCI_HEALTH_STATS) {
+		result = DIAG_DCI_NO_ERROR;
+		break;
+	case DIAG_IOCTL_DCI_HEALTH_STATS:
 		if (copy_from_user(&stats, (void *)ioarg,
 				 sizeof(struct diag_dci_health_stats)))
 			return -EFAULT;
-		for (i = 0; i < MAX_DCI_CLIENTS; i++) {
+		mutex_lock(&dci_health_mutex);
+		i = diag_dci_find_client_index(current->tgid);
+		if (i != DCI_CLIENT_INDEX_INVALID) {
 			dci_params = &(driver->dci_client_tbl[i]);
-			if (dci_params->client &&
-				dci_params->client->tgid == current->tgid) {
-				stats.dropped_logs = dci_params->dropped_logs;
-				stats.dropped_events =
-						 dci_params->dropped_events;
-				stats.received_logs = dci_params->received_logs;
-				stats.received_events =
-						 dci_params->received_events;
-				if (stats.reset_status) {
-					dci_params->dropped_logs = 0;
-					dci_params->dropped_events = 0;
-					dci_params->received_logs = 0;
-					dci_params->received_events = 0;
-				}
-				break;
+			stats.dropped_logs = dci_params->dropped_logs;
+			stats.dropped_events =
+					dci_params->dropped_events;
+			stats.received_logs =
+					dci_params->received_logs;
+			stats.received_events =
+					dci_params->received_events;
+			if (stats.reset_status) {
+				dci_params->dropped_logs = 0;
+				dci_params->dropped_events = 0;
+				dci_params->received_logs = 0;
+				dci_params->received_events = 0;
 			}
 		}
+		mutex_unlock(&dci_health_mutex);
 		if (copy_to_user((void *)ioarg, &stats,
 				   sizeof(struct diag_dci_health_stats)))
 			return -EFAULT;
-		return DIAG_DCI_NO_ERROR;
-	} else if (iocmd == DIAG_IOCTL_LSM_DEINIT) {
+		result = DIAG_DCI_NO_ERROR;
+		break;
+	case DIAG_IOCTL_DCI_LOG_STATUS:
+		if (copy_from_user(&le_stats, (void *)ioarg,
+				sizeof(struct diag_log_event_stats)))
+			return -EFAULT;
+		le_stats.is_set = diag_dci_query_log_mask(le_stats.code);
+		if (copy_to_user((void *)ioarg, &le_stats,
+				sizeof(struct diag_log_event_stats)))
+			return -EFAULT;
+		result = DIAG_DCI_NO_ERROR;
+		break;
+	case DIAG_IOCTL_DCI_EVENT_STATUS:
+		if (copy_from_user(&le_stats, (void *)ioarg,
+					sizeof(struct diag_log_event_stats)))
+			return -EFAULT;
+		le_stats.is_set = diag_dci_query_event_mask(le_stats.code);
+		if (copy_to_user((void *)ioarg, &le_stats,
+				sizeof(struct diag_log_event_stats)))
+			return -EFAULT;
+		result = DIAG_DCI_NO_ERROR;
+		break;
+	case DIAG_IOCTL_DCI_CLEAR_LOGS:
+		if (copy_from_user((void *)&client_id, (void *)ioarg,
+				sizeof(int)))
+			return -EFAULT;
+		result = diag_dci_clear_log_mask();
+		break;
+	case DIAG_IOCTL_DCI_CLEAR_EVENTS:
+		if (copy_from_user(&client_id, (void *)ioarg,
+				sizeof(int)))
+			return -EFAULT;
+		result = diag_dci_clear_event_mask();
+		break;
+	case DIAG_IOCTL_LSM_DEINIT:
 		for (i = 0; i < driver->num_clients; i++)
 			if (driver->client_map[i].pid == current->tgid)
 				break;
@@ -810,138 +1073,20 @@
 			return -EINVAL;
 		driver->data_ready[i] |= DEINIT_TYPE;
 		wake_up_interruptible(&driver->wait_q);
-		success = 1;
-	} else if (iocmd == DIAG_IOCTL_SWITCH_LOGGING) {
-		mutex_lock(&driver->diagchar_mutex);
-		temp = driver->logging_mode;
-		driver->logging_mode = (int)ioarg;
-		if (temp == driver->logging_mode) {
-			mutex_unlock(&driver->diagchar_mutex);
-			pr_alert("diag: forbidden logging change requested\n");
-			return 0;
-		}
-		if (driver->logging_mode == MEMORY_DEVICE_MODE) {
-			diag_clear_hsic_tbl();
-			driver->mask_check = 1;
-			if (driver->socket_process) {
-				/*
-				 * Notify the socket logging process that we
-				 * are switching to MEMORY_DEVICE_MODE
-				 */
-				status = send_sig(SIGCONT,
-					 driver->socket_process, 0);
-				if (status) {
-					pr_err("diag: %s, Error notifying ",
-						__func__);
-					pr_err("socket process, status: %d\n",
-						status);
-				}
-			}
-		}
-		if (driver->logging_mode == SOCKET_MODE)
-			driver->socket_process = current;
-		if (driver->logging_mode == CALLBACK_MODE)
-			driver->callback_process = current;
-		if (driver->logging_mode == UART_MODE ||
-			driver->logging_mode == SOCKET_MODE ||
-			driver->logging_mode == CALLBACK_MODE) {
-			diag_clear_hsic_tbl();
-			driver->mask_check = 0;
-			driver->logging_mode = MEMORY_DEVICE_MODE;
-		}
-		driver->logging_process_id = current->tgid;
-		mutex_unlock(&driver->diagchar_mutex);
-		if (temp == MEMORY_DEVICE_MODE && driver->logging_mode
-							== NO_LOGGING_MODE) {
-			for (i = 0; i < NUM_SMD_DATA_CHANNELS; i++) {
-				driver->smd_data[i].in_busy_1 = 0;
-				driver->smd_data[i].in_busy_2 = 0;
-			}
-#ifdef CONFIG_DIAG_SDIO_PIPE
-			driver->in_busy_sdio = 1;
-#endif
-#ifdef CONFIG_DIAGFWD_BRIDGE_CODE
-			diagfwd_disconnect_bridge(0);
-			diag_clear_hsic_tbl();
-#endif
-		} else if (temp == NO_LOGGING_MODE && driver->logging_mode
-							== MEMORY_DEVICE_MODE) {
-			for (i = 0; i < NUM_SMD_DATA_CHANNELS; i++) {
-				driver->smd_data[i].in_busy_1 = 0;
-				driver->smd_data[i].in_busy_2 = 0;
-				/* Poll SMD channels to check for data*/
-				if (driver->smd_data[i].ch)
-					queue_work(driver->diag_wq,
-						&(driver->smd_data[i].
-							diag_read_smd_work));
-			}
-#ifdef CONFIG_DIAG_SDIO_PIPE
-			driver->in_busy_sdio = 0;
-			/* Poll SDIO channel to check for data */
-			if (driver->sdio_ch)
-				queue_work(driver->diag_sdio_wq,
-					&(driver->diag_read_sdio_work));
-#endif
-#ifdef CONFIG_DIAGFWD_BRIDGE_CODE
-			diagfwd_connect_bridge(0);
-#endif
-		}
-#ifdef CONFIG_DIAG_OVER_USB
-		else if (temp == USB_MODE && driver->logging_mode
-							 == NO_LOGGING_MODE) {
-			diagfwd_disconnect();
-#ifdef CONFIG_DIAGFWD_BRIDGE_CODE
-			diagfwd_disconnect_bridge(0);
-#endif
-		} else if (temp == NO_LOGGING_MODE && driver->logging_mode
-								== USB_MODE) {
-			diagfwd_connect();
-#ifdef CONFIG_DIAGFWD_BRIDGE_CODE
-			diagfwd_connect_bridge(0);
-#endif
-		} else if (temp == USB_MODE && driver->logging_mode
-							== MEMORY_DEVICE_MODE) {
-			diagfwd_disconnect();
-			for (i = 0; i < NUM_SMD_DATA_CHANNELS; i++) {
-				driver->smd_data[i].in_busy_1 = 0;
-				driver->smd_data[i].in_busy_2 = 0;
-				/* Poll SMD channels to check for data*/
-				if (driver->smd_data[i].ch)
-					queue_work(driver->diag_wq,
-						&(driver->smd_data[i].
-							diag_read_smd_work));
-			}
-#ifdef CONFIG_DIAG_SDIO_PIPE
-			driver->in_busy_sdio = 0;
-			/* Poll SDIO channel to check for data */
-			if (driver->sdio_ch)
-				queue_work(driver->diag_sdio_wq,
-					&(driver->diag_read_sdio_work));
-#endif
-#ifdef CONFIG_DIAGFWD_BRIDGE_CODE
-			diagfwd_cancel_hsic();
-			diagfwd_connect_bridge(0);
-#endif
-		} else if (temp == MEMORY_DEVICE_MODE &&
-				 driver->logging_mode == USB_MODE) {
-			diagfwd_connect();
-#ifdef CONFIG_DIAGFWD_BRIDGE_CODE
-			diag_clear_hsic_tbl();
-			diagfwd_cancel_hsic();
-			diagfwd_connect_bridge(0);
-#endif
-		}
-#endif /* DIAG over USB */
-		success = 1;
-	} else if (iocmd == DIAG_IOCTL_REMOTE_DEV) {
-		uint16_t remote_dev = diag_get_remote_device_mask();
+		result = 1;
+		break;
+	case DIAG_IOCTL_SWITCH_LOGGING:
+		result = diag_switch_logging(ioarg);
+		break;
+	case DIAG_IOCTL_REMOTE_DEV:
+		remote_dev = diag_get_remote_device_mask();
 		if (copy_to_user((void *)ioarg, &remote_dev, sizeof(uint16_t)))
-			success = -EFAULT;
+			result = -EFAULT;
 		else
-			success = 1;
+			result = 1;
+		break;
 	}
-
-	return success;
+	return result;
 }
 
 static int diagchar_read(struct file *file, char __user *buf, size_t count,
@@ -1068,7 +1213,7 @@
 		/* copy number of data fields */
 		COPY_USER_SPACE_OR_EXIT(buf+4, num_data, 4);
 		ret -= 4;
-		driver->data_ready[index] ^= USER_SPACE_DATA_TYPE;
+		diag_update_data_ready(index);
 		for (i = 0; i < NUM_SMD_DATA_CHANNELS; i++) {
 			if (driver->smd_data[i].ch)
 				queue_work(driver->diag_wq,
@@ -1654,6 +1799,7 @@
 		diag_masks_init();
 		diagfwd_init();
 #ifdef CONFIG_DIAGFWD_BRIDGE_CODE
+		spin_lock_init(&driver->hsic_ready_spinlock);
 		diagfwd_bridge_init(HSIC);
 		diagfwd_bridge_init(HSIC_2);
 		/* register HSIC device */
diff --git a/drivers/char/diag/diagfwd.c b/drivers/char/diag/diagfwd.c
index 2aca8cf..6a14143 100644
--- a/drivers/char/diag/diagfwd.c
+++ b/drivers/char/diag/diagfwd.c
@@ -351,12 +351,32 @@
 	diag_smd_send_req(smd_info);
 }
 
+#ifdef CONFIG_DIAGFWD_BRIDGE_CODE
+static void diag_mem_dev_mode_ready_update(int index, int hsic_updated)
+{
+	if (hsic_updated) {
+		unsigned long flags;
+		spin_lock_irqsave(&driver->hsic_ready_spinlock, flags);
+		driver->data_ready[index] |= USER_SPACE_DATA_TYPE;
+		spin_unlock_irqrestore(&driver->hsic_ready_spinlock, flags);
+	} else {
+		driver->data_ready[index] |= USER_SPACE_DATA_TYPE;
+	}
+}
+#else
+static void diag_mem_dev_mode_ready_update(int index, int hsic_updated)
+{
+	(void) hsic_updated;
+	driver->data_ready[index] |= USER_SPACE_DATA_TYPE;
+}
+#endif
 int diag_device_write(void *buf, int data_type, struct diag_request *write_ptr)
 {
 	int i, err = 0, index;
 	index = 0;
 
 	if (driver->logging_mode == MEMORY_DEVICE_MODE) {
+		int hsic_updated = 0;
 		if (data_type == APPS_DATA) {
 			for (i = 0; i < driver->poolsize_write_struct; i++)
 				if (driver->buf_tbl[i].length == 0) {
@@ -377,6 +397,7 @@
 		else if (data_type == HSIC_DATA || data_type == HSIC_2_DATA) {
 			unsigned long flags;
 			int foundIndex = -1;
+			hsic_updated = 1;
 			index = data_type - HSIC_DATA;
 			spin_lock_irqsave(&diag_hsic[index].hsic_spinlock,
 									flags);
@@ -409,7 +430,7 @@
 						 driver->logging_process_id)
 				break;
 		if (i < driver->num_clients) {
-			driver->data_ready[i] |= USER_SPACE_DATA_TYPE;
+			diag_mem_dev_mode_ready_update(i, hsic_updated);
 			pr_debug("diag: wake up logging process\n");
 			wake_up_interruptible(&driver->wait_q);
 		} else
diff --git a/drivers/char/diag/diagfwd.h b/drivers/char/diag/diagfwd.h
index 5a67b0c..afbe4be 100644
--- a/drivers/char/diag/diagfwd.h
+++ b/drivers/char/diag/diagfwd.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2008-2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2008-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
@@ -39,6 +39,10 @@
 int diag_smd_constructor(struct diag_smd_info *smd_info, int peripheral,
 			 int type);
 void diag_smd_destructor(struct diag_smd_info *smd_info);
+int diag_switch_logging(unsigned long);
+int diag_command_reg(unsigned long);
+void diag_cmp_logging_modes_sdio_pipe(int old_mode, int new_mode);
+void diag_cmp_logging_modes_diagfwd_bridge(int old_mode, int new_mode);
 /* State for diag forwarding */
 #ifdef CONFIG_DIAG_OVER_USB
 int diagfwd_connect(void);
diff --git a/drivers/char/misc.c b/drivers/char/misc.c
index 522136d..2cfafc3 100644
--- a/drivers/char/misc.c
+++ b/drivers/char/misc.c
@@ -59,7 +59,7 @@
 /*
  * Assigned numbers, used for dynamic minors
  */
-#define DYNAMIC_MINORS 64 /* like dynamic majors */
+#define DYNAMIC_MINORS 96 /* like dynamic majors */
 static DECLARE_BITMAP(misc_minors, DYNAMIC_MINORS);
 
 #ifdef CONFIG_PROC_FS
diff --git a/drivers/coresight/coresight-etm.c b/drivers/coresight/coresight-etm.c
index 2ae54ea..1033233 100644
--- a/drivers/coresight/coresight-etm.c
+++ b/drivers/coresight/coresight-etm.c
@@ -265,6 +265,16 @@
 
 static struct etm_drvdata *etmdrvdata[NR_CPUS];
 
+static bool etm_os_lock_present(struct etm_drvdata *drvdata)
+{
+	uint32_t etmoslsr;
+
+	etmoslsr = etm_readl(drvdata, ETMOSLSR);
+	if (!BVAL(etmoslsr, 0) && !BVAL(etmoslsr, 3))
+		return false;
+	return true;
+}
+
 /*
  * Memory mapped writes to clear os lock are not supported on Krait v1, v2
  * and OS lock must be unlocked before any memory mapped access, otherwise
@@ -272,10 +282,17 @@
  */
 static void etm_os_unlock(void *info)
 {
+	struct etm_drvdata *drvdata = (struct etm_drvdata *) info;
+
+	ETM_UNLOCK(drvdata);
 	if (cpu_is_krait()) {
 		etm_writel_cp14(0x0, ETMOSLAR);
 		isb();
+	} else if (etm_os_lock_present(drvdata)) {
+		etm_writel(drvdata, 0x0, ETMOSLAR);
+		mb();
 	}
+	ETM_LOCK(drvdata);
 }
 
 /*
@@ -2104,7 +2121,7 @@
 	get_online_cpus();
 	etmdrvdata[drvdata->cpu] = drvdata;
 
-	if (!smp_call_function_single(drvdata->cpu, etm_os_unlock, NULL, 1))
+	if (!smp_call_function_single(drvdata->cpu, etm_os_unlock, drvdata, 1))
 		drvdata->os_unlock = true;
 	/*
 	 * Use CPU0 to populate read-only configuration data for ETM0. For
diff --git a/drivers/crypto/msm/qce50.c b/drivers/crypto/msm/qce50.c
index 1facf24..9d8e825 100644
--- a/drivers/crypto/msm/qce50.c
+++ b/drivers/crypto/msm/qce50.c
@@ -353,6 +353,9 @@
 	pce = cmdlistinfo->auth_seg_size;
 	pce->data = sreq->size;
 
+	pce = cmdlistinfo->encr_seg_cfg;
+	pce->data = 0;
+
 	/* write auth seg size start*/
 	pce = cmdlistinfo->auth_seg_start;
 	pce->data = 0;
@@ -521,8 +524,12 @@
 			pce->data = totallen_in - creq->authsize;
 		pce = cmdlistinfo->auth_seg_start;
 		pce->data = 0;
+	} else {
+		if (creq->op != QCE_REQ_AEAD) {
+			pce = cmdlistinfo->auth_seg_cfg;
+			pce->data = 0;
+		}
 	}
-
 	switch (creq->mode) {
 	case QCE_MODE_ECB:
 		encr_cfg |= (CRYPTO_ENCR_MODE_ECB << CRYPTO_ENCR_MODE);
@@ -1289,7 +1296,7 @@
 					CRYPTO_RESULT_DUMP_SIZE,
 					  &pce_dev->ce_sps.out_transfer);
 		_qce_set_flag(&pce_dev->ce_sps.out_transfer,
-				SPS_IOVEC_FLAG_EOT|SPS_IOVEC_FLAG_INT);
+				SPS_IOVEC_FLAG_INT);
 		rc = sps_transfer(pce_dev->ce_sps.producer.pipe,
 					  &pce_dev->ce_sps.out_transfer);
 		if (rc) {
@@ -1364,7 +1371,7 @@
 					CRYPTO_RESULT_DUMP_SIZE,
 					  &pce_dev->ce_sps.out_transfer);
 		_qce_set_flag(&pce_dev->ce_sps.out_transfer,
-				SPS_IOVEC_FLAG_EOT|SPS_IOVEC_FLAG_INT);
+				SPS_IOVEC_FLAG_INT);
 		rc = sps_transfer(pce_dev->ce_sps.producer.pipe,
 					  &pce_dev->ce_sps.out_transfer);
 		if (rc) {
diff --git a/drivers/devfreq/governor_performance.c b/drivers/devfreq/governor_performance.c
index 574a06b..af75ddd 100644
--- a/drivers/devfreq/governor_performance.c
+++ b/drivers/devfreq/governor_performance.c
@@ -10,6 +10,7 @@
  */
 
 #include <linux/devfreq.h>
+#include "governor.h"
 
 static int devfreq_performance_func(struct devfreq *df,
 				    unsigned long *freq)
@@ -25,8 +26,14 @@
 	return 0;
 }
 
+static int performance_init(struct devfreq *devfreq)
+{
+	return update_devfreq(devfreq);
+}
+
 const struct devfreq_governor devfreq_performance = {
 	.name = "performance",
+	.init = performance_init,
 	.get_target_freq = devfreq_performance_func,
 	.no_central_polling = true,
 };
diff --git a/drivers/devfreq/governor_powersave.c b/drivers/devfreq/governor_powersave.c
index d742d4a..fec0cdb 100644
--- a/drivers/devfreq/governor_powersave.c
+++ b/drivers/devfreq/governor_powersave.c
@@ -10,6 +10,7 @@
  */
 
 #include <linux/devfreq.h>
+#include "governor.h"
 
 static int devfreq_powersave_func(struct devfreq *df,
 				  unsigned long *freq)
@@ -22,8 +23,14 @@
 	return 0;
 }
 
+static int powersave_init(struct devfreq *devfreq)
+{
+	return update_devfreq(devfreq);
+}
+
 const struct devfreq_governor devfreq_powersave = {
 	.name = "powersave",
+	.init = powersave_init,
 	.get_target_freq = devfreq_powersave_func,
 	.no_central_polling = true,
 };
diff --git a/drivers/gpu/ion/ion.c b/drivers/gpu/ion/ion.c
index 0904f9fe..9ab2343 100644
--- a/drivers/gpu/ion/ion.c
+++ b/drivers/gpu/ion/ion.c
@@ -914,7 +914,7 @@
 		if (type == ION_HEAP_TYPE_SYSTEM_CONTIG ||
 			type == ION_HEAP_TYPE_CARVEOUT ||
 			type == (enum ion_heap_type) ION_HEAP_TYPE_CP)
-			seq_printf(s, " : %12lx", handle->buffer->priv_phys);
+			seq_printf(s, " : %12pa", &handle->buffer->priv_phys);
 		else
 			seq_printf(s, " : %12s", "N/A");
 
@@ -1988,8 +1988,8 @@
 		ret = memblock_reserve(data->heaps[i].base,
 				       data->heaps[i].size);
 		if (ret)
-			pr_err("memblock reserve of %x@%lx failed\n",
+			pr_err("memblock reserve of %x@%pa failed\n",
 			       data->heaps[i].size,
-			       data->heaps[i].base);
+			       &data->heaps[i].base);
 	}
 }
diff --git a/drivers/gpu/ion/ion_carveout_heap.c b/drivers/gpu/ion/ion_carveout_heap.c
index 3e55a57..b51fa6a 100644
--- a/drivers/gpu/ion/ion_carveout_heap.c
+++ b/drivers/gpu/ion/ion_carveout_heap.c
@@ -297,8 +297,11 @@
 			const char *client_name = "(null)";
 
 			if (last_end < data->addr) {
-				seq_printf(s, "%16.s %14lx %14lx %14lu (%lx)\n",
-					   "FREE", last_end, data->addr-1,
+				phys_addr_t da;
+
+				da = data->addr-1;
+				seq_printf(s, "%16.s %14pa %14pa %14lu (%lx)\n",
+					   "FREE", &last_end, &da,
 					   data->addr-last_end,
 					   data->addr-last_end);
 			}
@@ -306,9 +309,9 @@
 			if (data->client_name)
 				client_name = data->client_name;
 
-			seq_printf(s, "%16.s %14lx %14lx %14lu (%lx)\n",
-				   client_name, data->addr,
-				   data->addr_end,
+			seq_printf(s, "%16.s %14pa %14pa %14lu (%lx)\n",
+				   client_name, &data->addr,
+				   &data->addr_end,
 				   data->size, data->size);
 			last_end = data->addr_end+1;
 		}
diff --git a/drivers/gpu/ion/ion_cma_heap.c b/drivers/gpu/ion/ion_cma_heap.c
index 4f5ac75..8063138 100644
--- a/drivers/gpu/ion/ion_cma_heap.c
+++ b/drivers/gpu/ion/ion_cma_heap.c
@@ -325,9 +325,9 @@
 			if (data->client_name)
 				client_name = data->client_name;
 
-			seq_printf(s, "%16.s %14lx %14lx %14lu (%lx)\n",
-				   client_name, data->addr,
-				   data->addr_end,
+			seq_printf(s, "%16.s %14pa %14pa %14lu (%lx)\n",
+				   client_name, &data->addr,
+				   &data->addr_end,
 				   data->size, data->size);
 		}
 	}
diff --git a/drivers/gpu/ion/ion_cma_secure_heap.c b/drivers/gpu/ion/ion_cma_secure_heap.c
index 2c0e5ae..496e5b4 100644
--- a/drivers/gpu/ion/ion_cma_secure_heap.c
+++ b/drivers/gpu/ion/ion_cma_secure_heap.c
@@ -359,9 +359,9 @@
 			if (data->client_name)
 				client_name = data->client_name;
 
-			seq_printf(s, "%16.s %14lx %14lx %14lu (%lx)\n",
-				   client_name, data->addr,
-				   data->addr_end,
+			seq_printf(s, "%16.s %14pa %14pa %14lu (%lx)\n",
+				   client_name, &data->addr,
+				   &data->addr_end,
 				   data->size, data->size);
 		}
 	}
diff --git a/drivers/gpu/ion/ion_cp_heap.c b/drivers/gpu/ion/ion_cp_heap.c
index 56ccc8f..a7473e2 100644
--- a/drivers/gpu/ion/ion_cp_heap.c
+++ b/drivers/gpu/ion/ion_cp_heap.c
@@ -256,8 +256,8 @@
 			atomic_dec(&cp_heap->protect_cnt);
 		} else {
 			cp_heap->heap_protected = HEAP_PROTECTED;
-			pr_debug("Protected heap %s @ 0x%lx\n",
-				heap->name, cp_heap->base);
+			pr_debug("Protected heap %s @ 0x%pa\n",
+				heap->name, &cp_heap->base);
 		}
 	}
 out:
@@ -804,8 +804,11 @@
 			const char *client_name = "(null)";
 
 			if (last_end < data->addr) {
-				seq_printf(s, "%16.s %14lx %14lx %14lu (%lx)\n",
-					   "FREE", last_end, data->addr-1,
+				phys_addr_t da;
+
+				da = data->addr-1;
+				seq_printf(s, "%16.s %14pa %14pa %14lu (%lx)\n",
+					   "FREE", &last_end, &da,
 					   data->addr-last_end,
 					   data->addr-last_end);
 			}
@@ -813,9 +816,9 @@
 			if (data->client_name)
 				client_name = data->client_name;
 
-			seq_printf(s, "%16.s %14lx %14lx %14lu (%lx)\n",
-				   client_name, data->addr,
-				   data->addr_end,
+			seq_printf(s, "%16.s %14pa %14pa %14lu (%lx)\n",
+				   client_name, &data->addr,
+				   &data->addr_end,
 				   data->size, data->size);
 			last_end = data->addr_end+1;
 		}
diff --git a/drivers/gpu/ion/ion_heap.c b/drivers/gpu/ion/ion_heap.c
index ff2b8dd..46fefb5 100644
--- a/drivers/gpu/ion/ion_heap.c
+++ b/drivers/gpu/ion/ion_heap.c
@@ -56,9 +56,9 @@
 	}
 
 	if (IS_ERR_OR_NULL(heap)) {
-		pr_err("%s: error creating heap %s type %d base %lu size %u\n",
+		pr_err("%s: error creating heap %s type %d base %pa size %u\n",
 		       __func__, heap_data->name, heap_data->type,
-		       heap_data->base, heap_data->size);
+		       &heap_data->base, heap_data->size);
 		return ERR_PTR(-EINVAL);
 	}
 
diff --git a/drivers/gpu/ion/ion_priv.h b/drivers/gpu/ion/ion_priv.h
index 9d1e90e..2ab2ed6 100644
--- a/drivers/gpu/ion/ion_priv.h
+++ b/drivers/gpu/ion/ion_priv.h
@@ -189,8 +189,8 @@
  */
 struct mem_map_data {
 	struct rb_node node;
-	unsigned long addr;
-	unsigned long addr_end;
+	ion_phys_addr_t addr;
+	ion_phys_addr_t addr_end;
 	unsigned long size;
 	const char *client_name;
 };
diff --git a/drivers/gpu/ion/msm/msm_ion.c b/drivers/gpu/ion/msm/msm_ion.c
index 7840d87..bd27385 100644
--- a/drivers/gpu/ion/msm/msm_ion.c
+++ b/drivers/gpu/ion/msm/msm_ion.c
@@ -172,7 +172,7 @@
 }
 EXPORT_SYMBOL(msm_ion_do_cache_op);
 
-static unsigned long msm_ion_get_base(unsigned long size, int memory_type,
+static ion_phys_addr_t msm_ion_get_base(unsigned long size, int memory_type,
 				    unsigned int align)
 {
 	switch (memory_type) {
@@ -340,10 +340,10 @@
 static int is_heap_overlapping(const struct ion_platform_heap *heap1,
 				const struct ion_platform_heap *heap2)
 {
-	unsigned long heap1_base = heap1->base;
-	unsigned long heap2_base = heap2->base;
-	unsigned long heap1_end = heap1->base + heap1->size - 1;
-	unsigned long heap2_end = heap2->base + heap2->size - 1;
+	ion_phys_addr_t heap1_base = heap1->base;
+	ion_phys_addr_t heap2_base = heap2->base;
+	ion_phys_addr_t heap1_end = heap1->base + heap1->size - 1;
+	ion_phys_addr_t heap2_end = heap2->base + heap2->size - 1;
 
 	if (heap1_base == heap2_base)
 		return 1;
@@ -792,9 +792,9 @@
 			continue;
 		} else {
 			if (heap_data->size)
-				pr_info("ION heap %s created at %lx "
+				pr_info("ION heap %s created at %pa "
 					"with size %x\n", heap_data->name,
-							  heap_data->base,
+							  &heap_data->base,
 							  heap_data->size);
 			else
 				pr_info("ION heap %s created\n",
diff --git a/drivers/gpu/msm/kgsl.c b/drivers/gpu/msm/kgsl.c
index 6e1ecd1..e2869d4 100644
--- a/drivers/gpu/msm/kgsl.c
+++ b/drivers/gpu/msm/kgsl.c
@@ -2477,7 +2477,11 @@
 		mutex_unlock(&dev_priv->device->mutex);
 	}
 
-	if (ret == 0 && (cmd & IOC_OUT)) {
+	/*
+	 * Still copy back on failure, but assume function took
+	 * all necessary precautions sanitizing the return values.
+	 */
+	if (cmd & IOC_OUT) {
 		if (copy_to_user((void __user *) arg, uptr, _IOC_SIZE(cmd)))
 			ret = -EFAULT;
 	}
diff --git a/drivers/gpu/msm/kgsl.h b/drivers/gpu/msm/kgsl.h
index 70a704b..c568db5 100644
--- a/drivers/gpu/msm/kgsl.h
+++ b/drivers/gpu/msm/kgsl.h
@@ -158,7 +158,7 @@
 	void *hostptr; /* kernel virtual address */
 	unsigned long useraddr; /* userspace address */
 	unsigned int gpuaddr;
-	unsigned int physaddr;
+	phys_addr_t physaddr;
 	unsigned int size;
 	unsigned int priv; /* Internal flags and settings */
 	struct scatterlist *sg;
diff --git a/drivers/gpu/msm/kgsl_gpummu.c b/drivers/gpu/msm/kgsl_gpummu.c
index 8f28505..9a1a431 100644
--- a/drivers/gpu/msm/kgsl_gpummu.c
+++ b/drivers/gpu/msm/kgsl_gpummu.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011-2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2011-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -161,7 +161,7 @@
 }
 
 static void *
-_kgsl_ptpool_get_entry(struct kgsl_ptpool *pool, unsigned int *physaddr)
+_kgsl_ptpool_get_entry(struct kgsl_ptpool *pool, phys_addr_t *physaddr)
 {
 	struct kgsl_ptpool_chunk *chunk;
 
@@ -227,7 +227,7 @@
  */
 
 static void *kgsl_ptpool_alloc(struct kgsl_ptpool *pool,
-				unsigned int *physaddr)
+				phys_addr_t *physaddr)
 {
 	void *addr = NULL;
 	int ret;
diff --git a/drivers/gpu/msm/kgsl_gpummu.h b/drivers/gpu/msm/kgsl_gpummu.h
index 99e7d5f..1753aff 100644
--- a/drivers/gpu/msm/kgsl_gpummu.h
+++ b/drivers/gpu/msm/kgsl_gpummu.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011-2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2011-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -57,7 +57,7 @@
 	int dynamic;
 
 	void *data;
-	unsigned int phys;
+	phys_addr_t phys;
 
 	unsigned long *bitmap;
 	struct list_head list;
diff --git a/drivers/gpu/msm/kgsl_mmu.c b/drivers/gpu/msm/kgsl_mmu.c
index 83cf83d..01b255c 100644
--- a/drivers/gpu/msm/kgsl_mmu.c
+++ b/drivers/gpu/msm/kgsl_mmu.c
@@ -759,9 +759,8 @@
 
 	/*global mappings must have the same gpu address in all pagetables*/
 	if (gpuaddr && gpuaddr != memdesc->gpuaddr) {
-		KGSL_CORE_ERR("pt %p addr mismatch phys 0x%08x"
-			"gpu 0x%0x 0x%08x", pagetable, memdesc->physaddr,
-			gpuaddr, memdesc->gpuaddr);
+		KGSL_CORE_ERR("pt %p addr mismatch phys %pa gpu 0x%0x 0x%08x",
+		     pagetable, &memdesc->physaddr, gpuaddr, memdesc->gpuaddr);
 		goto error_unmap;
 	}
 	return result;
diff --git a/drivers/gpu/msm/kgsl_pwrctrl.c b/drivers/gpu/msm/kgsl_pwrctrl.c
index 0dcbfdf..d9dbad8 100644
--- a/drivers/gpu/msm/kgsl_pwrctrl.c
+++ b/drivers/gpu/msm/kgsl_pwrctrl.c
@@ -130,6 +130,16 @@
 	 */
 
 	pwr->active_pwrlevel = new_level;
+	pwrlevel = &pwr->pwrlevels[pwr->active_pwrlevel];
+
+	if (test_bit(KGSL_PWRFLAGS_AXI_ON, &pwr->power_flags)) {
+
+		if (pwr->pcl)
+			msm_bus_scale_client_update_request(pwr->pcl,
+				pwrlevel->bus_freq);
+		else if (pwr->ebi1_clk)
+			clk_set_rate(pwr->ebi1_clk, pwrlevel->bus_freq);
+	}
 
 	if (test_bit(KGSL_PWRFLAGS_CLK_ON, &pwr->power_flags) ||
 		(device->state == KGSL_STATE_NAP)) {
@@ -156,16 +166,6 @@
 		}
 	}
 
-	pwrlevel = &pwr->pwrlevels[pwr->active_pwrlevel];
-
-	if (test_bit(KGSL_PWRFLAGS_AXI_ON, &pwr->power_flags)) {
-
-		if (pwr->pcl)
-			msm_bus_scale_client_update_request(pwr->pcl,
-				pwrlevel->bus_freq);
-		else if (pwr->ebi1_clk)
-			clk_set_rate(pwr->ebi1_clk, pwrlevel->bus_freq);
-	}
 
 	trace_kgsl_pwrlevel(device, pwr->active_pwrlevel, pwrlevel->gpu_freq);
 }
diff --git a/drivers/hwmon/epm_adc.c b/drivers/hwmon/epm_adc.c
index c2b5f38..51ffd21 100644
--- a/drivers/hwmon/epm_adc.c
+++ b/drivers/hwmon/epm_adc.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
@@ -586,12 +586,16 @@
 	return 0;
 }
 
-static int epm_psoc_scale_result(uint32_t result, uint32_t index)
+static int epm_psoc_scale_result(int16_t result, uint32_t index)
 {
 	struct epm_adc_drv *epm_adc = epm_adc_drv;
-	int32_t result_cur;
+	int32_t result_cur, neg = 0;
 
 	if ((1 << index) & epm_adc->channel_mask) {
+		if (result & 0x800) {
+			neg = 1;
+			result = result & 0x7ff;
+		}
 		/* result = (2.048V * code)/(4096 * gain * rsense) */
 		result_cur = ((EPM_PSOC_VREF_VOLTAGE * result)/
 				EPM_PSOC_MAX_ADC_CODE_12_BIT);
@@ -599,14 +603,22 @@
 		result_cur = (result_cur/
 			(epm_adc->epm_psoc_ch_prop[index].gain *
 			epm_adc->epm_psoc_ch_prop[index].resistorvalue));
+		if (neg)
+			result_cur -= result_cur;
 	} else {
+		if (result & 0x8000) {
+			neg = 1;
+			result = result & 0x7fff;
+		}
 		/* result = (2.048V * code)/(32767 * gain * rsense) */
-		result_cur = (((EPM_PSOC_VREF_VOLTAGE * result)/
+		result_cur = (((EPM_PSOC_VREF_VOLTAGE * (int) result)/
 				EPM_PSOC_MAX_ADC_CODE_15_BIT) * 1000);
 
 		result_cur = (result_cur/
 		(epm_adc->epm_psoc_ch_prop[index].gain *
 			epm_adc->epm_psoc_ch_prop[index].resistorvalue));
+		if (neg)
+			result_cur -= result_cur;
 	}
 
 	return result_cur;
@@ -869,10 +881,8 @@
 	psoc_get_meas->timestamp_resp_value = (rx_buf[3] << 24) |
 			(rx_buf[4] << 16) | (rx_buf[5] << 8) |
 			rx_buf[6];
-	psoc_get_meas->reading_value = (rx_buf[7] << 8) | rx_buf[8];
+	psoc_get_meas->reading_raw = (rx_buf[7] << 8) | rx_buf[8];
 
-	pr_debug("dev_num:%d, chan_num:%d\n", rx_buf[1], rx_buf[2]);
-	pr_debug("data %d\n", psoc_get_meas->reading_value);
 	return rc;
 }
 
@@ -1336,7 +1346,7 @@
 			}
 
 			psoc_get_data.reading_value = epm_psoc_scale_result(
-				psoc_get_data.reading_value,
+				psoc_get_data.reading_raw,
 				psoc_get_data.chan_num);
 
 			if (copy_to_user((void __user *)arg, &psoc_get_data,
@@ -1753,8 +1763,6 @@
 	conv.device_idx = attr->index / pdata->chan_per_adc;
 	conv.channel_idx = attr->index % pdata->chan_per_adc;
 	conv.physical = 0;
-	pr_info("%s: device_idx=%d channel_idx=%d", __func__, conv.device_idx,
-			conv.channel_idx);
 
 	if (!epm_adc_expander_register) {
 		rc = epm_adc_i2c_expander_register();
diff --git a/drivers/iommu/Kconfig b/drivers/iommu/Kconfig
index db4ec9d..330c850 100644
--- a/drivers/iommu/Kconfig
+++ b/drivers/iommu/Kconfig
@@ -16,7 +16,7 @@
 # MSM IOMMU support
 config MSM_IOMMU
 	bool "MSM IOMMU Support"
-	depends on ARCH_MSM8X60 || ARCH_MSM8960 || ARCH_APQ8064 || ARCH_MSM8974 || ARCH_MPQ8092 || ARCH_MSM8610 || ARCH_MSM8226
+	depends on ARCH_MSM8X60 || ARCH_MSM8960 || ARCH_APQ8064 || ARCH_MSM8974 || ARCH_MPQ8092 || ARCH_MSM8610 || ARCH_MSM8226 || ARCH_MSMZINC
 	select IOMMU_API
 	help
 	  Support for the IOMMUs found on certain Qualcomm SOCs.
diff --git a/drivers/media/platform/msm/camera_v1/gemini/msm_gemini_platform.c b/drivers/media/platform/msm/camera_v1/gemini/msm_gemini_platform.c
index d5a8098..f0882f7 100644
--- a/drivers/media/platform/msm/camera_v1/gemini/msm_gemini_platform.c
+++ b/drivers/media/platform/msm/camera_v1/gemini/msm_gemini_platform.c
@@ -15,7 +15,7 @@
 #include <linux/clk.h>
 #include <mach/clk.h>
 #include <linux/io.h>
-#include <linux/android_pmem.h>
+
 #include <mach/camera.h>
 #include <mach/iommu_domains.h>
 
@@ -35,8 +35,6 @@
 	ion_unmap_iommu(gemini_client, *ionhandle, CAMERA_DOMAIN, GEN_POOL);
 	ion_free(gemini_client, *ionhandle);
 	*ionhandle = NULL;
-#elif CONFIG_ANDROID_PMEM
-	put_pmem_file(file);
 #endif
 }
 
@@ -53,9 +51,6 @@
 
 	rc = ion_map_iommu(gemini_client, *ionhandle, CAMERA_DOMAIN, GEN_POOL,
 			SZ_4K, 0, &paddr, (unsigned long *)&size, 0, 0);
-#elif CONFIG_ANDROID_PMEM
-	unsigned long kvstart;
-	rc = get_pmem_file(fd, &paddr, &kvstart, &size, file_p);
 #else
 	rc = 0;
 	paddr = 0;
diff --git a/drivers/media/platform/msm/camera_v1/mercury/msm_mercury_platform.c b/drivers/media/platform/msm/camera_v1/mercury/msm_mercury_platform.c
index e6392fe..3607f2e 100644
--- a/drivers/media/platform/msm/camera_v1/mercury/msm_mercury_platform.c
+++ b/drivers/media/platform/msm/camera_v1/mercury/msm_mercury_platform.c
@@ -13,7 +13,7 @@
 #include <linux/module.h>
 #include <linux/clk.h>
 #include <linux/io.h>
-#include <linux/android_pmem.h>
+
 #include <mach/clk.h>
 #include <mach/camera.h>
 #include <mach/msm_subsystem_map.h>
@@ -39,8 +39,6 @@
 		GEN_POOL);
 	ion_free(mercury_client, *ionhandle);
 	*ionhandle = NULL;
-#elif CONFIG_ANDROID_PMEM
-	put_pmem_file(file);
 #endif
 }
 
@@ -59,10 +57,6 @@
 	rc = ion_map_iommu(mercury_client, *ionhandle, CAMERA_DOMAIN,
 		GEN_POOL, SZ_4K, 0, &paddr,
 		(unsigned long *)&size, 0, 0);
-#elif CONFIG_ANDROID_PMEM
-	unsigned long kvstart;
-	rc = get_pmem_file(fd, &paddr, &kvstart, &size, file_p);
-#else
 	rc = 0;
 	paddr = 0;
 	size = 0;
diff --git a/drivers/media/platform/msm/camera_v1/msm_camera.c b/drivers/media/platform/msm/camera_v1/msm_camera.c
index 622ecfd..213ccc7 100644
--- a/drivers/media/platform/msm/camera_v1/msm_camera.c
+++ b/drivers/media/platform/msm/camera_v1/msm_camera.c
@@ -28,7 +28,7 @@
 #include <linux/fs.h>
 #include <linux/list.h>
 #include <linux/uaccess.h>
-#include <linux/android_pmem.h>
+
 #include <linux/poll.h>
 #include <media/msm_camera.h>
 #include <mach/camera.h>
@@ -319,15 +319,6 @@
 			goto out1;
 		ion_phys(client_for_ion, region->handle,
 			&paddr, (size_t *)&len);
-#else
-	rc = get_pmem_file(info->fd, &paddr, &kvstart, &len, &file);
-	if (rc < 0) {
-		pr_err("%s: get_pmem_file fd %d error %d\n",
-			__func__,
-			info->fd, rc);
-		goto out1;
-	}
-	region->file = file;
 #endif
 	if (!info->len)
 		info->len = len;
@@ -364,8 +355,6 @@
 out2:
 #ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
 	ion_free(client_for_ion, region->handle);
-#else
-	put_pmem_file(region->file);
 #endif
 out1:
 	kfree(region);
@@ -649,8 +638,6 @@
 				hlist_del(node);
 #ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
 				ion_free(client_for_ion, region->handle);
-#else
-				put_pmem_file(region->file);
 #endif
 				kfree(region);
 				CDBG("%s: type %d, vaddr  0x%p\n",
@@ -673,8 +660,6 @@
 				hlist_del(node);
 #ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
 				ion_free(client_for_ion, region->handle);
-#else
-				put_pmem_file(region->file);
 #endif
 				kfree(region);
 				CDBG("%s: type %d, vaddr  0x%p\n",
@@ -696,8 +681,6 @@
 				hlist_del(node);
 #ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
 				ion_free(client_for_ion, region->handle);
-#else
-				put_pmem_file(region->file);
 #endif
 				kfree(region);
 				CDBG("%s: type %d, vaddr  0x%p\n",
@@ -3012,8 +2995,6 @@
 			hlist_del(hnode);
 #ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
 				ion_free(client_for_ion, region->handle);
-#else
-			put_pmem_file(region->file);
 #endif
 			kfree(region);
 		}
@@ -3023,8 +3004,6 @@
 			hlist_del(hnode);
 #ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
 				ion_free(client_for_ion, region->handle);
-#else
-			put_pmem_file(region->file);
 #endif
 			kfree(region);
 		}
diff --git a/drivers/media/platform/msm/camera_v1/msm_isp.c b/drivers/media/platform/msm/camera_v1/msm_isp.c
index f646f09..59290ec 100644
--- a/drivers/media/platform/msm/camera_v1/msm_isp.c
+++ b/drivers/media/platform/msm/camera_v1/msm_isp.c
@@ -21,7 +21,7 @@
 #include <linux/videodev2.h>
 #include <linux/proc_fs.h>
 #include <linux/vmalloc.h>
-#include <linux/android_pmem.h>
+
 
 #include <media/v4l2-dev.h>
 #include <media/v4l2-ioctl.h>
diff --git a/drivers/media/platform/msm/camera_v1/msm_mctl.c b/drivers/media/platform/msm/camera_v1/msm_mctl.c
index 0210d23..95e889d 100644
--- a/drivers/media/platform/msm/camera_v1/msm_mctl.c
+++ b/drivers/media/platform/msm/camera_v1/msm_mctl.c
@@ -26,7 +26,7 @@
 #include <media/v4l2-ioctl.h>
 #include <media/v4l2-device.h>
 
-#include <linux/android_pmem.h>
+
 
 #include "msm.h"
 #include "msm_cam_server.h"
diff --git a/drivers/media/platform/msm/camera_v1/msm_mctl_buf.c b/drivers/media/platform/msm/camera_v1/msm_mctl_buf.c
index 3ccd258..041f674 100644
--- a/drivers/media/platform/msm/camera_v1/msm_mctl_buf.c
+++ b/drivers/media/platform/msm/camera_v1/msm_mctl_buf.c
@@ -23,7 +23,7 @@
 #include <media/v4l2-ioctl.h>
 #include <media/v4l2-device.h>
 
-#include <linux/android_pmem.h>
+
 
 #include "msm.h"
 #include "msm_cam_server.h"
@@ -1015,78 +1015,6 @@
 	D("%s Frame mapped successfully ", __func__);
 	return 0;
 }
-#else
-/* Unmap using PMEM APIs */
-static int __msm_mctl_unmap_user_frame(struct msm_cam_meta_frame *meta_frame,
-	struct ion_client *client, int domain_num)
-{
-	int i = 0, rc = 0;
-
-	for (i = 0; i < meta_frame->frame.num_planes; i++) {
-		D("%s Plane %d handle %p", __func__, i,
-			meta_frame->map[i].handle);
-		put_pmem_file(meta_frame->map[i].file);
-	}
-}
-
-/* Map using PMEM APIs */
-static int __msm_mctl_map_user_frame(struct msm_cam_meta_frame *meta_frame,
-	struct ion_client *client, int domain_num)
-{
-	unsigned long kvstart = 0;
-	unsigned long paddr = 0;
-	struct file *file = NULL;
-	unsigned long len;
-	int i = 0, j = 0;
-
-	for (i = 0; i < meta_frame->frame.num_planes; i++) {
-		rc = get_pmem_file(meta_frame->frame.mp[i].fd,
-			&paddr, &kvstart, &len, &file);
-		if (rc < 0) {
-			pr_err("%s: get_pmem_file fd %d error %d\n",
-				__func__, meta_frame->frame.mp[i].fd, rc);
-			/* Roll back previous plane mappings, if any */
-			for (j = i-1; j >= 0; j--)
-				if (meta_frame->map[j].file)
-					put_pmem_file(meta_frame->map[j].file);
-
-			return -EACCES;
-		}
-		D("%s Got pmem file for fd %d plane %d as %p", __func__,
-			meta_frame->frame.mp[i].fd, i, file);
-		meta_frame->map[i].file = file;
-		/* Validate the offsets with the mapped length. */
-		if ((meta_frame->frame.mp[i].addr_offset > len) ||
-			(meta_frame->frame.mp[i].data_offset +
-			meta_frame->frame.mp[i].length > len)) {
-			pr_err("%s: Invalid offsets A %d D %d L %d len %ld",
-				__func__, meta_frame->frame.mp[i].addr_offset,
-				meta_frame->frame.mp[i].data_offset,
-				meta_frame->frame.mp[i].length, len);
-			/* Roll back previous plane mappings, if any */
-			for (j = i; j >= 0; j--)
-				if (meta_frame->map[j].file)
-					put_pmem_file(meta_frame->map[j].file);
-
-			return -EINVAL;
-		}
-		meta_frame->map[i].data_offset =
-			meta_frame->frame.mp[i].data_offset;
-		/* Add the addr_offset to the paddr here itself. The addr_offset
-		 * will be non-zero only if the user has allocated a buffer with
-		 * a single fd, but logically partitioned it into
-		 * multiple planes or buffers.*/
-		paddr += meta_frame->frame.mp[i].addr_offset;
-		meta_frame->map[i].paddr = paddr;
-		meta_frame->map[i].len = len;
-		D("%s Plane %d fd %d handle %p paddr %x", __func__,
-			i, meta_frame->frame.mp[i].fd,
-			meta_frame->map[i].handle,
-			(uint32_t)meta_frame->map[i].paddr);
-	}
-	D("%s Frame mapped successfully ", __func__);
-	return 0;
-}
 #endif
 
 int msm_mctl_map_user_frame(struct msm_cam_meta_frame *meta_frame,
diff --git a/drivers/media/platform/msm/camera_v1/msm_mctl_pp.c b/drivers/media/platform/msm/camera_v1/msm_mctl_pp.c
index 9267c9f..ae3ce63 100644
--- a/drivers/media/platform/msm/camera_v1/msm_mctl_pp.c
+++ b/drivers/media/platform/msm/camera_v1/msm_mctl_pp.c
@@ -25,7 +25,7 @@
 #include <media/v4l2-ioctl.h>
 #include <media/v4l2-device.h>
 
-#include <linux/android_pmem.h>
+
 
 #include "msm.h"
 #include "msm_vpe.h"
diff --git a/drivers/media/platform/msm/camera_v1/msm_mem.c b/drivers/media/platform/msm/camera_v1/msm_mem.c
index 8144415..c9a87d7 100644
--- a/drivers/media/platform/msm/camera_v1/msm_mem.c
+++ b/drivers/media/platform/msm/camera_v1/msm_mem.c
@@ -25,7 +25,7 @@
 #include <media/v4l2-ioctl.h>
 #include <media/v4l2-device.h>
 
-#include <linux/android_pmem.h>
+
 
 #include "msm.h"
 
@@ -71,26 +71,6 @@
 
 static DEFINE_MUTEX(hlist_mut);
 
-#ifdef CONFIG_ANDROID_PMEM
-static int check_pmem_info(struct msm_pmem_info *info, int len)
-{
-	if (info->offset < len &&
-		info->offset + info->len <= len &&
-		info->planar0_off < len &&
-		info->planar1_off < len)
-		return 0;
-
-	pr_err("%s: check failed: off %d len %d y %d cbcr %d (total len %d)\n",
-						__func__,
-						info->offset,
-						info->len,
-						info->planar0_off,
-						info->planar1_off,
-						len);
-	return -EINVAL;
-}
-#endif
-
 static int check_overlap(struct hlist_head *ptype,
 				unsigned long paddr,
 				unsigned long len)
@@ -138,14 +118,6 @@
 	if (ion_map_iommu(client, region->handle, domain_num, 0,
 				  SZ_4K, 0, &paddr, &len, 0, 0) < 0)
 		goto out2;
-#elif CONFIG_ANDROID_PMEM
-	rc = get_pmem_file(info->fd, &paddr, &kvstart, &len, &file);
-	if (rc < 0) {
-		pr_err("%s: get_pmem_file fd %d error %d\n",
-				__func__, info->fd, rc);
-		goto out1;
-	}
-	region->file = file;
 #else
 	paddr = 0;
 	file = NULL;
@@ -153,9 +125,6 @@
 #endif
 	if (!info->len)
 		info->len = len;
-	rc = check_pmem_info(info, len);
-	if (rc < 0)
-		goto out3;
 	paddr += info->offset;
 	len = info->len;
 
@@ -185,8 +154,6 @@
 #ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
 out2:
 	ion_free(client, region->handle);
-#elif CONFIG_ANDROID_PMEM
-	put_pmem_file(region->file);
 #endif
 out1:
 	kfree(region);
@@ -256,8 +223,6 @@
 				ion_unmap_iommu(client, region->handle,
 					domain_num, 0);
 				ion_free(client, region->handle);
-#else
-				put_pmem_file(region->file);
 #endif
 				kfree(region);
 			}
diff --git a/drivers/media/platform/msm/camera_v1/vfe/msm_vfe7x.c b/drivers/media/platform/msm/camera_v1/vfe/msm_vfe7x.c
index bbf9d1b..d7ec547 100644
--- a/drivers/media/platform/msm/camera_v1/vfe/msm_vfe7x.c
+++ b/drivers/media/platform/msm/camera_v1/vfe/msm_vfe7x.c
@@ -14,7 +14,7 @@
 #include <linux/msm_adsp.h>
 #include <linux/uaccess.h>
 #include <linux/fs.h>
-#include <linux/android_pmem.h>
+
 #include <linux/slab.h>
 #include <mach/msm_adsp.h>
 #include <mach/clk.h>
diff --git a/drivers/media/platform/msm/camera_v1/vfe/msm_vfe7x27a.c b/drivers/media/platform/msm/camera_v1/vfe/msm_vfe7x27a.c
index 0279c78..6b41b03 100644
--- a/drivers/media/platform/msm/camera_v1/vfe/msm_vfe7x27a.c
+++ b/drivers/media/platform/msm/camera_v1/vfe/msm_vfe7x27a.c
@@ -13,7 +13,7 @@
 #include <linux/msm_adsp.h>
 #include <linux/uaccess.h>
 #include <linux/fs.h>
-#include <linux/android_pmem.h>
+
 #include <linux/slab.h>
 #include <linux/pm_qos.h>
 #include <linux/delay.h>
diff --git a/drivers/media/platform/msm/camera_v1/vfe/msm_vfe7x27a_v4l2.c b/drivers/media/platform/msm/camera_v1/vfe/msm_vfe7x27a_v4l2.c
index f3388d9..3a8f1b2 100644
--- a/drivers/media/platform/msm/camera_v1/vfe/msm_vfe7x27a_v4l2.c
+++ b/drivers/media/platform/msm/camera_v1/vfe/msm_vfe7x27a_v4l2.c
@@ -13,7 +13,7 @@
 #include <linux/msm_adsp.h>
 #include <linux/uaccess.h>
 #include <linux/fs.h>
-#include <linux/android_pmem.h>
+
 #include <linux/slab.h>
 #include <linux/pm_qos.h>
 #include <linux/delay.h>
diff --git a/drivers/media/platform/msm/camera_v1/vfe/msm_vfe_stats_buf.c b/drivers/media/platform/msm/camera_v1/vfe/msm_vfe_stats_buf.c
index a6807ed..a550d78 100644
--- a/drivers/media/platform/msm/camera_v1/vfe/msm_vfe_stats_buf.c
+++ b/drivers/media/platform/msm/camera_v1/vfe/msm_vfe_stats_buf.c
@@ -25,7 +25,7 @@
 #include <media/v4l2-ioctl.h>
 #include <media/v4l2-device.h>
 
-#include <linux/android_pmem.h>
+
 #include <media/msm_camera.h>
 #include <media/msm_isp.h>
 #include "msm.h"
@@ -162,25 +162,6 @@
 	return rc;
 }
 
-#ifdef CONFIG_ANDROID_PMEM
-static int msm_stats_check_pmem_info(struct msm_stats_buf_info *info, int len)
-{
-	if (info->offset < len &&
-		info->offset + info->len <= len &&
-		info->planar0_off < len && info->planar1_off < len)
-		return 0;
-
-	pr_err("%s: check failed: off %d len %d y %d cbcr %d (total len %d)\n",
-		   __func__,
-		   info->offset,
-		   info->len,
-		   info->planar0_off,
-		   info->planar1_off,
-		   len);
-	return -EINVAL;
-}
-#endif
-
 static int msm_stats_buf_prepare(struct msm_stats_bufq_ctrl *stats_ctrl,
 	struct msm_stats_buf_info *info, struct ion_client *client,
 	int domain_num)
@@ -226,14 +207,6 @@
 		pr_err("%s: cannot map address", __func__);
 		goto out2;
 	}
-#elif CONFIG_ANDROID_PMEM
-	rc = get_pmem_file(info->fd, &paddr, &kvstart, &len, &file);
-	if (rc < 0) {
-		pr_err("%s: get_pmem_file fd %d error %d\n",
-			   __func__, info->fd, rc);
-		goto out1;
-	}
-	stats_buf->file = file;
 #else
 	paddr = 0;
 	file = NULL;
@@ -241,11 +214,6 @@
 #endif
 	if (!info->len)
 		info->len = len;
-	rc = msm_stats_check_pmem_info(info, len);
-	if (rc < 0) {
-		pr_err("%s: msm_stats_check_pmem_info err = %d", __func__, rc);
-		goto out3;
-	}
 	paddr += info->offset;
 	len = info->len;
 	stats_buf->paddr = paddr;
@@ -256,15 +224,12 @@
 	D("%s pmem_stats address is 0x%ld\n", __func__, paddr);
 	stats_buf->state = MSM_STATS_BUFFER_STATE_PREPARED;
 	return 0;
-out3:
 #ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
 	ion_unmap_iommu(client, stats_buf->handle, domain_num, 0);
 #endif
 #ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
 out2:
 	ion_free(client, stats_buf->handle);
-#elif CONFIG_ANDROID_PMEM
-	put_pmem_file(stats_buf->file);
 #endif
 out1:
 	return rc;
@@ -295,8 +260,6 @@
 	ion_unmap_iommu(client, stats_buf->handle,
 					domain_num, 0);
 	ion_free(client, stats_buf->handle);
-#else
-	put_pmem_file(stats_buf->file);
 #endif
 	if (stats_buf->state == MSM_STATS_BUFFER_STATE_QUEUED) {
 		/* buf queued need delete from list */
diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_buf_mgr.c b/drivers/media/platform/msm/camera_v2/isp/msm_buf_mgr.c
index c8873b8..3a24428 100644
--- a/drivers/media/platform/msm/camera_v2/isp/msm_buf_mgr.c
+++ b/drivers/media/platform/msm/camera_v2/isp/msm_buf_mgr.c
@@ -20,7 +20,7 @@
 #include <linux/proc_fs.h>
 #include <linux/videodev2.h>
 #include <linux/vmalloc.h>
-#include <linux/android_pmem.h>
+
 
 #include <media/v4l2-dev.h>
 #include <media/v4l2-ioctl.h>
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 69d523c..38130db 100644
--- a/drivers/media/platform/msm/camera_v2/isp/msm_isp.h
+++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp.h
@@ -378,8 +378,8 @@
 	struct msm_vfe_tasklet_queue_cmd
 		tasklet_queue_cmd[MSM_VFE_TASKLETQ_SIZE];
 
+	uint32_t vfe_hw_version;
 	struct msm_vfe_hardware_info *hw_info;
-
 	struct msm_vfe_axi_shared_data axi_data;
 	struct msm_vfe_stats_shared_data stats_data;
 	struct msm_vfe_error_info error_info;
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 fc0a8b5..b136125 100644
--- a/drivers/media/platform/msm/camera_v2/isp/msm_isp40.c
+++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp40.c
@@ -29,6 +29,9 @@
 #define CDBG(fmt, args...) do { } while (0)
 #endif
 
+#define VFE40_V1_VERSION 0x10000018
+#define VFE40_V2_VERSION 0x1001001A
+
 #define VFE40_BURST_LEN 3
 #define VFE40_STATS_BURST_LEN 2
 #define VFE40_UB_SIZE 1536
@@ -123,53 +126,99 @@
 static void msm_vfe40_init_qos_parms(struct vfe_device *vfe_dev)
 {
 	void __iomem *vfebase = vfe_dev->vfe_base;
-	msm_camera_io_w(0xAAAAAAAA, vfebase + VFE40_BUS_BDG_QOS_CFG_0);
-	msm_camera_io_w(0xAAAAAAAA, vfebase + VFE40_BUS_BDG_QOS_CFG_1);
-	msm_camera_io_w(0xAAAAAAAA, vfebase + VFE40_BUS_BDG_QOS_CFG_2);
-	msm_camera_io_w(0xAAAAAAAA, vfebase + VFE40_BUS_BDG_QOS_CFG_3);
-	msm_camera_io_w(0xAAAAAAAA, vfebase + VFE40_BUS_BDG_QOS_CFG_4);
-	msm_camera_io_w(0xAAAAAAAA, vfebase + VFE40_BUS_BDG_QOS_CFG_5);
-	msm_camera_io_w(0xAAAAAAAA, vfebase + VFE40_BUS_BDG_QOS_CFG_6);
-	msm_camera_io_w(0x0002AAAA, vfebase + VFE40_BUS_BDG_QOS_CFG_7);
+	if (vfe_dev->vfe_hw_version == VFE40_V1_VERSION) {
+		msm_camera_io_w(0xAAAAAAAA, vfebase + VFE40_BUS_BDG_QOS_CFG_0);
+		msm_camera_io_w(0xAAAAAAAA, vfebase + VFE40_BUS_BDG_QOS_CFG_1);
+		msm_camera_io_w(0xAAAAAAAA, vfebase + VFE40_BUS_BDG_QOS_CFG_2);
+		msm_camera_io_w(0xAAAAAAAA, vfebase + VFE40_BUS_BDG_QOS_CFG_3);
+		msm_camera_io_w(0xAAAAAAAA, vfebase + VFE40_BUS_BDG_QOS_CFG_4);
+		msm_camera_io_w(0xAAAAAAAA, vfebase + VFE40_BUS_BDG_QOS_CFG_5);
+		msm_camera_io_w(0xAAAAAAAA, vfebase + VFE40_BUS_BDG_QOS_CFG_6);
+		msm_camera_io_w(0x0002AAAA, vfebase + VFE40_BUS_BDG_QOS_CFG_7);
+	} else if (vfe_dev->vfe_hw_version == VFE40_V2_VERSION) {
+		msm_camera_io_w(0xAAA9AAA9, vfebase + VFE40_BUS_BDG_QOS_CFG_0);
+		msm_camera_io_w(0xAAA9AAA9, vfebase + VFE40_BUS_BDG_QOS_CFG_1);
+		msm_camera_io_w(0xAAA9AAA9, vfebase + VFE40_BUS_BDG_QOS_CFG_2);
+		msm_camera_io_w(0xAAA9AAA9, vfebase + VFE40_BUS_BDG_QOS_CFG_3);
+		msm_camera_io_w(0xAAA9AAA9, vfebase + VFE40_BUS_BDG_QOS_CFG_4);
+		msm_camera_io_w(0xAAA9AAA9, vfebase + VFE40_BUS_BDG_QOS_CFG_5);
+		msm_camera_io_w(0xAAA9AAA9, vfebase + VFE40_BUS_BDG_QOS_CFG_6);
+		msm_camera_io_w(0x0001AAA9, vfebase + VFE40_BUS_BDG_QOS_CFG_7);
+	}
 }
 
-static void msm_vfe40_init_vbif_parms(
-	void __iomem *vfe_vbif_base)
+static void msm_vfe40_init_vbif_parms(struct vfe_device *vfe_dev)
 {
-	msm_camera_io_w(0x1,
-		vfe_vbif_base + VFE40_VBIF_CLKON);
-	msm_camera_io_w(0x01010101,
-		vfe_vbif_base + VFE40_VBIF_IN_RD_LIM_CONF0);
-	msm_camera_io_w(0x01010101,
-		vfe_vbif_base + VFE40_VBIF_IN_RD_LIM_CONF1);
-	msm_camera_io_w(0x10010110,
-		vfe_vbif_base + VFE40_VBIF_IN_RD_LIM_CONF2);
-	msm_camera_io_w(0x10101010,
-		vfe_vbif_base + VFE40_VBIF_IN_WR_LIM_CONF0);
-	msm_camera_io_w(0x10101010,
-		vfe_vbif_base + VFE40_VBIF_IN_WR_LIM_CONF1);
-	msm_camera_io_w(0x10101010,
-		vfe_vbif_base + VFE40_VBIF_IN_WR_LIM_CONF2);
-	msm_camera_io_w(0x00001010,
-		vfe_vbif_base + VFE40_VBIF_OUT_RD_LIM_CONF0);
-	msm_camera_io_w(0x00001010,
-		vfe_vbif_base + VFE40_VBIF_OUT_WR_LIM_CONF0);
-	msm_camera_io_w(0x00000707,
-		vfe_vbif_base + VFE40_VBIF_DDR_OUT_MAX_BURST);
-	msm_camera_io_w(0x00000707,
-		vfe_vbif_base + VFE40_VBIF_OCMEM_OUT_MAX_BURST);
-	msm_camera_io_w(0x00000030,
-		vfe_vbif_base + VFE40_VBIF_ARB_CTL);
-	msm_camera_io_w(0x00000FFF,
-		vfe_vbif_base + VFE40_VBIF_OUT_AXI_AOOO_EN);
-	msm_camera_io_w(0x0FFF0FFF,
-		vfe_vbif_base + VFE40_VBIF_OUT_AXI_AOOO);
-	msm_camera_io_w(0x00000001,
-		vfe_vbif_base + VFE40_VBIF_ROUND_ROBIN_QOS_ARB);
-	msm_camera_io_w(0x22222222,
-		vfe_vbif_base + VFE40_VBIF_OUT_AXI_AMEMTYPE_CONF0);
-	msm_camera_io_w(0x00002222,
-		vfe_vbif_base + VFE40_VBIF_OUT_AXI_AMEMTYPE_CONF1);
+	void __iomem *vfe_vbif_base = vfe_dev->vfe_vbif_base;
+	if (vfe_dev->vfe_hw_version == VFE40_V1_VERSION) {
+		msm_camera_io_w(0x1,
+			vfe_vbif_base + VFE40_VBIF_CLKON);
+		msm_camera_io_w(0x01010101,
+			vfe_vbif_base + VFE40_VBIF_IN_RD_LIM_CONF0);
+		msm_camera_io_w(0x01010101,
+			vfe_vbif_base + VFE40_VBIF_IN_RD_LIM_CONF1);
+		msm_camera_io_w(0x10010110,
+			vfe_vbif_base + VFE40_VBIF_IN_RD_LIM_CONF2);
+		msm_camera_io_w(0x10101010,
+			vfe_vbif_base + VFE40_VBIF_IN_WR_LIM_CONF0);
+		msm_camera_io_w(0x10101010,
+			vfe_vbif_base + VFE40_VBIF_IN_WR_LIM_CONF1);
+		msm_camera_io_w(0x10101010,
+			vfe_vbif_base + VFE40_VBIF_IN_WR_LIM_CONF2);
+		msm_camera_io_w(0x00001010,
+			vfe_vbif_base + VFE40_VBIF_OUT_RD_LIM_CONF0);
+		msm_camera_io_w(0x00001010,
+			vfe_vbif_base + VFE40_VBIF_OUT_WR_LIM_CONF0);
+		msm_camera_io_w(0x00000707,
+			vfe_vbif_base + VFE40_VBIF_DDR_OUT_MAX_BURST);
+		msm_camera_io_w(0x00000707,
+			vfe_vbif_base + VFE40_VBIF_OCMEM_OUT_MAX_BURST);
+		msm_camera_io_w(0x00000030,
+			vfe_vbif_base + VFE40_VBIF_ARB_CTL);
+		msm_camera_io_w(0x00000FFF,
+			vfe_vbif_base + VFE40_VBIF_OUT_AXI_AOOO_EN);
+		msm_camera_io_w(0x0FFF0FFF,
+			vfe_vbif_base + VFE40_VBIF_OUT_AXI_AOOO);
+		msm_camera_io_w(0x00000001,
+			vfe_vbif_base + VFE40_VBIF_ROUND_ROBIN_QOS_ARB);
+		msm_camera_io_w(0x22222222,
+			vfe_vbif_base + VFE40_VBIF_OUT_AXI_AMEMTYPE_CONF0);
+		msm_camera_io_w(0x00002222,
+			vfe_vbif_base + VFE40_VBIF_OUT_AXI_AMEMTYPE_CONF1);
+	} else if (vfe_dev->vfe_hw_version == VFE40_V2_VERSION) {
+		msm_camera_io_w(0x1,
+			vfe_vbif_base + VFE40_VBIF_CLKON);
+		msm_camera_io_w(0x10101010,
+			vfe_vbif_base + VFE40_VBIF_IN_RD_LIM_CONF0);
+		msm_camera_io_w(0x10101010,
+			vfe_vbif_base + VFE40_VBIF_IN_RD_LIM_CONF1);
+		msm_camera_io_w(0x10101010,
+			vfe_vbif_base + VFE40_VBIF_IN_RD_LIM_CONF2);
+		msm_camera_io_w(0x10101010,
+			vfe_vbif_base + VFE40_VBIF_IN_WR_LIM_CONF0);
+		msm_camera_io_w(0x10101010,
+			vfe_vbif_base + VFE40_VBIF_IN_WR_LIM_CONF1);
+		msm_camera_io_w(0x10101010,
+			vfe_vbif_base + VFE40_VBIF_IN_WR_LIM_CONF2);
+		msm_camera_io_w(0x00000010,
+			vfe_vbif_base + VFE40_VBIF_OUT_RD_LIM_CONF0);
+		msm_camera_io_w(0x00000010,
+			vfe_vbif_base + VFE40_VBIF_OUT_WR_LIM_CONF0);
+		msm_camera_io_w(0x00000707,
+			vfe_vbif_base + VFE40_VBIF_DDR_OUT_MAX_BURST);
+		msm_camera_io_w(0x00000010,
+			vfe_vbif_base + VFE40_VBIF_ARB_CTL);
+		msm_camera_io_w(0x00000FFF,
+			vfe_vbif_base + VFE40_VBIF_OUT_AXI_AOOO_EN);
+		msm_camera_io_w(0x0FFF0FFF,
+			vfe_vbif_base + VFE40_VBIF_OUT_AXI_AOOO);
+		msm_camera_io_w(0x00000003,
+			vfe_vbif_base + VFE40_VBIF_ROUND_ROBIN_QOS_ARB);
+		msm_camera_io_w(0x22222222,
+			vfe_vbif_base + VFE40_VBIF_OUT_AXI_AMEMTYPE_CONF0);
+		msm_camera_io_w(0x00002222,
+			vfe_vbif_base + VFE40_VBIF_OUT_AXI_AMEMTYPE_CONF1);
+	}
 }
 
 static int msm_vfe40_init_hardware(struct vfe_device *vfe_dev)
@@ -254,7 +303,7 @@
 static void msm_vfe40_init_hardware_reg(struct vfe_device *vfe_dev)
 {
 	msm_vfe40_init_qos_parms(vfe_dev);
-	msm_vfe40_init_vbif_parms(vfe_dev->vfe_vbif_base);
+	msm_vfe40_init_vbif_parms(vfe_dev);
 	/* CGC_OVERRIDE */
 	msm_camera_io_w(0x3FFFFFFF, vfe_dev->vfe_base + 0x14);
 	msm_camera_io_w(0xC001FF7F, vfe_dev->vfe_base + 0x974);
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 5baeb28..f337e27 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
@@ -637,6 +637,9 @@
 		mutex_unlock(&vfe_dev->mutex);
 		return -EINVAL;
 	}
+	vfe_dev->vfe_hw_version = msm_camera_io_r(vfe_dev->vfe_base);
+	ISP_DBG("%s: HW Version: 0x%x\n", __func__, vfe_dev->vfe_hw_version);
+
 	vfe_dev->hw_info->vfe_ops.core_ops.init_hw_reg(vfe_dev);
 
 	for (i = 0; i < vfe_dev->hw_info->num_iommu_ctx; i++)
@@ -649,10 +652,6 @@
 		sizeof(struct msm_vfe_stats_shared_data));
 	memset(&vfe_dev->error_info, 0, sizeof(vfe_dev->error_info));
 	vfe_dev->axi_data.hw_info = vfe_dev->hw_info->axi_hw_info;
-
-	ISP_DBG("%s: HW Version: 0x%x\n",
-		__func__, msm_camera_io_r(vfe_dev->vfe_base));
-
 	vfe_dev->vfe_open_cnt++;
 	vfe_dev->taskletq_idx = 0;
 	mutex_unlock(&vfe_dev->mutex);
diff --git a/drivers/media/platform/msm/camera_v2/jpeg_10/msm_jpeg_platform.c b/drivers/media/platform/msm/camera_v2/jpeg_10/msm_jpeg_platform.c
index 8c484e7..b1253fa 100644
--- a/drivers/media/platform/msm/camera_v2/jpeg_10/msm_jpeg_platform.c
+++ b/drivers/media/platform/msm/camera_v2/jpeg_10/msm_jpeg_platform.c
@@ -17,7 +17,7 @@
 #include <linux/clk.h>
 #include <mach/clk.h>
 #include <linux/io.h>
-#include <linux/android_pmem.h>
+
 #include <mach/camera.h>
 #include <mach/iommu_domains.h>
 #include <mach/msm_bus.h>
diff --git a/drivers/media/platform/msm/camera_v2/msm.c b/drivers/media/platform/msm/camera_v2/msm.c
index f8cddb2..6418f21 100644
--- a/drivers/media/platform/msm/camera_v2/msm.c
+++ b/drivers/media/platform/msm/camera_v2/msm.c
@@ -268,6 +268,8 @@
 	msm_enqueue(&session->stream_q, &stream->list);
 	session->stream_q.len++;
 
+	INIT_LIST_HEAD(&stream->queued_list);
+
 	return 0;
 }
 
@@ -852,6 +854,31 @@
 	return stream->vb2_q;
 }
 
+struct msm_stream *msm_get_stream_from_vb2q(struct vb2_queue *q)
+{
+	struct msm_session *session;
+	struct msm_stream *stream;
+	unsigned long flags1;
+	unsigned long flags2;
+	spin_lock_irqsave(&msm_session_q->lock, flags1);
+	list_for_each_entry(session, &(msm_session_q->list), list) {
+		spin_lock_irqsave(&(session->stream_q.lock), flags2);
+		list_for_each_entry(
+			stream, &(session->stream_q.list), list) {
+			if (stream->vb2_q == q) {
+				spin_unlock_irqrestore
+					(&(session->stream_q.lock), flags2);
+				spin_unlock_irqrestore
+					(&msm_session_q->lock, flags1);
+				return stream;
+			}
+		}
+		spin_unlock_irqrestore(&(session->stream_q.lock), flags2);
+	}
+	spin_unlock_irqrestore(&msm_session_q->lock, flags1);
+	return NULL;
+}
+
 static struct v4l2_subdev *msm_sd_find(const char *name)
 {
 	unsigned long flags;
diff --git a/drivers/media/platform/msm/camera_v2/msm.h b/drivers/media/platform/msm/camera_v2/msm.h
index eb15cab..39901ad 100644
--- a/drivers/media/platform/msm/camera_v2/msm.h
+++ b/drivers/media/platform/msm/camera_v2/msm.h
@@ -51,5 +51,6 @@
 	unsigned int stream_id);
 struct vb2_queue *msm_get_stream_vb2q(unsigned int session_id,
 	unsigned int stream_id);
+struct msm_stream *msm_get_stream_from_vb2q(struct vb2_queue *q);
 
 #endif /*_MSM_H */
diff --git a/drivers/media/platform/msm/camera_v2/msm_vb2/msm_vb2.c b/drivers/media/platform/msm/camera_v2/msm_vb2/msm_vb2.c
index 079dbb5..29262af 100644
--- a/drivers/media/platform/msm/camera_v2/msm_vb2/msm_vb2.c
+++ b/drivers/media/platform/msm/camera_v2/msm_vb2/msm_vb2.c
@@ -38,22 +38,107 @@
 
 int msm_vb2_buf_init(struct vb2_buffer *vb)
 {
+	struct msm_stream *stream;
 	struct msm_vb2_buffer *msm_vb2_buf;
 
+	stream = msm_get_stream_from_vb2q(vb->vb2_queue);
+	if (!stream) {
+		pr_err("%s: Couldn't find stream\n", __func__);
+		return -EINVAL;
+	}
 	msm_vb2_buf = container_of(vb, struct msm_vb2_buffer, vb2_buf);
 	msm_vb2_buf->in_freeq = 0;
+	msm_vb2_buf->stream = stream;
 
 	return 0;
 }
 
 static void msm_vb2_buf_queue(struct vb2_buffer *vb)
 {
+	struct msm_vb2_buffer *msm_vb2;
+	struct msm_stream *stream;
+	unsigned long flags;
+
+	msm_vb2 = container_of(vb, struct msm_vb2_buffer, vb2_buf);
+
+	if (!msm_vb2) {
+		pr_err("%s:%d] vb2_buf NULL", __func__, __LINE__);
+		return;
+	}
+
+	stream = msm_vb2->stream;
+	if (!stream) {
+		pr_err("%s:%d] NULL stream", __func__, __LINE__);
+		return;
+	}
+
+	spin_lock_irqsave(&stream->stream_lock, flags);
+	list_add_tail(&msm_vb2->list, &stream->queued_list);
+	spin_unlock_irqrestore(&stream->stream_lock, flags);
+}
+
+static int msm_vb2_buf_finish(struct vb2_buffer *vb)
+{
+	struct msm_vb2_buffer *msm_vb2;
+	struct msm_stream *stream;
+	unsigned long flags;
+	struct msm_vb2_buffer *msm_vb2_entry, *temp;
+
+	msm_vb2 = container_of(vb, struct msm_vb2_buffer, vb2_buf);
+
+	if (!msm_vb2) {
+		pr_err("%s:%d] vb2_buf NULL", __func__, __LINE__);
+		return -EINVAL;
+	}
+
+	stream = msm_vb2->stream;
+	if (!stream) {
+		pr_err("%s:%d] NULL stream", __func__, __LINE__);
+		return -EINVAL;
+	}
+
+	spin_lock_irqsave(&stream->stream_lock, flags);
+	list_for_each_entry_safe(msm_vb2_entry, temp, &(stream->queued_list),
+		list) {
+		if (msm_vb2_entry == msm_vb2) {
+			list_del_init(&msm_vb2_entry->list);
+			break;
+		}
+	}
+	spin_unlock_irqrestore(&stream->stream_lock, flags);
+	return 0;
+}
+
+static void msm_vb2_buf_cleanup(struct vb2_buffer *vb)
+{
+	struct msm_vb2_buffer *msm_vb2;
+	struct msm_stream *stream;
+	unsigned long flags;
+
+	msm_vb2 = container_of(vb, struct msm_vb2_buffer, vb2_buf);
+
+	if (!msm_vb2) {
+		pr_err("%s:%d] vb2 NULL", __func__, __LINE__);
+		return;
+	}
+
+	stream = msm_vb2->stream;
+	if (!stream) {
+		pr_err("%s:%d] NULL stream", __func__, __LINE__);
+		return;
+	}
+
+	spin_lock_irqsave(&stream->stream_lock, flags);
+	INIT_LIST_HEAD(&stream->queued_list);
+	spin_unlock_irqrestore(&stream->stream_lock, flags);
 }
 
 static struct vb2_ops msm_vb2_get_q_op = {
-	.queue_setup		= msm_vb2_queue_setup,
-	.buf_init		= msm_vb2_buf_init,
-	.buf_queue              = msm_vb2_buf_queue,
+	.queue_setup	= msm_vb2_queue_setup,
+	.buf_init	= msm_vb2_buf_init,
+	.buf_queue	= msm_vb2_buf_queue,
+	.buf_cleanup	= msm_vb2_buf_cleanup,
+	.buf_finish	= msm_vb2_buf_finish,
 };
 
 
@@ -101,7 +186,7 @@
 {
 	struct msm_stream *stream;
 	struct vb2_buffer *vb2_buf = NULL;
-	struct msm_vb2_buffer *msm_vb2;
+	struct msm_vb2_buffer *msm_vb2 = NULL;
 	unsigned long flags;
 
 	stream = msm_get_stream(session_id, stream_id);
@@ -115,18 +200,18 @@
 		goto end;
 	}
 
-	list_for_each_entry(vb2_buf, &(stream->vb2_q->queued_list),
-		queued_entry) {
+	list_for_each_entry(msm_vb2, &(stream->queued_list), list) {
+		vb2_buf = &(msm_vb2->vb2_buf);
 		if (vb2_buf->state != VB2_BUF_STATE_ACTIVE)
 			continue;
 
-		msm_vb2 = container_of(vb2_buf, struct msm_vb2_buffer, vb2_buf);
 		if (msm_vb2->in_freeq)
 			continue;
 
 		msm_vb2->in_freeq = 1;
 		goto end;
 	}
+	msm_vb2 = NULL;
 	vb2_buf = NULL;
 end:
 	spin_unlock_irqrestore(&stream->stream_lock, flags);
@@ -136,9 +221,15 @@
 static int msm_vb2_put_buf(struct vb2_buffer *vb, int session_id,
 				unsigned int stream_id)
 {
+	struct msm_stream *stream;
 	struct msm_vb2_buffer *msm_vb2;
 	int rc = 0;
+	unsigned long flags;
+	stream = msm_get_stream(session_id, stream_id);
+	if (IS_ERR_OR_NULL(stream))
+		return -EINVAL;
 
+	spin_lock_irqsave(&stream->stream_lock, flags);
 	if (vb) {
 		msm_vb2 =
 			container_of(vb, struct msm_vb2_buffer, vb2_buf);
@@ -151,6 +242,7 @@
 		pr_err("%s: VB buffer is null\n", __func__);
 		rc = -EINVAL;
 	}
+	spin_unlock_irqrestore(&stream->stream_lock, flags);
 	return rc;
 }
 
diff --git a/drivers/media/platform/msm/camera_v2/msm_vb2/msm_vb2.h b/drivers/media/platform/msm/camera_v2/msm_vb2/msm_vb2.h
index cecc85e..027d344 100644
--- a/drivers/media/platform/msm/camera_v2/msm_vb2/msm_vb2.h
+++ b/drivers/media/platform/msm/camera_v2/msm_vb2/msm_vb2.h
@@ -42,6 +42,7 @@
 	struct vb2_buffer vb2_buf;
 	struct list_head list;
 	int in_freeq;
+	struct msm_stream *stream;
 };
 
 struct msm_vb2_private_data {
@@ -60,6 +61,7 @@
 	/* vb2 buffer handling */
 	struct vb2_queue *vb2_q;
 	spinlock_t stream_lock;
+	struct list_head queued_list;
 };
 
 struct vb2_ops *msm_vb2_get_q_ops(void);
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 41234c3..ca5e646 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
@@ -754,6 +754,9 @@
 	case VIDIOC_MSM_CPP_CFG:
 		rc = msm_cpp_cfg(cpp_dev, ioctl_ptr);
 		break;
+	case VIDIOC_MSM_CPP_FLUSH_QUEUE:
+		rc = msm_cpp_send_frame_to_hardware(cpp_dev);
+		break;
 	case VIDIOC_MSM_CPP_GET_EVENTPAYLOAD: {
 		struct msm_device_queue *queue = &cpp_dev->eventData_q;
 		struct msm_queue_cmd *event_qcmd;
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 46002c3..b9fdc5e 100644
--- a/drivers/media/platform/msm/dvb/video/mpq_dvb_video.c
+++ b/drivers/media/platform/msm/dvb/video/mpq_dvb_video.c
@@ -28,7 +28,7 @@
 #include <linux/uaccess.h>
 #include <linux/wait.h>
 #include <linux/workqueue.h>
-#include <linux/android_pmem.h>
+
 #include <linux/clk.h>
 #include <linux/timer.h>
 #include <mach/msm_subsystem_map.h>
@@ -43,8 +43,6 @@
 #define ERR(x...) pr_err(x)
 
 #define MPQ_VID_DEC_NAME "mpq_vidc_dec"
-static unsigned int vidc_mmu_subsystem[] = {
-	MSM_SUBSYSTEM_VIDEO};
 
 static char vid_thread_names[DVB_MPQ_NUM_VIDEO_DEVICES][10] = {
 				"dvb-vid-0",
@@ -1060,10 +1058,7 @@
 {
 	struct vcd_property_hdr vcd_property_hdr;
 	struct vcd_property_h264_mv_buffer *vcd_h264_mv_buffer = NULL;
-	struct msm_mapped_buffer *mapped_buffer = NULL;
 	u32 vcd_status = VCD_ERR_FAIL;
-	u32 len = 0, flags = 0;
-	struct file *file;
 	int rc = 0;
 	unsigned long ionflag = 0;
 	unsigned long buffer_size = 0;
@@ -1084,28 +1079,8 @@
 	vcd_h264_mv_buffer->offset = mv_data->offset;
 
 	if (!vcd_get_ion_status()) {
-		if (get_pmem_file(vcd_h264_mv_buffer->pmem_fd,
-			(unsigned long *) (&(vcd_h264_mv_buffer->
-			physical_addr)),
-			(unsigned long *) (&vcd_h264_mv_buffer->
-						kernel_virtual_addr),
-			(unsigned long *) (&len), &file)) {
-			ERR("%s(): get_pmem_file failed\n", __func__);
-			return -EIO;
-		}
-		put_pmem_file(file);
-		flags = MSM_SUBSYSTEM_MAP_IOVA;
-		mapped_buffer = msm_subsystem_map_buffer(
-			(unsigned long)vcd_h264_mv_buffer->physical_addr, len,
-				flags, vidc_mmu_subsystem,
-				sizeof(vidc_mmu_subsystem)/
-				sizeof(unsigned int));
-		if (IS_ERR(mapped_buffer)) {
-			ERR("buffer map failed");
-			return PTR_ERR(mapped_buffer);
-		}
-		vcd_h264_mv_buffer->client_data = (void *) mapped_buffer;
-		vcd_h264_mv_buffer->dev_addr = (u8 *)mapped_buffer->iova[0];
+		pr_err("PMEM not available");
+		return -EINVAL;
 	} else {
 		client_ctx->h264_mv_ion_handle = ion_import_dma_buf(
 					client_ctx->user_ion_client,
diff --git a/drivers/media/platform/msm/vidc/msm_vidc_common.c b/drivers/media/platform/msm/vidc/msm_vidc_common.c
index e55c0f1..b71a816 100644
--- a/drivers/media/platform/msm/vidc/msm_vidc_common.c
+++ b/drivers/media/platform/msm/vidc/msm_vidc_common.c
@@ -11,6 +11,7 @@
  *
  */
 
+#include <linux/jiffies.h>
 #include <linux/sched.h>
 #include <linux/slab.h>
 #include <asm/div64.h>
@@ -21,7 +22,7 @@
 #include "msm_smem.h"
 #include "msm_vidc_debug.h"
 
-#define HW_RESPONSE_TIMEOUT (5 * 60 * 1000)
+#define HW_RESPONSE_TIMEOUT msecs_to_jiffies(200)
 
 #define IS_ALREADY_IN_STATE(__p, __d) ({\
 	int __rc = (__p >= __d);\
@@ -313,7 +314,7 @@
 	enum command_response cmd)
 {
 	int rc = 0;
-	rc = wait_for_completion_interruptible_timeout(
+	rc = wait_for_completion_timeout(
 		&inst->completions[SESSION_MSG_INDEX(cmd)],
 		msecs_to_jiffies(HW_RESPONSE_TIMEOUT));
 	if (!rc) {
diff --git a/drivers/media/platform/msm/vidc/msm_vidc_debug.c b/drivers/media/platform/msm/vidc/msm_vidc_debug.c
index 65542bc..62158b0 100644
--- a/drivers/media/platform/msm/vidc/msm_vidc_debug.c
+++ b/drivers/media/platform/msm/vidc/msm_vidc_debug.c
@@ -18,7 +18,7 @@
 int msm_vidc_debug = 0x3;
 int msm_fw_debug = 0x18;
 int msm_fw_debug_mode = 0x1;
-int msm_fw_low_power_mode = 0x1;
+int msm_fw_low_power_mode = 0x0;
 
 struct debug_buffer {
 	char ptr[MAX_DBG_BUF_SIZE];
diff --git a/drivers/media/platform/msm/vidc/q6_hfi.c b/drivers/media/platform/msm/vidc/q6_hfi.c
index 88dc4fe..d1948d1 100644
--- a/drivers/media/platform/msm/vidc/q6_hfi.c
+++ b/drivers/media/platform/msm/vidc/q6_hfi.c
@@ -1188,6 +1188,13 @@
 	return 0;
 }
 
+static int q6_hfi_get_stride_scanline(int color_fmt,
+	int width, int height, int *stride, int *scanlines) {
+	*stride = VENUS_Y_STRIDE(color_fmt, width);
+	*scanlines = VENUS_Y_SCANLINES(color_fmt, height);
+	return 0;
+}
+
 static void q6_init_hfi_callbacks(struct hfi_device *hdev)
 {
 	hdev->core_init = q6_hfi_core_init;
@@ -1223,6 +1230,7 @@
 	hdev->load_fw = q6_hfi_load_fw;
 	hdev->unload_fw = q6_hfi_unload_fw;
 	hdev->get_fw_info = q6_hfi_get_fw_info;
+	hdev->get_stride_scanline = q6_hfi_get_stride_scanline;
 }
 
 
diff --git a/drivers/media/platform/msm/vidc/venus_hfi.c b/drivers/media/platform/msm/vidc/venus_hfi.c
index 1b7ecf0..424af64 100644
--- a/drivers/media/platform/msm/vidc/venus_hfi.c
+++ b/drivers/media/platform/msm/vidc/venus_hfi.c
@@ -2002,12 +2002,8 @@
 		dprintk(VIDC_ERR, "Invalid params: %p\n", device);
 		return;
 	}
-	if (device->clocks_enabled) {
-		cl = &device->resources.clock[VCODEC_CLK];
-		clk_disable_unprepare(cl->clk);
-	}
 
-	for (i = VCODEC_CLK; i < VCODEC_MAX_CLKS; i++) {
+	for (i = 0; i < VCODEC_MAX_CLKS; i++) {
 		cl = &device->resources.clock[i];
 		clk_disable_unprepare(cl->clk);
 	}
@@ -2022,17 +2018,7 @@
 		dprintk(VIDC_ERR, "Invalid params: %p\n", device);
 		return -EINVAL;
 	}
-	if (!device->clocks_enabled) {
-		cl = &device->resources.clock[VCODEC_CLK];
-		rc = clk_prepare_enable(cl->clk);
-		if (rc) {
-			dprintk(VIDC_ERR, "Failed to enable clocks\n");
-			goto fail_clk_enable;
-		} else {
-			dprintk(VIDC_DBG, "Clock: %s enabled\n", cl->name);
-		}
-	}
-	for (i = VCODEC_CLK; i < VCODEC_MAX_CLKS; i++) {
+	for (i = 0; i < VCODEC_MAX_CLKS; i++) {
 		cl = &device->resources.clock[i];
 		rc = clk_prepare_enable(cl->clk);
 		if (rc) {
diff --git a/drivers/media/video/videobuf-msm-mem.c b/drivers/media/video/videobuf-msm-mem.c
index 9e2cc22..eeda13a 100644
--- a/drivers/media/video/videobuf-msm-mem.c
+++ b/drivers/media/video/videobuf-msm-mem.c
@@ -24,7 +24,7 @@
 #include <linux/pagemap.h>
 #include <linux/sched.h>
 #include <linux/io.h>
-#include <linux/android_pmem.h>
+
 #include <linux/memory_alloc.h>
 #include <media/videobuf-msm-mem.h>
 #include <media/msm_camera.h>
@@ -140,55 +140,6 @@
 	.close    = videobuf_vm_close,
 };
 
-/**
- * videobuf_pmem_contig_user_put() - reset pointer to user space buffer
- * @mem: per-buffer private videobuf-contig-pmem data
- *
- * This function resets the user space pointer
- */
-static void videobuf_pmem_contig_user_put(struct videobuf_contig_pmem *mem)
-{
-	if (mem->phyaddr) {
-		put_pmem_file(mem->file);
-		mem->is_userptr = 0;
-		mem->phyaddr = 0;
-		mem->size = 0;
-	}
-}
-
-/**
- * videobuf_pmem_contig_user_get() - setup user space memory pointer
- * @mem: per-buffer private videobuf-contig-pmem data
- * @vb: video buffer to map
- *
- * This function validates and sets up a pointer to user space memory.
- * Only physically contiguous pfn-mapped memory is accepted.
- *
- * Returns 0 if successful.
- */
-static int videobuf_pmem_contig_user_get(struct videobuf_contig_pmem *mem,
-					struct videobuf_buffer *vb)
-{
-	unsigned long kvstart;
-	unsigned long len;
-	int rc;
-
-	mem->size = PAGE_ALIGN(vb->size);
-	rc = get_pmem_file(vb->baddr, (unsigned long *)&mem->phyaddr,
-					&kvstart, &len, &mem->file);
-	if (rc < 0) {
-		pr_err("%s: get_pmem_file fd %lu error %d\n",
-					__func__, vb->baddr,
-							rc);
-		return rc;
-	}
-	mem->phyaddr += vb->boff;
-	mem->y_off = 0;
-	mem->cbcr_off = (vb->size)*2/3;
-	mem->is_userptr = 1;
-	return rc;
-}
-
 static struct videobuf_buffer *__videobuf_alloc(size_t size)
 {
 	struct videobuf_contig_pmem *mem;
@@ -229,12 +180,6 @@
 
 		/* All handling should be done by __videobuf_mmap_mapper() */
 		break;
-	case V4L2_MEMORY_USERPTR:
-		D("%s memory method USERPTR\n", __func__);
-
-		/* handle pointer from user space */
-		rc = videobuf_pmem_contig_user_get(mem, vb);
-		break;
 	case V4L2_MEMORY_OVERLAY:
 	default:
 		pr_err("%s memory method OVERLAY/unknown\n", __func__);
@@ -383,7 +328,6 @@
 
 	/* handle user space pointer case */
 	if (buf->baddr) {
-		videobuf_pmem_contig_user_put(mem);
 		return 0;
 	} else {
 		/* don't support read() method */
diff --git a/drivers/media/video/videobuf2-msm-mem.c b/drivers/media/video/videobuf2-msm-mem.c
index cd07db8..8dbb522 100644
--- a/drivers/media/video/videobuf2-msm-mem.c
+++ b/drivers/media/video/videobuf2-msm-mem.c
@@ -24,7 +24,7 @@
 #include <linux/pagemap.h>
 #include <linux/sched.h>
 #include <linux/io.h>
-#include <linux/android_pmem.h>
+
 #include <linux/memory_alloc.h>
 #include <media/videobuf2-msm-mem.h>
 #include <media/msm_camera.h>
@@ -177,15 +177,14 @@
 					struct ion_client *client,
 					int domain_num)
 {
-	unsigned long len;
 	int rc = 0;
-#ifndef CONFIG_MSM_MULTIMEDIA_USE_ION
-	unsigned long kvstart;
+#ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
+	unsigned long len;
 #endif
 	unsigned long paddr = 0;
 	if (mem->phyaddr != 0)
 		return 0;
-#ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
+#if defined(CONFIG_MSM_MULTIMEDIA_USE_ION)
 	mem->ion_handle = ion_import_dma_buf(client, (int)mem->vaddr);
 	if (IS_ERR_OR_NULL(mem->ion_handle)) {
 		pr_err("%s ION import failed\n", __func__);
@@ -195,17 +194,8 @@
 		SZ_4K, 0, (unsigned long *)&mem->phyaddr, &len, 0, 0);
 	if (rc < 0)
 		ion_free(client, mem->ion_handle);
-#elif CONFIG_ANDROID_PMEM
-	rc = get_pmem_file((int)mem->vaddr, (unsigned long *)&mem->phyaddr,
-					&kvstart, &len, &mem->file);
-	if (rc < 0) {
-		pr_err("%s: get_pmem_file fd %d error %d\n",
-					__func__, (int)mem->vaddr, rc);
-		return rc;
-	}
 #else
 	paddr = 0;
-	kvstart = 0;
 #endif
 	if (offset)
 		mem->offset = *offset;
@@ -224,12 +214,10 @@
 				struct ion_client *client, int domain_num)
 {
 	if (mem->is_userptr) {
-#ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
+#if defined(CONFIG_MSM_MULTIMEDIA_USE_ION)
 		ion_unmap_iommu(client, mem->ion_handle,
 				domain_num, 0);
 		ion_free(client, mem->ion_handle);
-#elif CONFIG_ANDROID_PMEM
-		put_pmem_file(mem->file);
 #endif
 	}
 	mem->is_userptr = 0;
diff --git a/drivers/mmc/core/host.c b/drivers/mmc/core/host.c
index 0d7d98b..c0a4cef 100644
--- a/drivers/mmc/core/host.c
+++ b/drivers/mmc/core/host.c
@@ -4,7 +4,7 @@
  *  Copyright (C) 2003 Russell King, All Rights Reserved.
  *  Copyright (C) 2007-2008 Pierre Ossman
  *  Copyright (C) 2010 Linus Walleij
- *  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 as
@@ -43,6 +43,9 @@
 	struct mmc_host *host = cls_dev_to_mmc_host(dev);
 	int ret = 0;
 
+	if (!mmc_use_core_runtime_pm(host))
+		return 0;
+
 	ret = mmc_suspend_host(host);
 	if (ret < 0)
 		pr_err("%s: %s: suspend host failed: %d\n", mmc_hostname(host),
@@ -56,6 +59,9 @@
 	struct mmc_host *host = cls_dev_to_mmc_host(dev);
 	int ret = 0;
 
+	if (!mmc_use_core_runtime_pm(host))
+		return 0;
+
 	ret = mmc_resume_host(host);
 	if (ret < 0) {
 		pr_err("%s: %s: resume host: failed: ret: %d\n",
@@ -72,6 +78,9 @@
 	struct mmc_host *host = cls_dev_to_mmc_host(dev);
 	int ret = 0;
 
+	if (!mmc_use_core_runtime_pm(host))
+		return 0;
+
 	if (!pm_runtime_suspended(dev)) {
 		ret = mmc_suspend_host(host);
 		if (ret < 0)
@@ -86,6 +95,9 @@
 	struct mmc_host *host = cls_dev_to_mmc_host(dev);
 	int ret = 0;
 
+	if (!mmc_use_core_runtime_pm(host))
+		return 0;
+
 	if (!pm_runtime_suspended(dev)) {
 		ret = mmc_resume_host(host);
 		if (ret < 0)
diff --git a/drivers/net/ethernet/msm/ecm_ipa.c b/drivers/net/ethernet/msm/ecm_ipa.c
index 28ba41a..41dd6e7 100644
--- a/drivers/net/ethernet/msm/ecm_ipa.c
+++ b/drivers/net/ethernet/msm/ecm_ipa.c
@@ -118,8 +118,8 @@
 
 static int ecm_ipa_rules_cfg(struct ecm_ipa_dev *dev,
 		const void *dst_mac, const void *src_mac);
-static int ecm_ipa_register_tx(struct ecm_ipa_dev *dev);
-static void ecm_ipa_deregister_tx(struct ecm_ipa_dev *dev);
+static int ecm_ipa_register_properties(void);
+static void ecm_ipa_deregister_properties(void);
 static int ecm_ipa_debugfs_init(struct ecm_ipa_dev *dev);
 static void ecm_ipa_debugfs_destroy(struct ecm_ipa_dev *dev);
 static int ecm_ipa_debugfs_tx_open(struct inode *inode, struct file *file);
@@ -262,13 +262,13 @@
 	strlcpy(ipv4_hdr->name, ECM_IPA_IPV4_HDR_NAME, IPA_RESOURCE_NAME_MAX);
 	memcpy(eth_ipv4->h_dest, dst_mac, ETH_ALEN);
 	memcpy(eth_ipv4->h_source, src_mac, ETH_ALEN);
-	eth_ipv4->h_proto = ETH_P_IP;
+	eth_ipv4->h_proto = htons(ETH_P_IP);
 	ipv4_hdr->hdr_len = ETH_HLEN;
 	ipv4_hdr->is_partial = 0;
 	strlcpy(ipv6_hdr->name, ECM_IPA_IPV6_HDR_NAME, IPA_RESOURCE_NAME_MAX);
 	memcpy(eth_ipv6->h_dest, dst_mac, ETH_ALEN);
 	memcpy(eth_ipv6->h_source, src_mac, ETH_ALEN);
-	eth_ipv6->h_proto = ETH_P_IPV6;
+	eth_ipv6->h_proto = htons(ETH_P_IPV6);
 	ipv6_hdr->hdr_len = ETH_HLEN;
 	ipv6_hdr->is_partial = 0;
 	hdrs->commit = 1;
@@ -320,14 +320,29 @@
 		ECM_IPA_ERROR("ipa_del_hdr failed");
 }
 
-static int ecm_ipa_register_tx(struct ecm_ipa_dev *dev)
+/* ecm_ipa_register_properties() - set Tx/Rx properties for ipacm
+ *
+ * Register ecm0 interface with 2 Tx properties and 2 Rx properties:
+ * The 2 Tx properties are for data flowing from IPA to USB, they
+ * have Header-Insertion properties both for Ipv4 and Ipv6 Ethernet framing.
+ * The 2 Rx properties are for data flowing from USB to IPA, they have
+ * simple rule which always "hit".
+ *
+ */
+static int ecm_ipa_register_properties(void)
 {
 	struct ipa_tx_intf tx_properties = {0};
 	struct ipa_ioc_tx_intf_prop properties[2] = { {0}, {0} };
 	struct ipa_ioc_tx_intf_prop *ipv4_property;
 	struct ipa_ioc_tx_intf_prop *ipv6_property;
+	struct ipa_ioc_rx_intf_prop rx_ioc_properties[2] = { {0}, {0} };
+	struct ipa_rx_intf rx_properties = {0};
+	struct ipa_ioc_rx_intf_prop *rx_ipv4_property;
+	struct ipa_ioc_rx_intf_prop *rx_ipv6_property;
 	int result = 0;
+
 	ECM_IPA_LOG_ENTRY();
+
 	tx_properties.prop = properties;
 	ipv4_property = &tx_properties.prop[0];
 	ipv4_property->ip = IPA_IP_v4;
@@ -340,18 +355,32 @@
 	strlcpy(ipv6_property->hdr_name, ECM_IPA_IPV6_HDR_NAME,
 			IPA_RESOURCE_NAME_MAX);
 	tx_properties.num_props = 2;
-	result = ipa_register_intf("ecm0", &tx_properties, NULL);
+
+	rx_properties.prop = rx_ioc_properties;
+	rx_ipv4_property = &rx_properties.prop[0];
+	rx_ipv4_property->ip = IPA_IP_v4;
+	rx_ipv4_property->attrib.attrib_mask = 0;
+	rx_ipv4_property->src_pipe = IPA_CLIENT_USB_PROD;
+	rx_ipv6_property = &rx_properties.prop[1];
+	rx_ipv6_property->ip = IPA_IP_v6;
+	rx_ipv6_property->attrib.attrib_mask = 0;
+	rx_ipv6_property->src_pipe = IPA_CLIENT_USB_PROD;
+	rx_properties.num_props = 2;
+
+	result = ipa_register_intf("ecm0", &tx_properties, &rx_properties);
 	if (result)
-		ECM_IPA_ERROR("fail on Tx_prop registration\n");
+		ECM_IPA_ERROR("fail on Tx/Rx properties registration\n");
+
 	ECM_IPA_LOG_EXIT();
+
 	return result;
 }
 
-static void ecm_ipa_deregister_tx(struct ecm_ipa_dev *dev)
+static void ecm_ipa_deregister_properties(void)
 {
 	int result;
 	ECM_IPA_LOG_ENTRY();
-	result = ipa_deregister_intf(dev->net->name);
+	result = ipa_deregister_intf("ecm0");
 	if (result)
 		ECM_IPA_DEBUG("Fail on Tx prop deregister\n");
 	ECM_IPA_LOG_EXIT();
@@ -407,12 +436,12 @@
 		goto fail_set_device_ethernet;
 	}
 	ECM_IPA_DEBUG("Ethernet header insertion was set\n");
-	result = ecm_ipa_register_tx(dev);
+	result = ecm_ipa_register_properties();
 	if (result) {
 		ECM_IPA_ERROR("fail on properties set\n");
 		goto fail_register_tx;
 	}
-	ECM_IPA_DEBUG("ECM Tx properties were registered\n");
+	ECM_IPA_DEBUG("ECM 2 Tx and 2 Rx properties were registered\n");
 	result = register_netdev(net);
 	if (result) {
 		ECM_IPA_ERROR("register_netdev failed: %d\n", result);
@@ -422,7 +451,7 @@
 	ECM_IPA_LOG_EXIT();
 	return 0;
 fail_register_netdev:
-	ecm_ipa_deregister_tx(dev);
+	ecm_ipa_deregister_properties();
 fail_register_tx:
 fail_set_device_ethernet:
 	ecm_ipa_rules_destroy(dev);
diff --git a/drivers/net/usb/usbnet.c b/drivers/net/usb/usbnet.c
index e9130f6..fa0c568 100644
--- a/drivers/net/usb/usbnet.c
+++ b/drivers/net/usb/usbnet.c
@@ -35,7 +35,6 @@
 
 #include <linux/module.h>
 #include <linux/init.h>
-#include <linux/if_arp.h>
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
 #include <linux/ctype.h>
@@ -362,9 +361,6 @@
 		return -ENOMEM;
 	}
 
-	if (dev->net->type != ARPHRD_RAWIP)
-		skb_reserve(skb, NET_IP_ALIGN);
-
 	entry = (struct skb_data *) skb->cb;
 	entry->urb = urb;
 	entry->dev = dev;
diff --git a/drivers/power/qpnp-bms.c b/drivers/power/qpnp-bms.c
index 0fdadb9..bc6f289 100644
--- a/drivers/power/qpnp-bms.c
+++ b/drivers/power/qpnp-bms.c
@@ -115,8 +115,7 @@
 
 	u8				revision1;
 	u8				revision2;
-	int				charger_status;
-	bool				online;
+	int				battery_present;
 	/* platform data */
 	int				r_sense_uohm;
 	unsigned int			v_cutoff_uv;
@@ -149,6 +148,9 @@
 	int				shutdown_soc;
 	int				shutdown_iavg_ma;
 
+	struct wake_lock		low_voltage_wake_lock;
+	bool				low_voltage_wake_lock_held;
+	int				low_voltage_threshold;
 	int				low_soc_calc_threshold;
 	int				low_soc_calculate_soc_ms;
 	int				calculate_soc_ms;
@@ -204,8 +206,7 @@
 };
 
 static enum power_supply_property msm_bms_power_props[] = {
-	POWER_SUPPLY_PROP_STATUS,
-	POWER_SUPPLY_PROP_ONLINE,
+	POWER_SUPPLY_PROP_PRESENT,
 	POWER_SUPPLY_PROP_CAPACITY,
 	POWER_SUPPLY_PROP_CURRENT_NOW,
 	POWER_SUPPLY_PROP_CURRENT_MAX,
@@ -1141,7 +1142,11 @@
 		pr_err("vadc read failed with rc: %d\n", rc);
 		return rc;
 	}
-	*ibat_ua = (int)i_result.result_ua;
+	/*
+	 * reverse the current read by the iadc, since the bms uses
+	 * flipped battery current polarity.
+	 */
+	*ibat_ua = -1 * (int)i_result.result_ua;
 	*vbat_uv = (int)v_result.physical;
 
 	return 0;
@@ -1285,6 +1290,25 @@
 	return chip->prev_chg_soc;
 }
 
+static void very_low_voltage_check(struct qpnp_bms_chip *chip, int vbat_uv)
+{
+	/*
+	 * if battery is very low (v_cutoff voltage + 20mv) hold
+	 * a wakelock untill soc = 0%
+	 */
+	if (vbat_uv <= chip->low_voltage_threshold
+			&& !chip->low_voltage_wake_lock_held) {
+		pr_debug("voltage = %d low holding wakelock\n", vbat_uv);
+		wake_lock(&chip->low_voltage_wake_lock);
+		chip->low_voltage_wake_lock_held = 1;
+	} else if (vbat_uv > chip->low_voltage_threshold
+			&& chip->low_voltage_wake_lock_held) {
+		pr_debug("voltage = %d releasing wakelock\n", vbat_uv);
+		chip->low_voltage_wake_lock_held = 0;
+		wake_unlock(&chip->low_voltage_wake_lock);
+	}
+}
+
 static int adjust_soc(struct qpnp_bms_chip *chip, struct soc_params *params,
 							int soc, int batt_temp)
 {
@@ -1305,6 +1329,8 @@
 		goto out;
 	}
 
+	very_low_voltage_check(chip, vbat_uv);
+
 	delta_ocv_uv_limit = DIV_ROUND_CLOSEST(ibat_ua, 1000);
 
 	ocv_est_uv = vbat_uv + (ibat_ua * params->rbatt_mohm)/1000;
@@ -1620,7 +1646,8 @@
 				calculate_soc_delayed_work.work);
 	int soc = recalculate_soc(chip);
 
-	if (soc < chip->low_soc_calc_threshold)
+	if (soc < chip->low_soc_calc_threshold
+			|| chip->low_voltage_wake_lock_held)
 		schedule_delayed_work(&chip->calculate_soc_delayed_work,
 			round_jiffies_relative(msecs_to_jiffies
 			(chip->low_soc_calculate_soc_ms)));
@@ -1838,24 +1865,15 @@
 	return chip->fcc;
 }
 
-static bool get_prop_bms_online(struct qpnp_bms_chip *chip)
+static int get_prop_bms_present(struct qpnp_bms_chip *chip)
 {
-	return chip->online;
+	return chip->battery_present;
 }
 
-static int get_prop_bms_status(struct qpnp_bms_chip *chip)
+static void set_prop_bms_present(struct qpnp_bms_chip *chip, int present)
 {
-	return chip->charger_status;
-}
-
-static void set_prop_bms_online(struct qpnp_bms_chip *chip, bool online)
-{
-	chip->online = online;
-}
-
-static void set_prop_bms_status(struct qpnp_bms_chip *chip, int status)
-{
-	chip->charger_status = status;
+	if (chip->battery_present != present)
+		chip->battery_present = present;
 }
 
 static void qpnp_bms_external_power_changed(struct power_supply *psy)
@@ -1882,11 +1900,8 @@
 	case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN:
 		val->intval = get_prop_bms_charge_full_design(chip);
 		break;
-	case POWER_SUPPLY_PROP_STATUS:
-		val->intval = get_prop_bms_status(chip);
-		break;
-	case POWER_SUPPLY_PROP_ONLINE:
-		val->intval = get_prop_bms_online(chip);
+	case POWER_SUPPLY_PROP_PRESENT:
+		val->intval = get_prop_bms_present(chip);
 		break;
 	default:
 		return -EINVAL;
@@ -1902,11 +1917,8 @@
 								bms_psy);
 
 	switch (psp) {
-	case POWER_SUPPLY_PROP_ONLINE:
-		set_prop_bms_online(chip, val->intval);
-		break;
-	case POWER_SUPPLY_PROP_STATUS:
-		set_prop_bms_status(chip, (bool)val->intval);
+	case POWER_SUPPLY_PROP_PRESENT:
+		set_prop_bms_present(chip, val->intval);
 		break;
 	default:
 		return -EINVAL;
@@ -2121,6 +2133,7 @@
 			"ocv-voltage-high-threshold-uv", rc);
 	SPMI_PROP_READ(ocv_low_threshold_uv,
 			"ocv-voltage-low-threshold-uv", rc);
+	SPMI_PROP_READ(low_voltage_threshold, "low-voltage-threshold", rc);
 
 	if (chip->adjust_soc_low_threshold >= 45)
 		chip->adjust_soc_low_threshold = 45;
@@ -2294,6 +2307,7 @@
 static int __devinit qpnp_bms_probe(struct spmi_device *spmi)
 {
 	struct qpnp_bms_chip *chip;
+	union power_supply_propval retval = {0,};
 	int rc, vbatt;
 
 	chip = kzalloc(sizeof *chip, GFP_KERNEL);
@@ -2373,6 +2387,8 @@
 
 	wake_lock_init(&chip->soc_wake_lock, WAKE_LOCK_SUSPEND,
 			"qpnp_soc_lock");
+	wake_lock_init(&chip->low_voltage_wake_lock, WAKE_LOCK_SUSPEND,
+			"qpnp_low_voltage_lock");
 	INIT_DELAYED_WORK(&chip->calculate_soc_delayed_work,
 			calculate_soc_work);
 
@@ -2381,6 +2397,14 @@
 	dev_set_drvdata(&spmi->dev, chip);
 	device_init_wakeup(&spmi->dev, 1);
 
+	if (!chip->batt_psy)
+		chip->batt_psy = power_supply_get_by_name("battery");
+	if (chip->batt_psy) {
+		chip->batt_psy->get_property(chip->batt_psy,
+					POWER_SUPPLY_PROP_PRESENT, &retval);
+		chip->battery_present = retval.intval;
+	}
+
 	calculate_soc_work(&(chip->calculate_soc_delayed_work.work));
 
 	/* setup & register the battery power supply */
@@ -2417,6 +2441,7 @@
 
 unregister_dc:
 	wake_lock_destroy(&chip->soc_wake_lock);
+	wake_lock_destroy(&chip->low_voltage_wake_lock);
 	power_supply_unregister(&chip->bms_psy);
 	dev_set_drvdata(&spmi->dev, NULL);
 error_resource:
diff --git a/drivers/power/qpnp-charger.c b/drivers/power/qpnp-charger.c
index 3d9e4b7..eb0d6d4 100644
--- a/drivers/power/qpnp-charger.c
+++ b/drivers/power/qpnp-charger.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2013 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
@@ -546,6 +546,9 @@
 		power_supply_changed(&chip->batt_psy);
 	}
 
+	if (chip->bms_psy)
+		power_supply_set_present(chip->bms_psy, batt_present);
+
 	return IRQ_HANDLED;
 }
 
@@ -1638,6 +1641,7 @@
 	struct qpnp_chg_chip	*chip;
 	struct resource *resource;
 	struct spmi_resource *spmi_resource;
+	bool present;
 	int rc = 0;
 
 	chip = kzalloc(sizeof *chip, GFP_KERNEL);
@@ -1936,6 +1940,14 @@
 		if (rc)
 			goto fail_chg_enable;
 
+		/* if bms exists, notify it of the presence of the battery */
+		if (!chip->bms_psy)
+			chip->bms_psy = power_supply_get_by_name("bms");
+		if (chip->bms_psy) {
+			present = get_prop_batt_present(chip);
+			power_supply_set_present(chip->bms_psy, present);
+		}
+
 		chip->batt_psy.name = "battery";
 		chip->batt_psy.type = POWER_SUPPLY_TYPE_BATTERY;
 		chip->batt_psy.properties = msm_batt_power_props;
diff --git a/drivers/slimbus/slimbus.c b/drivers/slimbus/slimbus.c
index bec0399..e9f056e 100644
--- a/drivers/slimbus/slimbus.c
+++ b/drivers/slimbus/slimbus.c
@@ -2568,11 +2568,12 @@
 					struct slim_pending_ch, pending);
 		struct slim_ich *slc = &ctrl->chans[pch->chan];
 		u32 sl = slc->seglen << slc->rootexp;
-		if (revert) {
+		if (revert || slc->def > 0) {
 			if (slc->coeff == SLIM_COEFF_3)
 				sl *= 3;
 			ctrl->sched.usedslots += sl;
-			slc->def = 1;
+			if (revert)
+				slc->def++;
 			slc->state = SLIM_CH_ACTIVE;
 		} else
 			slim_remove_ch(ctrl, slc);
@@ -2635,7 +2636,11 @@
 			/* Disconnect source port to free it up */
 			if (SLIM_HDL_TO_LA(slc->srch) == sb->laddr)
 				slc->srch = 0;
-			if (slc->def != 0) {
+			/*
+			 * If controller overrides BW allocation,
+			 * delete this in remove channel itself
+			 */
+			if (slc->def != 0 && !ctrl->allocbw) {
 				list_del(&pch->pending);
 				kfree(pch);
 			}
diff --git a/drivers/thermal/msm8974-tsens.c b/drivers/thermal/msm8974-tsens.c
index b04213c..7d3664a 100644
--- a/drivers/thermal/msm8974-tsens.c
+++ b/drivers/thermal/msm8974-tsens.c
@@ -54,6 +54,7 @@
 #define TSENS_SW_RST			BIT(1)
 #define TSENS_ADC_CLK_SEL		BIT(2)
 #define TSENS_SENSOR0_SHIFT		3
+#define TSENS_62_5_MS_MEAS_PERIOD	1
 #define TSENS_312_5_MS_MEAS_PERIOD	2
 #define TSENS_MEAS_PERIOD_SHIFT		18
 
@@ -239,6 +240,7 @@
 	struct platform_device		*pdev;
 	bool				prev_reading_avail;
 	bool				calibration_less_mode;
+	bool				tsens_local_init;
 	int				tsens_factor;
 	uint32_t			tsens_num_sensor;
 	int				tsens_irq;
@@ -570,24 +572,28 @@
 	unsigned int reg_cntl = 0;
 	unsigned int i;
 
-	reg_cntl = readl_relaxed(TSENS_CTRL_ADDR(tmdev->tsens_addr));
-	writel_relaxed(reg_cntl | TSENS_SW_RST,
+	if (tmdev->tsens_local_init) {
+		writel_relaxed(reg_cntl, TSENS_CTRL_ADDR(tmdev->tsens_addr));
+		writel_relaxed(reg_cntl | TSENS_SW_RST,
 			TSENS_CTRL_ADDR(tmdev->tsens_addr));
-	reg_cntl |= ((TSENS_312_5_MS_MEAS_PERIOD << TSENS_MEAS_PERIOD_SHIFT) |
+		reg_cntl |= ((TSENS_62_5_MS_MEAS_PERIOD <<
+		TSENS_MEAS_PERIOD_SHIFT) |
 		(((1 << tmdev->tsens_num_sensor) - 1) << TSENS_SENSOR0_SHIFT) |
 		TSENS_EN);
-	writel_relaxed(reg_cntl, TSENS_CTRL_ADDR(tmdev->tsens_addr));
-	writel_relaxed(TSENS_GLOBAL_INIT_DATA,
+		writel_relaxed(reg_cntl, TSENS_CTRL_ADDR(tmdev->tsens_addr));
+		writel_relaxed(TSENS_GLOBAL_INIT_DATA,
 			TSENS_GLOBAL_CONFIG(tmdev->tsens_addr));
-	writel_relaxed(TSENS_S0_MAIN_CFG_INIT_DATA,
+		writel_relaxed(TSENS_S0_MAIN_CFG_INIT_DATA,
 			TSENS_S0_MAIN_CONFIG(tmdev->tsens_addr));
-	for (i = 0; i < tmdev->tsens_num_sensor; i++) {
-		writel_relaxed(TSENS_SN_MIN_MAX_STATUS_CTRL_DATA,
+		for (i = 0; i < tmdev->tsens_num_sensor; i++) {
+			writel_relaxed(TSENS_SN_MIN_MAX_STATUS_CTRL_DATA,
 			TSENS_SN_MIN_MAX_STATUS_CTRL(tmdev->tsens_addr)
 				+ (i * TSENS_SN_ADDR_OFFSET));
-		writel_relaxed(TSENS_SN_REMOTE_CFG_DATA,
+			writel_relaxed(TSENS_SN_REMOTE_CFG_DATA,
 			TSENS_SN_REMOTE_CONFIG(tmdev->tsens_addr)
 				+ (i * TSENS_SN_ADDR_OFFSET));
+		}
+		pr_debug("Local TSENS control initialization\n");
 	}
 	writel_relaxed(TSENS_INTERRUPT_EN,
 		TSENS_UPPER_LOWER_INTERRUPT_CTRL(tmdev->tsens_addr));
@@ -1156,6 +1162,8 @@
 	tmdev->calibration_less_mode = of_property_read_bool(of_node,
 				"qcom,calibration-less-mode");
 	tmdev->calib_mode = calib_type;
+	tmdev->tsens_local_init = of_property_read_bool(of_node,
+				"qcom,tsens_local_init");
 
 	tmdev->tsens_irq = platform_get_irq(pdev, 0);
 	if (tmdev->tsens_irq < 0) {
diff --git a/drivers/tty/serial/msm_serial_hs.c b/drivers/tty/serial/msm_serial_hs.c
index 65e4989..63acde1 100644
--- a/drivers/tty/serial/msm_serial_hs.c
+++ b/drivers/tty/serial/msm_serial_hs.c
@@ -1746,7 +1746,8 @@
 	if (msm_uport->rx.flush != FLUSH_SHUTDOWN) {
 		if (msm_uport->rx.flush == FLUSH_NONE) {
 			msm_hs_stop_rx_locked(uport);
-			msm_uport->rx_discard_flush_issued = true;
+			if (!is_blsp_uart(msm_uport))
+				msm_uport->rx_discard_flush_issued = true;
 		}
 
 		spin_unlock_irqrestore(&uport->lock, flags);
diff --git a/drivers/usb/gadget/u_serial.c b/drivers/usb/gadget/u_serial.c
index 502c33a..350e723 100644
--- a/drivers/usb/gadget/u_serial.c
+++ b/drivers/usb/gadget/u_serial.c
@@ -1048,6 +1048,13 @@
 	struct gs_port		*port = tty->driver_data;
 	unsigned long		flags;
 
+	/*
+	 * tty's driver data is set to NULL during port close.  Nothing
+	 * to do here.
+	 */
+	if (!port)
+		return;
+
 	spin_lock_irqsave(&port->port_lock, flags);
 	if (port->port_usb) {
 		/* Kickstart read queue processing.  We don't do xon/xoff,
diff --git a/drivers/usb/host/ehci-msm-hsic.c b/drivers/usb/host/ehci-msm-hsic.c
index 8c0894c..ca4b01a 100644
--- a/drivers/usb/host/ehci-msm-hsic.c
+++ b/drivers/usb/host/ehci-msm-hsic.c
@@ -624,6 +624,15 @@
 	int ret;
 	void __iomem *reg;
 
+	if (pdata && pdata->resume_gpio) {
+		ret = gpio_request(pdata->resume_gpio, "HSIC_RESUME_GPIO");
+		if (ret < 0) {
+			dev_err(mehci->dev,
+				"gpio req failed for hsic resume:%d\n", ret);
+			pdata->resume_gpio = 0;
+		}
+	}
+
 	/* HSIC init sequence when HSIC signals (Strobe/Data) are
 	routed via GPIOs */
 	if (pdata && pdata->strobe && pdata->data) {
@@ -645,7 +654,7 @@
 		ret = msm_hsic_config_gpios(mehci, 1);
 		if (ret) {
 			dev_err(mehci->dev, " gpio configuarion failed\n");
-			return ret;
+			goto free_resume_gpio;
 		}
 		if (pdata->strobe_pad_offset) {
 			/* Set CORE_CTL_EN in STROBE GPIO PAD_CTL register */
@@ -694,6 +703,12 @@
 	ulpi_write(mehci, ULPI_IFC_CTRL_AUTORESUME, ULPI_CLR(ULPI_IFC_CTRL));
 
 	return 0;
+
+free_resume_gpio:
+	if (pdata && pdata->resume_gpio)
+		gpio_free(pdata->resume_gpio);
+
+	return ret;
 }
 
 #define PHY_SUSPEND_TIMEOUT_USEC	(500 * 1000)
@@ -1312,6 +1327,10 @@
 	struct ehci_hcd		*ehci = hcd_to_ehci(hcd);
 	u32			temp;
 	struct task_struct	*resume_thread = NULL;
+	struct msm_hsic_host_platform_data *pdata =  mehci->dev->platform_data;
+
+	if (pdata->resume_gpio)
+		gpio_direction_output(pdata->resume_gpio, 1);
 
 	mehci->resume_status = 0;
 	resume_thread = kthread_run(msm_hsic_resume_thread,
@@ -1351,6 +1370,9 @@
 
 	spin_unlock_irq(&ehci->lock);
 
+	if (pdata->resume_gpio)
+		gpio_direction_output(pdata->resume_gpio, 0);
+
 	return 0;
 }
 
@@ -1781,6 +1803,11 @@
 		res_gpio = 0;
 	pdata->data = res_gpio;
 
+	res_gpio = of_get_named_gpio(node, "hsic,resume-gpio", 0);
+	if (res_gpio < 0)
+		res_gpio = 0;
+	pdata->resume_gpio = res_gpio;
+
 	pdata->ignore_cal_pad_config = of_property_read_bool(node,
 					"hsic,ignore-cal-pad-config");
 	of_property_read_u32(node, "hsic,strobe-pad-offset",
@@ -2099,6 +2126,10 @@
 	destroy_workqueue(ehci_wq);
 
 	msm_hsic_config_gpios(mehci, 0);
+
+	if (pdata && pdata->resume_gpio)
+		gpio_free(pdata->resume_gpio);
+
 	msm_hsic_init_vddcx(mehci, 0);
 	msm_hsic_init_gdsc(mehci, 0);
 
diff --git a/drivers/video/msm/mdss/mdss_dsi.c b/drivers/video/msm/mdss/mdss_dsi.c
index 9c77445..bfcd7ec 100644
--- a/drivers/video/msm/mdss/mdss_dsi.c
+++ b/drivers/video/msm/mdss/mdss_dsi.c
@@ -28,48 +28,73 @@
 
 static unsigned char *mdss_dsi_base;
 
-static int mdss_dsi_regulator_init(struct platform_device *pdev,
-				   struct dsi_drv_cm_data *dsi_drv)
+static int mdss_dsi_regulator_init(struct platform_device *pdev)
 {
-	int ret;
+	int ret = 0;
+	struct mdss_dsi_ctrl_pdata *ctrl_pdata = NULL;
+	struct dsi_drv_cm_data *dsi_drv = NULL;
 
-	dsi_drv->vdd_vreg = devm_regulator_get(&pdev->dev, "vdd");
-	if (IS_ERR(dsi_drv->vdd_vreg)) {
-		pr_err("could not get 8941_l22, rc = %ld\n",
-				PTR_ERR(dsi_drv->vdd_vreg));
-		return -ENODEV;
-	}
-
-	ret = regulator_set_voltage(dsi_drv->vdd_vreg, 3000000, 3000000);
-	if (ret) {
-		pr_err("vdd_vreg->set_voltage failed, rc=%d\n", ret);
+	if (!pdev) {
+		pr_err("%s: invalid input\n", __func__);
 		return -EINVAL;
 	}
 
-	dsi_drv->vdd_io_vreg = devm_regulator_get(&pdev->dev, "vdd_io");
-	if (IS_ERR(dsi_drv->vdd_io_vreg)) {
-		pr_err("could not get 8941_l12, rc = %ld\n",
-				PTR_ERR(dsi_drv->vdd_io_vreg));
-		return -ENODEV;
-	}
-
-	ret = regulator_set_voltage(dsi_drv->vdd_io_vreg, 1800000, 1800000);
-	if (ret) {
-		pr_err("vdd_io_vreg->set_voltage failed, rc=%d\n", ret);
+	ctrl_pdata = platform_get_drvdata(pdev);
+	if (!ctrl_pdata) {
+		pr_err("%s: invalid driver data\n", __func__);
 		return -EINVAL;
 	}
 
-	dsi_drv->dsi_vreg = devm_regulator_get(&pdev->dev, "vreg");
-	if (IS_ERR(dsi_drv->dsi_vreg)) {
-		pr_err("could not get 8941_l2, rc = %ld\n",
-				PTR_ERR(dsi_drv->dsi_vreg));
-		return -ENODEV;
-	}
+	dsi_drv = &(ctrl_pdata->shared_pdata);
+	if (ctrl_pdata->power_data.num_vreg > 0) {
+		ret = msm_dss_config_vreg(&pdev->dev,
+				ctrl_pdata->power_data.vreg_config,
+				ctrl_pdata->power_data.num_vreg, 1);
+	} else {
+		dsi_drv->vdd_vreg = devm_regulator_get(&pdev->dev, "vdd");
+		if (IS_ERR(dsi_drv->vdd_vreg)) {
+			pr_err("%s: could not get vdda vreg, rc=%ld\n",
+				__func__, PTR_ERR(dsi_drv->vdd_vreg));
+			return PTR_ERR(dsi_drv->vdd_vreg);
+		}
 
-	ret = regulator_set_voltage(dsi_drv->dsi_vreg, 1200000, 1200000);
-	if (ret) {
-		pr_err("dsi_vreg->set_voltage failed, rc=%d\n", ret);
-		return -EINVAL;
+		ret = regulator_set_voltage(dsi_drv->vdd_vreg, 3000000,
+				3000000);
+		if (ret) {
+			pr_err("%s: set voltage failed on vdda vreg, rc=%d\n",
+				__func__, ret);
+			return ret;
+		}
+
+		dsi_drv->vdd_io_vreg = devm_regulator_get(&pdev->dev, "vddio");
+		if (IS_ERR(dsi_drv->vdd_io_vreg)) {
+			pr_err("%s: could not get vddio reg, rc=%ld\n",
+				__func__, PTR_ERR(dsi_drv->vdd_io_vreg));
+			return PTR_ERR(dsi_drv->vdd_io_vreg);
+		}
+
+		ret = regulator_set_voltage(dsi_drv->vdd_io_vreg, 1800000,
+				1800000);
+		if (ret) {
+			pr_err("%s: set voltage failed on vddio vreg, rc=%d\n",
+				__func__, ret);
+			return ret;
+		}
+
+		dsi_drv->vdda_vreg = devm_regulator_get(&pdev->dev, "vdda");
+		if (IS_ERR(dsi_drv->vdda_vreg)) {
+			pr_err("%s: could not get vdda vreg, rc=%ld\n",
+				__func__, PTR_ERR(dsi_drv->vdda_vreg));
+			return PTR_ERR(dsi_drv->vdda_vreg);
+		}
+
+		ret = regulator_set_voltage(dsi_drv->vdda_vreg, 1200000,
+				1200000);
+		if (ret) {
+			pr_err("%s: set voltage failed on vdda vreg, rc=%d\n",
+				__func__, ret);
+			return ret;
+		}
 	}
 
 	return 0;
@@ -90,51 +115,73 @@
 	pr_debug("%s: enable=%d\n", __func__, enable);
 
 	if (enable) {
-		ret = regulator_set_optimum_mode
-		  ((ctrl_pdata->shared_pdata).vdd_vreg, 100000);
-		if (ret < 0) {
-			pr_err("%s: vdd_vreg set regulator mode failed.\n",
-						       __func__);
-			return ret;
+		if (ctrl_pdata->power_data.num_vreg > 0) {
+			ret = msm_dss_enable_vreg(
+				ctrl_pdata->power_data.vreg_config,
+				ctrl_pdata->power_data.num_vreg, 1);
+			if (ret) {
+				pr_err("%s:Failed to enable regulators.rc=%d\n",
+					__func__, ret);
+				return ret;
+			}
+
+			/*
+			 * A small delay is needed here after enabling
+			 * all regulators and before issuing panel reset
+			 */
+			msleep(20);
+		} else {
+			ret = regulator_set_optimum_mode(
+				(ctrl_pdata->shared_pdata).vdd_vreg, 100000);
+			if (ret < 0) {
+				pr_err("%s: vdd_vreg set opt mode failed.\n",
+					 __func__);
+				return ret;
+			}
+
+			ret = regulator_set_optimum_mode(
+				(ctrl_pdata->shared_pdata).vdd_io_vreg, 100000);
+			if (ret < 0) {
+				pr_err("%s: vdd_io_vreg set opt mode failed.\n",
+					__func__);
+				return ret;
+			}
+
+			ret = regulator_set_optimum_mode
+			  ((ctrl_pdata->shared_pdata).vdda_vreg, 100000);
+			if (ret < 0) {
+				pr_err("%s: vdda_vreg set opt mode failed.\n",
+					__func__);
+				return ret;
+			}
+
+			ret = regulator_enable(
+				(ctrl_pdata->shared_pdata).vdd_io_vreg);
+			if (ret) {
+				pr_err("%s: Failed to enable regulator.\n",
+					__func__);
+				return ret;
+			}
+			msleep(20);
+
+			ret = regulator_enable(
+				(ctrl_pdata->shared_pdata).vdd_vreg);
+			if (ret) {
+				pr_err("%s: Failed to enable regulator.\n",
+					__func__);
+				return ret;
+			}
+			msleep(20);
+
+			ret = regulator_enable(
+				(ctrl_pdata->shared_pdata).vdda_vreg);
+			if (ret) {
+				pr_err("%s: Failed to enable regulator.\n",
+					__func__);
+				return ret;
+			}
 		}
 
-		ret = regulator_set_optimum_mode
-		  ((ctrl_pdata->shared_pdata).vdd_io_vreg, 100000);
-		if (ret < 0) {
-			pr_err("%s: vdd_io_vreg set regulator mode failed.\n",
-						       __func__);
-			return ret;
-		}
-
-		ret = regulator_set_optimum_mode
-		  ((ctrl_pdata->shared_pdata).dsi_vreg, 100000);
-		if (ret < 0) {
-			pr_err("%s: dsi_vreg set regulator mode failed.\n",
-						       __func__);
-			return ret;
-		}
-
-		ret = regulator_enable((ctrl_pdata->shared_pdata).vdd_io_vreg);
-		if (ret) {
-			pr_err("%s: Failed to enable regulator.\n", __func__);
-			return ret;
-		}
-		msleep(20);
-		wmb();
-
-		ret = regulator_enable((ctrl_pdata->shared_pdata).vdd_vreg);
-		if (ret) {
-			pr_err("%s: Failed to enable regulator.\n", __func__);
-			return ret;
-		}
-		msleep(20);
-		wmb();
-
-		ret = regulator_enable((ctrl_pdata->shared_pdata).dsi_vreg);
-		if (ret) {
-			pr_err("%s: Failed to enable regulator.\n", __func__);
-			return ret;
-		}
 		if (pdata->panel_info.panel_power_on == 0)
 			mdss_dsi_panel_reset(pdata, 1);
 
@@ -142,45 +189,62 @@
 
 		mdss_dsi_panel_reset(pdata, 0);
 
-		ret = regulator_disable((ctrl_pdata->shared_pdata).vdd_vreg);
-		if (ret) {
-			pr_err("%s: Failed to disable regulator.\n", __func__);
-			return ret;
-		}
+		if (ctrl_pdata->power_data.num_vreg > 0) {
+			ret = msm_dss_enable_vreg(
+				ctrl_pdata->power_data.vreg_config,
+				ctrl_pdata->power_data.num_vreg, 0);
+			if (ret) {
+				pr_err("%s: Failed to disable regs.rc=%d\n",
+					__func__, ret);
+				return ret;
+			}
+		} else {
+			ret = regulator_disable(
+				(ctrl_pdata->shared_pdata).vdd_vreg);
+			if (ret) {
+				pr_err("%s: Failed to disable regulator.\n",
+					__func__);
+				return ret;
+			}
 
-		ret = regulator_disable((ctrl_pdata->shared_pdata).dsi_vreg);
-		if (ret) {
-			pr_err("%s: Failed to disable regulator.\n", __func__);
-			return ret;
-		}
+			ret = regulator_disable(
+				(ctrl_pdata->shared_pdata).vdda_vreg);
+			if (ret) {
+				pr_err("%s: Failed to disable regulator.\n",
+					__func__);
+				return ret;
+			}
 
-		ret = regulator_disable((ctrl_pdata->shared_pdata).vdd_io_vreg);
-		if (ret) {
-			pr_err("%s: Failed to disable regulator.\n", __func__);
-			return ret;
-		}
+			ret = regulator_disable(
+				(ctrl_pdata->shared_pdata).vdd_io_vreg);
+			if (ret) {
+				pr_err("%s: Failed to disable regulator.\n",
+					__func__);
+				return ret;
+			}
 
-		ret = regulator_set_optimum_mode
-		  ((ctrl_pdata->shared_pdata).vdd_vreg, 100);
-		if (ret < 0) {
-			pr_err("%s: vdd_vreg set regulator mode failed.\n",
-						       __func__);
-			return ret;
-		}
+			ret = regulator_set_optimum_mode(
+				(ctrl_pdata->shared_pdata).vdd_vreg, 100);
+			if (ret < 0) {
+				pr_err("%s: vdd_vreg set opt mode failed.\n",
+					 __func__);
+				return ret;
+			}
 
-		ret = regulator_set_optimum_mode
-		  ((ctrl_pdata->shared_pdata).vdd_io_vreg, 100);
-		if (ret < 0) {
-			pr_err("%s: vdd_io_vreg set regulator mode failed.\n",
-						       __func__);
-			return ret;
-		}
-		ret = regulator_set_optimum_mode
-		  ((ctrl_pdata->shared_pdata).dsi_vreg, 100);
-		if (ret < 0) {
-			pr_err("%s: dsi_vreg set regulator mode failed.\n",
-						       __func__);
-			return ret;
+			ret = regulator_set_optimum_mode(
+				(ctrl_pdata->shared_pdata).vdd_io_vreg, 100);
+			if (ret < 0) {
+				pr_err("%s: vdd_io_vreg set opt mode failed.\n",
+					__func__);
+				return ret;
+			}
+			ret = regulator_set_optimum_mode(
+				(ctrl_pdata->shared_pdata).vdda_vreg, 100);
+			if (ret < 0) {
+				pr_err("%s: vdda_vreg set opt mode failed.\n",
+					__func__);
+				return ret;
+			}
 		}
 	}
 	return 0;
@@ -212,6 +276,154 @@
 	return ret;
 }
 
+static void mdss_dsi_put_dt_vreg_data(struct device *dev,
+	struct dss_module_power *module_power)
+{
+	if (!module_power) {
+		pr_err("%s: invalid input\n", __func__);
+		return;
+	}
+
+	if (module_power->vreg_config) {
+		devm_kfree(dev, module_power->vreg_config);
+		module_power->vreg_config = NULL;
+	}
+	module_power->num_vreg = 0;
+}
+
+static int mdss_dsi_get_dt_vreg_data(struct device *dev,
+	struct dss_module_power *mp)
+{
+	int i, rc = 0;
+	int dt_vreg_total = 0;
+	u32 *val_array = NULL;
+	struct device_node *of_node = NULL;
+
+	if (!dev || !mp) {
+		pr_err("%s: invalid input\n", __func__);
+		rc = -EINVAL;
+		goto error;
+	}
+
+	of_node = dev->of_node;
+
+	mp->num_vreg = 0;
+	dt_vreg_total = of_property_count_strings(of_node, "qcom,supply-names");
+	if (dt_vreg_total < 0) {
+		pr_debug("%s: vreg not found. rc=%d\n", __func__,
+			dt_vreg_total);
+		rc = 0;
+		goto error;
+	} else {
+		pr_debug("%s: vreg found. count=%d\n", __func__, dt_vreg_total);
+	}
+
+	if (dt_vreg_total > 0) {
+		mp->num_vreg = dt_vreg_total;
+		mp->vreg_config = devm_kzalloc(dev, sizeof(struct dss_vreg) *
+			dt_vreg_total, GFP_KERNEL);
+		if (!mp->vreg_config) {
+			pr_err("%s: can't alloc vreg mem\n", __func__);
+			goto error;
+		}
+	} else {
+		pr_debug("%s: no vreg\n", __func__);
+		return 0;
+	}
+
+	val_array = devm_kzalloc(dev, sizeof(u32) * dt_vreg_total, GFP_KERNEL);
+	if (!val_array) {
+		pr_err("%s: can't allocate vreg scratch mem\n", __func__);
+		rc = -ENOMEM;
+		goto error;
+	}
+
+	for (i = 0; i < dt_vreg_total; i++) {
+		const char *st = NULL;
+		/* vreg-name */
+		rc = of_property_read_string_index(of_node, "qcom,supply-names",
+			i, &st);
+		if (rc) {
+			pr_err("%s: error reading name. i=%d, rc=%d\n",
+				__func__, i, rc);
+			goto error;
+		}
+		snprintf(mp->vreg_config[i].vreg_name,
+			ARRAY_SIZE((mp->vreg_config[i].vreg_name)), "%s", st);
+
+		/* vreg-type */
+		rc = of_property_read_string_index(of_node, "qcom,supply-type",
+			i, &st);
+		if (rc) {
+			pr_err("%s: error reading vreg type. rc=%d\n",
+				__func__, rc);
+			goto error;
+		}
+		if (!strncmp(st, "regulator", 9))
+			mp->vreg_config[i].type = 0;
+		else if (!strncmp(st, "switch", 6))
+			mp->vreg_config[i].type = 1;
+
+		/* vreg-min-voltage */
+		memset(val_array, 0, sizeof(u32) * dt_vreg_total);
+		rc = of_property_read_u32_array(of_node,
+			"qcom,supply-min-voltage-level", val_array,
+			dt_vreg_total);
+		if (rc) {
+			pr_err("%s: error reading min volt. rc=%d\n",
+				__func__, rc);
+			goto error;
+		}
+		mp->vreg_config[i].min_voltage = val_array[i];
+
+		/* vreg-max-voltage */
+		memset(val_array, 0, sizeof(u32) * dt_vreg_total);
+		rc = of_property_read_u32_array(of_node,
+			"qcom,supply-max-voltage-level", val_array,
+			dt_vreg_total);
+		if (rc) {
+			pr_err("%s: error reading max volt. rc=%d\n",
+				__func__, rc);
+			goto error;
+		}
+		mp->vreg_config[i].max_voltage = val_array[i];
+
+		/* vreg-peak-current*/
+		memset(val_array, 0, sizeof(u32) * dt_vreg_total);
+		rc = of_property_read_u32_array(of_node,
+			"qcom,supply-peak-current", val_array,
+			dt_vreg_total);
+		if (rc) {
+			pr_err("%s: error reading peak current. rc=%d\n",
+				__func__, rc);
+			goto error;
+		}
+		mp->vreg_config[i].optimum_voltage = val_array[i];
+
+		pr_debug("%s: %s type=%d, min=%d, max=%d, op=%d\n",
+			__func__, mp->vreg_config[i].vreg_name,
+			mp->vreg_config[i].type,
+			mp->vreg_config[i].min_voltage,
+			mp->vreg_config[i].max_voltage,
+			mp->vreg_config[i].optimum_voltage);
+	}
+
+	devm_kfree(dev, val_array);
+
+	return rc;
+
+error:
+	if (mp->vreg_config) {
+		devm_kfree(dev, mp->vreg_config);
+		mp->vreg_config = NULL;
+	}
+	mp->num_vreg = 0;
+
+	if (val_array)
+		devm_kfree(dev, val_array);
+	return rc;
+}
+
 static int mdss_dsi_off(struct mdss_panel_data *pdata)
 {
 	int ret = 0;
@@ -460,6 +672,7 @@
 {
 	int rc = 0;
 	u32 index;
+	struct mdss_dsi_ctrl_pdata *ctrl_pdata = NULL;
 
 	pr_debug("%s\n", __func__);
 
@@ -467,6 +680,19 @@
 		struct resource *mdss_dsi_mres;
 		const char *ctrl_name;
 
+		ctrl_pdata = platform_get_drvdata(pdev);
+		if (!ctrl_pdata) {
+			ctrl_pdata = devm_kzalloc(&pdev->dev,
+				sizeof(struct mdss_dsi_ctrl_pdata), GFP_KERNEL);
+			if (!ctrl_pdata) {
+				pr_err("%s: FAILED: cannot alloc dsi ctrl\n",
+					__func__);
+				rc = -ENOMEM;
+				goto error_no_mem;
+			}
+			platform_set_drvdata(pdev, ctrl_pdata);
+		}
+
 		ctrl_name = of_get_property(pdev->dev.of_node, "label", NULL);
 		if (!ctrl_name)
 			pr_info("%s:%d, DSI Ctrl name not specified\n",
@@ -481,7 +707,7 @@
 			dev_err(&pdev->dev,
 				"%s: Cell-index not specified, rc=%d\n",
 							__func__, rc);
-			return rc;
+			goto error_no_mem;
 		}
 
 		if (index == 0)
@@ -493,7 +719,8 @@
 		if (!mdss_dsi_mres) {
 			pr_err("%s:%d unable to get the MDSS resources",
 				       __func__, __LINE__);
-			return -ENOMEM;
+			rc = -ENOMEM;
+			goto error_no_mem;
 		}
 		if (mdss_dsi_mres) {
 			mdss_dsi_base = ioremap(mdss_dsi_mres->start,
@@ -501,7 +728,8 @@
 			if (!mdss_dsi_base) {
 				pr_err("%s:%d unable to remap dsi resources",
 					       __func__, __LINE__);
-				return -ENOMEM;
+				rc = -ENOMEM;
+				goto error_no_mem;
 			}
 		}
 
@@ -511,20 +739,48 @@
 			dev_err(&pdev->dev,
 				"%s: failed to add child nodes, rc=%d\n",
 							__func__, rc);
-			iounmap(mdss_dsi_base);
-			return rc;
+			goto error_ioremap;
+		}
+
+		/* Parse the regulator information */
+		rc = mdss_dsi_get_dt_vreg_data(&pdev->dev,
+			&ctrl_pdata->power_data);
+		if (rc) {
+			pr_err("%s: failed to get vreg data from dt. rc=%d\n",
+				__func__, rc);
+			goto error_vreg;
 		}
 
 		pr_debug("%s: Dsi Ctrl->%d initialized\n", __func__, index);
 	}
 
 	return 0;
+
+error_ioremap:
+	iounmap(mdss_dsi_base);
+error_no_mem:
+	devm_kfree(&pdev->dev, ctrl_pdata);
+error_vreg:
+	mdss_dsi_put_dt_vreg_data(&pdev->dev, &ctrl_pdata->power_data);
+
+	return rc;
 }
 
 static int __devexit mdss_dsi_ctrl_remove(struct platform_device *pdev)
 {
 	struct msm_fb_data_type *mfd;
+	struct mdss_dsi_ctrl_pdata *ctrl_pdata = platform_get_drvdata(pdev);
 
+	if (!ctrl_pdata) {
+		pr_err("%s: no driver data\n", __func__);
+		return -ENODEV;
+	}
+
+	if (msm_dss_config_vreg(&pdev->dev,
+			ctrl_pdata->power_data.vreg_config,
+			ctrl_pdata->power_data.num_vreg, 1) < 0)
+		pr_err("%s: failed to de-init vregs\n", __func__);
+	mdss_dsi_put_dt_vreg_data(&pdev->dev, &ctrl_pdata->power_data);
 	mfd = platform_get_drvdata(pdev);
 	iounmap(mdss_dsi_base);
 	return 0;
@@ -592,7 +848,7 @@
 	int rc;
 	u8 lanes = 0, bpp;
 	u32 h_period, v_period, dsi_pclk_rate;
-	struct mdss_dsi_ctrl_pdata *ctrl_pdata = NULL;
+	struct mdss_dsi_ctrl_pdata *ctrl_pdata;
 	struct device_node *dsi_ctrl_np = NULL;
 	struct platform_device *ctrl_pdev = NULL;
 	unsigned char *ctrl_addr;
@@ -663,27 +919,25 @@
 		dsi_pclk_rate = 35000000;
 	mipi->dsi_pclk_rate = dsi_pclk_rate;
 
-	ctrl_pdata = devm_kzalloc(&pdev->dev,
-		sizeof(struct mdss_dsi_ctrl_pdata), GFP_KERNEL);
-	if (!ctrl_pdata)
-		return -ENOMEM;
-
 	dsi_ctrl_np = of_parse_phandle(pdev->dev.of_node,
 				       "qcom,dsi-ctrl-phandle", 0);
 	if (!dsi_ctrl_np) {
 		pr_err("%s: Dsi controller node not initialized\n", __func__);
-		devm_kfree(&pdev->dev, ctrl_pdata);
 		return -EPROBE_DEFER;
 	}
 
 	ctrl_pdev = of_find_device_by_node(dsi_ctrl_np);
+	ctrl_pdata = platform_get_drvdata(ctrl_pdev);
+	if (!ctrl_pdata) {
+		pr_err("%s: no dsi ctrl driver data\n", __func__);
+		return -EINVAL;
+	}
 
-	rc = mdss_dsi_regulator_init(ctrl_pdev, &(ctrl_pdata->shared_pdata));
+	rc = mdss_dsi_regulator_init(ctrl_pdev);
 	if (rc) {
 		dev_err(&pdev->dev,
 			"%s: failed to init regulator, rc=%d\n",
 						__func__, rc);
-		devm_kfree(&pdev->dev, ctrl_pdata);
 		return rc;
 	}
 
@@ -726,7 +980,6 @@
 
 	if (mdss_dsi_clk_init(ctrl_pdev, ctrl_pdata)) {
 		pr_err("%s: unable to initialize Dsi ctrl clks\n", __func__);
-		devm_kfree(&pdev->dev, ctrl_pdata);
 		return -EPERM;
 	}
 
@@ -734,7 +987,6 @@
 					     panel_data->panel_info.pdest,
 					     &ctrl_addr)) {
 		pr_err("%s: unable to get Dsi controller res\n", __func__);
-		devm_kfree(&pdev->dev, ctrl_pdata);
 		return -EPERM;
 	}
 
@@ -780,7 +1032,6 @@
 	rc = mdss_register_panel(ctrl_pdev, &(ctrl_pdata->panel_data));
 	if (rc) {
 		dev_err(&pdev->dev, "unable to register MIPI DSI panel\n");
-		devm_kfree(&pdev->dev, ctrl_pdata);
 		if (ctrl_pdata->rst_gpio)
 			gpio_free(ctrl_pdata->rst_gpio);
 		if (gpio_is_valid(ctrl_pdata->disp_en_gpio))
diff --git a/drivers/video/msm/mdss/mdss_dsi.h b/drivers/video/msm/mdss/mdss_dsi.h
index 4b920a6..4a06be5 100644
--- a/drivers/video/msm/mdss/mdss_dsi.h
+++ b/drivers/video/msm/mdss/mdss_dsi.h
@@ -18,6 +18,7 @@
 #include <mach/scm-io.h>
 
 #include "mdss_panel.h"
+#include "mdss_io_util.h"
 
 #define MMSS_SERDES_BASE_PHY 0x04f01000 /* mmss (De)Serializer CFG */
 
@@ -267,7 +268,7 @@
 struct dsi_drv_cm_data {
 	struct regulator *vdd_vreg;
 	struct regulator *vdd_io_vreg;
-	struct regulator *dsi_vreg;
+	struct regulator *vdda_vreg;
 	int broadcast_enable;
 };
 
@@ -288,6 +289,7 @@
 	struct dsi_drv_cm_data shared_pdata;
 	u32 pclk_rate;
 	u32 byte_clk_rate;
+	struct dss_module_power power_data;
 };
 
 int dsi_panel_device_register(struct platform_device *pdev,
diff --git a/drivers/video/msm/mdss/mdss_fb.c b/drivers/video/msm/mdss/mdss_fb.c
index 1e0de89..3d632c7 100644
--- a/drivers/video/msm/mdss/mdss_fb.c
+++ b/drivers/video/msm/mdss/mdss_fb.c
@@ -1660,6 +1660,22 @@
 	return ret;
 }
 
+static int mdss_fb_get_hw_caps(struct msm_fb_data_type *mfd,
+		struct mdss_hw_caps *caps)
+{
+	struct mdss_data_type *mdata = mfd->mdata;
+
+	if (!mdata)
+		return -ENODEV;
+
+	caps->mdp_rev = mdata->mdp_rev;
+	caps->vig_pipes = mdata->nvig_pipes;
+	caps->rgb_pipes = mdata->nrgb_pipes;
+	caps->dma_pipes = mdata->ndma_pipes;
+
+	return 0;
+}
+
 static int mdss_fb_get_metadata(struct msm_fb_data_type *mfd,
 				struct msmfb_metadata *metadata)
 {
@@ -1669,6 +1685,9 @@
 		metadata->data.panel_frame_rate =
 			mdss_get_panel_framerate(mfd);
 		break;
+	case metadata_op_get_caps:
+		ret = mdss_fb_get_hw_caps(mfd, &metadata->data.caps);
+		break;
 	default:
 		pr_warn("Unsupported request to MDP META IOCTL.\n");
 		ret = -EINVAL;
diff --git a/drivers/video/msm/mdss/mdss_hdmi_tx.c b/drivers/video/msm/mdss/mdss_hdmi_tx.c
index 6c7a1195..e8a3795 100644
--- a/drivers/video/msm/mdss/mdss_hdmi_tx.c
+++ b/drivers/video/msm/mdss/mdss_hdmi_tx.c
@@ -24,6 +24,7 @@
 
 #define REG_DUMP 0
 
+#include "mdss_debug.h"
 #include "mdss_fb.h"
 #include "mdss_hdmi_tx.h"
 #include "mdss_hdmi_edid.h"
@@ -448,6 +449,18 @@
 		hdmi_ctrl->feature_data[HDMI_TX_FEAT_EDID]) ? 0 : 1;
 } /* hdmi_tx_is_dvi_mode */
 
+static inline void hdmi_tx_send_cable_notification(
+	struct hdmi_tx_ctrl *hdmi_ctrl, int val)
+{
+	if (!hdmi_ctrl) {
+		DEV_ERR("%s: invalid input\n", __func__);
+		return;
+	}
+
+	if (!hdmi_ctrl->pdata.primary && (hdmi_ctrl->sdev.state != val))
+		switch_set_state(&hdmi_ctrl->sdev, val);
+} /* hdmi_tx_send_cable_notification */
+
 static inline void hdmi_tx_set_audio_switch_node(struct hdmi_tx_ctrl *hdmi_ctrl,
 	int val, bool force)
 {
@@ -694,11 +707,11 @@
 
 	if (hdmi_ctrl->hpd_state) {
 		hdmi_tx_read_sink_info(hdmi_ctrl);
-		switch_set_state(&hdmi_ctrl->sdev, 1);
+		hdmi_tx_send_cable_notification(hdmi_ctrl, 1);
 		DEV_INFO("%s: sense cable CONNECTED: state switch to %d\n",
 			__func__, hdmi_ctrl->sdev.state);
 	} else {
-		switch_set_state(&hdmi_ctrl->sdev, 0);
+		hdmi_tx_send_cable_notification(hdmi_ctrl, 0);
 		DEV_INFO("%s: sense cable DISCONNECTED: state switch to %d\n",
 			__func__, hdmi_ctrl->sdev.state);
 	}
@@ -2096,6 +2109,7 @@
 
 static int hdmi_tx_power_on(struct mdss_panel_data *panel_data)
 {
+	u32 timeout;
 	int rc = 0;
 	struct dss_io_data *io = NULL;
 	struct hdmi_tx_ctrl *hdmi_ctrl =
@@ -2120,6 +2134,16 @@
 	/* If a power down is already underway, wait for it to finish */
 	flush_work_sync(&hdmi_ctrl->power_off_work);
 
+	if (hdmi_ctrl->pdata.primary) {
+		timeout = wait_for_completion_interruptible_timeout(
+			&hdmi_ctrl->hpd_done, HZ);
+		if (!timeout) {
+			DEV_ERR("%s: cable connection hasn't happened yet\n",
+				__func__);
+			return -ETIMEDOUT;
+		}
+	}
+
 	rc = hdmi_tx_set_video_fmt(hdmi_ctrl, &panel_data->panel_info);
 	if (rc) {
 		DEV_ERR("%s: cannot set video_fmt.rc=%d\n", __func__, rc);
@@ -2188,6 +2212,7 @@
 		DEV_INFO("%s: Failed to disable hpd power. Error=%d\n",
 			__func__, rc);
 
+	hdmi_ctrl->hpd_state = false;
 	hdmi_ctrl->hpd_initialized = false;
 } /* hdmi_tx_hpd_off */
 
@@ -2263,7 +2288,7 @@
 		} else {
 			hdmi_ctrl->hpd_off_pending = true;
 
-			switch_set_state(&hdmi_ctrl->sdev, 0);
+			hdmi_tx_send_cable_notification(hdmi_ctrl, 0);
 			DEV_DBG("%s: Hdmi state switch to %d\n", __func__,
 				hdmi_ctrl->sdev.state);
 		}
@@ -2439,6 +2464,20 @@
 			hdmi_tx_sysfs_remove(hdmi_ctrl);
 			return rc;
 		}
+
+		if (hdmi_ctrl->pdata.primary) {
+			INIT_COMPLETION(hdmi_ctrl->hpd_done);
+			rc = hdmi_tx_sysfs_enable_hpd(hdmi_ctrl, true);
+			if (rc) {
+				DEV_ERR("%s: hpd_enable failed. rc=%d\n",
+					__func__, rc);
+				hdmi_tx_sysfs_remove(hdmi_ctrl);
+				return rc;
+			} else {
+				hdmi_ctrl->hpd_feature_on = true;
+			}
+		}
+
 		break;
 
 	case MDSS_EVENT_CHECK_PARAMS:
@@ -2485,7 +2524,7 @@
 			if (!timeout & !hdmi_ctrl->hpd_state) {
 				DEV_INFO("%s: cable removed during suspend\n",
 					__func__);
-				switch_set_state(&hdmi_ctrl->sdev, 0);
+				hdmi_tx_send_cable_notification(hdmi_ctrl, 0);
 				rc = -EPERM;
 			} else {
 				DEV_DBG("%s: cable present after resume\n",
@@ -3114,6 +3153,13 @@
 		}
 	}
 
+	if (of_find_property(pdev->dev.of_node, "qcom,primary_panel", NULL)) {
+		u32 tmp;
+		of_property_read_u32(pdev->dev.of_node, "qcom,primary_panel",
+			&tmp);
+		pdata->primary = tmp ? true : false;
+	}
+
 	return rc;
 
 error:
@@ -3173,15 +3219,18 @@
 	if (rc) {
 		DEV_ERR("%s: Failed to add child devices. rc=%d\n",
 			__func__, rc);
-		goto failed_init_features;
+		goto failed_reg_panel;
 	} else {
 		DEV_DBG("%s: Add child devices.\n", __func__);
 	}
 
+	if (mdss_debug_register_base("hdmi",
+			hdmi_ctrl->pdata.io[HDMI_TX_CORE_IO].base,
+			hdmi_ctrl->pdata.io[HDMI_TX_CORE_IO].len))
+		DEV_WARN("%s: hdmi_tx debugfs register failed\n", __func__);
+
 	return rc;
 
-failed_init_features:
-	hdmi_tx_sysfs_remove(hdmi_ctrl);
 failed_reg_panel:
 	hdmi_tx_dev_deinit(hdmi_ctrl);
 failed_dev_init:
diff --git a/drivers/video/msm/mdss/mdss_hdmi_tx.h b/drivers/video/msm/mdss/mdss_hdmi_tx.h
index 06ae427..8d9a477 100644
--- a/drivers/video/msm/mdss/mdss_hdmi_tx.h
+++ b/drivers/video/msm/mdss/mdss_hdmi_tx.h
@@ -30,8 +30,9 @@
 	HDMI_TX_MAX_PM
 };
 
+/* Data filled from device tree */
 struct hdmi_tx_platform_data {
-	/* Data filled from device tree nodes */
+	bool primary;
 	struct dss_io_data io[HDMI_TX_MAX_IO];
 	struct dss_module_power power_data[HDMI_TX_MAX_PM];
 };
diff --git a/drivers/video/msm/mdss/mdss_mdp_intf_writeback.c b/drivers/video/msm/mdss/mdss_mdp_intf_writeback.c
index 97428cd..c6b6e3f 100644
--- a/drivers/video/msm/mdss/mdss_mdp_intf_writeback.c
+++ b/drivers/video/msm/mdss/mdss_mdp_intf_writeback.c
@@ -265,12 +265,12 @@
 	if (ctx->rot90) {
 		ctx->opmode |= BIT(5); /* ROT 90 */
 		swap(ctx->width, ctx->height);
+		ctx->format = mdss_mdp_get_rotator_dst_format(rot->format);
+	} else {
+		ctx->format = rot->format;
 	}
 
-	if (mdss_mdp_writeback_format_setup(ctx))
-		return -EINVAL;
-
-	return 0;
+	return mdss_mdp_writeback_format_setup(ctx);
 }
 
 static int mdss_mdp_writeback_stop(struct mdss_mdp_ctl *ctl)
diff --git a/drivers/video/msm/mdss/mdss_mdp_overlay.c b/drivers/video/msm/mdss/mdss_mdp_overlay.c
index dcefc09..98a8202 100644
--- a/drivers/video/msm/mdss/mdss_mdp_overlay.c
+++ b/drivers/video/msm/mdss/mdss_mdp_overlay.c
@@ -236,7 +236,7 @@
 	struct mdss_mdp_format_params *fmt;
 	struct mdss_mdp_pipe *pipe;
 	struct mdss_mdp_mixer *mixer = NULL;
-	u32 pipe_type, mixer_mux, len;
+	u32 pipe_type, mixer_mux, len, src_format;
 	int ret;
 
 	if (mfd == NULL || mfd->ctl == NULL)
@@ -255,9 +255,13 @@
 		return -ENOTSUPP;
 	}
 
-	fmt = mdss_mdp_get_format_params(req->src.format);
+	src_format = req->src.format;
+	if (req->flags & MDP_SOURCE_ROTATED_90)
+		src_format = mdss_mdp_get_rotator_dst_format(src_format);
+
+	fmt = mdss_mdp_get_format_params(src_format);
 	if (!fmt) {
-		pr_err("invalid pipe format %d\n", req->src.format);
+		pr_err("invalid pipe format %d\n", src_format);
 		return -EINVAL;
 	}
 
@@ -539,9 +543,9 @@
 	virt = ion_map_kernel(iclient, ihdl);
 	ion_phys(iclient, ihdl, &phys, &size);
 
-	pr_debug("%s %d Allocating %u bytes at 0x%lx (%lx phys)\n",
+	pr_debug("%s %d Allocating %u bytes at 0x%lx (%pa phys)\n",
 			__func__, __LINE__, size,
-			(unsigned long int)virt, phys);
+			(unsigned long int)virt, &phys);
 
 	bl_fb_addr_va = (unsigned long *)ioremap(bl_fb_addr, size);
 
@@ -1148,7 +1152,7 @@
 	ret = wait_for_completion_interruptible_timeout(&mfd->vsync_comp,
 			timeout);
 	if (ret <= 0) {
-		pr_warn("Sending current time as vsync timestamp for fb%d\n",
+		pr_debug("Sending current time as vsync timestamp for fb%d\n",
 				mfd->index);
 		mfd->vsync_time = ktime_get();
 	}
diff --git a/drivers/video/msm/mdss/mdss_mdp_rotator.h b/drivers/video/msm/mdss/mdss_mdp_rotator.h
index 70ef6bf..c46f271 100644
--- a/drivers/video/msm/mdss/mdss_mdp_rotator.h
+++ b/drivers/video/msm/mdss/mdss_mdp_rotator.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -42,6 +42,18 @@
 	struct list_head head;
 };
 
+static inline u32 mdss_mdp_get_rotator_dst_format(u32 in_format)
+{
+	switch (in_format) {
+	case MDP_Y_CBCR_H2V2_VENUS:
+		return MDP_Y_CBCR_H2V2;
+	case MDP_Y_CR_CB_GH2V2:
+		return MDP_Y_CR_CB_H2V2;
+	default:
+		return in_format;
+	}
+}
+
 struct mdss_mdp_rotator_session *mdss_mdp_rotator_session_alloc(void);
 struct mdss_mdp_rotator_session *mdss_mdp_rotator_session_get(u32 session_id);
 
diff --git a/include/linux/diagchar.h b/include/linux/diagchar.h
index 7a5ab0d..d208f1e 100644
--- a/include/linux/diagchar.h
+++ b/include/linux/diagchar.h
@@ -43,6 +43,10 @@
 #define DIAG_IOCTL_DCI_REG		23
 #define DIAG_IOCTL_DCI_STREAM_INIT	24
 #define DIAG_IOCTL_DCI_HEALTH_STATS	25
+#define DIAG_IOCTL_DCI_LOG_STATUS	26
+#define DIAG_IOCTL_DCI_EVENT_STATUS	27
+#define DIAG_IOCTL_DCI_CLEAR_LOGS	28
+#define DIAG_IOCTL_DCI_CLEAR_EVENTS	29
 #define DIAG_IOCTL_REMOTE_DEV		32
 
 /* PC Tools IDs */
diff --git a/include/linux/epm_adc.h b/include/linux/epm_adc.h
index 14cb148..4fa41b5 100644
--- a/include/linux/epm_adc.h
+++ b/include/linux/epm_adc.h
@@ -39,7 +39,8 @@
 	uint8_t		dev_num;
 	uint8_t		chan_num;
 	uint32_t	timestamp_resp_value;
-	uint32_t	reading_value;
+	int16_t		reading_raw;
+	int32_t		reading_value;
 };
 
 struct epm_psoc_get_buffered_data {
diff --git a/include/linux/msm_mdp.h b/include/linux/msm_mdp.h
index 4149552..6a2c95d 100644
--- a/include/linux/msm_mdp.h
+++ b/include/linux/msm_mdp.h
@@ -70,11 +70,11 @@
 #define MSMFB_MDP_PP _IOWR(MSMFB_IOCTL_MAGIC, 156, struct msmfb_mdp_pp)
 #define MSMFB_OVERLAY_VSYNC_CTRL _IOW(MSMFB_IOCTL_MAGIC, 160, unsigned int)
 #define MSMFB_VSYNC_CTRL  _IOW(MSMFB_IOCTL_MAGIC, 161, unsigned int)
-#define MSMFB_METADATA_SET  _IOW(MSMFB_IOCTL_MAGIC, 162, struct msmfb_metadata)
+#define MSMFB_BUFFER_SYNC  _IOW(MSMFB_IOCTL_MAGIC, 162, struct mdp_buf_sync)
 #define MSMFB_OVERLAY_COMMIT      _IO(MSMFB_IOCTL_MAGIC, 163)
-#define MSMFB_BUFFER_SYNC  _IOW(MSMFB_IOCTL_MAGIC, 164, struct mdp_buf_sync)
-#define MSMFB_DISPLAY_COMMIT      _IOW(MSMFB_IOCTL_MAGIC, 165, \
+#define MSMFB_DISPLAY_COMMIT      _IOW(MSMFB_IOCTL_MAGIC, 164, \
 						struct mdp_display_commit)
+#define MSMFB_METADATA_SET  _IOW(MSMFB_IOCTL_MAGIC, 165, struct msmfb_metadata)
 #define MSMFB_METADATA_GET  _IOW(MSMFB_IOCTL_MAGIC, 166, struct msmfb_metadata)
 
 #define FB_TYPE_3D_PANEL 0x10101010
@@ -595,6 +595,7 @@
 	metadata_op_frame_rate,
 	metadata_op_vic,
 	metadata_op_wb_format,
+	metadata_op_get_caps,
 	metadata_op_max
 };
 
@@ -607,6 +608,13 @@
 	uint32_t alpha;
 };
 
+struct mdss_hw_caps {
+	uint32_t mdp_rev;
+	uint8_t rgb_pipes;
+	uint8_t vig_pipes;
+	uint8_t dma_pipes;
+};
+
 struct msmfb_metadata {
 	uint32_t op;
 	uint32_t flags;
@@ -615,6 +623,7 @@
 		struct mdp_mixer_cfg mixer_cfg;
 		uint32_t panel_frame_rate;
 		uint32_t video_info_code;
+		struct mdss_hw_caps caps;
 	} data;
 };
 
diff --git a/include/linux/regulator/krait-regulator.h b/include/linux/regulator/krait-regulator.h
index b784531..2683fd7 100644
--- a/include/linux/regulator/krait-regulator.h
+++ b/include/linux/regulator/krait-regulator.h
@@ -27,22 +27,6 @@
 #ifdef CONFIG_ARCH_MSM8974
 int __init krait_power_init(void);
 void secondary_cpu_hs_init(void *base_ptr);
-
-/**
- * krait_power_mdd_enable - function to turn on/off MDD. Turning off MDD
- *				turns off badngap reference for LDO. If
- *				a core is running on a LDO, requests to
- *				turn off MDD will not be honoured
- * @on:	boolean to indicate whether to turn MDD on/off
- *
- * CONTEXT: Can be called in interrupt context, only when the core
- *		is about to go to idle, this guarantees that there are no
- *		frequency changes on that cpu happening. Note if going from off
- *		to on mode there will be settling delays
- *
- * RETURNS: -EINVAL if MDD cannot be turned off
- */
-int krait_power_mdd_enable(int cpu_num, bool on);
 #else
 static inline int __init krait_power_init(void)
 {
@@ -50,10 +34,6 @@
 }
 
 static inline void secondary_cpu_hs_init(void *base_ptr) {}
-static inline int krait_power_mdd_enable(int cpu_num, bool on)
-{
-	return -EINVAL;
-}
 #endif
 
 #endif
diff --git a/include/linux/rq_stats.h b/include/linux/rq_stats.h
index 65d8e8f..0accf38 100644
--- a/include/linux/rq_stats.h
+++ b/include/linux/rq_stats.h
@@ -19,6 +19,7 @@
 	unsigned long rq_poll_total_jiffies;
 	unsigned long def_timer_last_jiffy;
 	unsigned int def_interval;
+	unsigned int hotplug_disabled;
 	int64_t def_start_time;
 	struct attribute_group *attr_group;
 	struct kobject *kobj;
diff --git a/include/linux/usb/msm_hsusb.h b/include/linux/usb/msm_hsusb.h
index 48e7155..79fe16b 100644
--- a/include/linux/usb/msm_hsusb.h
+++ b/include/linux/usb/msm_hsusb.h
@@ -406,6 +406,9 @@
 	struct msm_bus_scale_pdata *bus_scale_table;
 	unsigned log2_irq_thresh;
 
+	/* gpio used to resume peripheral */
+	unsigned resume_gpio;
+
 	/*swfi latency is required while driving resume on to the bus */
 	u32 swfi_latency;
 
diff --git a/include/media/msmb_pproc.h b/include/media/msmb_pproc.h
index 56c257d..6f8e865 100644
--- a/include/media/msmb_pproc.h
+++ b/include/media/msmb_pproc.h
@@ -109,6 +109,9 @@
 #define VIDIOC_MSM_CPP_GET_HW_INFO \
 	_IOWR('V', BASE_VIDIOC_PRIVATE + 4, struct msm_camera_v4l2_ioctl_t)
 
+#define VIDIOC_MSM_CPP_FLUSH_QUEUE \
+	_IOWR('V', BASE_VIDIOC_PRIVATE + 5, struct msm_camera_v4l2_ioctl_t)
+
 #define V4L2_EVENT_CPP_FRAME_DONE  (V4L2_EVENT_PRIVATE_START + 0)
 
 struct msm_camera_v4l2_ioctl_t {
diff --git a/include/sound/Kbuild b/include/sound/Kbuild
index ba75dca..edadaa9 100644
--- a/include/sound/Kbuild
+++ b/include/sound/Kbuild
@@ -11,3 +11,4 @@
 header-y += tlv.h
 header-y += compress_params.h
 header-y += compress_offload.h
+header-y += lsm_params.h
diff --git a/include/sound/apr_audio-v2.h b/include/sound/apr_audio-v2.h
index bc68c24..f88c817 100644
--- a/include/sound/apr_audio-v2.h
+++ b/include/sound/apr_audio-v2.h
@@ -658,6 +658,11 @@
 #define SLIMBUS_3_TX		0x4007
 #define SLIMBUS_4_RX		0x4008
 #define SLIMBUS_4_TX		0x4009		/* index = 24 */
+#define SLIMBUS_5_RX		0x400a
+#define SLIMBUS_5_TX		0x400b
+#define SLIMBUS_6_RX		0x400c
+#define SLIMBUS_6_TX		0x400d
+#define SLIMBUS_PORT_LAST	SLIMBUS_6_TX
 #define INT_BT_SCO_RX 0x3000		/* index = 25 */
 #define INT_BT_SCO_TX 0x3001		/* index = 26 */
 #define INT_BT_A2DP_RX 0x3002		/* index = 27 */
@@ -798,6 +803,15 @@
 #define AFE_PORT_ID_SLIMBUS_MULTI_CHAN_4_RX      0x4008
 /* SLIMbus Tx port on channel 4. */
 #define AFE_PORT_ID_SLIMBUS_MULTI_CHAN_4_TX      0x4009
+/* SLIMbus Rx port on channel 5. */
+#define AFE_PORT_ID_SLIMBUS_MULTI_CHAN_5_RX      0x400a
+/* SLIMbus Tx port on channel 5. */
+#define AFE_PORT_ID_SLIMBUS_MULTI_CHAN_5_TX      0x400b
+/* SLIMbus Rx port on channel 6. */
+#define AFE_PORT_ID_SLIMBUS_MULTI_CHAN_6_RX      0x400c
+/* SLIMbus Tx port on channel 6. */
+#define AFE_PORT_ID_SLIMBUS_MULTI_CHAN_6_TX      0x400d
+
 /* Generic pseudoport 1. */
 #define AFE_PORT_ID_PSEUDOPORT_01      0x8001
 /* Generic pseudoport 2. */
@@ -1972,7 +1986,6 @@
 	 */
 } __packed;
 
-
 union afe_port_config {
 	struct afe_param_id_pcm_cfg               pcm;
 	struct afe_param_id_i2s_cfg               i2s;
@@ -6442,6 +6455,56 @@
 } __packed;
 /* SRS TruMedia end */
 
+/* LSM Specific */
+#define VW_FEAT_DIM					(39)
+
+#define APRV2_IDS_SERVICE_ID_ADSP_LSM_V			(0xD)
+#define APRV2_IDS_DOMAIN_ID_ADSP_V			(0x4)
+#define APRV2_IDS_DOMAIN_ID_APPS_V			(0x5)
+
+#define LSM_SESSION_CMD_SHARED_MEM_MAP_REGIONS		(0x00012A7F)
+#define LSM_SESSION_CMDRSP_SHARED_MEM_MAP_REGIONS	(0x00012A80)
+#define LSM_SESSION_CMD_SHARED_MEM_UNMAP_REGIONS	(0x00012A81)
+#define LSM_SESSION_CMD_OPEN_TX				(0x00012A82)
+#define LSM_SESSION_CMD_CLOSE_TX			(0x00012A88)
+#define LSM_SESSION_CMD_SET_PARAMS			(0x00012A83)
+#define LSM_SESSION_CMD_REGISTER_SOUND_MODEL		(0x00012A84)
+#define LSM_SESSION_CMD_DEREGISTER_SOUND_MODEL		(0x00012A85)
+#define LSM_SESSION_CMD_START				(0x00012A86)
+#define LSM_SESSION_CMD_STOP				(0x00012A87)
+
+#define LSM_SESSION_EVENT_DETECTION_STATUS		(0x00012B00)
+
+#define LSM_MODULE_ID_VOICE_WAKEUP			(0x00012C00)
+#define LSM_PARAM_ID_ENDPOINT_DETECT_THRESHOLD		(0x00012C01)
+#define LSM_PARAM_ID_OPERATION_MODE			(0x00012C02)
+#define LSM_PARAM_ID_GAIN				(0x00012C03)
+#define LSM_PARAM_ID_CONNECT_TO_PORT			(0x00012C04)
+#define LSM_PARAM_ID_KEYWORD_DETECT_SENSITIVITY		(0x00012C05)
+#define LSM_PARAM_ID_USER_DETECT_SENSITIVITY		(0x00012C06)
+#define LSM_PARAM_ID_FEATURE_COMPENSATION_DATA		(0x00012C07)
+
+
+/* HW MAD specific */
+#define AFE_MODULE_HW_MAD				(0x00010230)
+#define AFE_PARAM_ID_HW_MAD_CFG				(0x00010231)
+#define AFE_PARAM_ID_HW_MAD_CTRL			(0x00010232)
+#define AFE_PARAM_ID_SLIMBUS_SLAVE_PORT_CFG		(0x00010233)
+
+/* SW MAD specific */
+#define AFE_MODULE_SW_MAD				(0x0001022D)
+#define AFE_PARAM_ID_SW_MAD_CFG				(0x0001022E)
+#define AFE_PARAM_ID_SVM_MODEL				(0x0001022F)
+
+/* Commands/Params to pass the codec/slimbus data to DSP */
+#define AFE_SVC_CMD_SET_PARAM				(0x000100f3)
+#define AFE_MODULE_CDC_DEV_CFG				(0x00010234)
+#define AFE_PARAM_ID_CDC_SLIMBUS_SLAVE_CFG		(0x00010235)
+#define AFE_PARAM_ID_CDC_REG_CFG			(0x00010236)
+#define AFE_PARAM_ID_CDC_REG_CFG_INIT			(0x00010237)
+
+#define AFE_MAX_CDC_REGISTERS_TO_CONFIG			(20)
+
 /* ERROR CODES */
 /* Success. The operation completed with no errors. */
 #define ADSP_EOK          0x00000000
@@ -6669,4 +6732,104 @@
 	uint16_t                  reserved;
 } __packed;
 
+enum afe_config_type {
+	AFE_SLIMBUS_SLAVE_PORT_CONFIG,
+	AFE_SLIMBUS_SLAVE_CONFIG,
+	AFE_CDC_REGISTERS_CONFIG,
+	AFE_MAX_CONFIG_TYPES,
+};
+
+struct afe_param_slimbus_slave_port_cfg {
+	uint32_t minor_version;
+	uint16_t slimbus_dev_id;
+	uint16_t slave_dev_pgd_la;
+	uint16_t slave_dev_intfdev_la;
+	uint16_t bit_width;
+	uint16_t data_format;
+	uint16_t num_channels;
+	uint16_t slave_port_mapping[AFE_PORT_MAX_AUDIO_CHAN_CNT];
+} __packed;
+
+struct afe_param_cdc_slimbus_slave_cfg {
+	uint32_t minor_version;
+	uint32_t device_enum_addr_lsw;
+	uint32_t device_enum_addr_msw;
+	uint16_t tx_slave_port_offset;
+	uint16_t rx_slave_port_offset;
+} __packed;
+
+struct afe_param_cdc_reg_cfg {
+	uint32_t minor_version;
+	uint32_t reg_logical_addr;
+	uint32_t reg_field_type;
+	uint32_t reg_field_bit_mask;
+	uint16_t reg_bit_width;
+	uint16_t reg_offset_scale;
+} __packed;
+
+struct afe_param_cdc_reg_cfg_data {
+	uint32_t num_registers;
+	struct afe_param_cdc_reg_cfg *reg_data;
+} __packed;
+
+struct afe_svc_cmd_set_param {
+	uint32_t payload_size;
+	uint32_t payload_address_lsw;
+	uint32_t payload_address_msw;
+	uint32_t mem_map_handle;
+} __packed;
+
+struct afe_param_hw_mad_ctrl {
+	uint32_t minor_version;
+	uint16_t mad_type;
+	uint16_t mad_enable;
+} __packed;
+
+struct afe_cmd_hw_mad_ctrl {
+	struct apr_hdr hdr;
+	struct afe_port_cmd_set_param_v2 param;
+	struct afe_port_param_data_v2 pdata;
+	struct afe_param_hw_mad_ctrl payload;
+} __packed;
+
+struct afe_cmd_hw_mad_slimbus_slave_port_cfg {
+	struct apr_hdr hdr;
+	struct afe_port_cmd_set_param_v2 param;
+	struct afe_port_param_data_v2 pdata;
+	struct afe_param_slimbus_slave_port_cfg sb_port_cfg;
+} __packed;
+
+struct afe_cmd_sw_mad_enable {
+	struct apr_hdr hdr;
+	struct afe_port_cmd_set_param_v2 param;
+	struct afe_port_param_data_v2 pdata;
+} __packed;
+
+struct afe_param_cdc_reg_cfg_payload {
+	struct afe_port_param_data_v2 common;
+	struct afe_param_cdc_reg_cfg  reg_cfg;
+} __packed;
+
+/*
+ * reg_data's size can be up to AFE_MAX_CDC_REGISTERS_TO_CONFIG
+ */
+struct afe_svc_cmd_cdc_reg_cfg {
+	struct apr_hdr hdr;
+	struct afe_svc_cmd_set_param param;
+	struct afe_param_cdc_reg_cfg_payload reg_data[0];
+} __packed;
+
+struct afe_svc_cmd_init_cdc_reg_cfg {
+	struct apr_hdr hdr;
+	struct afe_svc_cmd_set_param param;
+	struct afe_port_param_data_v2 init;
+} __packed;
+
+struct afe_svc_cmd_sb_slave_cfg {
+	struct apr_hdr hdr;
+	struct afe_svc_cmd_set_param param;
+	struct afe_port_param_data_v2 pdata;
+	struct afe_param_cdc_slimbus_slave_cfg sb_slave_cfg;
+} __packed;
+
 #endif /*_APR_AUDIO_V2_H_ */
diff --git a/include/sound/lsm_params.h b/include/sound/lsm_params.h
new file mode 100644
index 0000000..0edd8b5
--- /dev/null
+++ b/include/sound/lsm_params.h
@@ -0,0 +1,36 @@
+#ifndef __LSM_PARAMS_H__
+#define __LSM_PARAMS_H__
+
+#include <linux/types.h>
+#include <sound/asound.h>
+
+#define SNDRV_LSM_VERSION SNDRV_PROTOCOL_VERSION(0, 1, 0)
+
+enum lsm_detection_mode {
+	LSM_MODE_KEYWORD_ONLY_DETECTION = 1,
+	LSM_MODE_USER_KEYWORD_DETECTION
+};
+
+struct snd_lsm_sound_model {
+	__u8 *data;
+	__u32 data_size;
+	enum lsm_detection_mode detection_mode;
+	__u16 min_keyw_confidence;
+	__u16 min_user_confidence;
+	bool detect_failure;
+};
+
+struct snd_lsm_event_status {
+	__u16 status;
+	__u16 payload_size;
+	__u8 payload[0];
+};
+
+#define SNDRV_LSM_REG_SND_MODEL	 _IOW('U', 0x00, struct snd_lsm_sound_model)
+#define SNDRV_LSM_DEREG_SND_MODEL _IOW('U', 0x01, int)
+#define SNDRV_LSM_EVENT_STATUS	_IOW('U', 0x02, struct snd_lsm_event_status)
+#define SNDRV_LSM_ABORT_EVENT	_IOW('U', 0x03, int)
+#define SNDRV_LSM_START		_IOW('U', 0x04, int)
+#define SNDRV_LSM_STOP		_IOW('U', 0x05, int)
+
+#endif
diff --git a/include/sound/q6afe-v2.h b/include/sound/q6afe-v2.h
index feac314..22ddbbc 100644
--- a/include/sound/q6afe-v2.h
+++ b/include/sound/q6afe-v2.h
@@ -64,24 +64,34 @@
 	IDX_SLIMBUS_3_TX = 22,
 	IDX_SLIMBUS_4_RX = 23,
 	IDX_SLIMBUS_4_TX = 24,
-	IDX_INT_BT_SCO_RX = 25,
-	IDX_INT_BT_SCO_TX = 26,
-	IDX_INT_BT_A2DP_RX = 27,
-	IDX_INT_FM_RX = 28,
-	IDX_INT_FM_TX = 29,
-	IDX_RT_PROXY_PORT_001_RX = 30,
-	IDX_RT_PROXY_PORT_001_TX = 31,
-	IDX_AFE_PORT_ID_QUATERNARY_MI2S_RX = 32,
-	IDX_AFE_PORT_ID_QUATERNARY_MI2S_TX = 33,
-	IDX_AFE_PORT_ID_SECONDARY_MI2S_RX = 34,
-	IDX_AFE_PORT_ID_SECONDARY_MI2S_TX = 35,
-	IDX_AFE_PORT_ID_TERTIARY_MI2S_RX = 36,
-	IDX_AFE_PORT_ID_TERTIARY_MI2S_TX = 37,
-	IDX_AFE_PORT_ID_PRIMARY_MI2S_RX = 38,
-	IDX_AFE_PORT_ID_PRIMARY_MI2S_TX = 39,
+	IDX_SLIMBUS_5_RX = 25,
+	IDX_SLIMBUS_5_TX = 26,
+	IDX_INT_BT_SCO_RX = 27,
+	IDX_INT_BT_SCO_TX = 28,
+	IDX_INT_BT_A2DP_RX = 29,
+	IDX_INT_FM_RX = 30,
+	IDX_INT_FM_TX = 31,
+	IDX_RT_PROXY_PORT_001_RX = 32,
+	IDX_RT_PROXY_PORT_001_TX = 33,
+	IDX_AFE_PORT_ID_QUATERNARY_MI2S_RX = 34,
+	IDX_AFE_PORT_ID_QUATERNARY_MI2S_TX = 35,
+	IDX_AFE_PORT_ID_SECONDARY_MI2S_RX = 36,
+	IDX_AFE_PORT_ID_SECONDARY_MI2S_TX = 37,
+	IDX_AFE_PORT_ID_TERTIARY_MI2S_RX = 38,
+	IDX_AFE_PORT_ID_TERTIARY_MI2S_TX = 39,
+	IDX_AFE_PORT_ID_PRIMARY_MI2S_RX = 40,
+	IDX_AFE_PORT_ID_PRIMARY_MI2S_TX = 41,
+	IDX_GLOBAL_CFG,
 	AFE_MAX_PORTS
 };
 
+enum afe_mad_type {
+	MAD_HW_NONE = 0x00,
+	MAD_HW_AUDIO = 0x01,
+	MAD_HW_BEACON = 0x02,
+	MAD_HW_ULTRASOUND = 0x04
+};
+
 struct afe_audio_buffer {
 	dma_addr_t phys;
 	void       *data;
@@ -172,4 +182,10 @@
 				struct afe_digital_clk_cfg *cfg);
 int q6afe_check_osr_clk_freq(u32 freq);
 
+int afe_turn_onoff_hw_mad(u16 mad_type, u16 mad_enable);
+int afe_port_set_mad_type(u16 port_id, enum afe_mad_type mad_type);
+enum afe_mad_type afe_port_get_mad_type(u16 port_id);
+int afe_set_config(enum afe_config_type config_type, void *config_data,
+		   int arg);
+
 #endif /* __Q6AFE_V2_H__ */
diff --git a/include/sound/q6lsm.h b/include/sound/q6lsm.h
new file mode 100644
index 0000000..5c9d4b9
--- /dev/null
+++ b/include/sound/q6lsm.h
@@ -0,0 +1,134 @@
+/*
+ * Copyright (c) 2013, Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+#ifndef __Q6LSM_H__
+#define __Q6LSM_H__
+
+#include <linux/list.h>
+#include <linux/msm_ion.h>
+#include <sound/apr_audio-v2.h>
+#include <sound/lsm_params.h>
+#include <mach/qdsp6v2/apr.h>
+#include <mach/msm_subsystem_map.h>
+
+typedef void (*app_cb)(uint32_t opcode, uint32_t token,
+		       uint32_t *payload, void *priv);
+
+struct lsm_sound_model {
+	dma_addr_t      phys;
+	void		*data;
+	uint32_t	size; /* size of buffer */
+	uint32_t	actual_size; /* actual number of bytes read by DSP */
+	struct ion_handle *handle;
+	struct ion_client *client;
+	uint32_t	mem_map_handle;
+};
+
+struct lsm_client {
+	int		session;
+	app_cb		cb;
+	atomic_t	cmd_state;
+	void		*priv;
+	struct apr_svc  *apr;
+	struct apr_svc  *mmap_apr;
+	struct mutex    cmd_lock;
+	struct lsm_sound_model sound_model;
+	wait_queue_head_t cmd_wait;
+	uint16_t	mode;
+	uint16_t	connect_to_port;
+	uint16_t	user_sensitivity;
+	uint16_t	kw_sensitivity;
+	bool		started;
+};
+
+struct lsm_stream_cmd_open_tx {
+	struct apr_hdr  hdr;
+	uint16_t	app_id;
+	uint16_t	reserved;
+	uint32_t	sampling_rate;
+} __packed;
+
+struct lsm_param_payload_common {
+	uint32_t	module_id;
+	uint32_t	param_id;
+	uint16_t	param_size;
+	uint16_t	reserved;
+} __packed;
+
+struct lsm_param_op_mode {
+	struct lsm_param_payload_common common;
+	uint32_t	minor_version;
+	uint16_t	mode;
+	uint16_t	reserved;
+} __packed;
+
+struct lsm_param_connect_to_port {
+	struct lsm_param_payload_common common;
+	uint32_t	minor_version;
+	/* AFE port id that receives voice wake up data */
+	uint16_t	port_id;
+	uint16_t	reserved;
+} __packed;
+
+struct lsm_param_kw_detect_sensitivity {
+	struct lsm_param_payload_common common;
+	uint32_t	minor_version;
+	/* scale factor to change the keyword confidence thresholds */
+	uint16_t	keyword_sensitivity;
+	uint16_t	reserved;
+} __packed;
+
+struct lsm_param_user_detect_sensitivity {
+	struct lsm_param_payload_common common;
+	uint32_t	minor_version;
+	/* scale factor to change the user confidence thresholds */
+	uint16_t	user_sensitivity;
+	uint16_t	reserved;
+} __packed;
+
+struct lsm_params_payload {
+	struct lsm_param_connect_to_port connect_to_port;
+	struct lsm_param_op_mode	op_mode;
+	struct lsm_param_kw_detect_sensitivity kwds;
+	struct lsm_param_user_detect_sensitivity uds;
+} __packed;
+
+struct lsm_cmd_set_params {
+	struct apr_hdr  hdr;
+	uint32_t	data_payload_size;
+	uint32_t	data_payload_addr_lsw;
+	uint32_t	data_payload_addr_msw;
+	uint32_t	mem_map_handle;
+	struct lsm_params_payload payload;
+} __packed;
+
+struct lsm_cmd_reg_snd_model {
+	struct apr_hdr	hdr;
+	uint32_t	model_size;
+	uint32_t	model_addr_lsw;
+	uint32_t	model_addr_msw;
+	uint32_t	mem_map_handle;
+} __packed;
+
+struct lsm_client *q6lsm_client_alloc(app_cb cb, void *priv);
+void q6lsm_client_free(struct lsm_client *client);
+int q6lsm_open(struct lsm_client *client);
+int q6lsm_start(struct lsm_client *client, bool wait);
+int q6lsm_stop(struct lsm_client *client, bool wait);
+int q6lsm_snd_model_buf_alloc(struct lsm_client *client, uint32_t len);
+int q6lsm_close(struct lsm_client *client);
+int q6lsm_register_sound_model(struct lsm_client *client,
+			       enum lsm_detection_mode mode, u16 minkeyword,
+			       u16 minuser, bool detectfailure);
+int q6lsm_deregister_sound_model(struct lsm_client *client);
+
+#endif /* __Q6LSM_H__ */
diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c
index 4636247..7403b40 100644
--- a/sound/core/pcm_native.c
+++ b/sound/core/pcm_native.c
@@ -1534,6 +1534,20 @@
 	err = substream->ops->ioctl(substream, cmd, arg);
 	return err;
 }
+
+static int snd_user_ioctl(struct snd_pcm_substream *substream,
+			  unsigned int cmd, void __user *arg)
+{
+	struct snd_pcm_runtime *runtime;
+	int err = 0;
+
+	if (PCM_RUNTIME_CHECK(substream))
+		return -ENXIO;
+	runtime = substream->runtime;
+	err = substream->ops->ioctl(substream, cmd, arg);
+	return err;
+}
+
 /*
  * drop ioctl
  *
@@ -2605,6 +2619,9 @@
 	case SNDRV_COMPRESS_TSTAMP:
 	case SNDRV_COMPRESS_DRAIN:
 		return snd_compressed_ioctl(substream, cmd, arg);
+	default:
+		if (((cmd >> 8) & 0xff) == 'U')
+			return snd_user_ioctl(substream, cmd, arg);
 	}
 	snd_printd("unknown ioctl = 0x%x\n", cmd);
 	return -ENOTTY;
@@ -2788,10 +2805,12 @@
 				  unsigned long arg)
 {
 	struct snd_pcm_file *pcm_file;
+	unsigned char ioctl_magic;
 
 	pcm_file = file->private_data;
+	ioctl_magic = ((cmd >> 8) & 0xff);
 
-	if ((((cmd >> 8) & 0xff) != 'A') && (((cmd >> 8) & 0xff) != 'C'))
+	if (ioctl_magic != 'A' && ioctl_magic != 'C' && ioctl_magic != 'U')
 		return -ENOTTY;
 
 	return snd_pcm_capture_ioctl1(file, pcm_file->substream, cmd,
diff --git a/sound/soc/codecs/wcd9320.c b/sound/soc/codecs/wcd9320.c
index f4ea679..78d1749 100644
--- a/sound/soc/codecs/wcd9320.c
+++ b/sound/soc/codecs/wcd9320.c
@@ -38,6 +38,9 @@
 #include "wcd9xxx-resmgr.h"
 #include "wcd9xxx-common.h"
 
+#define TAIKO_MAD_SLIMBUS_TX_PORT 12
+#define TAIKO_MAD_AUDIO_FIRMWARE_PATH "wcd9320/wcd9320_mad_audio.bin"
+
 static atomic_t kp_taiko_priv;
 static int spkr_drv_wrnd_param_set(const char *val,
 				   const struct kernel_param *kp);
@@ -47,6 +50,121 @@
 	.set = spkr_drv_wrnd_param_set,
 	.get = param_get_int,
 };
+
+static struct afe_param_slimbus_slave_port_cfg taiko_slimbus_slave_port_cfg = {
+	.minor_version = 1,
+	.slimbus_dev_id = AFE_SLIMBUS_DEVICE_1,
+	.slave_dev_pgd_la = 0,
+	.slave_dev_intfdev_la = 0,
+	.bit_width = 16,
+	.data_format = 0,
+	.num_channels = 1
+};
+
+enum {
+	RESERVED = 0,
+	AANC_LPF_FF_FB = 1,
+	AANC_LPF_COEFF_MSB,
+	AANC_LPF_COEFF_LSB,
+	HW_MAD_AUDIO_ENABLE,
+	HW_MAD_ULTR_ENABLE,
+	HW_MAD_BEACON_ENABLE,
+	HW_MAD_AUDIO_SLEEP_TIME,
+	HW_MAD_ULTR_SLEEP_TIME,
+	HW_MAD_BEACON_SLEEP_TIME,
+	HW_MAD_TX_AUDIO_SWITCH_OFF,
+	HW_MAD_TX_ULTR_SWITCH_OFF,
+	HW_MAD_TX_BEACON_SWITCH_OFF,
+	MAD_AUDIO_INT_DEST_SELECT_REG,
+	MAD_ULT_INT_DEST_SELECT_REG,
+	MAD_BEACON_INT_DEST_SELECT_REG,
+	MAD_CLIP_INT_DEST_SELECT_REG,
+	MAD_VBAT_INT_DEST_SELECT_REG,
+	MAD_AUDIO_INT_MASK_REG,
+	MAD_ULT_INT_MASK_REG,
+	MAD_BEACON_INT_MASK_REG,
+	MAD_CLIP_INT_MASK_REG,
+	MAD_VBAT_INT_MASK_REG,
+	MAD_AUDIO_INT_STATUS_REG,
+	MAD_ULT_INT_STATUS_REG,
+	MAD_BEACON_INT_STATUS_REG,
+	MAD_CLIP_INT_STATUS_REG,
+	MAD_VBAT_INT_STATUS_REG,
+	MAD_AUDIO_INT_CLEAR_REG,
+	MAD_ULT_INT_CLEAR_REG,
+	MAD_BEACON_INT_CLEAR_REG,
+	MAD_CLIP_INT_CLEAR_REG,
+	MAD_VBAT_INT_CLEAR_REG,
+	SB_PGD_PORT_TX_WATERMARK_n,
+	SB_PGD_PORT_TX_ENABLE_n,
+	SB_PGD_PORT_RX_WATERMARK_n,
+	SB_PGD_PORT_RX_ENABLE_n,
+	MAX_CFG_REGISTERS,
+};
+
+static struct afe_param_cdc_reg_cfg mad_audio_reg_cfg[] = {
+	{
+		1,
+		(TAIKO_REGISTER_START_OFFSET + TAIKO_A_CDC_MAD_MAIN_CTL_1),
+		HW_MAD_AUDIO_ENABLE, 0x1, 8, 0
+	},
+	{
+		1,
+		(TAIKO_REGISTER_START_OFFSET + TAIKO_A_CDC_MAD_AUDIO_CTL_3),
+		HW_MAD_AUDIO_SLEEP_TIME, 0xF, 8, 0
+	},
+	{
+		1,
+		(TAIKO_REGISTER_START_OFFSET + TAIKO_A_CDC_MAD_AUDIO_CTL_4),
+		HW_MAD_TX_AUDIO_SWITCH_OFF, 0x1, 8, 0
+	},
+	{
+		1,
+		(TAIKO_REGISTER_START_OFFSET + TAIKO_A_INTR_DESTN3),
+		MAD_AUDIO_INT_DEST_SELECT_REG, 0x1, 8, 0
+	},
+	{
+		1,
+		(TAIKO_REGISTER_START_OFFSET + TAIKO_A_INTR_MASK3),
+		MAD_AUDIO_INT_MASK_REG, 0x1, 8, 0
+	},
+	{
+		1,
+		(TAIKO_REGISTER_START_OFFSET + TAIKO_A_INTR_STATUS3),
+		MAD_AUDIO_INT_STATUS_REG, 0x1, 8, 0
+	},
+	{
+		1,
+		(TAIKO_REGISTER_START_OFFSET + TAIKO_A_INTR_CLEAR3),
+		MAD_AUDIO_INT_CLEAR_REG, 0x1, 8, 0
+	},
+	{
+		1,
+		(TAIKO_REGISTER_START_OFFSET + TAIKO_SB_PGD_PORT_TX_BASE),
+		SB_PGD_PORT_TX_WATERMARK_n, 0x1E, 8, 0x1
+	},
+	{
+		1,
+		(TAIKO_REGISTER_START_OFFSET + TAIKO_SB_PGD_PORT_TX_BASE),
+		SB_PGD_PORT_TX_ENABLE_n, 0x1, 8, 0x1
+	},
+	{
+		1,
+		(TAIKO_REGISTER_START_OFFSET + TAIKO_SB_PGD_PORT_RX_BASE),
+		SB_PGD_PORT_RX_WATERMARK_n, 0x1E, 8, 0x1
+	},
+	{
+		1,
+		(TAIKO_REGISTER_START_OFFSET + TAIKO_SB_PGD_PORT_RX_BASE),
+		SB_PGD_PORT_RX_ENABLE_n, 0x1, 8, 0x1
+	}
+};
+
+static struct afe_param_cdc_reg_cfg_data taiko_mad_audio_reg_cfg = {
+	.num_registers = ARRAY_SIZE(mad_audio_reg_cfg),
+	.reg_data = mad_audio_reg_cfg,
+};
+
 module_param_cb(spkr_drv_wrnd, &spkr_drv_wrnd_param_ops, &spkr_drv_wrnd, 0644);
 MODULE_PARM_DESC(spkr_drv_wrnd,
 	       "Run software workaround to avoid leakage on the speaker drive");
@@ -84,6 +202,7 @@
 	AIF3_PB,
 	AIF3_CAP,
 	AIF4_VIFEED,
+	AIF4_MAD_TX,
 	NUM_CODEC_DAIS,
 };
 
@@ -237,6 +356,8 @@
 
 	bool spkr_pa_widget_on;
 
+	struct afe_param_cdc_slimbus_slave_cfg slimbus_slave_cfg;
+
 	/* resmgr module */
 	struct wcd9xxx_resmgr resmgr;
 	/* mbhc module */
@@ -1555,6 +1676,9 @@
 static const struct snd_kcontrol_new lineout4_ground_switch =
 	SOC_DAPM_SINGLE("Switch", TAIKO_A_RX_LINE_4_DAC_CTL, 6, 1, 0);
 
+static const struct snd_kcontrol_new aif4_mad_switch =
+	SOC_DAPM_SINGLE("Switch", TAIKO_A_CDC_CLK_OTHR_CTL, 4, 1, 0);
+
 /* virtual port entries */
 static int slim_tx_mixer_get(struct snd_kcontrol *kcontrol,
 			     struct snd_ctl_elem_value *ucontrol)
@@ -2155,6 +2279,108 @@
 	return 0;
 }
 
+static int taiko_codec_config_mad(struct snd_soc_codec *codec)
+{
+	int ret;
+	const struct firmware *fw;
+	struct mad_audio_cal *mad_cal;
+	const char *filename = TAIKO_MAD_AUDIO_FIRMWARE_PATH;
+
+	pr_debug("%s: enter\n", __func__);
+	ret = request_firmware(&fw, filename, codec->dev);
+	if (ret != 0) {
+		pr_err("Failed to acquire MAD firwmare data %s: %d\n", filename,
+		       ret);
+		return -ENODEV;
+	}
+
+	if (fw->size < sizeof(struct mad_audio_cal)) {
+		pr_err("%s: incorrect firmware size %u\n", __func__, fw->size);
+		release_firmware(fw);
+		return -ENOMEM;
+	}
+
+	mad_cal = (struct mad_audio_cal *)(fw->data);
+	if (!mad_cal) {
+		pr_err("%s: Invalid calibration data\n", __func__);
+		release_firmware(fw);
+		return -EINVAL;
+	}
+
+	snd_soc_update_bits(codec, TAIKO_A_CDC_CONN_MAD,
+			    0x0F, mad_cal->microphone_info.input_microphone);
+	snd_soc_write(codec, TAIKO_A_CDC_MAD_MAIN_CTL_2,
+		      mad_cal->microphone_info.cycle_time);
+	snd_soc_update_bits(codec, TAIKO_A_CDC_MAD_MAIN_CTL_1, 0xFF << 3,
+			    ((uint16_t)mad_cal->microphone_info.settle_time)
+			    << 3);
+
+	/* Audio */
+	snd_soc_write(codec, TAIKO_A_CDC_MAD_AUDIO_CTL_8,
+		      mad_cal->audio_info.rms_omit_samples);
+	snd_soc_update_bits(codec, TAIKO_A_CDC_MAD_AUDIO_CTL_1,
+			    0x07 << 4, mad_cal->audio_info.rms_comp_time << 4);
+	snd_soc_update_bits(codec, TAIKO_A_CDC_MAD_AUDIO_CTL_2, 0x03 << 2,
+			    mad_cal->audio_info.detection_mechanism << 2);
+	snd_soc_write(codec, TAIKO_A_CDC_MAD_AUDIO_CTL_7,
+		      mad_cal->audio_info.rms_diff_threshold & 0x3F);
+	snd_soc_write(codec, TAIKO_A_CDC_MAD_AUDIO_CTL_5,
+		      mad_cal->audio_info.rms_threshold_lsb);
+	snd_soc_write(codec, TAIKO_A_CDC_MAD_AUDIO_CTL_6,
+		      mad_cal->audio_info.rms_threshold_msb);
+
+
+	/* Beacon */
+	snd_soc_write(codec, TAIKO_A_CDC_MAD_BEACON_CTL_8,
+		      mad_cal->beacon_info.rms_omit_samples);
+	snd_soc_update_bits(codec, TAIKO_A_CDC_MAD_BEACON_CTL_1,
+			    0x07 << 4, mad_cal->beacon_info.rms_comp_time);
+	snd_soc_update_bits(codec, TAIKO_A_CDC_MAD_BEACON_CTL_2, 0x03 << 2,
+			    mad_cal->beacon_info.detection_mechanism << 2);
+	snd_soc_write(codec, TAIKO_A_CDC_MAD_BEACON_CTL_7,
+		      mad_cal->beacon_info.rms_diff_threshold & 0x1F);
+	snd_soc_write(codec, TAIKO_A_CDC_MAD_BEACON_CTL_5,
+		      mad_cal->beacon_info.rms_threshold_lsb);
+	snd_soc_write(codec, TAIKO_A_CDC_MAD_BEACON_CTL_6,
+		      mad_cal->beacon_info.rms_threshold_msb);
+
+	/* Ultrasound */
+	snd_soc_update_bits(codec, TAIKO_A_CDC_MAD_BEACON_CTL_1,
+			    0x07 << 4, mad_cal->beacon_info.rms_comp_time);
+	snd_soc_update_bits(codec, TAIKO_A_CDC_MAD_ULTR_CTL_2, 0x03 << 2,
+			    mad_cal->ultrasound_info.detection_mechanism);
+	snd_soc_write(codec, TAIKO_A_CDC_MAD_ULTR_CTL_7,
+		      mad_cal->ultrasound_info.rms_diff_threshold & 0x1F);
+	snd_soc_write(codec, TAIKO_A_CDC_MAD_ULTR_CTL_5,
+		      mad_cal->ultrasound_info.rms_threshold_lsb);
+	snd_soc_write(codec, TAIKO_A_CDC_MAD_ULTR_CTL_6,
+		      mad_cal->ultrasound_info.rms_threshold_msb);
+
+	release_firmware(fw);
+	pr_debug("%s: leave ret %d\n", __func__, ret);
+
+	return ret;
+}
+
+static int taiko_codec_enable_mad(struct snd_soc_dapm_widget *w,
+				  struct snd_kcontrol *kcontrol, int event)
+{
+	struct snd_soc_codec *codec = w->codec;
+	int ret = 0;
+
+	pr_debug("%s %d\n", __func__, event);
+	switch (event) {
+	case SND_SOC_DAPM_PRE_PMU:
+		ret = taiko_codec_config_mad(codec);
+		if (ret) {
+			pr_err("%s: Failed to config MAD\n", __func__);
+			break;
+		}
+		break;
+	}
+	return ret;
+}
+
 static int taiko_codec_enable_micbias(struct snd_soc_dapm_widget *w,
 	struct snd_kcontrol *kcontrol, int event)
 {
@@ -2564,12 +2790,12 @@
 
 	pr_debug("%s: %s event = %d\n", __func__, w->name, event);
 	if (w->shift == 5) {
-		e_pre_on = WCD9XXX_EVENT_PRE_HPHR_PA_ON;
-		e_post_off = WCD9XXX_EVENT_POST_HPHR_PA_OFF;
-		req_clsh_state = WCD9XXX_CLSH_STATE_HPHL;
-	} else if (w->shift == 4) {
 		e_pre_on = WCD9XXX_EVENT_PRE_HPHL_PA_ON;
 		e_post_off = WCD9XXX_EVENT_POST_HPHL_PA_OFF;
+		req_clsh_state = WCD9XXX_CLSH_STATE_HPHL;
+	} else if (w->shift == 4) {
+		e_pre_on = WCD9XXX_EVENT_PRE_HPHR_PA_ON;
+		e_post_off = WCD9XXX_EVENT_POST_HPHR_PA_OFF;
 		req_clsh_state = WCD9XXX_CLSH_STATE_HPHR;
 	} else {
 		pr_err("%s: Invalid w->shift %d\n", __func__, w->shift);
@@ -2674,6 +2900,11 @@
 	{"AIF3 CAP", NULL, "AIF3_CAP Mixer"},
 	{"AIF4 VI", NULL, "SPK_OUT"},
 
+	/* MAD */
+	{"AIF4 MAD", NULL, "CDC_CONN"},
+	{"MADONOFF", "Switch", "MADINPUT"},
+	{"AIF4 MAD", NULL, "MADONOFF"},
+
 	/* SLIM_MIXER("AIF1_CAP Mixer"),*/
 	{"AIF1_CAP Mixer", "SLIM TX1", "SLIM TX1 MUX"},
 	{"AIF1_CAP Mixer", "SLIM TX2", "SLIM TX2 MUX"},
@@ -3184,6 +3415,8 @@
 
 static int taiko_volatile(struct snd_soc_codec *ssc, unsigned int reg)
 {
+	int i;
+
 	/* Registers lower than 0x100 are top level registers which can be
 	 * written by the Taiko core driver.
 	 */
@@ -3222,6 +3455,11 @@
 		return 1;
 	}
 
+	for (i = 0; i < ARRAY_SIZE(mad_audio_reg_cfg); i++)
+		if (mad_audio_reg_cfg[i].reg_logical_addr -
+		    TAIKO_REGISTER_START_OFFSET == reg)
+			return 1;
+
 	return 0;
 }
 
@@ -3428,6 +3666,7 @@
 	case AIF2_CAP:
 	case AIF3_CAP:
 	case AIF4_VIFEED:
+	case AIF4_MAD_TX:
 		if (!tx_slot || !tx_num) {
 			pr_err("%s: Invalid tx_slot %d or tx_num %d\n",
 				 __func__, (u32) tx_slot, (u32) tx_num);
@@ -3858,6 +4097,20 @@
 	 },
 		.ops = &taiko_dai_ops,
 	},
+	{
+		.name = "taiko_mad1",
+		.id = AIF4_MAD_TX,
+		.capture = {
+			.stream_name = "AIF4 MAD TX",
+			.rates = SNDRV_PCM_RATE_16000,
+			.formats = TAIKO_FORMATS,
+			.rate_min = 16000,
+			.rate_max = 16000,
+			.channels_min = 1,
+			.channels_max = 1,
+		},
+		.ops = &taiko_dai_ops,
+	},
 };
 
 static struct snd_soc_dai_driver taiko_i2s_dai[] = {
@@ -4556,6 +4809,12 @@
 	SND_SOC_DAPM_AIF_OUT_E("AIF4 VI", "VIfeed", 0, SND_SOC_NOPM,
 		AIF4_VIFEED, 0, taiko_codec_enable_slimvi_feedback,
 		SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+	SND_SOC_DAPM_AIF_OUT_E("AIF4 MAD", "AIF4 MAD TX", 0,
+			       SND_SOC_NOPM, 0, 0,
+			       taiko_codec_enable_mad, SND_SOC_DAPM_PRE_PMU),
+	SND_SOC_DAPM_SWITCH("MADONOFF", SND_SOC_NOPM, 0, 0,
+			    &aif4_mad_switch),
+	SND_SOC_DAPM_INPUT("MADINPUT"),
 
 	SND_SOC_DAPM_MIXER("AIF1_CAP Mixer", SND_SOC_NOPM, AIF1_CAP, 0,
 		aif_cap_mixer, ARRAY_SIZE(aif_cap_mixer)),
@@ -4884,6 +5143,26 @@
 	TAIKO_REG_VAL(TAIKO_A_CDC_RX5_B6_CTL, 0x80),
 	TAIKO_REG_VAL(TAIKO_A_CDC_RX6_B6_CTL, 0x80),
 	TAIKO_REG_VAL(TAIKO_A_CDC_RX7_B6_CTL, 0x80),
+
+	/* MAD registers */
+	TAIKO_REG_VAL(TAIKO_A_MAD_ANA_CTRL, 0xF1),
+	TAIKO_REG_VAL(TAIKO_A_CDC_MAD_MAIN_CTL_1, 0x00),
+	TAIKO_REG_VAL(TAIKO_A_CDC_MAD_MAIN_CTL_2, 0x00),
+	TAIKO_REG_VAL(TAIKO_A_CDC_MAD_AUDIO_CTL_1, 0x00),
+	/* Set SAMPLE_TX_EN bit */
+	TAIKO_REG_VAL(TAIKO_A_CDC_MAD_AUDIO_CTL_2, 0x03),
+	TAIKO_REG_VAL(TAIKO_A_CDC_MAD_AUDIO_CTL_3, 0x00),
+	TAIKO_REG_VAL(TAIKO_A_CDC_MAD_AUDIO_CTL_4, 0x00),
+	TAIKO_REG_VAL(TAIKO_A_CDC_MAD_AUDIO_CTL_5, 0x00),
+	TAIKO_REG_VAL(TAIKO_A_CDC_MAD_AUDIO_CTL_6, 0x00),
+	TAIKO_REG_VAL(TAIKO_A_CDC_MAD_AUDIO_CTL_7, 0x00),
+	TAIKO_REG_VAL(TAIKO_A_CDC_MAD_AUDIO_CTL_8, 0x00),
+	TAIKO_REG_VAL(TAIKO_A_CDC_MAD_AUDIO_IIR_CTL_PTR, 0x00),
+	TAIKO_REG_VAL(TAIKO_A_CDC_MAD_AUDIO_IIR_CTL_VAL, 0x40),
+	TAIKO_REG_VAL(TAIKO_A_CDC_DEBUG_B7_CTL, 0x00),
+	TAIKO_REG_VAL(TAIKO_A_CDC_CLK_OTHR_RESET_B1_CTL, 0x00),
+	TAIKO_REG_VAL(TAIKO_A_CDC_CLK_OTHR_CTL, 0x00),
+	TAIKO_REG_VAL(TAIKO_A_CDC_CONN_MAD, 0x01),
 };
 
 static const struct wcd9xxx_reg_mask_val taiko_1_0_reg_defaults[] = {
@@ -5121,6 +5400,26 @@
 }
 EXPORT_SYMBOL_GPL(taiko_hs_detect);
 
+static void taiko_init_slim_slave_cfg(struct snd_soc_codec *codec)
+{
+	struct taiko_priv *priv = snd_soc_codec_get_drvdata(codec);
+	struct afe_param_cdc_slimbus_slave_cfg *cfg;
+	struct wcd9xxx *wcd9xxx = codec->control_data;
+	uint64_t eaddr = 0;
+
+	cfg = &priv->slimbus_slave_cfg;
+	cfg->minor_version = 1;
+	cfg->tx_slave_port_offset = 0;
+	cfg->rx_slave_port_offset = 16;
+
+	memcpy(&eaddr, &wcd9xxx->slim->e_addr, sizeof(wcd9xxx->slim->e_addr));
+	WARN_ON(sizeof(wcd9xxx->slim->e_addr) != 6);
+	cfg->device_enum_addr_lsw = eaddr & 0xFFFFFFFF;
+	cfg->device_enum_addr_msw = eaddr >> 32;
+
+	pr_debug("%s: slimbus logical address 0x%llx\n", __func__, eaddr);
+}
+
 static int taiko_post_reset_cb(struct wcd9xxx *wcd9xxx)
 {
 	int ret = 0;
@@ -5150,6 +5449,8 @@
 	if (IS_ERR_VALUE(ret))
 		pr_err("%s: bad pdata\n", __func__);
 
+	taiko_init_slim_slave_cfg(codec);
+
 	wcd9xxx_mbhc_deinit(&taiko->mbhc);
 	ret = wcd9xxx_mbhc_init(&taiko->mbhc, &taiko->resmgr, codec);
 	if (ret)
@@ -5160,6 +5461,23 @@
 	return ret;
 }
 
+void *taiko_get_afe_config(struct snd_soc_codec *codec,
+			   enum afe_config_type config_type)
+{
+	struct taiko_priv *priv = snd_soc_codec_get_drvdata(codec);
+
+	switch (config_type) {
+	case AFE_SLIMBUS_SLAVE_CONFIG:
+		return &priv->slimbus_slave_cfg;
+	case AFE_CDC_REGISTERS_CONFIG:
+		return &taiko_mad_audio_reg_cfg;
+	case AFE_SLIMBUS_SLAVE_PORT_CONFIG:
+		return &taiko_slimbus_slave_port_cfg;
+	default:
+		pr_err("%s: Unknown config_type 0x%x\n", __func__, config_type);
+		return NULL;
+	}
+}
 
 static struct wcd9xxx_reg_address taiko_reg_address = {
 	.micb_4_mbhc = TAIKO_A_MICB_4_MBHC,
@@ -5353,6 +5671,14 @@
 			INIT_LIST_HEAD(&taiko->dai[i].wcd9xxx_ch_list);
 			init_waitqueue_head(&taiko->dai[i].dai_wait);
 		}
+		taiko_slimbus_slave_port_cfg.slave_dev_intfdev_la =
+		    control->slim_slave->laddr;
+		taiko_slimbus_slave_port_cfg.slave_dev_pgd_la =
+		    control->slim->laddr;
+		taiko_slimbus_slave_port_cfg.slave_port_mapping[0] =
+		    TAIKO_MAD_SLIMBUS_TX_PORT;
+
+		taiko_init_slim_slave_cfg(codec);
 	}
 
 	if (TAIKO_IS_1_0(control->version))
diff --git a/sound/soc/codecs/wcd9320.h b/sound/soc/codecs/wcd9320.h
index 89a0b9f..36310e5 100644
--- a/sound/soc/codecs/wcd9320.h
+++ b/sound/soc/codecs/wcd9320.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -14,6 +14,7 @@
 
 #include <sound/soc.h>
 #include <sound/jack.h>
+#include <sound/apr_audio-v2.h>
 #include <linux/mfd/wcd9xxx/wcd9xxx-slimslave.h>
 #include "wcd9xxx-mbhc.h"
 #include "wcd9xxx-resmgr.h"
@@ -25,6 +26,10 @@
 #define TAIKO_REG_VAL(reg, val)		{reg, 0, val}
 #define TAIKO_MCLK_ID 0
 
+#define TAIKO_REGISTER_START_OFFSET 0x800
+#define TAIKO_SB_PGD_PORT_RX_BASE   0x40
+#define TAIKO_SB_PGD_PORT_TX_BASE   0x50
+
 extern const u8 taiko_reg_readable[TAIKO_CACHE_SIZE];
 extern const u8 taiko_reset_reg_defaults[TAIKO_CACHE_SIZE];
 struct taiko_codec_dai_data {
@@ -90,9 +95,62 @@
 	u32 num_anc_slots;
 };
 
+struct mad_audio_header {
+	u32 reserved[3];
+	u32 num_reg_cfg;
+};
+
+struct mad_microphone_info {
+	uint8_t input_microphone;
+	uint8_t cycle_time;
+	uint8_t settle_time;
+	uint8_t padding;
+} __packed;
+
+struct mad_micbias_info {
+	uint8_t micbias;
+	uint8_t k_factor;
+	uint8_t external_bypass_capacitor;
+	uint8_t internal_biasing;
+	uint8_t cfilter;
+	uint8_t padding[3];
+} __packed;
+
+struct mad_rms_audio_beacon_info {
+	uint8_t rms_omit_samples;
+	uint8_t rms_comp_time;
+	uint8_t detection_mechanism;
+	uint8_t rms_diff_threshold;
+	uint8_t rms_threshold_lsb;
+	uint8_t rms_threshold_msb;
+	uint8_t padding[2];
+	uint8_t iir_coefficients[36];
+} __packed;
+
+struct mad_rms_ultrasound_info {
+	uint8_t rms_comp_time;
+	uint8_t detection_mechanism;
+	uint8_t rms_diff_threshold;
+	uint8_t rms_threshold_lsb;
+	uint8_t rms_threshold_msb;
+	uint8_t padding[3];
+	uint8_t iir_coefficients[36];
+} __packed;
+
+struct mad_audio_cal {
+	uint32_t version;
+	struct mad_microphone_info microphone_info;
+	struct mad_micbias_info micbias_info;
+	struct mad_rms_audio_beacon_info audio_info;
+	struct mad_rms_audio_beacon_info beacon_info;
+	struct mad_rms_ultrasound_info ultrasound_info;
+} __packed;
+
 extern int taiko_mclk_enable(struct snd_soc_codec *codec, int mclk_enable,
 			     bool dapm);
 extern int taiko_hs_detect(struct snd_soc_codec *codec,
 			   struct wcd9xxx_mbhc_config *mbhc_cfg);
+extern void *taiko_get_afe_config(struct snd_soc_codec *codec,
+				  enum afe_config_type config_type);
 
 #endif
diff --git a/sound/soc/codecs/wcd9xxx-mbhc.c b/sound/soc/codecs/wcd9xxx-mbhc.c
index 88f0567..5b54e1b 100644
--- a/sound/soc/codecs/wcd9xxx-mbhc.c
+++ b/sound/soc/codecs/wcd9xxx-mbhc.c
@@ -1039,7 +1039,7 @@
 		goto exit;
 	}
 
-	for (i = 0, d = dt, ch = 0; i < size; i++, d++) {
+	for (i = 0, d = dt; i < size; i++, d++) {
 		if ((i > 0) && (d->_type != dprev->_type)) {
 			pr_debug("%s: Invalid, inconsistent types\n", __func__);
 			type = PLUG_TYPE_INVALID;
@@ -1068,7 +1068,12 @@
 		     maxv))
 			type = PLUG_TYPE_GND_MIC_SWAP;
 	}
-
+	if (((type == PLUG_TYPE_HEADSET || type == PLUG_TYPE_HEADPHONE) &&
+	    ch != size) || (type == PLUG_TYPE_GND_MIC_SWAP && ch)) {
+		pr_debug("%s: Invalid, not fully inserted, TYPE %d\n",
+		    __func__, type);
+		type = PLUG_TYPE_INVALID;
+	}
 exit:
 	pr_debug("%s: Plug type %d detected\n", __func__, type);
 	return type;
@@ -2455,8 +2460,10 @@
 
 	if (mbhc) {
 		codec = mbhc->codec;
-		if (mbhc->hphlocp_cnt++ < OCP_ATTEMPT) {
+		if ((mbhc->hphlocp_cnt < OCP_ATTEMPT) &&
+		    (!mbhc->hphrocp_cnt)) {
 			pr_info("%s: retry\n", __func__);
+			mbhc->hphlocp_cnt++;
 			snd_soc_update_bits(codec, WCD9XXX_A_RX_HPH_OCP_CTL,
 					    0x10, 0x00);
 			snd_soc_update_bits(codec, WCD9XXX_A_RX_HPH_OCP_CTL,
@@ -2464,7 +2471,6 @@
 		} else {
 			wcd9xxx_disable_irq(codec->control_data,
 					  WCD9XXX_IRQ_HPH_PA_OCPL_FAULT);
-			mbhc->hphlocp_cnt = 0;
 			mbhc->hph_status |= SND_JACK_OC_HPHL;
 			wcd9xxx_jack_report(mbhc, &mbhc->headset_jack,
 					    mbhc->hph_status,
@@ -2484,8 +2490,10 @@
 
 	pr_info("%s: received HPHR OCP irq\n", __func__);
 	codec = mbhc->codec;
-	if (mbhc->hphrocp_cnt++ < OCP_ATTEMPT) {
+	if ((mbhc->hphrocp_cnt < OCP_ATTEMPT) &&
+	    (!mbhc->hphlocp_cnt)) {
 		pr_info("%s: retry\n", __func__);
+		mbhc->hphrocp_cnt++;
 		snd_soc_update_bits(codec, WCD9XXX_A_RX_HPH_OCP_CTL, 0x10,
 				    0x00);
 		snd_soc_update_bits(codec, WCD9XXX_A_RX_HPH_OCP_CTL, 0x10,
@@ -2493,7 +2501,6 @@
 	} else {
 		wcd9xxx_disable_irq(mbhc->resmgr->core,
 				    WCD9XXX_IRQ_HPH_PA_OCPR_FAULT);
-		mbhc->hphrocp_cnt = 0;
 		mbhc->hph_status |= SND_JACK_OC_HPHR;
 		wcd9xxx_jack_report(mbhc, &mbhc->headset_jack,
 				    mbhc->hph_status, WCD9XXX_JACK_MASK);
diff --git a/sound/soc/msm/msm-dai-fe.c b/sound/soc/msm/msm-dai-fe.c
index 96709be..e00e409 100644
--- a/sound/soc/msm/msm-dai-fe.c
+++ b/sound/soc/msm/msm-dai-fe.c
@@ -612,6 +612,20 @@
 		.ops = &msm_fe_dai_ops,
 		.name = "DTMF_RX_HOSTLESS",
 	},
+	{
+		.capture = {
+			.stream_name = "Listen Audio Service Capture",
+			.aif_name = "LSM_UL_HL",
+			.rates = SNDRV_PCM_RATE_16000,
+			.formats = SNDRV_PCM_FMTBIT_S16_LE,
+			.channels_min = 1,
+			.channels_max = 1,
+			.rate_min = 16000,
+			.rate_max = 16000,
+		},
+		.ops = &msm_fe_dai_ops,
+		.name = "LSM",
+	},
 };
 
 static __devinit int msm_fe_dai_dev_probe(struct platform_device *pdev)
diff --git a/sound/soc/msm/msm8226.c b/sound/soc/msm/msm8226.c
index 7766b60..235b527 100644
--- a/sound/soc/msm/msm8226.c
+++ b/sound/soc/msm/msm8226.c
@@ -84,6 +84,7 @@
 static int msm_btsco_ch = 1;
 
 static struct mutex cdc_mclk_mutex;
+static struct clk *codec_clk;
 static int clk_users;
 
 static int msm_snd_enable_codec_ext_clk(struct snd_soc_codec *codec, int enable,
@@ -95,21 +96,35 @@
 
 	mutex_lock(&cdc_mclk_mutex);
 	if (enable) {
+		if (!codec_clk) {
+			dev_err(codec->dev, "%s: did not get Taiko MCLK\n",
+					__func__);
+			ret = -EINVAL;
+			goto exit;
+		}
 
 		clk_users++;
 		if (clk_users != 1)
 			goto exit;
-		/* TODO: clk_disable */
-		tapan_mclk_enable(codec, 1, dapm);
+		if (codec_clk) {
+			clk_set_rate(codec_clk, TAPAN_EXT_CLK_RATE);
+			clk_prepare_enable(codec_clk);
+			tapan_mclk_enable(codec, 1, dapm);
+		} else {
+			pr_err("%s: Error setting Tapan MCLK\n", __func__);
+			clk_users--;
+			ret = -EINVAL;
+			goto exit;
+		}
 	} else {
 		if (clk_users > 0) {
 			clk_users--;
 			if (clk_users == 0) {
 				tapan_mclk_enable(codec, 0, dapm);
-				/* TODO: clk_enable */
+				clk_disable_unprepare(codec_clk);
 			}
 		} else {
-			pr_err("%s: Error releasing Tabla MCLK\n", __func__);
+			pr_err("%s: Error releasing Tapan MCLK\n", __func__);
 			ret = -EINVAL;
 			goto exit;
 		}
@@ -349,6 +364,11 @@
 
 	snd_soc_dapm_sync(dapm);
 
+	codec_clk = clk_get(cpu_dai->dev, "osr_clk");
+	if (codec_clk < 0)
+		pr_err("%s() Failed to get clock for %s\n",
+			   __func__, dev_name(cpu_dai->dev));
+
 	snd_soc_dai_set_channel_map(codec_dai, ARRAY_SIZE(tx_ch),
 				    tx_ch, ARRAY_SIZE(rx_ch), rx_ch);
 
@@ -739,6 +759,21 @@
 		.codec_name = "snd-soc-dummy",
 		.be_id = MSM_FRONTEND_DAI_VOLTE,
 	},
+	{
+		.name = "MSM8226 LowLatency",
+		.stream_name = "MultiMedia5",
+		.cpu_dai_name   = "MultiMedia5",
+		.platform_name  = "msm-pcm-dsp.1",
+		.dynamic = 1,
+		.codec_dai_name = "snd-soc-dummy-dai",
+		.codec_name = "snd-soc-dummy",
+		.trigger = {SND_SOC_DPCM_TRIGGER_POST,
+				SND_SOC_DPCM_TRIGGER_POST},
+		.ignore_suspend = 1,
+		/* this dainlink has playback support */
+		.ignore_pmdown_time = 1,
+		.be_id = MSM_FRONTEND_DAI_MULTIMEDIA5,
+	},
 	/* Backend BT/FM DAI Links */
 	{
 		.name = LPASS_BE_INT_BT_SCO_RX,
@@ -957,6 +992,17 @@
 
 static int msm8226_prepare_codec_mclk(struct snd_soc_card *card)
 {
+	struct msm8226_asoc_mach_data *pdata = snd_soc_card_get_drvdata(card);
+	int ret;
+	if (pdata->mclk_gpio) {
+		ret = gpio_request(pdata->mclk_gpio, "TAPAN_CODEC_PMIC_MCLK");
+		if (ret) {
+			dev_err(card->dev,
+				"%s: Failed to request taiko mclk gpio %d\n",
+				__func__, pdata->mclk_gpio);
+			return ret;
+		}
+	}
 	return 0;
 }
 
@@ -1008,7 +1054,16 @@
 		goto err;
 	}
 
-	/* TODO: MCLK GPIO */
+	pdata->mclk_gpio = of_get_named_gpio(pdev->dev.of_node,
+				"qcom,cdc-mclk-gpios", 0);
+	if (pdata->mclk_gpio < 0) {
+		dev_err(&pdev->dev,
+			"Looking up %s property in node %s failed %d\n",
+			"qcom, cdc-mclk-gpios", pdev->dev.of_node->full_name,
+			pdata->mclk_gpio);
+		ret = -ENODEV;
+		goto err;
+	}
 
 	ret = msm8226_prepare_codec_mclk(card);
 	if (ret)
@@ -1024,6 +1079,12 @@
 
 	return 0;
 err:
+	if (pdata->mclk_gpio > 0) {
+		dev_dbg(&pdev->dev, "%s free gpio %d\n",
+			__func__, pdata->mclk_gpio);
+		gpio_free(pdata->mclk_gpio);
+		pdata->mclk_gpio = 0;
+	}
 	devm_kfree(&pdev->dev, pdata);
 	return ret;
 }
@@ -1031,8 +1092,9 @@
 static int __devexit msm8226_asoc_machine_remove(struct platform_device *pdev)
 {
 	struct snd_soc_card *card = platform_get_drvdata(pdev);
+	struct msm8226_asoc_mach_data *pdata = snd_soc_card_get_drvdata(card);
 
-	/* TODO: GPIO MCLK */
+	gpio_free(pdata->mclk_gpio);
 	snd_soc_unregister_card(card);
 
 	return 0;
diff --git a/sound/soc/msm/msm8974.c b/sound/soc/msm/msm8974.c
index 747e027..0dbe3f7 100644
--- a/sound/soc/msm/msm8974.c
+++ b/sound/soc/msm/msm8974.c
@@ -24,6 +24,7 @@
 #include <sound/soc-dapm.h>
 #include <sound/pcm.h>
 #include <sound/jack.h>
+#include <sound/q6afe-v2.h>
 #include <asm/mach-types.h>
 #include <mach/socinfo.h>
 #include <sound/pcm_params.h>
@@ -1003,6 +1004,33 @@
 	return 0;
 }
 
+static int msm_slim_5_tx_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
+					    struct snd_pcm_hw_params *params)
+{
+	int rc;
+	void *config;
+	struct snd_soc_codec *codec = rtd->codec;
+	struct snd_interval *rate =
+	    hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE);
+	struct snd_interval *channels =
+	    hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
+
+	pr_debug("%s enter\n", __func__);
+	rate->min = rate->max = 16000;
+	channels->min = channels->max = 1;
+
+	config = taiko_get_afe_config(codec, AFE_SLIMBUS_SLAVE_PORT_CONFIG);
+	rc = afe_set_config(AFE_SLIMBUS_SLAVE_PORT_CONFIG, config,
+			    SLIMBUS_5_TX);
+	if (rc) {
+		pr_err("%s: Failed to set slimbus slave port config %d\n",
+		       __func__, rc);
+		return rc;
+	}
+
+	return 0;
+}
+
 static int msm_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
 				struct snd_pcm_hw_params *params)
 {
@@ -1054,6 +1082,7 @@
 static int msm_audrx_init(struct snd_soc_pcm_runtime *rtd)
 {
 	int err;
+	void *config_data;
 	struct snd_soc_codec *codec = rtd->codec;
 	struct snd_soc_dapm_context *dapm = &codec->dapm;
 	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
@@ -1108,6 +1137,23 @@
 	snd_soc_dai_set_channel_map(codec_dai, ARRAY_SIZE(tx_ch),
 				    tx_ch, ARRAY_SIZE(rx_ch), rx_ch);
 
+
+	config_data = taiko_get_afe_config(codec, AFE_CDC_REGISTERS_CONFIG);
+	err = afe_set_config(AFE_CDC_REGISTERS_CONFIG, config_data, 0);
+	if (err) {
+		pr_err("%s: Failed to set codec registers config %d\n",
+		       __func__, err);
+		return err;
+	}
+
+	config_data = taiko_get_afe_config(codec, AFE_SLIMBUS_SLAVE_CONFIG);
+	err = afe_set_config(AFE_SLIMBUS_SLAVE_CONFIG, config_data, 0);
+	if (err) {
+		pr_err("%s: Failed to set slimbus slave config %d\n", __func__,
+		       err);
+		return err;
+	}
+
 	/* start mbhc */
 	mbhc_cfg.calibration = def_taiko_mbhc_cal();
 	if (mbhc_cfg.calibration)
@@ -1574,6 +1620,22 @@
 		.ignore_pmdown_time = 1,
 		.be_id = MSM_FRONTEND_DAI_MULTIMEDIA5,
 	},
+	/* LSM FE */
+	{
+		.name = "Listen Audio Service",
+		.stream_name = "Listen Audio Service",
+		.cpu_dai_name = "LSM",
+		.platform_name = "msm-lsm-client",
+		.dynamic = 1,
+		.trigger = { SND_SOC_DPCM_TRIGGER_POST,
+			     SND_SOC_DPCM_TRIGGER_POST },
+		.no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
+		.ignore_suspend = 1,
+		.ignore_pmdown_time = 1,
+		.codec_dai_name = "snd-soc-dummy-dai",
+		.codec_name = "snd-soc-dummy",
+		.be_id = MSM_FRONTEND_DAI_LSM1,
+	},
 	/* Backend BT/FM DAI Links */
 	{
 		.name = LPASS_BE_INT_BT_SCO_RX,
@@ -1837,6 +1899,19 @@
 		.be_hw_params_fixup = msm_be_hw_params_fixup,
 		.ignore_suspend = 1,
 	},
+	/* MAD BE */
+	{
+		.name = LPASS_BE_SLIMBUS_5_TX,
+		.stream_name = "Slimbus5 Capture",
+		.cpu_dai_name = "msm-dai-q6-dev.16395",
+		.platform_name = "msm-pcm-routing",
+		.codec_name = "taiko_codec",
+		.codec_dai_name = "taiko_mad1",
+		.no_pcm = 1,
+		.be_id = MSM_BACKEND_DAI_SLIMBUS_5_TX,
+		.be_hw_params_fixup = msm_slim_5_tx_be_hw_params_fixup,
+		.ops = &msm8974_be_ops,
+	},
 	/* Incall Music BACK END DAI Link */
 	{
 		.name = LPASS_BE_VOICE_PLAYBACK_TX,
diff --git a/sound/soc/msm/qdsp6v2/Makefile b/sound/soc/msm/qdsp6v2/Makefile
index 69c0976..391b3da 100644
--- a/sound/soc/msm/qdsp6v2/Makefile
+++ b/sound/soc/msm/qdsp6v2/Makefile
@@ -1,6 +1,11 @@
-snd-soc-qdsp6v2-objs += msm-dai-q6-v2.o msm-pcm-q6-v2.o msm-pcm-routing-v2.o msm-compr-q6-v2.o  msm-multi-ch-pcm-q6-v2.o
-snd-soc-qdsp6v2-objs += msm-pcm-lpa-v2.o msm-pcm-afe-v2.o msm-pcm-voip-v2.o msm-pcm-voice-v2.o msm-dai-q6-hdmi-v2.o
-obj-$(CONFIG_SND_SOC_QDSP6V2) += snd-soc-qdsp6v2.o msm-pcm-dtmf-v2.o msm-dai-stub-v2.o
-obj-y += q6adm.o q6afe.o q6asm.o q6audio-v2.o q6voice.o q6core.o audio_acdb.o rtac.o
+snd-soc-qdsp6v2-objs += msm-dai-q6-v2.o msm-pcm-q6-v2.o msm-pcm-routing-v2.o \
+			msm-compr-q6-v2.o msm-multi-ch-pcm-q6-v2.o \
+			msm-pcm-lpa-v2.o msm-pcm-afe-v2.o msm-pcm-voip-v2.o \
+			msm-pcm-voice-v2.o msm-dai-q6-hdmi-v2.o \
+			msm-lsm-client.o
+obj-$(CONFIG_SND_SOC_QDSP6V2) += snd-soc-qdsp6v2.o msm-pcm-dtmf-v2.o \
+				 msm-dai-stub-v2.o
+obj-y += q6adm.o q6afe.o q6asm.o q6audio-v2.o q6voice.o q6core.o audio_acdb.o \
+	 rtac.o q6lsm.o
 ocmem-audio-objs += audio_ocmem.o
 obj-$(CONFIG_AUDIO_OCMEM) += ocmem-audio.o
diff --git a/sound/soc/msm/qdsp6v2/audio_acdb.c b/sound/soc/msm/qdsp6v2/audio_acdb.c
index ccaf39d..259f3ed 100644
--- a/sound/soc/msm/qdsp6v2/audio_acdb.c
+++ b/sound/soc/msm/qdsp6v2/audio_acdb.c
@@ -839,7 +839,7 @@
 {
 	int			result;
 	int			i;
-	unsigned long		paddr;
+	ion_phys_addr_t		paddr;
 	void                    *kvptr;
 	unsigned long		kvaddr;
 	unsigned long		mem_len;
diff --git a/sound/soc/msm/qdsp6v2/msm-dai-q6-v2.c b/sound/soc/msm/qdsp6v2/msm-dai-q6-v2.c
index 557ec65..916be0b 100644
--- a/sound/soc/msm/qdsp6v2/msm-dai-q6-v2.c
+++ b/sound/soc/msm/qdsp6v2/msm-dai-q6-v2.c
@@ -701,6 +701,7 @@
 	case SLIMBUS_2_TX:
 	case SLIMBUS_3_TX:
 	case SLIMBUS_4_TX:
+	case SLIMBUS_5_TX:
 		rc = msm_dai_q6_slim_bus_hw_params(params, dai,
 				substream->stream);
 		break;
@@ -831,6 +832,7 @@
 	case SLIMBUS_2_TX:
 	case SLIMBUS_3_TX:
 	case SLIMBUS_4_TX:
+	case SLIMBUS_5_TX:
 		/*
 		 * channel number to be between 128 and 255.
 		 * For TX port use channel numbers
@@ -1980,6 +1982,7 @@
 		break;
 	case SLIMBUS_0_TX:
 	case SLIMBUS_2_TX:
+	case SLIMBUS_5_TX:
 		rc = snd_soc_register_dai(&pdev->dev,
 					  &msm_dai_q6_slimbus_tx_dai);
 		break;
diff --git a/sound/soc/msm/qdsp6v2/msm-lsm-client.c b/sound/soc/msm/qdsp6v2/msm-lsm-client.c
new file mode 100644
index 0000000..ea6f390
--- /dev/null
+++ b/sound/soc/msm/qdsp6v2/msm-lsm-client.c
@@ -0,0 +1,370 @@
+/*
+ * Copyright (c) 2013, Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+#include <linux/init.h>
+#include <linux/err.h>
+#include <linux/module.h>
+#include <linux/time.h>
+#include <linux/wait.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/dma-mapping.h>
+#include <linux/android_pmem.h>
+#include <linux/of.h>
+#include <sound/core.h>
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+#include <sound/pcm.h>
+#include <sound/timer.h>
+#include <sound/initval.h>
+#include <sound/control.h>
+#include <sound/q6lsm.h>
+#include <sound/lsm_params.h>
+#include "msm-pcm-routing-v2.h"
+
+struct lsm_priv {
+	struct snd_pcm_substream *substream;
+	struct lsm_client *lsm_client;
+
+	struct snd_lsm_event_status *event_status;
+	spinlock_t event_lock;
+	wait_queue_head_t event_wait;
+	unsigned long event_avail;
+	atomic_t event_wait_stop;
+};
+
+static void lsm_event_handler(uint32_t opcode, uint32_t token,
+			      void *payload, void *priv)
+{
+	unsigned long flags;
+	struct snd_lsm_event_status *event_status;
+	struct lsm_priv *prtd = priv;
+	struct snd_pcm_substream *substream = prtd->substream;
+
+	pr_debug("%s: enter opcode 0x%x\n", __func__, opcode);
+	switch (opcode) {
+	case LSM_SESSION_EVENT_DETECTION_STATUS:
+		event_status = payload;
+
+		spin_lock_irqsave(&prtd->event_lock, flags);
+		prtd->event_status = krealloc(prtd->event_status,
+					      sizeof(*event_status) +
+					      event_status->payload_size,
+					      GFP_ATOMIC);
+		if (likely(prtd->event_status)) {
+			memcpy(prtd->event_status, event_status,
+			       sizeof(*event_status) +
+			       event_status->payload_size);
+			prtd->event_avail = 1;
+			spin_unlock_irqrestore(&prtd->event_lock, flags);
+			wake_up(&prtd->event_wait);
+		} else {
+			spin_unlock_irqrestore(&prtd->event_lock, flags);
+			pr_err("%s: Couldn't allocate %d bytes of memory\n",
+			       __func__, event_status->payload_size);
+		}
+		if (substream->timer_running)
+			snd_timer_interrupt(substream->timer, 1);
+		break;
+	default:
+		pr_debug("%s: Unsupported Event opcode 0x%x\n", __func__,
+			 opcode);
+		break;
+	}
+}
+
+static int msm_lsm_ioctl(struct snd_pcm_substream *substream,
+			 unsigned int cmd, void *arg)
+{
+	unsigned long flags;
+	int ret;
+	struct snd_lsm_sound_model snd_model;
+	int rc = 0;
+	int xchg = 0;
+	int size = 0;
+	struct snd_lsm_event_status *event_status = NULL;
+	struct snd_pcm_runtime *runtime = substream->runtime;
+	struct lsm_priv *prtd = runtime->private_data;
+	struct snd_lsm_event_status *user = arg;
+
+	pr_debug("%s: enter cmd %x\n", __func__, cmd);
+	switch (cmd) {
+	case SNDRV_LSM_REG_SND_MODEL:
+		pr_debug("%s: Registering sound model\n", __func__);
+		if (copy_from_user(&snd_model, (void *)arg,
+				   sizeof(struct snd_lsm_sound_model))) {
+			rc = -EFAULT;
+			pr_err("%s: copy from user failed, size %d\n", __func__,
+			       sizeof(struct snd_lsm_sound_model));
+			break;
+		}
+
+		rc = q6lsm_snd_model_buf_alloc(prtd->lsm_client,
+					       snd_model.data_size);
+		if (rc) {
+			pr_err("%s: q6lsm buffer alloc failed, size %d\n",
+			       __func__, snd_model.data_size);
+			break;
+		}
+
+		if (copy_from_user(prtd->lsm_client->sound_model.data,
+				   snd_model.data, snd_model.data_size)) {
+			pr_err("%s: copy from user data failed size %d\n",
+			       __func__, snd_model.data_size);
+			rc = -EFAULT;
+			break;
+		}
+
+		rc = q6lsm_register_sound_model(prtd->lsm_client,
+						snd_model.detection_mode,
+						snd_model.min_keyw_confidence,
+						snd_model.min_user_confidence,
+						snd_model.detect_failure);
+		if (rc < 0)
+			pr_err("%s: q6lsm_register_sound_model failed =%d\n",
+			       __func__, rc);
+		break;
+
+	case SNDRV_LSM_DEREG_SND_MODEL:
+		pr_debug("%s: Deregistering sound model\n", __func__);
+		rc = q6lsm_deregister_sound_model(prtd->lsm_client);
+		break;
+
+	case SNDRV_LSM_EVENT_STATUS:
+		pr_debug("%s: Get event status\n", __func__);
+		atomic_set(&prtd->event_wait_stop, 0);
+		rc = wait_event_interruptible(prtd->event_wait,
+				(cmpxchg(&prtd->event_avail, 1, 0) ||
+				 (xchg = atomic_cmpxchg(&prtd->event_wait_stop,
+							1, 0))));
+		pr_debug("%s: wait_event_interruptible %d event_wait_stop %d\n",
+			 __func__, rc, xchg);
+		if (!rc && !xchg) {
+			pr_debug("%s: New event available %ld\n", __func__,
+				 prtd->event_avail);
+			spin_lock_irqsave(&prtd->event_lock, flags);
+			if (prtd->event_status) {
+				size = sizeof(*event_status) +
+				       prtd->event_status->payload_size;
+				event_status = kmemdup(prtd->event_status, size,
+						       GFP_ATOMIC);
+			}
+			spin_unlock_irqrestore(&prtd->event_lock, flags);
+			if (!event_status) {
+				pr_err("%s: Couldn't allocate %d bytes\n",
+				       __func__, size);
+				/*
+				 * Don't use -ENOMEM as userspace will check
+				 * it for increasing buffer
+				 */
+				rc = -EFAULT;
+			} else {
+				if (user->payload_size <
+				    event_status->payload_size) {
+					pr_debug("%s: provided %dbytes isn't enough, needs %dbytes\n",
+						 __func__, user->payload_size,
+						 size);
+					rc = -ENOMEM;
+				} else if (!access_ok(VERIFY_WRITE, arg,
+						      size)) {
+					rc = -EFAULT;
+				} else {
+					rc = copy_to_user(arg, event_status,
+							  size);
+					if (rc)
+						pr_err("%s: copy to user failed %d\n",
+						       __func__, rc);
+				}
+				kfree(event_status);
+			}
+		} else if (xchg) {
+			pr_debug("%s: Wait aborted\n", __func__);
+			rc = 0;
+		}
+		break;
+
+	case SNDRV_LSM_ABORT_EVENT:
+		pr_debug("%s: Aborting event status wait\n", __func__);
+		atomic_set(&prtd->event_wait_stop, 1);
+		wake_up(&prtd->event_wait);
+		break;
+
+	case SNDRV_LSM_START:
+		pr_debug("%s: Starting LSM client session\n", __func__);
+		if (!prtd->lsm_client->started) {
+			ret = q6lsm_start(prtd->lsm_client, true);
+			if (!ret) {
+				prtd->lsm_client->started = true;
+				pr_debug("%s: LSM client session started\n",
+					 __func__);
+			}
+		}
+		break;
+
+	case SNDRV_LSM_STOP:
+		pr_debug("%s: Stopping LSM client session\n", __func__);
+		if (prtd->lsm_client->started) {
+			ret = q6lsm_stop(prtd->lsm_client, true);
+			if (!ret) {
+				prtd->lsm_client->started = false;
+				pr_debug("%s: LSM client session stopped\n",
+					 __func__);
+			}
+		}
+		break;
+
+	default:
+		pr_debug("%s: Falling into default snd_lib_ioctl cmd 0x%x\n",
+			 __func__, cmd);
+		rc = snd_pcm_lib_ioctl(substream, cmd, arg);
+		break;
+	}
+
+	if (!rc)
+		pr_debug("%s: leave (%d)\n", __func__, rc);
+	else
+		pr_err("%s: cmd 0x%x failed %d\n", __func__, cmd, rc);
+
+	return rc;
+}
+
+static int msm_lsm_open(struct snd_pcm_substream *substream)
+{
+	struct snd_pcm_runtime *runtime = substream->runtime;
+	struct lsm_priv *prtd;
+	int ret = 0;
+
+	pr_debug("%s\n", __func__);
+	prtd = kzalloc(sizeof(struct lsm_priv), GFP_KERNEL);
+	if (!prtd) {
+		pr_err("%s: Failed to allocate memory for lsm_priv\n",
+		       __func__);
+		return -ENOMEM;
+	}
+	prtd->substream = substream;
+	prtd->lsm_client = q6lsm_client_alloc((app_cb)lsm_event_handler, prtd);
+	if (!prtd->lsm_client) {
+		pr_err("%s: Could not allocate memory\n", __func__);
+		kfree(prtd);
+		return -ENOMEM;
+	}
+	ret = q6lsm_open(prtd->lsm_client);
+	if (ret < 0) {
+		pr_err("%s: lsm out open failed\n", __func__);
+		q6lsm_client_free(prtd->lsm_client);
+		kfree(prtd);
+		return -ENOMEM;
+	}
+
+	pr_debug("%s: Session ID %d\n", __func__, prtd->lsm_client->session);
+	prtd->lsm_client->started = false;
+	spin_lock_init(&prtd->event_lock);
+	init_waitqueue_head(&prtd->event_wait);
+	runtime->private_data = prtd;
+
+	return 0;
+}
+
+static int msm_lsm_close(struct snd_pcm_substream *substream)
+{
+	unsigned long flags;
+	struct snd_pcm_runtime *runtime = substream->runtime;
+	struct lsm_priv *prtd = runtime->private_data;
+
+	pr_debug("%s\n", __func__);
+
+	q6lsm_close(prtd->lsm_client);
+	q6lsm_client_free(prtd->lsm_client);
+
+	spin_lock_irqsave(&prtd->event_lock, flags);
+	kfree(prtd->event_status);
+	prtd->event_status = NULL;
+	spin_unlock_irqrestore(&prtd->event_lock, flags);
+	kfree(prtd);
+
+	return 0;
+}
+
+static struct snd_pcm_ops msm_lsm_ops = {
+	.open           = msm_lsm_open,
+	.close          = msm_lsm_close,
+	.ioctl          = msm_lsm_ioctl,
+};
+
+static int msm_asoc_lsm_new(struct snd_soc_pcm_runtime *rtd)
+{
+	struct snd_card *card = rtd->card->snd_card;
+
+	if (!card->dev->coherent_dma_mask)
+		card->dev->coherent_dma_mask = DMA_BIT_MASK(32);
+
+	return 0;
+}
+
+static int msm_asoc_lsm_probe(struct snd_soc_platform *platform)
+{
+	pr_debug("enter %s\n", __func__);
+
+	return 0;
+}
+
+static struct snd_soc_platform_driver msm_soc_platform = {
+	.ops		= &msm_lsm_ops,
+	.pcm_new	= msm_asoc_lsm_new,
+	.probe		= msm_asoc_lsm_probe,
+};
+
+static __devinit int msm_lsm_probe(struct platform_device *pdev)
+{
+	if (pdev->dev.of_node)
+		dev_set_name(&pdev->dev, "%s", "msm-lsm-client");
+
+	return snd_soc_register_platform(&pdev->dev, &msm_soc_platform);
+}
+
+static int msm_lsm_remove(struct platform_device *pdev)
+{
+	snd_soc_unregister_platform(&pdev->dev);
+
+	return 0;
+}
+
+static const struct of_device_id msm_lsm_client_dt_match[] = {
+	{.compatible = "qcom,msm-lsm-client" },
+	{ }
+};
+
+static struct platform_driver msm_lsm_driver = {
+	.driver = {
+		.name = "msm-lsm-client",
+		.owner = THIS_MODULE,
+		.of_match_table = of_match_ptr(msm_lsm_client_dt_match),
+	},
+	.probe = msm_lsm_probe,
+	.remove = __devexit_p(msm_lsm_remove),
+};
+
+static int __init msm_soc_platform_init(void)
+{
+	return platform_driver_register(&msm_lsm_driver);
+}
+module_init(msm_soc_platform_init);
+
+static void __exit msm_soc_platform_exit(void)
+{
+	platform_driver_unregister(&msm_lsm_driver);
+}
+module_exit(msm_soc_platform_exit);
+
+MODULE_DESCRIPTION("LSM client platform driver");
+MODULE_DEVICE_TABLE(of, msm_lsm_client_dt_match);
+MODULE_LICENSE("GPL v2");
diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c b/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c
index 9fe438c..819512d 100644
--- a/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c
+++ b/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c
@@ -55,6 +55,27 @@
 static int fm_switch_enable;
 static int fm_pcmrx_switch_enable;
 static int srs_alsa_ctrl_ever_called;
+static int lsm_mux_slim_port;
+
+enum {
+	MADNONE,
+	MADAUDIO,
+	MADBEACON,
+	MADULTRASOUND
+};
+
+#define SLIMBUS_0_TX_TEXT "SLIMBUS_0_TX"
+#define SLIMBUS_1_TX_TEXT "SLIMBUS_1_TX"
+#define SLIMBUS_2_TX_TEXT "SLIMBUS_2_TX"
+#define SLIMBUS_3_TX_TEXT "SLIMBUS_3_TX"
+#define SLIMBUS_4_TX_TEXT "SLIMBUS_4_TX"
+#define SLIMBUS_5_TX_TEXT "SLIMBUS_5_TX"
+#define LSM_FUNCTION_TEXT "LSM Function"
+static const char * const mad_audio_mux_text[] = {
+	"None",
+	SLIMBUS_0_TX_TEXT, SLIMBUS_1_TX_TEXT, SLIMBUS_2_TX_TEXT,
+	SLIMBUS_3_TX_TEXT, SLIMBUS_4_TX_TEXT, SLIMBUS_5_TX_TEXT
+};
 
 #define INT_RX_VOL_MAX_STEPS 0x2000
 #define INT_RX_VOL_GAIN 0x2000
@@ -190,6 +211,7 @@
 	{ SLIMBUS_4_TX, 0, 0, 0, 0, 0},
 	{ SLIMBUS_3_RX, 0, 0, 0, 0, 0},
 	{ SLIMBUS_3_TX, 0, 0, 0, 0, 0},
+	{ SLIMBUS_5_TX, 0, 0, 0, 0, 0 },
 	{ SLIMBUS_EXTPROC_RX, 0, 0, 0, 0, 0},
 	{ SLIMBUS_EXTPROC_RX, 0, 0, 0, 0, 0},
 	{ SLIMBUS_EXTPROC_RX, 0, 0, 0, 0, 0},
@@ -731,6 +753,118 @@
 	return 1;
 }
 
+static int msm_routing_lsm_mux_get(struct snd_kcontrol *kcontrol,
+				   struct snd_ctl_elem_value *ucontrol)
+{
+	ucontrol->value.integer.value[0] = lsm_mux_slim_port;
+	return 0;
+}
+
+static int msm_routing_lsm_mux_put(struct snd_kcontrol *kcontrol,
+				   struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_dapm_widget_list *wlist = snd_kcontrol_chip(kcontrol);
+	struct snd_soc_dapm_widget *widget = wlist->widgets[0];
+	struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
+	int mux = ucontrol->value.enumerated.item[0];
+
+	pr_debug("%s: LSM enable %ld\n", __func__,
+		 ucontrol->value.integer.value[0]);
+	if (ucontrol->value.integer.value[0]) {
+		lsm_mux_slim_port = ucontrol->value.integer.value[0];
+		snd_soc_dapm_mux_update_power(widget, kcontrol, 1, mux, e);
+	} else {
+		snd_soc_dapm_mux_update_power(widget, kcontrol, 1, mux, e);
+		lsm_mux_slim_port = ucontrol->value.integer.value[0];
+	}
+
+	return 0;
+}
+
+static int msm_routing_lsm_func_get(struct snd_kcontrol *kcontrol,
+				    struct snd_ctl_elem_value *ucontrol)
+{
+	int i;
+	u16 port_id;
+	enum afe_mad_type mad_type;
+
+	pr_debug("%s: enter\n", __func__);
+	for (i = 0; i < ARRAY_SIZE(mad_audio_mux_text); i++)
+		if (!strncmp(kcontrol->id.name, mad_audio_mux_text[i],
+			    strlen(mad_audio_mux_text[i])))
+			break;
+
+	if (i-- == ARRAY_SIZE(mad_audio_mux_text)) {
+		WARN(1, "Invalid id name %s\n", kcontrol->id.name);
+		return -EINVAL;
+	}
+
+	port_id = i * 2 + 1 + SLIMBUS_0_RX;
+	mad_type = afe_port_get_mad_type(port_id);
+	pr_debug("%s: port_id 0x%x, mad_type %d\n", __func__, port_id,
+		 mad_type);
+	switch (mad_type) {
+	case MAD_HW_NONE:
+		ucontrol->value.integer.value[0] = MADNONE;
+		break;
+	case MAD_HW_AUDIO:
+		ucontrol->value.integer.value[0] = MADAUDIO;
+		break;
+	case MAD_HW_BEACON:
+		ucontrol->value.integer.value[0] = MADBEACON;
+		break;
+	case MAD_HW_ULTRASOUND:
+		ucontrol->value.integer.value[0] = MADULTRASOUND;
+		break;
+	default:
+		WARN(1, "Unknown\n");
+		return -EINVAL;
+	}
+	return 0;
+}
+
+static int msm_routing_lsm_func_put(struct snd_kcontrol *kcontrol,
+				    struct snd_ctl_elem_value *ucontrol)
+{
+	int i;
+	u16 port_id;
+	enum afe_mad_type mad_type;
+
+	pr_debug("%s: enter\n", __func__);
+	for (i = 0; i < ARRAY_SIZE(mad_audio_mux_text); i++)
+		if (!strncmp(kcontrol->id.name, mad_audio_mux_text[i],
+			    strlen(mad_audio_mux_text[i])))
+			break;
+
+	if (i-- == ARRAY_SIZE(mad_audio_mux_text)) {
+		WARN(1, "Invalid id name %s\n", kcontrol->id.name);
+		return -EINVAL;
+	}
+
+	port_id = i * 2 + 1 + SLIMBUS_0_RX;
+	switch (ucontrol->value.integer.value[0]) {
+	case MADNONE:
+		mad_type = MAD_HW_NONE;
+		break;
+	case MADAUDIO:
+		mad_type = MAD_HW_AUDIO;
+		break;
+	case MADBEACON:
+		mad_type = MAD_HW_BEACON;
+		break;
+	case MADULTRASOUND:
+		mad_type = MAD_HW_ULTRASOUND;
+		break;
+	default:
+		WARN(1, "Unknown\n");
+		return -EINVAL;
+	}
+
+	pr_debug("%s: port_id 0x%x, mad_type %d\n", __func__, port_id,
+		 mad_type);
+	return afe_port_set_mad_type(port_id, mad_type);
+}
+
 static int msm_routing_get_port_mixer(struct snd_kcontrol *kcontrol,
 				struct snd_ctl_elem_value *ucontrol)
 {
@@ -1734,6 +1868,33 @@
 	0, 1, 0, msm_routing_get_fm_pcmrx_switch_mixer,
 	msm_routing_put_fm_pcmrx_switch_mixer);
 
+static const struct soc_enum lsm_mux_enum =
+	SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(mad_audio_mux_text), mad_audio_mux_text);
+static const struct snd_kcontrol_new lsm_mux =
+	SOC_DAPM_ENUM_EXT("LSM1 MUX", lsm_mux_enum,
+			  msm_routing_lsm_mux_get,
+			  msm_routing_lsm_mux_put);
+
+static const char * const lsm_func_text[] = {
+	"None", "AUDIO", "BEACON", "ULTRASOUND"
+};
+static const struct soc_enum lsm_func_enum =
+	SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(lsm_func_text), lsm_func_text);
+static const struct snd_kcontrol_new lsm_function[] = {
+	SOC_ENUM_EXT(SLIMBUS_0_TX_TEXT" "LSM_FUNCTION_TEXT, lsm_func_enum,
+		     msm_routing_lsm_func_get, msm_routing_lsm_func_put),
+	SOC_ENUM_EXT(SLIMBUS_1_TX_TEXT" "LSM_FUNCTION_TEXT, lsm_func_enum,
+		     msm_routing_lsm_func_get, msm_routing_lsm_func_put),
+	SOC_ENUM_EXT(SLIMBUS_2_TX_TEXT" "LSM_FUNCTION_TEXT, lsm_func_enum,
+		     msm_routing_lsm_func_get, msm_routing_lsm_func_put),
+	SOC_ENUM_EXT(SLIMBUS_3_TX_TEXT" "LSM_FUNCTION_TEXT, lsm_func_enum,
+		     msm_routing_lsm_func_get, msm_routing_lsm_func_put),
+	SOC_ENUM_EXT(SLIMBUS_4_TX_TEXT" "LSM_FUNCTION_TEXT, lsm_func_enum,
+		     msm_routing_lsm_func_get, msm_routing_lsm_func_put),
+	SOC_ENUM_EXT(SLIMBUS_5_TX_TEXT" "LSM_FUNCTION_TEXT, lsm_func_enum,
+		     msm_routing_lsm_func_get, msm_routing_lsm_func_put),
+};
+
 static const struct snd_kcontrol_new int_fm_vol_mixer_controls[] = {
 	SOC_SINGLE_EXT_TLV("Internal FM RX Volume", SND_SOC_NOPM, 0,
 	INT_RX_VOL_GAIN, 0, msm_routing_get_fm_vol_mixer,
@@ -2111,6 +2272,9 @@
 		0, 0, 0, 0),
 	SND_SOC_DAPM_AIF_IN("DTMF_DL_HL", "DTMF_RX_HOSTLESS Playback",
 		0, 0, 0, 0),
+	/* LSM */
+	SND_SOC_DAPM_AIF_OUT("LSM_UL_HL", "Listen Audio Service Capture",
+			     0, 0, 0, 0),
 	/* Backend AIF */
 	/* Stream name equals to backend dai link stream name
 	*/
@@ -2156,6 +2320,7 @@
 				0, 0, 0, 0),
 	SND_SOC_DAPM_AIF_IN("SLIMBUS_4_TX", "Slimbus4 Capture",
 				0, 0, 0, 0),
+	SND_SOC_DAPM_AIF_IN("SLIMBUS_5_TX", "Slimbus5 Capture", 0, 0, 0, 0),
 
 	SND_SOC_DAPM_AIF_OUT("AUX_PCM_RX", "AUX PCM Playback", 0, 0, 0, 0),
 	SND_SOC_DAPM_AIF_IN("AUX_PCM_TX", "AUX PCM Capture", 0, 0, 0, 0),
@@ -2180,6 +2345,10 @@
 				&fm_switch_mixer_controls),
 	SND_SOC_DAPM_SWITCH("PCM_RX_DL_HL", SND_SOC_NOPM, 0, 0,
 				&pcm_rx_switch_mixer_controls),
+
+	/* Mux Definitions */
+	SND_SOC_DAPM_MUX("LSM1 MUX", SND_SOC_NOPM, 0, 0, &lsm_mux),
+
 	/* Mixer definitions */
 	SND_SOC_DAPM_MIXER("PRI_RX Audio Mixer", SND_SOC_NOPM, 0, 0,
 	pri_i2s_rx_mixer_controls, ARRAY_SIZE(pri_i2s_rx_mixer_controls)),
@@ -2514,6 +2683,14 @@
 	{"SLIM1_UL_HL", NULL, "SLIMBUS_1_TX"},
 	{"SLIM3_UL_HL", NULL, "SLIMBUS_3_TX"},
 	{"SLIM4_UL_HL", NULL, "SLIMBUS_4_TX"},
+
+	{"LSM1 MUX", "SLIMBUS_0_TX", "SLIMBUS_0_TX"},
+	{"LSM1 MUX", "SLIMBUS_1_TX", "SLIMBUS_1_TX"},
+	{"LSM1 MUX", "SLIMBUS_3_TX", "SLIMBUS_3_TX"},
+	{"LSM1 MUX", "SLIMBUS_4_TX", "SLIMBUS_4_TX"},
+	{"LSM1 MUX", "SLIMBUS_5_TX", "SLIMBUS_5_TX"},
+	{"LSM_UL_HL", NULL, "LSM1 MUX"},
+
 	{"INT_FM_RX", NULL, "INTFM_DL_HL"},
 	{"INTFM_UL_HL", NULL, "INT_FM_TX"},
 	{"AUX_PCM_RX", NULL, "AUXPCM_DL_HL"},
@@ -2600,6 +2777,7 @@
 	{"SLIMBUS_1_TX", NULL, "BE_IN" },
 	{"SLIMBUS_3_TX", NULL, "BE_IN" },
 	{"SLIMBUS_4_TX", NULL, "BE_IN" },
+	{"SLIMBUS_5_TX", NULL, "BE_IN" },
 	{"BE_OUT", NULL, "INT_BT_SCO_RX"},
 	{"INT_BT_SCO_TX", NULL, "BE_IN"},
 	{"BE_OUT", NULL, "INT_FM_RX"},
@@ -2821,6 +2999,9 @@
 	snd_soc_add_platform_controls(platform,
 				multi_ch_channel_map_mixer_controls,
 			ARRAY_SIZE(multi_ch_channel_map_mixer_controls));
+
+	snd_soc_add_platform_controls(platform, lsm_function,
+				      ARRAY_SIZE(lsm_function));
 	return 0;
 }
 
diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.h b/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.h
index 7ecdff3..798f676 100644
--- a/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.h
+++ b/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.h
@@ -51,6 +51,7 @@
 #define LPASS_BE_SLIMBUS_3_TX "SLIMBUS_3_TX"
 #define LPASS_BE_SLIMBUS_4_RX "SLIMBUS_4_RX"
 #define LPASS_BE_SLIMBUS_4_TX "SLIMBUS_4_TX"
+#define LPASS_BE_SLIMBUS_5_TX "SLIMBUS_5_TX"
 
 /* For multimedia front-ends, asm session is allocated dynamically.
  * Hence, asm session/multimedia front-end mapping has to be maintained.
@@ -71,6 +72,7 @@
 	MSM_FRONTEND_DAI_VOICE_STUB,
 	MSM_FRONTEND_DAI_VOLTE,
 	MSM_FRONTEND_DAI_DTMF_RX,
+	MSM_FRONTEND_DAI_LSM1,
 	MSM_FRONTEND_DAI_MAX,
 };
 
@@ -103,6 +105,7 @@
 	MSM_BACKEND_DAI_SLIMBUS_4_TX,
 	MSM_BACKEND_DAI_SLIMBUS_3_RX,
 	MSM_BACKEND_DAI_SLIMBUS_3_TX,
+	MSM_BACKEND_DAI_SLIMBUS_5_TX,
 	MSM_BACKEND_DAI_EXTPROC_RX,
 	MSM_BACKEND_DAI_EXTPROC_TX,
 	MSM_BACKEND_DAI_EXTPROC_EC_TX,
diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-voice-v2.h b/sound/soc/msm/qdsp6v2/msm-pcm-voice-v2.h
index d0b119c..a25fb2a 100644
--- a/sound/soc/msm/qdsp6v2/msm-pcm-voice-v2.h
+++ b/sound/soc/msm/qdsp6v2/msm-pcm-voice-v2.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -11,7 +11,7 @@
  */
 #ifndef _MSM_PCM_VOICE_H
 #define _MSM_PCM_VOICE_H
-#include <sound/apr_audio.h>
+#include <sound/apr_audio-v2.h>
 
 enum {
 	VOICE_SESSION_INDEX,
diff --git a/sound/soc/msm/qdsp6v2/q6afe.c b/sound/soc/msm/qdsp6v2/q6afe.c
index 5e1da59..97cd3fc 100644
--- a/sound/soc/msm/qdsp6v2/q6afe.c
+++ b/sound/soc/msm/qdsp6v2/q6afe.c
@@ -9,7 +9,6 @@
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
  */
-
 #include <linux/slab.h>
 #include <linux/debugfs.h>
 #include <linux/kernel.h>
@@ -22,6 +21,7 @@
 #include <sound/apr_audio-v2.h>
 #include <sound/q6afe-v2.h>
 #include <sound/q6audio-v2.h>
+#include "msm-pcm-routing-v2.h"
 
 #include "audio_acdb.h"
 
@@ -47,6 +47,8 @@
 	int vi_tx_port;
 };
 
+static atomic_t afe_ports_mad_type[SLIMBUS_PORT_LAST - SLIMBUS_0_RX];
+
 static struct afe_ctl this_afe;
 
 #define TIMEOUT_MS 1000
@@ -121,6 +123,7 @@
 			case AFE_SERVICE_CMD_SHARED_MEM_UNMAP_REGIONS:
 			case AFE_SERVICE_CMD_UNREGISTER_RT_PORT_DRIVER:
 			case AFE_PORTS_CMD_DTMF_CTL:
+			case AFE_SVC_CMD_SET_PARAM:
 				atomic_set(&this_afe.state, 0);
 				wake_up(&this_afe.wait[data->token]);
 				break;
@@ -218,6 +221,7 @@
 	case SLIMBUS_2_TX:
 	case SLIMBUS_3_TX:
 	case SLIMBUS_4_TX:
+	case SLIMBUS_5_TX:
 	case INT_FM_TX:
 	case VOICE_RECORD_RX:
 	case INT_BT_SCO_TX:
@@ -298,6 +302,37 @@
 	return ret;
 }
 
+/*
+ * afe_apr_send_pkt : returns 0 on success, negative otherwise.
+ */
+static int afe_apr_send_pkt(void *data, wait_queue_head_t *wait)
+{
+	int ret;
+
+	atomic_set(&this_afe.state, 1);
+	atomic_set(&this_afe.status, 0);
+	ret = apr_send_pkt(this_afe.apr, data);
+	if (ret > 0) {
+		if (wait) {
+			ret = wait_event_timeout(*wait,
+					(atomic_read(&this_afe.state) == 0),
+					msecs_to_jiffies(TIMEOUT_MS));
+			if (ret)
+				ret = 0;
+			else
+				ret = -ETIMEDOUT;
+		} else {
+			ret = 0;
+		}
+	} else if (ret == 0) {
+		/* apr_send_pkt can return 0 when nothing is transmitted */
+		ret = -EINVAL;
+	}
+
+	pr_debug("%s: leave %d\n", __func__, ret);
+	return ret;
+}
+
 static void afe_send_cal_block(int32_t path, u16 port_id)
 {
 	int						result = 0;
@@ -350,22 +385,13 @@
 		__func__, port_id, path,
 		cal_block.cal_size, cal_block.cal_paddr);
 
-	atomic_set(&this_afe.state, 1);
-	result = apr_send_pkt(this_afe.apr, (uint32_t *) &afe_cal);
-	if (result < 0) {
-		pr_err("%s: AFE cal for port %d failed\n",
-			__func__, port_id);
-	}
-
-	result = wait_event_timeout(this_afe.wait[index],
-				 (atomic_read(&this_afe.state) == 0),
-				 msecs_to_jiffies(TIMEOUT_MS));
-	if (!result) {
-		pr_err("%s: wait_event timeout SET AFE CAL\n", __func__);
-		goto done;
-	}
-
-	pr_debug("%s: AFE cal sent for path %d device!\n", __func__, path);
+	result = afe_apr_send_pkt(&afe_cal, &this_afe.wait[index]);
+	if (result)
+		pr_err("%s: AFE cal for port %d failed %d\n",
+		       __func__, port_id, result);
+	else
+		pr_debug("%s: AFE cal sent for path %d device!\n", __func__,
+			 path);
 done:
 	return;
 }
@@ -506,14 +532,319 @@
 	}
 }
 
+int afe_turn_onoff_hw_mad(u16 mad_type, u16 enable)
+{
+	int ret;
+	struct afe_cmd_hw_mad_ctrl config;
+
+	pr_debug("%s: enter\n", __func__);
+	memset(&config, 0, sizeof(config));
+	config.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
+					     APR_HDR_LEN(APR_HDR_SIZE),
+					     APR_PKT_VER);
+	config.hdr.pkt_size = sizeof(config);
+	config.hdr.src_port = 0;
+	config.hdr.dest_port = 0;
+	config.hdr.token = IDX_GLOBAL_CFG;
+	config.hdr.opcode = AFE_PORT_CMD_SET_PARAM_V2;
+	config.param.port_id = SLIMBUS_5_TX;
+	config.param.payload_size = sizeof(config) - sizeof(struct apr_hdr) -
+				    sizeof(config.param);
+	config.param.payload_address_lsw = 0x00;
+	config.param.payload_address_msw = 0x00;
+	config.param.mem_map_handle = 0x00;
+	config.pdata.module_id = AFE_MODULE_HW_MAD;
+	config.pdata.param_id = AFE_PARAM_ID_HW_MAD_CTRL;
+	config.pdata.param_size = sizeof(config.payload);
+	config.payload.minor_version = 1;
+	config.payload.mad_type = mad_type;
+	config.payload.mad_enable = enable;
+
+	ret = afe_apr_send_pkt(&config, &this_afe.wait[IDX_GLOBAL_CFG]);
+	if (ret)
+		pr_err("%s: AFE_PARAM_ID_HW_MAD_CTRL failed %d\n", __func__,
+		       ret);
+	return ret;
+}
+
+static int afe_send_slimbus_slave_cfg(
+	struct afe_param_cdc_slimbus_slave_cfg *sb_slave_cfg)
+{
+	int ret;
+	struct afe_svc_cmd_sb_slave_cfg config;
+
+	pr_debug("%s: enter\n", __func__);
+
+	config.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
+					     APR_HDR_LEN(APR_HDR_SIZE),
+					     APR_PKT_VER);
+	config.hdr.pkt_size = sizeof(config);
+	config.hdr.src_port = 0;
+	config.hdr.dest_port = 0;
+	config.hdr.token = IDX_GLOBAL_CFG;
+	config.hdr.opcode = AFE_SVC_CMD_SET_PARAM;
+	config.param.payload_size = sizeof(config) - sizeof(struct apr_hdr) -
+				    sizeof(config.param);
+	config.param.payload_address_lsw = 0x00;
+	config.param.payload_address_msw = 0x00;
+	config.param.mem_map_handle = 0x00;
+	config.pdata.module_id = AFE_MODULE_CDC_DEV_CFG;
+	config.pdata.param_id = AFE_PARAM_ID_CDC_SLIMBUS_SLAVE_CFG;
+	config.pdata.param_size =
+	    sizeof(struct afe_param_cdc_slimbus_slave_cfg);
+	config.sb_slave_cfg = *sb_slave_cfg;
+
+	ret = afe_apr_send_pkt(&config, &this_afe.wait[IDX_GLOBAL_CFG]);
+	if (ret)
+		pr_err("%s: AFE_PARAM_ID_CDC_SLIMBUS_SLAVE_CFG failed %d\n",
+		       __func__, ret);
+
+	pr_debug("%s: leave %d\n", __func__, ret);
+	return ret;
+}
+
+static int afe_send_codec_reg_config(
+	struct afe_param_cdc_reg_cfg_data *cdc_reg_cfg)
+{
+	int i, ret;
+	int pkt_size, payload_size;
+	struct afe_svc_cmd_cdc_reg_cfg *config;
+	struct afe_svc_cmd_set_param *param;
+
+	pr_debug("%s: enter\n", __func__);
+	payload_size = sizeof(struct afe_param_cdc_reg_cfg_payload) *
+		       cdc_reg_cfg->num_registers;
+	pkt_size = sizeof(*config) + payload_size;
+
+	pr_debug("%s: pkt_size %d, payload %d\n", __func__, pkt_size,
+		 payload_size);
+	config = kzalloc(pkt_size, GFP_KERNEL);
+	if (!config) {
+		pr_warn("%s: Not enought memory, pkt_size %d\n", __func__,
+			pkt_size);
+		return -ENOMEM;
+	}
+
+	config->hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
+					      APR_HDR_LEN(APR_HDR_SIZE),
+					      APR_PKT_VER);
+	config->hdr.pkt_size = pkt_size;
+	config->hdr.src_port = 0;
+	config->hdr.dest_port = 0;
+	config->hdr.token = IDX_GLOBAL_CFG;
+	config->hdr.opcode = AFE_SVC_CMD_SET_PARAM;
+
+	param = &config->param;
+	param->payload_size = payload_size;
+	param->payload_address_lsw = 0x00;
+	param->payload_address_msw = 0x00;
+	param->mem_map_handle = 0x00;
+
+	for (i = 0; i < cdc_reg_cfg->num_registers; i++) {
+		config->reg_data[i].common.module_id = AFE_MODULE_CDC_DEV_CFG;
+		config->reg_data[i].common.param_id = AFE_PARAM_ID_CDC_REG_CFG;
+		config->reg_data[i].common.param_size =
+		    sizeof(config->reg_data[i].reg_cfg);
+		config->reg_data[i].reg_cfg = cdc_reg_cfg->reg_data[i];
+	}
+
+	ret = afe_apr_send_pkt(config, &this_afe.wait[IDX_GLOBAL_CFG]);
+	if (ret)
+		pr_err("%s: AFE_PARAM_ID_CDC_REG_CFG failed %d\n", __func__,
+		       ret);
+
+	kfree(config);
+	pr_debug("%s: leave ret %d\n", __func__, ret);
+	return ret;
+}
+
+static int afe_init_cdc_reg_config(void)
+{
+	int ret;
+	struct afe_svc_cmd_init_cdc_reg_cfg config;
+
+	pr_debug("%s: enter\n", __func__);
+	config.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
+					     APR_HDR_LEN(APR_HDR_SIZE),
+					     APR_PKT_VER);
+	config.hdr.pkt_size = sizeof(config);
+	config.hdr.src_port = 0;
+	config.hdr.dest_port = 0;
+	config.hdr.token = IDX_GLOBAL_CFG;
+	config.hdr.opcode = AFE_SVC_CMD_SET_PARAM;
+
+	config.param.payload_size = sizeof(struct afe_port_param_data_v2);
+	config.param.payload_address_lsw = 0x00;
+	config.param.payload_address_msw = 0x00;
+	config.param.mem_map_handle = 0x00;
+
+	config.init.module_id = AFE_MODULE_CDC_DEV_CFG;
+	config.init.param_id = AFE_PARAM_ID_CDC_REG_CFG_INIT;
+	config.init.param_size = 0;
+
+	ret = afe_apr_send_pkt(&config, &this_afe.wait[IDX_GLOBAL_CFG]);
+	if (ret) {
+		pr_err("%s: AFE_PARAM_ID_CDC_INIT_REG_CFG failed %d\n",
+		       __func__, ret);
+	} else if (atomic_read(&this_afe.status) != 0) {
+		pr_err("%s: config cmd failed\n", __func__);
+		ret = -EINVAL;
+	}
+
+	pr_debug("%s: leave ret %d\n", __func__, 0);
+	return ret;
+}
+
+static int afe_send_slimbus_slave_port_cfg(
+	struct afe_param_slimbus_slave_port_cfg *port_config, u16 port_id)
+{
+	int ret, index;
+	struct afe_cmd_hw_mad_slimbus_slave_port_cfg config;
+
+	pr_debug("%s: enter, port_id %u\n", __func__, port_id);
+	index = q6audio_get_port_index(port_id);
+	if (q6audio_validate_port(port_id) < 0) {
+		pr_err("%s: port id: %#x\n", __func__, port_id);
+		return -EINVAL;
+	}
+
+	config.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
+					     APR_HDR_LEN(APR_HDR_SIZE),
+					     APR_PKT_VER);
+	config.hdr.pkt_size = sizeof(config);
+	config.hdr.src_port = 0;
+	config.hdr.dest_port = 0;
+	config.hdr.token = index;
+	config.hdr.opcode = AFE_PORT_CMD_SET_PARAM_V2;
+	config.param.port_id = port_id;
+	config.param.payload_size = sizeof(config) - sizeof(struct apr_hdr) -
+				    sizeof(config.param);
+	config.param.payload_address_lsw = 0x00;
+	config.param.payload_address_msw = 0x00;
+	config.param.mem_map_handle = 0x00;
+	config.pdata.module_id = AFE_MODULE_HW_MAD;
+	config.pdata.param_id = AFE_PARAM_ID_SLIMBUS_SLAVE_PORT_CFG;
+	config.pdata.param_size = sizeof(*port_config);
+	config.sb_port_cfg = *port_config;
+
+	ret = afe_apr_send_pkt(&config, &this_afe.wait[index]);
+	if (ret) {
+		pr_err("%s: AFE_PARAM_ID_SLIMBUS_SLAVE_PORT_CFG failed %d\n",
+			__func__, ret);
+	} else if (atomic_read(&this_afe.status) != 0) {
+		pr_err("%s: config cmd failed\n", __func__);
+		ret = -EINVAL;
+	}
+	pr_debug("%s: leave %d\n", __func__, ret);
+	return ret;
+}
+
+int afe_port_set_mad_type(u16 port_id, enum afe_mad_type mad_type)
+{
+	int i;
+
+	i = port_id - SLIMBUS_0_RX;
+	if (i < 0 || i > ARRAY_SIZE(afe_ports_mad_type)) {
+		pr_err("%s: Invalid port_id 0x%x\n", __func__, port_id);
+		return -EINVAL;
+	}
+	atomic_set(&afe_ports_mad_type[i], mad_type);
+	return 0;
+}
+
+enum afe_mad_type afe_port_get_mad_type(u16 port_id)
+{
+	int i;
+
+	i = port_id - SLIMBUS_0_RX;
+	if (i < 0 || i > ARRAY_SIZE(afe_ports_mad_type)) {
+		pr_err("%s: Invalid port_id 0x%x\n", __func__, port_id);
+		return MAD_HW_NONE;
+	}
+	return (enum afe_mad_type) atomic_read(&afe_ports_mad_type[i]);
+}
+
+int afe_set_config(enum afe_config_type config_type, void *config_data, int arg)
+{
+	int ret;
+
+	pr_debug("%s: enter config_type %d\n", __func__, config_type);
+	ret = afe_q6_interface_prepare();
+	if (ret) {
+		pr_err("%s: Q6 interface prepare failed %d\n", __func__, ret);
+		return ret;
+	}
+
+	switch (config_type) {
+	case AFE_SLIMBUS_SLAVE_CONFIG:
+		ret = afe_send_slimbus_slave_cfg(config_data);
+		if (!ret)
+			ret = afe_init_cdc_reg_config();
+		else
+			pr_err("%s: Sending slimbus slave config failed %d\n",
+			       __func__, ret);
+		break;
+	case AFE_CDC_REGISTERS_CONFIG:
+		ret = afe_send_codec_reg_config(config_data);
+		break;
+	case AFE_SLIMBUS_SLAVE_PORT_CONFIG:
+		ret = afe_send_slimbus_slave_port_cfg(config_data, arg);
+		break;
+	default:
+		pr_err("%s: unknown configuration type", __func__);
+		ret = -EINVAL;
+	}
+
+	pr_debug("%s: leave ret %d\n", __func__, ret);
+	return ret;
+}
+
+static int afe_send_cmd_port_start(u16 port_id)
+{
+	struct afe_port_cmd_device_start start;
+	int ret, index;
+
+	pr_debug("%s: enter\n", __func__);
+	index = q6audio_get_port_index(port_id);
+	if (q6audio_validate_port(port_id) < 0) {
+		pr_err("%s: port id: %#x\n", __func__, port_id);
+		return -EINVAL;
+	}
+
+	start.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
+					    APR_HDR_LEN(APR_HDR_SIZE),
+					    APR_PKT_VER);
+	start.hdr.pkt_size = sizeof(start);
+	start.hdr.src_port = 0;
+	start.hdr.dest_port = 0;
+	start.hdr.token = index;
+	start.hdr.opcode = AFE_PORT_CMD_DEVICE_START;
+	start.port_id = q6audio_get_port_id(port_id);
+	pr_debug("%s: cmd device start opcode[0x%x] port id[0x%x]\n",
+		 __func__, start.hdr.opcode, start.port_id);
+
+	ret = afe_apr_send_pkt(&start, &this_afe.wait[index]);
+	if (ret) {
+		pr_err("%s: AFE enable for port %#x failed %d\n", __func__,
+		       port_id, ret);
+	} else if (this_afe.task != current) {
+		this_afe.task = current;
+		pr_debug("task_name = %s pid = %d\n",
+			 this_afe.task->comm, this_afe.task->pid);
+	}
+
+	pr_debug("%s: leave %d\n", __func__, ret);
+	return ret;
+}
+
 int afe_port_start(u16 port_id, union afe_port_config *afe_config,
 	u32 rate) /* This function is no blocking */
 {
-	struct afe_port_cmd_device_start start;
 	struct afe_audioif_config_command config;
-	int ret;
+	int ret = 0;
 	int cfg_type;
 	int index = 0;
+	enum afe_mad_type mad_type;
 
 	if (!afe_config) {
 		pr_err("%s: Error, no configuration data\n", __func__);
@@ -529,6 +860,7 @@
 		port_id = VIRTUAL_ID_TO_PORTID(port_id);
 
 	pr_debug("%s: port id: %#x\n", __func__, port_id);
+
 	index = q6audio_get_port_index(port_id);
 	if (q6audio_validate_port(port_id) < 0) {
 		pr_err("%s: port id: %#x\n", __func__, port_id);
@@ -539,11 +871,19 @@
 	if (IS_ERR_VALUE(ret))
 		return ret;
 
-	if (q6audio_validate_port(port_id) < 0) {
-		pr_err("%s: Failed : Invalid Port id = %#x\n", __func__,
-				port_id);
-		ret = -EINVAL;
-		goto fail_cmd;
+	afe_send_cal(port_id);
+
+	/* Start SW MAD module */
+	mad_type = afe_port_get_mad_type(port_id);
+	pr_debug("%s: port_id 0x%x, mad_type %d\n", __func__, port_id,
+		 mad_type);
+	if (mad_type != MAD_HW_NONE) {
+		ret = afe_turn_onoff_hw_mad(mad_type, true);
+		if (ret) {
+			pr_err("%s: afe_turn_onoff_hw_mad failed %d\n",
+			       __func__, ret);
+			return ret;
+		}
 	}
 
 	config.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
@@ -593,6 +933,7 @@
 	case SLIMBUS_3_TX:
 	case SLIMBUS_4_RX:
 	case SLIMBUS_4_TX:
+	case SLIMBUS_5_TX:
 		cfg_type = AFE_PARAM_ID_SLIMBUS_CONFIG;
 		break;
 	case RT_PROXY_PORT_001_RX:
@@ -623,69 +964,17 @@
 
 	config.port = *afe_config;
 
-	atomic_set(&this_afe.state, 1);
-	atomic_set(&this_afe.status, 0);
-	ret = apr_send_pkt(this_afe.apr, (uint32_t *) &config);
-	if (ret < 0) {
+	ret = afe_apr_send_pkt(&config, &this_afe.wait[index]);
+	if (ret) {
 		pr_err("%s: AFE enable for port %#x failed\n", __func__,
 				port_id);
-		ret = -EINVAL;
 		goto fail_cmd;
-	}
-	ret = wait_event_timeout(this_afe.wait[index],
-				(atomic_read(&this_afe.state) == 0),
-					msecs_to_jiffies(TIMEOUT_MS));
-
-	if (!ret) {
-		pr_err("%s: wait_event timeout IF CONFIG\n", __func__);
-		ret = -EINVAL;
-		goto fail_cmd;
-	}
-	if (atomic_read(&this_afe.status) != 0) {
+	} else if (atomic_read(&this_afe.status) != 0) {
 		pr_err("%s: config cmd failed\n", __func__);
 		ret = -EINVAL;
 		goto fail_cmd;
 	}
-	/* send AFE cal */
-	afe_send_cal(port_id);
-
-	start.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
-				APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
-	start.hdr.pkt_size = sizeof(start);
-	start.hdr.src_port = 0;
-	start.hdr.dest_port = 0;
-	start.hdr.token = index;
-	start.hdr.opcode = AFE_PORT_CMD_DEVICE_START;
-	start.port_id = q6audio_get_port_id(port_id);
-	pr_debug("%s: cmd device start opcode[0x%x] port id[0x%x]\n",
-		 __func__, start.hdr.opcode, start.port_id);
-
-	atomic_set(&this_afe.state, 1);
-	ret = apr_send_pkt(this_afe.apr, (uint32_t *) &start);
-
-	if (IS_ERR_VALUE(ret)) {
-		pr_err("%s: AFE enable for port %#x failed\n", __func__,
-				port_id);
-		ret = -EINVAL;
-		goto fail_cmd;
-	}
-
-	ret = wait_event_timeout(this_afe.wait[index],
-				(atomic_read(&this_afe.state) == 0),
-					msecs_to_jiffies(TIMEOUT_MS));
-
-	if (!ret) {
-		pr_err("%s: wait_event timeout PORT START\n", __func__);
-		 ret = -EINVAL;
-		goto fail_cmd;
-	}
-	if (this_afe.task != current)
-		this_afe.task = current;
-
-	pr_debug("task_name = %s pid = %d\n",
-		this_afe.task->comm, this_afe.task->pid);
-
-	return 0;
+	return afe_send_cmd_port_start(port_id);
 
 fail_cmd:
 	return ret;
@@ -725,6 +1014,7 @@
 	case RT_PROXY_PORT_001_TX: return IDX_RT_PROXY_PORT_001_TX;
 	case SLIMBUS_4_RX: return IDX_SLIMBUS_4_RX;
 	case SLIMBUS_4_TX: return IDX_SLIMBUS_4_TX;
+	case SLIMBUS_5_TX: return IDX_SLIMBUS_5_TX;
 	case AFE_PORT_ID_PRIMARY_MI2S_RX:
 		return IDX_AFE_PORT_ID_PRIMARY_MI2S_RX;
 	case AFE_PORT_ID_QUATERNARY_MI2S_RX:
@@ -837,25 +1127,13 @@
 		__func__, config.param.payload_size, config.pdata.param_size,
 		sizeof(config), sizeof(config.param), sizeof(config.port),
 		sizeof(struct apr_hdr), config.pdata.param_id);
-	atomic_set(&this_afe.state, 1);
-	atomic_set(&this_afe.status, 0);
-	ret = apr_send_pkt(this_afe.apr, (uint32_t *) &config);
-	if (ret < 0) {
+
+	ret = afe_apr_send_pkt(&config, &this_afe.wait[index]);
+	if (ret) {
 		pr_err("%s: AFE enable for port %d opcode[0x%x]failed\n",
 			__func__, port_id, cfg_type);
-		ret = -EINVAL;
 		goto fail_cmd;
-	}
-
-	ret = wait_event_timeout(this_afe.wait[index],
-			(atomic_read(&this_afe.state) == 0),
-				msecs_to_jiffies(TIMEOUT_MS));
-	if (!ret) {
-		pr_err("%s: wait_event timeout\n", __func__);
-		ret = -EINVAL;
-		goto fail_cmd;
-	}
-	if (atomic_read(&this_afe.status) != 0) {
+	} else if (atomic_read(&this_afe.status) != 0) {
 		pr_err("%s: config cmd failed\n", __func__);
 		ret = -EINVAL;
 		goto fail_cmd;
@@ -870,24 +1148,14 @@
 	start.port_id = q6audio_get_port_id(port_id);
 	pr_debug("%s: cmd device start opcode[0x%x] port id[0x%x]\n",
 		__func__, start.hdr.opcode, start.port_id);
-	atomic_set(&this_afe.state, 1);
-	ret = apr_send_pkt(this_afe.apr, (uint32_t *) &start);
-	if (ret < 0) {
+
+	ret = afe_apr_send_pkt(&start, &this_afe.wait[index]);
+	if (ret) {
 		pr_err("%s: AFE enable for port %d failed\n", __func__,
 				port_id);
-		ret = -EINVAL;
-		goto fail_cmd;
-	}
-	ret = wait_event_timeout(this_afe.wait[index],
-			(atomic_read(&this_afe.state) == 0),
-				msecs_to_jiffies(TIMEOUT_MS));
-	if (!ret) {
-		pr_err("%s: wait_event timeout\n", __func__);
-		ret = -EINVAL;
 		goto fail_cmd;
 	}
 
-	return 0;
 fail_cmd:
 	return ret;
 }
@@ -934,23 +1202,10 @@
 	lb_cmd.routing_mode = LB_MODE_DEFAULT;
 	lb_cmd.enable = (enable ? 1 : 0);
 	lb_cmd.loopback_cfg_minor_version = AFE_API_VERSION_LOOPBACK_CONFIG;
-	atomic_set(&this_afe.state, 1);
 
-	ret = apr_send_pkt(this_afe.apr, (uint32_t *) &lb_cmd);
-	if (ret < 0) {
-		pr_err("%s: AFE loopback failed\n", __func__);
-		ret = -EINVAL;
-		goto done;
-	}
-	pr_debug("%s: waiting for this_afe.wait[%d]\n", __func__, index);
-	ret = wait_event_timeout(this_afe.wait[index],
-				 (atomic_read(&this_afe.state) == 0),
-				 msecs_to_jiffies(TIMEOUT_MS));
-	if (!ret) {
-		pr_err("%s: wait_event timeout\n", __func__);
-		ret = -EINVAL;
-	}
-done:
+	ret = afe_apr_send_pkt(&lb_cmd, &this_afe.wait[index]);
+	if (ret)
+		pr_err("%s: AFE loopback failed %d\n", __func__, ret);
 	return ret;
 }
 
@@ -1016,24 +1271,13 @@
 	set_param.rx_port_id = port_id;
 	set_param.gain = volume;
 
-	atomic_set(&this_afe.state, 1);
-	ret = apr_send_pkt(this_afe.apr, (uint32_t *) &set_param);
-	if (ret < 0) {
+	ret = afe_apr_send_pkt(&set_param, &this_afe.wait[index]);
+	if (ret) {
 		pr_err("%s: AFE param set failed for port %d\n",
 					__func__, port_id);
-		ret = -EINVAL;
 		goto fail_cmd;
 	}
 
-	ret = wait_event_timeout(this_afe.wait[index],
-				 (atomic_read(&this_afe.state) == 0),
-				 msecs_to_jiffies(TIMEOUT_MS));
-	if (ret < 0) {
-		pr_err("%s: wait_event timeout\n", __func__);
-		ret = -EINVAL;
-		goto fail_cmd;
-	}
-	return 0;
 fail_cmd:
 	return ret;
 }
@@ -1060,9 +1304,8 @@
 	start.port_id = port_id;
 	start.timing = 1;
 
-	atomic_set(&this_afe.state, 1);
-	ret = apr_send_pkt(this_afe.apr, (uint32_t *) &start);
-	if (ret < 0) {
+	ret = afe_apr_send_pkt(&start, NULL);
+	if (ret) {
 		pr_err("%s: AFE enable for port %d failed %d\n",
 		       __func__, port_id, ret);
 		return -EINVAL;
@@ -1095,25 +1338,13 @@
 	start.hdr.opcode = AFE_PSEUDOPORT_CMD_START;
 	start.port_id = port_id;
 	start.timing = 1;
-
 	start.hdr.token = index;
-	atomic_set(&this_afe.state, 1);
-	ret = apr_send_pkt(this_afe.apr, (uint32_t *) &start);
-	if (ret < 0) {
+
+	ret = afe_apr_send_pkt(&start, &this_afe.wait[index]);
+	if (ret)
 		pr_err("%s: AFE enable for port %d failed %d\n",
 		       __func__, port_id, ret);
-		return -EINVAL;
-	}
-
-	ret = wait_event_timeout(this_afe.wait[index],
-				 (atomic_read(&this_afe.state) == 0),
-				 msecs_to_jiffies(TIMEOUT_MS));
-	if (!ret) {
-		pr_err("%s: wait_event timeout\n", __func__);
-		return -EINVAL;
-	}
-
-	return 0;
+	return ret;
 }
 
 int afe_pseudo_port_stop_nowait(u16 port_id)
@@ -1141,17 +1372,13 @@
 	stop.hdr.opcode = AFE_PSEUDOPORT_CMD_STOP;
 	stop.port_id = port_id;
 	stop.reserved = 0;
-
 	stop.hdr.token = index;
-	atomic_set(&this_afe.state, 1);
-	ret = apr_send_pkt(this_afe.apr, (uint32_t *) &stop);
-	if (ret < 0) {
+
+	ret = afe_apr_send_pkt(&stop, NULL);
+	if (ret)
 		pr_err("%s: AFE close failed %d\n", __func__, ret);
-		return -EINVAL;
-	}
 
-	return 0;
-
+	return ret;
 }
 
 int afe_stop_pseudo_port(u16 port_id)
@@ -1180,24 +1407,13 @@
 	stop.hdr.opcode = AFE_PSEUDOPORT_CMD_STOP;
 	stop.port_id = port_id;
 	stop.reserved = 0;
-
 	stop.hdr.token = index;
-	atomic_set(&this_afe.state, 1);
-	ret = apr_send_pkt(this_afe.apr, (uint32_t *) &stop);
-	if (ret < 0) {
+
+	ret = afe_apr_send_pkt(&stop, &this_afe.wait[index]);
+	if (ret)
 		pr_err("%s: AFE close failed %d\n", __func__, ret);
-		return -EINVAL;
-	}
 
-	ret = wait_event_timeout(this_afe.wait[index],
-				 (atomic_read(&this_afe.state) == 0),
-				 msecs_to_jiffies(TIMEOUT_MS));
-	if (!ret) {
-		pr_err("%s: wait_event timeout\n", __func__);
-		return -EINVAL;
-	}
-
-	return 0;
+	return ret;
 }
 
 uint32_t afe_req_mmap_handle(struct afe_audio_client *ac)
@@ -1480,15 +1696,11 @@
 	mregion_pl->shm_addr_msw = 0x00;
 	mregion_pl->mem_size_bytes = dma_buf_sz;
 
-	atomic_set(&this_afe.state, 1);
-	ret = apr_send_pkt(this_afe.apr, (uint32_t *) mmap_region_cmd);
-	if (ret < 0) {
+	ret = afe_apr_send_pkt(mmap_region_cmd, NULL);
+	if (ret)
 		pr_err("%s: AFE memory map cmd failed %d\n",
 		       __func__, ret);
-		ret = -EINVAL;
-		return ret;
-	}
-	return 0;
+	return ret;
 }
 int q6afe_audio_client_buf_free_contiguous(unsigned int dir,
 			struct afe_audio_client *ac)
@@ -1576,24 +1788,11 @@
 	/* Todo */
 	index = mregion.hdr.token = IDX_RSVD_2;
 
-	atomic_set(&this_afe.state, 1);
-	ret = apr_send_pkt(this_afe.apr, (uint32_t *) &mregion);
-	if (ret < 0) {
+	ret = afe_apr_send_pkt(&mregion, &this_afe.wait[index]);
+	if (ret)
 		pr_err("%s: AFE memory unmap cmd failed %d\n",
 		       __func__, ret);
-		ret = -EINVAL;
-		return ret;
-	}
-
-	ret = wait_event_timeout(this_afe.wait[index],
-				 (atomic_read(&this_afe.state) == 0),
-				 msecs_to_jiffies(TIMEOUT_MS));
-	if (!ret) {
-		pr_err("%s: wait_event timeout\n", __func__);
-		ret = -EINVAL;
-		return ret;
-	}
-	return 0;
+	return ret;
 }
 
 int afe_cmd_memory_unmap_nowait(u32 mem_map_handle)
@@ -1623,13 +1822,11 @@
 	mregion.hdr.opcode = AFE_SERVICE_CMD_SHARED_MEM_UNMAP_REGIONS;
 	mregion.mem_map_handle = mem_map_handle;
 
-	ret = apr_send_pkt(this_afe.apr, (uint32_t *) &mregion);
-	if (ret < 0) {
+	ret = afe_apr_send_pkt(&mregion, NULL);
+	if (ret)
 		pr_err("%s: AFE memory unmap cmd failed %d\n",
 			__func__, ret);
-		ret = -EINVAL;
-	}
-	return 0;
+	return ret;
 }
 
 int afe_register_get_events(u16 port_id,
@@ -1675,14 +1872,11 @@
 	rtproxy.port_id = port_id;
 	rtproxy.reserved = 0;
 
-	ret = apr_send_pkt(this_afe.apr, (uint32_t *) &rtproxy);
-	if (ret < 0) {
+	ret = afe_apr_send_pkt(&rtproxy, NULL);
+	if (ret)
 		pr_err("%s: AFE  reg. rtproxy_event failed %d\n",
 			   __func__, ret);
-		ret = -EINVAL;
-		return ret;
-	}
-	return 0;
+	return ret;
 }
 
 int afe_unregister_get_events(u16 port_id)
@@ -1734,24 +1928,11 @@
 		this_afe.rx_private_data = NULL;
 	}
 
-	atomic_set(&this_afe.state, 1);
-	ret = apr_send_pkt(this_afe.apr, (uint32_t *) &rtproxy);
-	if (ret < 0) {
+	ret = afe_apr_send_pkt(&rtproxy, &this_afe.wait[index]);
+	if (ret)
 		pr_err("%s: AFE enable Unreg. rtproxy_event failed %d\n",
 			   __func__, ret);
-		ret = -EINVAL;
-		return ret;
-	}
-
-	ret = wait_event_timeout(this_afe.wait[index],
-				 (atomic_read(&this_afe.state) == 0),
-				 msecs_to_jiffies(TIMEOUT_MS));
-	if (!ret) {
-		pr_err("%s: wait_event timeout\n", __func__);
-		ret = -EINVAL;
-		return ret;
-	}
-	return 0;
+	return ret;
 }
 
 int afe_rt_proxy_port_write(u32 buf_addr_p, u32 mem_map_handle, int bytes)
@@ -1781,14 +1962,11 @@
 	afecmd_wr.available_bytes = bytes;
 	afecmd_wr.reserved = 0;
 
-	ret = apr_send_pkt(this_afe.apr, (uint32_t *) &afecmd_wr);
-	if (ret < 0) {
+	ret = afe_apr_send_pkt(&afecmd_wr, NULL);
+	if (ret)
 		pr_err("%s: AFE rtproxy write to port 0x%x failed %d\n",
 			   __func__, afecmd_wr.port_id, ret);
-		ret = -EINVAL;
-		return ret;
-	}
-	return 0;
+	return ret;
 
 }
 
@@ -1818,14 +1996,11 @@
 	afecmd_rd.available_bytes = bytes;
 	afecmd_rd.mem_map_handle = mem_map_handle;
 
-	ret = apr_send_pkt(this_afe.apr, (uint32_t *) &afecmd_rd);
-	if (ret < 0) {
+	ret = afe_apr_send_pkt(&afecmd_rd, NULL);
+	if (ret)
 		pr_err("%s: AFE rtproxy read  cmd to port 0x%x failed %d\n",
 			   __func__, afecmd_rd.port_id, ret);
-		ret = -EINVAL;
-		return ret;
-	}
-	return 0;
+	return ret;
 }
 
 #ifdef CONFIG_DEBUG_FS
@@ -2102,25 +2277,10 @@
 	cmd_sidetone.routing_mode = LB_MODE_SIDETONE;
 	cmd_sidetone.enable = enable;
 
-	atomic_set(&this_afe.state, 1);
-	ret = apr_send_pkt(this_afe.apr, (uint32_t *) &cmd_sidetone);
-	if (ret < 0) {
+	ret = afe_apr_send_pkt(&cmd_sidetone, &this_afe.wait[index]);
+	if (ret)
 		pr_err("%s: AFE sidetone failed for tx_port:%d rx_port:%d\n",
 					__func__, tx_port_id, rx_port_id);
-		ret = -EINVAL;
-		goto fail_cmd;
-	}
-
-	ret = wait_event_timeout(this_afe.wait[index],
-		(atomic_read(&this_afe.state) == 0),
-			msecs_to_jiffies(TIMEOUT_MS));
-	if (ret < 0) {
-		pr_err("%s: wait_event timeout\n", __func__);
-		ret = -EINVAL;
-		goto fail_cmd;
-	}
-	return 0;
-fail_cmd:
 	return ret;
 }
 
@@ -2217,12 +2377,9 @@
 	stop.port_id = port_id;
 	stop.reserved = 0;
 
-	ret = apr_send_pkt(this_afe.apr, (uint32_t *) &stop);
-
-	if (IS_ERR_VALUE(ret)) {
+	ret = afe_apr_send_pkt(&stop, NULL);
+	if (ret)
 		pr_err("%s: AFE close failed\n", __func__);
-		ret = -EINVAL;
-	}
 
 fail_cmd:
 	return ret;
@@ -2232,10 +2389,10 @@
 int afe_close(int port_id)
 {
 	struct afe_port_cmd_device_stop stop;
+	enum afe_mad_type mad_type;
 	int ret = 0;
 	int index = 0;
 
-
 	if (this_afe.apr == NULL) {
 		pr_err("AFE is already closed\n");
 		ret = -EINVAL;
@@ -2245,9 +2402,25 @@
 
 	port_id = q6audio_convert_virtual_to_portid(port_id);
 	index = q6audio_get_port_index(port_id);
-	if (q6audio_validate_port(port_id) < 0)
+	if (q6audio_validate_port(port_id) < 0) {
+		pr_warn("%s: Not a valid port id 0x0%x\n", __func__, port_id);
 		return -EINVAL;
+	}
 
+	mad_type = afe_port_get_mad_type(port_id);
+	pr_debug("%s: port_id 0x%x, mad_type %d\n", __func__, port_id,
+		 mad_type);
+	if (mad_type != MAD_HW_NONE) {
+		pr_debug("%s: Turn off MAD\n", __func__);
+		ret = afe_turn_onoff_hw_mad(mad_type, false);
+		if (ret) {
+			pr_err("%s: afe_turn_onoff_hw_mad failed %d\n",
+			       __func__, ret);
+			return ret;
+		}
+	} else {
+		pr_debug("%s: Not a MAD port\n", __func__);
+	}
 
 	stop.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
 				APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
@@ -2259,23 +2432,10 @@
 	stop.port_id = q6audio_get_port_id(port_id);
 	stop.reserved = 0;
 
-	atomic_set(&this_afe.state, 1);
-	ret = apr_send_pkt(this_afe.apr, (uint32_t *) &stop);
+	ret = afe_apr_send_pkt(&stop, &this_afe.wait[index]);
+	if (ret)
+		pr_err("%s: AFE close failed %d\n", __func__, ret);
 
-	if (ret < 0) {
-		pr_err("%s: AFE close failed\n", __func__);
-		ret = -EINVAL;
-		goto fail_cmd;
-	}
-
-	ret = wait_event_timeout(this_afe.wait[index],
-			(atomic_read(&this_afe.state) == 0),
-					msecs_to_jiffies(TIMEOUT_MS));
-	if (!ret) {
-		pr_err("%s: wait_event timeout\n", __func__);
-		ret = -EINVAL;
-		goto fail_cmd;
-	}
 fail_cmd:
 	return ret;
 }
diff --git a/sound/soc/msm/qdsp6v2/q6audio-v2.c b/sound/soc/msm/qdsp6v2/q6audio-v2.c
index 4ed0fb7..d3d335d 100644
--- a/sound/soc/msm/qdsp6v2/q6audio-v2.c
+++ b/sound/soc/msm/qdsp6v2/q6audio-v2.c
@@ -44,6 +44,7 @@
 	case SLIMBUS_2_RX: return IDX_SLIMBUS_2_RX;
 	case SLIMBUS_2_TX: return IDX_SLIMBUS_2_TX;
 	case SLIMBUS_4_TX: return IDX_SLIMBUS_4_TX;
+	case SLIMBUS_5_TX: return IDX_SLIMBUS_5_TX;
 	case INT_BT_SCO_RX: return IDX_INT_BT_SCO_RX;
 	case INT_BT_SCO_TX: return IDX_INT_BT_SCO_TX;
 	case INT_BT_A2DP_RX: return IDX_INT_BT_A2DP_RX;
@@ -91,6 +92,7 @@
 	case SLIMBUS_2_RX: return AFE_PORT_ID_SLIMBUS_MULTI_CHAN_2_RX;
 	case SLIMBUS_2_TX: return AFE_PORT_ID_SLIMBUS_MULTI_CHAN_2_TX;
 	case SLIMBUS_4_TX: return AFE_PORT_ID_SLIMBUS_MULTI_CHAN_4_TX;
+	case SLIMBUS_5_TX: return AFE_PORT_ID_SLIMBUS_MULTI_CHAN_5_TX;
 	case INT_BT_SCO_RX: return AFE_PORT_ID_INTERNAL_BT_SCO_RX;
 	case INT_BT_SCO_TX: return AFE_PORT_ID_INTERNAL_BT_SCO_TX;
 	case INT_BT_A2DP_RX: return AFE_PORT_ID_INTERNAL_BT_A2DP_RX;
@@ -109,7 +111,9 @@
 	case AFE_PORT_ID_SECONDARY_MI2S_TX:
 			     return AFE_PORT_ID_SECONDARY_MI2S_TX;
 
-	default: return -EINVAL;
+	default:
+		pr_warn("%s: Invalid port_id %d\n", __func__, port_id);
+		return -EINVAL;
 	}
 }
 int q6audio_convert_virtual_to_portid(u16 port_id)
@@ -185,6 +189,7 @@
 	case SLIMBUS_2_RX:
 	case SLIMBUS_2_TX:
 	case SLIMBUS_4_TX:
+	case SLIMBUS_5_TX:
 	case INT_BT_SCO_RX:
 	case INT_BT_SCO_TX:
 	case INT_BT_A2DP_RX:
diff --git a/sound/soc/msm/qdsp6v2/q6lsm.c b/sound/soc/msm/qdsp6v2/q6lsm.c
new file mode 100644
index 0000000..f2b531a
--- /dev/null
+++ b/sound/soc/msm/qdsp6v2/q6lsm.c
@@ -0,0 +1,813 @@
+/*
+ * Copyright (c) 2013, Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+#include <linux/fs.h>
+#include <linux/mutex.h>
+#include <linux/wait.h>
+#include <linux/miscdevice.h>
+#include <linux/uaccess.h>
+#include <linux/sched.h>
+#include <linux/miscdevice.h>
+#include <linux/delay.h>
+#include <linux/spinlock.h>
+#include <linux/slab.h>
+#include <linux/memory_alloc.h>
+#include <linux/debugfs.h>
+#include <linux/time.h>
+#include <linux/atomic.h>
+#include <sound/apr_audio-v2.h>
+#include <sound/lsm_params.h>
+#include <sound/q6lsm.h>
+#include <asm/ioctls.h>
+#include <mach/memory.h>
+#include <mach/debug_mm.h>
+#include <mach/msm_subsystem_map.h>
+#include "audio_acdb.h"
+
+#define APR_TIMEOUT	(5 * HZ)
+#define LSM_CAL_SIZE	4096
+
+enum {
+	CMD_STATE_CLEARED = 0,
+	CMD_STATE_WAIT_RESP = 1,
+};
+
+enum {
+	LSM_INVALID_SESSION_ID = 0,
+	LSM_MIN_SESSION_ID = 1,
+	LSM_MAX_SESSION_ID = 8,
+};
+
+struct lsm_common {
+	void *apr;
+	atomic_t apr_users;
+	uint32_t lsm_cal_addr;
+	uint32_t lsm_cal_size;
+	uint32_t mmap_handle_for_cal;
+	struct mutex apr_lock;
+};
+
+static struct lsm_common lsm_common;
+
+/*
+ * mmap_handle_p can point either client->sound_model.mem_map_handle or
+ * lsm_common.mmap_handle_for_cal.
+ * mmap_lock must be held while accessing this.
+ */
+static spinlock_t mmap_lock;
+static uint32_t *mmap_handle_p;
+
+static spinlock_t lsm_session_lock;
+static struct lsm_client *lsm_session[LSM_MAX_SESSION_ID + 1];
+
+static int q6lsm_mmapcallback(struct apr_client_data *data, void *priv);
+static int q6lsm_send_cal(struct lsm_client *client);
+static int q6lsm_snd_model_buf_free(struct lsm_client *client);
+
+static int q6lsm_callback(struct apr_client_data *data, void *priv)
+{
+	struct lsm_client *client = (struct lsm_client *)priv;
+	uint32_t token;
+	uint32_t *payload;
+
+	if (!client || !data) {
+		WARN_ON(1);
+		return -EINVAL;
+	}
+
+	payload = data->payload;
+	pr_debug("%s: Session %d opcode 0x%x token 0x%x payload size %d\n",
+		__func__, client->session,
+		data->opcode, data->token, data->payload_size);
+
+	if (data->opcode == APR_BASIC_RSP_RESULT) {
+		token = data->token;
+		switch (payload[0]) {
+		case LSM_SESSION_CMD_START:
+		case LSM_SESSION_CMD_STOP:
+		case LSM_SESSION_CMD_SET_PARAMS:
+		case LSM_SESSION_CMD_OPEN_TX:
+		case LSM_SESSION_CMD_CLOSE_TX:
+		case LSM_SESSION_CMD_REGISTER_SOUND_MODEL:
+		case LSM_SESSION_CMD_DEREGISTER_SOUND_MODEL:
+		case LSM_SESSION_CMD_SHARED_MEM_UNMAP_REGIONS:
+			if (token != client->session &&
+			    payload[0] !=
+				LSM_SESSION_CMD_DEREGISTER_SOUND_MODEL) {
+				pr_err("%s: Invalid session %d receivced expected %d\n",
+					__func__, token, client->session);
+				return -EINVAL;
+			}
+			if (atomic_cmpxchg(&client->cmd_state,
+					   CMD_STATE_WAIT_RESP,
+					   CMD_STATE_CLEARED) ==
+					       CMD_STATE_WAIT_RESP)
+				wake_up(&client->cmd_wait);
+			break;
+		default:
+			pr_debug("%s: Unknown command 0x%x\n",
+				__func__, payload[0]);
+			break;
+		}
+		return 0;
+	}
+
+	if (client->cb)
+		client->cb(data->opcode, data->token, data->payload,
+			   client->priv);
+
+	return 0;
+}
+
+static int q6lsm_session_alloc(struct lsm_client *client)
+{
+	unsigned long flags;
+	int n, ret = -ENOMEM;
+
+	spin_lock_irqsave(&lsm_session_lock, flags);
+	for (n = LSM_MIN_SESSION_ID; n <= LSM_MAX_SESSION_ID; n++) {
+		if (!lsm_session[n]) {
+			lsm_session[n] = client;
+			ret = n;
+			break;
+		}
+	}
+	spin_unlock_irqrestore(&lsm_session_lock, flags);
+	return ret;
+}
+
+static void q6lsm_session_free(struct lsm_client *client)
+{
+	unsigned long flags;
+
+	pr_debug("%s: Freeing session ID %d\n", __func__, client->session);
+	spin_lock_irqsave(&lsm_session_lock, flags);
+	lsm_session[client->session] = LSM_INVALID_SESSION_ID;
+	spin_unlock_irqrestore(&lsm_session_lock, flags);
+	client->session = LSM_INVALID_SESSION_ID;
+}
+
+static void *q6lsm_mmap_apr_reg(void)
+{
+	if (atomic_inc_return(&lsm_common.apr_users) == 1) {
+		lsm_common.apr =
+		    apr_register("ADSP", "LSM", q6lsm_mmapcallback,
+				 0x0FFFFFFFF, &lsm_common);
+		if (!lsm_common.apr) {
+			pr_debug("%s Unable to register APR LSM common port\n",
+				 __func__);
+			atomic_dec(&lsm_common.apr_users);
+		}
+	}
+
+	return lsm_common.apr;
+}
+
+static int q6lsm_mmap_apr_dereg(void)
+{
+	if (atomic_read(&lsm_common.apr_users) <= 0) {
+		WARN("%s: APR common port already closed\n", __func__);
+	} else {
+		if (atomic_dec_return(&lsm_common.apr_users) == 0) {
+			apr_deregister(lsm_common.apr);
+			pr_debug("%s:APR De-Register common port\n", __func__);
+		}
+	}
+	return 0;
+}
+
+struct lsm_client *q6lsm_client_alloc(app_cb cb, void *priv)
+{
+	struct lsm_client *client;
+	int n;
+
+	pr_debug("%s: enter\n", __func__);
+	client = kzalloc(sizeof(struct lsm_client), GFP_KERNEL);
+	if (!client)
+		return NULL;
+	n = q6lsm_session_alloc(client);
+	if (n <= 0) {
+		kfree(client);
+		return NULL;
+	}
+
+	pr_debug("%s: New client session %d\n", __func__, client->session);
+	client->session = n;
+	client->cb = cb;
+	client->priv = priv;
+	client->apr = apr_register("ADSP", "LSM", q6lsm_callback,
+				   ((client->session) << 8 | 0x0001), client);
+
+	if (client->apr == NULL) {
+		pr_err("%s: Registration with APR failed\n", __func__);
+		goto fail;
+	}
+
+	pr_debug("%s Registering the common port with APR\n", __func__);
+	client->mmap_apr = q6lsm_mmap_apr_reg();
+	if (!client->mmap_apr) {
+		pr_err("%s: APR registration failed\n", __func__);
+		goto fail;
+	}
+
+	init_waitqueue_head(&client->cmd_wait);
+	mutex_init(&client->cmd_lock);
+	atomic_set(&client->cmd_state, CMD_STATE_CLEARED);
+	pr_debug("%s: New client allocated\n", __func__);
+	return client;
+fail:
+	q6lsm_client_free(client);
+	return NULL;
+}
+
+void q6lsm_client_free(struct lsm_client *client)
+{
+	if (!client || !client->session)
+		return;
+
+	apr_deregister(client->apr);
+	client->mmap_apr = NULL;
+	q6lsm_session_free(client);
+	q6lsm_mmap_apr_dereg();
+	mutex_destroy(&client->cmd_lock);
+	kfree(client);
+}
+
+/*
+ * q6lsm_apr_send_pkt : If wait == true, hold mutex to prevent from preempting
+ *			other thread's wait.
+ *			If mmap_handle_p != NULL, disable irq and spin lock to
+ *			protect mmap_handle_p
+ */
+static int q6lsm_apr_send_pkt(struct lsm_client *client, void *handle,
+			      void *data, bool wait, uint32_t *mmap_p)
+{
+	int ret;
+	unsigned long flags = 0;
+
+	pr_debug("%s: enter wait %d\n", __func__, wait);
+	if (wait)
+		mutex_lock(&lsm_common.apr_lock);
+	if (mmap_p) {
+		WARN_ON(!wait);
+		spin_lock_irqsave(&mmap_lock, flags);
+		mmap_handle_p = mmap_p;
+	}
+	atomic_set(&client->cmd_state, CMD_STATE_WAIT_RESP);
+	ret = apr_send_pkt(client->apr, data);
+	if (mmap_p)
+		spin_unlock_irqrestore(&mmap_lock, flags);
+
+	if (ret < 0) {
+		pr_err("%s: apr_send_pkt failed %d\n", __func__, ret);
+	} else if (wait) {
+		ret = wait_event_timeout(client->cmd_wait,
+					 (atomic_read(&client->cmd_state) ==
+					      CMD_STATE_CLEARED),
+					 APR_TIMEOUT);
+		if (likely(ret))
+			ret = 0;
+		else
+			pr_err("%s: wait timedout\n", __func__);
+	} else {
+		ret = 0;
+	}
+	if (wait)
+		mutex_unlock(&lsm_common.apr_lock);
+
+	pr_debug("%s: leave ret %d\n", __func__, ret);
+	return ret;
+}
+
+static void q6lsm_add_hdr(struct lsm_client *client, struct apr_hdr *hdr,
+			uint32_t pkt_size, bool cmd_flg)
+{
+	pr_debug("%s: pkt_size %d cmd_flg %d session %d\n", __func__,
+		pkt_size, cmd_flg, client->session);
+	hdr->hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
+				       APR_HDR_LEN(sizeof(struct apr_hdr)),
+				       APR_PKT_VER);
+	hdr->src_svc = APR_SVC_LSM;
+	hdr->src_domain = APR_DOMAIN_APPS;
+	hdr->dest_svc = APR_SVC_LSM;
+	hdr->dest_domain = APR_DOMAIN_ADSP;
+	hdr->src_port = ((client->session << 8) & 0xFF00) | 0x01;
+	hdr->dest_port = ((client->session << 8) & 0xFF00) | 0x01;
+	hdr->pkt_size = pkt_size;
+	if (cmd_flg)
+		hdr->token = client->session;
+}
+
+int q6lsm_open(struct lsm_client *client)
+{
+	int rc;
+	struct lsm_stream_cmd_open_tx open;
+
+	memset(&open, 0, sizeof(open));
+	q6lsm_add_hdr(client, &open.hdr, sizeof(open), true);
+
+	open.hdr.opcode = LSM_SESSION_CMD_OPEN_TX;
+	open.app_id = 1;
+	open.sampling_rate = 16000;
+
+	rc = q6lsm_apr_send_pkt(client, client->apr, &open, true, NULL);
+	if (rc)
+		pr_err("%s: Open failed opcode 0x%x, rc %d\n",
+		       __func__, open.hdr.opcode, rc);
+
+	pr_debug("%s: leave %d\n", __func__, rc);
+	return rc;
+}
+
+static int q6lsm_set_params(struct lsm_client *client)
+{
+	int rc;
+	struct lsm_cmd_set_params params;
+	struct lsm_params_payload *payload = &params.payload;
+
+	pr_debug("%s: enter\n", __func__);
+	q6lsm_add_hdr(client, &params.hdr, sizeof(params), true);
+
+	params.hdr.opcode = LSM_SESSION_CMD_SET_PARAMS;
+	params.data_payload_addr_lsw = 0;
+	params.data_payload_addr_msw = 0;
+	params.mem_map_handle = 0;
+	params.data_payload_size = sizeof(struct lsm_params_payload);
+
+	payload->op_mode.common.module_id  = LSM_MODULE_ID_VOICE_WAKEUP;
+	payload->op_mode.common.param_id = LSM_PARAM_ID_OPERATION_MODE;
+	payload->op_mode.common.param_size =
+	    sizeof(struct lsm_param_op_mode) - sizeof(payload->op_mode.common);
+	payload->op_mode.common.reserved = 0;
+	payload->op_mode.minor_version = 1;
+	payload->op_mode.mode = client->mode;
+	payload->op_mode.reserved = 0;
+
+	payload->connect_to_port.common.module_id = LSM_MODULE_ID_VOICE_WAKEUP;
+	payload->connect_to_port.common.param_id = LSM_PARAM_ID_CONNECT_TO_PORT;
+	payload->connect_to_port.common.param_size =
+	    sizeof(payload->connect_to_port) - sizeof(payload->op_mode.common);
+	payload->connect_to_port.common.reserved = 0;
+	payload->connect_to_port.minor_version = 1;
+	payload->connect_to_port.port_id = client->connect_to_port;
+	payload->connect_to_port.reserved = 0;
+
+	payload->kwds.common.module_id = LSM_MODULE_ID_VOICE_WAKEUP;
+	payload->kwds.common.param_id = LSM_PARAM_ID_KEYWORD_DETECT_SENSITIVITY;
+	payload->kwds.common.param_size =
+	    sizeof(payload->kwds) - sizeof(payload->op_mode.common);
+	payload->kwds.common.reserved = 0;
+	payload->kwds.minor_version = 1;
+	payload->kwds.keyword_sensitivity = client->kw_sensitivity;
+	payload->kwds.reserved = 0;
+
+	payload->uds.common.module_id = LSM_MODULE_ID_VOICE_WAKEUP;
+	payload->uds.common.param_id = LSM_PARAM_ID_USER_DETECT_SENSITIVITY;
+	payload->uds.common.param_size =
+	    sizeof(payload->uds) - sizeof(payload->op_mode.common);
+	payload->uds.common.reserved = 0;
+	payload->uds.minor_version = 1;
+	payload->uds.user_sensitivity = client->user_sensitivity;
+	payload->uds.reserved = 0;
+
+	rc = q6lsm_apr_send_pkt(client, client->apr, &params, true, NULL);
+	if (rc)
+		pr_err("%s: Failed set_params opcode 0x%x, rc %d\n",
+		       __func__, params.hdr.opcode, rc);
+
+	pr_debug("%s: leave %d\n", __func__, rc);
+	return rc;
+}
+
+int q6lsm_register_sound_model(struct lsm_client *client,
+			       enum lsm_detection_mode mode, u16 minkeyword,
+			       u16 minuser, bool detectfailure)
+{
+	int rc;
+	struct lsm_cmd_reg_snd_model cmd;
+
+	memset(&cmd, 0, sizeof(cmd));
+	if (mode == LSM_MODE_KEYWORD_ONLY_DETECTION) {
+		client->mode = 0x01;
+	} else if (mode == LSM_MODE_USER_KEYWORD_DETECTION) {
+		client->mode = 0x03;
+	} else {
+		pr_err("%s: Incorrect detection mode %d\n", __func__, mode);
+		return -EINVAL;
+	}
+	client->mode |= detectfailure << 2;
+	client->kw_sensitivity = minkeyword;
+	client->user_sensitivity = minuser;
+	client->connect_to_port = AFE_PORT_ID_SLIMBUS_MULTI_CHAN_5_TX;
+
+	rc = q6lsm_set_params(client);
+	if (rc < 0) {
+		pr_err("%s: Failed to set lsm config params\n", __func__);
+		return rc;
+	}
+	rc = q6lsm_send_cal(client);
+	if (rc < 0) {
+		pr_err("%s: Failed to send calibration data\n", __func__);
+		return rc;
+	}
+
+	q6lsm_add_hdr(client, &cmd.hdr, sizeof(cmd), true);
+	cmd.hdr.opcode = LSM_SESSION_CMD_REGISTER_SOUND_MODEL;
+	cmd.model_addr_lsw = client->sound_model.phys;
+	cmd.model_addr_msw = 0;
+	cmd.model_size = client->sound_model.size;
+	/* read updated mem_map_handle by q6lsm_mmapcallback */
+	rmb();
+	cmd.mem_map_handle = client->sound_model.mem_map_handle;
+
+	pr_debug("%s: lsw %x, size %d, handle %x\n", __func__,
+		 cmd.model_addr_lsw, cmd.model_size, cmd.mem_map_handle);
+	rc = q6lsm_apr_send_pkt(client, client->apr, &cmd, true, NULL);
+	if (rc)
+		pr_err("%s: Failed cmd op[0x%x]rc[%d]\n", __func__,
+		       cmd.hdr.opcode, rc);
+	else
+		pr_debug("%s: Register sound model succeeded\n", __func__);
+
+	return rc;
+}
+
+int q6lsm_deregister_sound_model(struct lsm_client *client)
+{
+	int rc;
+	struct lsm_cmd_reg_snd_model cmd;
+
+	if (!client || !client->apr) {
+		pr_err("APR handle NULL\n");
+		return -EINVAL;
+	}
+	pr_debug("%s: session[%d]", __func__, client->session);
+
+	memset(&cmd, 0, sizeof(cmd));
+	q6lsm_add_hdr(client, &cmd.hdr, sizeof(cmd.hdr), false);
+	cmd.hdr.opcode = LSM_SESSION_CMD_DEREGISTER_SOUND_MODEL;
+
+	rc = q6lsm_apr_send_pkt(client, client->apr, &cmd.hdr, true, NULL);
+	if (rc < 0) {
+		pr_err("%s: Failed cmd opcode 0x%x, rc %d\n", __func__,
+		       cmd.hdr.opcode, rc);
+	} else {
+		pr_debug("%s: Deregister sound model succeeded\n", __func__);
+		q6lsm_snd_model_buf_free(client);
+	}
+
+	return rc;
+}
+
+static void q6lsm_add_mmaphdr(struct lsm_client *client, struct apr_hdr *hdr,
+			      u32 pkt_size, u32 cmd_flg, u32 token)
+{
+	pr_debug("%s:pkt size=%d cmd_flg=%d session=%d\n", __func__, pkt_size,
+		 cmd_flg, client->session);
+	hdr->hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
+				       APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
+	hdr->src_port = 0x00;
+	hdr->dest_port = client->session;
+	if (cmd_flg)
+		hdr->token = token;
+	hdr->pkt_size = pkt_size;
+	return;
+}
+
+static int q6lsm_memory_map_regions(struct lsm_client *client,
+				    uint32_t dma_addr_p, uint32_t dma_buf_sz,
+				    uint32_t *mmap_p)
+{
+	struct avs_cmd_shared_mem_map_regions *mmap_regions = NULL;
+	struct avs_shared_map_region_payload *mregions = NULL;
+	void *mmap_region_cmd = NULL;
+	void *payload = NULL;
+	int rc;
+	int cmd_size = 0;
+
+	pr_debug("%s: dma_addr_p 0x%x, dma_buf_sz %d, session %d\n",
+		 __func__, dma_addr_p, dma_buf_sz, client->session);
+
+	cmd_size = sizeof(struct avs_cmd_shared_mem_map_regions) +
+		   sizeof(struct avs_shared_map_region_payload);
+
+	mmap_region_cmd = kzalloc(cmd_size, GFP_KERNEL);
+	if (!mmap_region_cmd)
+		return -ENOMEM;
+
+	mmap_regions = (struct avs_cmd_shared_mem_map_regions *)mmap_region_cmd;
+	q6lsm_add_mmaphdr(client, &mmap_regions->hdr, cmd_size, true,
+			  (client->session << 8));
+
+	mmap_regions->hdr.opcode = LSM_SESSION_CMD_SHARED_MEM_MAP_REGIONS;
+	mmap_regions->mem_pool_id = ADSP_MEMORY_MAP_SHMEM8_4K_POOL;
+	mmap_regions->num_regions = 1;
+	mmap_regions->property_flag = 0x00;
+	payload = ((u8 *)mmap_region_cmd +
+		   sizeof(struct avs_cmd_shared_mem_map_regions));
+	mregions = (struct avs_shared_map_region_payload *)payload;
+
+	mregions->shm_addr_lsw = dma_addr_p;
+	mregions->shm_addr_msw = 0;
+	mregions->mem_size_bytes = dma_buf_sz;
+
+	rc = q6lsm_apr_send_pkt(client, client->mmap_apr, mmap_region_cmd,
+				true, mmap_p);
+	if (rc)
+		pr_err("%s: Failed mmap_regions opcode 0x%x, rc %d\n",
+			__func__, mmap_regions->hdr.opcode, rc);
+
+	pr_debug("%s: leave %d\n", __func__, rc);
+	kfree(mmap_region_cmd);
+	return rc;
+}
+
+static int q6lsm_send_cal(struct lsm_client *client)
+{
+	int rc;
+
+	struct lsm_cmd_set_params params;
+	struct acdb_cal_block lsm_cal;
+
+	pr_debug("%s: enter\n", __func__);
+
+	memset(&lsm_cal, 0, sizeof(lsm_cal));
+	get_lsm_cal(&lsm_cal);
+	if (!lsm_cal.cal_size) {
+		pr_err("%s: Could not get LSM calibration data\n", __func__);
+		rc = -EINVAL;
+		goto bail;
+	}
+
+	/* Cache mmap address, only map once or if new addr */
+	if ((lsm_common.lsm_cal_addr != lsm_cal.cal_paddr) ||
+	    (lsm_cal.cal_size > lsm_common.lsm_cal_size)) {
+		if (lsm_common.lsm_cal_addr != 0)
+			afe_cmd_memory_unmap(lsm_cal.cal_paddr);
+
+		rc = q6lsm_memory_map_regions(client, lsm_cal.cal_paddr,
+					      LSM_CAL_SIZE,
+					      &lsm_common.mmap_handle_for_cal);
+		if (rc < 0) {
+			pr_err("%s: Calibration data memory map failed\n",
+			       __func__);
+			goto bail;
+		}
+		lsm_common.lsm_cal_addr = lsm_cal.cal_paddr;
+		lsm_common.lsm_cal_size = LSM_CAL_SIZE;
+	}
+
+	q6lsm_add_hdr(client, &params.hdr, sizeof(params), true);
+	params.hdr.opcode = LSM_SESSION_CMD_SET_PARAMS;
+	params.data_payload_addr_lsw = lsm_cal.cal_paddr;
+	params.data_payload_addr_msw = 0;
+	/* read updated mem_map_handle by q6lsm_mmapcallback */
+	rmb();
+	params.mem_map_handle = lsm_common.mmap_handle_for_cal;
+	params.data_payload_size = lsm_cal.cal_size;
+
+	rc = q6lsm_apr_send_pkt(client, client->apr, &params, true, NULL);
+	if (rc)
+		pr_err("%s: Failed set_params opcode 0x%x, rc %d\n",
+		       __func__, params.hdr.opcode, rc);
+bail:
+	return rc;
+}
+
+static int q6lsm_memory_unmap_regions(struct lsm_client *client)
+{
+	struct avs_cmd_shared_mem_unmap_regions unmap;
+	int rc = 0;
+	int cmd_size = 0;
+
+	cmd_size = sizeof(struct avs_cmd_shared_mem_unmap_regions);
+	q6lsm_add_mmaphdr(client, &unmap.hdr, cmd_size,
+			  true, (client->session << 8));
+	unmap.hdr.opcode = LSM_SESSION_CMD_SHARED_MEM_UNMAP_REGIONS;
+	unmap.mem_map_handle = client->sound_model.mem_map_handle;
+
+	pr_debug("%s: unmap handle 0x%x\n", __func__, unmap.mem_map_handle);
+	rc = q6lsm_apr_send_pkt(client, client->mmap_apr, &unmap, true,
+				NULL);
+	if (rc)
+		pr_err("%s: Failed mmap_regions opcode 0x%x rc %d\n",
+		       __func__, unmap.hdr.opcode, rc);
+
+	return rc;
+}
+
+static int q6lsm_snd_model_buf_free(struct lsm_client *client)
+{
+	int rc;
+
+	pr_debug("%s: Session id %d\n", __func__, client->session);
+	mutex_lock(&client->cmd_lock);
+	rc = q6lsm_memory_unmap_regions(client);
+	if (rc < 0) {
+		pr_err("%s CMD Memory_unmap_regions failed\n", __func__);
+	} else if (client->sound_model.data) {
+		ion_unmap_kernel(client->sound_model.client,
+				 client->sound_model.handle);
+		ion_free(client->sound_model.client,
+			 client->sound_model.handle);
+		ion_client_destroy(client->sound_model.client);
+		client->sound_model.data = NULL;
+		client->sound_model.phys = 0;
+	}
+	mutex_unlock(&client->cmd_lock);
+	return rc;
+}
+
+static struct lsm_client *q6lsm_get_lsm_client(int session_id)
+{
+	unsigned long flags;
+	struct lsm_client *client = NULL;
+
+	spin_lock_irqsave(&lsm_session_lock, flags);
+	if (session_id < LSM_MIN_SESSION_ID || session_id > LSM_MAX_SESSION_ID)
+		pr_err("%s: Invalid session %d\n", __func__, session_id);
+	else if (!lsm_session[session_id])
+		pr_err("%s: Not an active session %d\n", __func__, session_id);
+	else
+		client = lsm_session[session_id];
+	spin_unlock_irqrestore(&lsm_session_lock, flags);
+
+	return client;
+}
+
+/*
+ * q6lsm_mmapcallback : atomic context
+ */
+static int q6lsm_mmapcallback(struct apr_client_data *data, void *priv)
+{
+	unsigned long flags;
+	uint32_t sid = 0;
+	const uint32_t *payload = data->payload;
+	const uint32_t command = payload[0];
+	const uint32_t retcode = payload[1];
+	struct lsm_client *client = NULL;
+
+	pr_debug("%s: opcode 0x%x command 0x%x return code 0x%x\n", __func__,
+		 data->opcode, command, retcode);
+
+	sid = (data->token >> 8) & 0x0F;
+	client = q6lsm_get_lsm_client(sid);
+	if (!client) {
+		pr_debug("%s: Session %d already freed\n", __func__, sid);
+		return 0;
+	}
+
+	switch (data->opcode) {
+	case LSM_SESSION_CMDRSP_SHARED_MEM_MAP_REGIONS:
+		if (atomic_read(&client->cmd_state) == CMD_STATE_WAIT_RESP) {
+			spin_lock_irqsave(&mmap_lock, flags);
+			*mmap_handle_p = command;
+			/* spin_unlock_irqrestore implies barrier */
+			spin_unlock_irqrestore(&mmap_lock, flags);
+			atomic_set(&client->cmd_state, CMD_STATE_CLEARED);
+			wake_up(&client->cmd_wait);
+		}
+		break;
+	case APR_BASIC_RSP_RESULT:
+		if (command == LSM_SESSION_CMD_SHARED_MEM_UNMAP_REGIONS) {
+			atomic_set(&client->cmd_state, CMD_STATE_CLEARED);
+			wake_up(&client->cmd_wait);
+		} else {
+			pr_warn("%s: Unexpected command 0x%x\n", __func__,
+				command);
+		}
+		break;
+	default:
+		pr_debug("%s: command 0x%x return code 0x%x\n",
+			 __func__, command, retcode);
+		break;
+	}
+	if (client->cb)
+		client->cb(data->opcode, data->token,
+			   data->payload, client->priv);
+	return 0;
+}
+
+int q6lsm_snd_model_buf_alloc(struct lsm_client *client, uint32_t len)
+{
+	int rc = -EINVAL;
+
+	if (!client)
+		goto fail;
+
+	mutex_lock(&client->cmd_lock);
+	if (!client->sound_model.data) {
+		client->sound_model.client =
+		    msm_ion_client_create(UINT_MAX, "lsm_client");
+		if (IS_ERR_OR_NULL(client->sound_model.client)) {
+			pr_err("%s: ION create client for AUDIO failed\n",
+			       __func__);
+			goto fail;
+		}
+		client->sound_model.handle =
+			ion_alloc(client->sound_model.client,
+				  len, SZ_4K, (0x1 << ION_AUDIO_HEAP_ID), 0);
+		if (IS_ERR_OR_NULL(client->sound_model.handle)) {
+			pr_err("%s: ION memory allocation for AUDIO failed\n",
+			       __func__);
+			goto fail;
+		}
+
+		rc = ion_phys(client->sound_model.client,
+			      client->sound_model.handle,
+			      (ion_phys_addr_t *)&client->sound_model.phys,
+			      (size_t *)&len);
+		if (rc) {
+			pr_err("%s: ION get physical mem failed, rc%d\n",
+			       __func__, rc);
+			goto fail;
+		}
+
+		client->sound_model.data =
+		    ion_map_kernel(client->sound_model.client,
+				   client->sound_model.handle);
+		if (IS_ERR_OR_NULL(client->sound_model.data)) {
+			pr_err("%s: ION memory mapping failed\n", __func__);
+			goto fail;
+		}
+		memset(client->sound_model.data, 0, len);
+		client->sound_model.size = len;
+	} else {
+		rc = -EBUSY;
+		goto fail;
+	}
+	mutex_unlock(&client->cmd_lock);
+
+	rc = q6lsm_memory_map_regions(client, client->sound_model.phys,
+				      client->sound_model.size,
+				      &client->sound_model.mem_map_handle);
+	if (rc < 0) {
+		pr_err("%s:CMD Memory_map_regions failed\n", __func__);
+		goto fail;
+	}
+
+	return 0;
+fail:
+	q6lsm_snd_model_buf_free(client);
+	return rc;
+}
+
+static int q6lsm_cmd(struct lsm_client *client, int opcode, bool wait)
+{
+	struct apr_hdr hdr;
+	int rc;
+
+	pr_debug("%s: enter opcode %d wait %d\n", __func__, opcode, wait);
+	q6lsm_add_hdr(client, &hdr, sizeof(hdr), true);
+	switch (opcode) {
+	case LSM_SESSION_CMD_START:
+	case LSM_SESSION_CMD_STOP:
+	case LSM_SESSION_CMD_CLOSE_TX:
+		hdr.opcode = opcode;
+		break;
+	default:
+		pr_err("%s: Invalid opcode %d\n", __func__, opcode);
+		return -EINVAL;
+	}
+	rc = q6lsm_apr_send_pkt(client, client->apr, &hdr, wait, NULL);
+	if (rc)
+		pr_err("%s: Failed commmand 0x%x\n", __func__, hdr.opcode);
+
+	pr_debug("%s: leave %d\n", __func__, rc);
+	return rc;
+}
+
+int q6lsm_start(struct lsm_client *client, bool wait)
+{
+	return q6lsm_cmd(client, LSM_SESSION_CMD_START, wait);
+}
+
+int q6lsm_stop(struct lsm_client *client, bool wait)
+{
+	return q6lsm_cmd(client, LSM_SESSION_CMD_STOP, wait);
+}
+
+int q6lsm_close(struct lsm_client *client)
+{
+	return q6lsm_cmd(client, LSM_SESSION_CMD_CLOSE_TX, true);
+}
+
+static int __init q6lsm_init(void)
+{
+	pr_debug("%s\n", __func__);
+	spin_lock_init(&lsm_session_lock);
+	spin_lock_init(&mmap_lock);
+	mutex_init(&lsm_common.apr_lock);
+	return 0;
+}
+
+device_initcall(q6lsm_init);