Merge "ASoC: msm: qdsp6v2: defer probe if memory allocation fails"
diff --git a/Documentation/devicetree/bindings/arm/msm/jtag-fuse.txt b/Documentation/devicetree/bindings/arm/msm/jtag-fuse.txt
new file mode 100644
index 0000000..617d2ba
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/msm/jtag-fuse.txt
@@ -0,0 +1,18 @@
+* JTAG-FUSE
+
+The jtag-fuse entry specifies the memory mapped addresses for the fuse
+registers. The jtag-fuse driver uses these to provide api(s) that can be used
+by jtag save and restore driver(s) to query whether the Hardware they manage
+is functionally disabled or not and take corresponding steps.
+
+Required Properties:
+compatible: component name used for driver matching, should be "qcom,jtag-fuse"
+reg: physical base address and length of the register set
+reg-names: should be "fuse-base"
+
+Example:
+	jtag_fuse: jtagfuse@fc4be024 {
+		compatible = "qcom,jtag-fuse";
+		reg = <0xfc4be024 0x8>;
+		reg-names = "fuse-base";
+	};
diff --git a/Documentation/devicetree/bindings/coresight/coresight.txt b/Documentation/devicetree/bindings/coresight/coresight.txt
index 8d1d46d..d24e671 100644
--- a/Documentation/devicetree/bindings/coresight/coresight.txt
+++ b/Documentation/devicetree/bindings/coresight/coresight.txt
@@ -21,6 +21,7 @@
 	"qcom,coresight-csr" for coresight csr device,
 	"arm,coresight-cti" for coresight cti devices,
 	"qcom,coresight-hwevent" for coresight hardware event devices
+	"arm,coresight-fuse" for coresight fuse device,
 - reg : physical base address and length of the register set(s) of the component
 - reg-names : names corresponding to each reg property value. The reg-names that
 	need to be used with corresponding compatible string for a coresight device
@@ -68,6 +69,10 @@
 			"<ss-mux>" - physical base address of hardware event mux
 				control registers where <ss-mux> is subsystem mux it
 				represents
+	- for coresight fuse device:
+		compatible : should be "arm,coresight-fuse"
+		reg-names  : should be:
+			"fuse-base" - physical base address of fuse registers
 - coresight-id : unique integer identifier for the component
 - coresight-name : unique descriptive name of the component
 - coresight-nr-inports : number of input ports on the component
@@ -236,3 +241,13 @@
 
 		qcom,hwevent-clks = "core_mmss_clk";
 	};
+
+	fuse: fuse@fc4be024 {
+		compatible = "arm,coresight-fuse";
+		reg = <0xfc4be024 0x8>;
+		reg-names = "fuse-base";
+
+		coresight-id = <30>;
+		coresight-name = "coresight-fuse";
+		coresight-nr-inports = <0>;
+	};
diff --git a/Documentation/devicetree/bindings/fb/mdss-mdp.txt b/Documentation/devicetree/bindings/fb/mdss-mdp.txt
index 9bc949e..514160e 100644
--- a/Documentation/devicetree/bindings/fb/mdss-mdp.txt
+++ b/Documentation/devicetree/bindings/fb/mdss-mdp.txt
@@ -123,7 +123,9 @@
 				offsets as well (i.e. the first mixer offset
 				corresponds to the same pathway as the first
 				AD offset).
-
+- qcom,mdss-has-wfd-blk: Boolean property to indicate the presence of dedicated
+			writeback wfd block in MDSS as opposed to writeback
+			block that is shared between rotator and wfd.
 Optional subnodes:
 Child nodes representing the frame buffer virtual devices.
 
@@ -161,6 +163,7 @@
 		qcom,mdss-rot-block-size = <64>;
 		qcom,mdss-has-bwc;
 		qcom,mdss-has-decimation;
+		qcom,mdss-has-wfd-blk;
 
 		qcom,mdss-ctl-off = <0x00000600 0x00000700 0x00000800
 				     0x00000900 0x0000A00>;
diff --git a/Documentation/devicetree/bindings/power/qpnp-charger.txt b/Documentation/devicetree/bindings/power/qpnp-charger.txt
index 6e125f2..66949af 100644
--- a/Documentation/devicetree/bindings/power/qpnp-charger.txt
+++ b/Documentation/devicetree/bindings/power/qpnp-charger.txt
@@ -65,6 +65,15 @@
 					detection, "bpd_thm_id" selects both.
 					If the property is not set, the temperatue pin will
 					be used.
+- qcom,btc-disabled:			If flag is set battery hot and cold monitoring is
+					disabled in hardware. This monitoring is turned on
+					by default.
+- qcom,batt-hot-percent:		Specify a supported hot threshold percentage.
+					Supported thresholds: 25% and 35%. If none is specified
+					hardware defaults will be used.
+- qcom,batt-cold-percent:		Specify a supported cold threshold percentage.
+					Supported thresholds: 70% and 80%. If none is specified
+					hardware defaults will be used.
 - otg-parent-supply			Specify a phandle to a parent supply regulator
 					for the OTG regulator.
 - boost-parent-supply			Specify a phandle to a parent supply regulator
@@ -182,6 +191,9 @@
 		qcom,warm-bat-mv = <4100>;
 		qcom,ibatmax-cool-ma = <350>;
 		qcom,vbatdet-delta-mv = <60>;
+		qcom,batt-hot-percent = <25>;
+		qcom,batt-cold-percent = <85>;
+		qcom,btc-disabled = <0>;
 
 		qcom,chgr@1000 {
 			reg = <0x1000 0x100>;
diff --git a/Documentation/devicetree/bindings/slimbus/slim-msm-ctrl.txt b/Documentation/devicetree/bindings/slimbus/slim-msm-ctrl.txt
index 6b090fa..64f2ddd 100644
--- a/Documentation/devicetree/bindings/slimbus/slim-msm-ctrl.txt
+++ b/Documentation/devicetree/bindings/slimbus/slim-msm-ctrl.txt
@@ -44,6 +44,17 @@
  - qcom,rxreg-access: This boolean indicates that slimbus RX should use direct
 		 register access to receive data. This flag is only needed if
 		 BAM pipe is not available to receive data from slimbus
+ - qcom,apps-ch-pipes: This value represents BAM pipe-mask used by application
+		 processor for data channels. If this property is not defined,
+		 default mask of 0x3F000000 is used indicating apps can use 6
+		 pipes from 24-29.
+ - qcom,ea-pc: This value represents product code (PC) field of enumeration
+		 address (EA) for the Qualcomm slimbus controller hardware.
+		 This value is needed if data-channels originating from apps
+		 are to be used, so that application processor can query
+		 logical address of the ported generic device to be used.
+		 Other than PC, fields of EA are same across platforms.
+
 Example:
 	slim@fe12f000 {
 		cell-index = <1>;
@@ -55,4 +66,6 @@
 		interrupt-names = "slimbus_irq", "slimbus_bam_irq";
 		qcom,min-clk-gear = <10>;
 		qcom,rxreg-access;
+		qcom,apps-ch-pipes = <0x60000000>;
+		qcom,ea-pc = <0x30>;
 	};
diff --git a/arch/arm/boot/dts/apq8026-mtp.dts b/arch/arm/boot/dts/apq8026-v1-mtp.dts
similarity index 95%
rename from arch/arm/boot/dts/apq8026-mtp.dts
rename to arch/arm/boot/dts/apq8026-v1-mtp.dts
index e14a6856..b89c676 100644
--- a/arch/arm/boot/dts/apq8026-mtp.dts
+++ b/arch/arm/boot/dts/apq8026-v1-mtp.dts
@@ -12,7 +12,7 @@
 
 
 /dts-v1/;
-/include/ "apq8026.dtsi"
+/include/ "apq8026-v1.dtsi"
 /include/ "msm8226-mtp.dtsi"
 
 / {
diff --git a/arch/arm/boot/dts/apq8026-xpm.dts b/arch/arm/boot/dts/apq8026-v1-xpm.dts
similarity index 95%
rename from arch/arm/boot/dts/apq8026-xpm.dts
rename to arch/arm/boot/dts/apq8026-v1-xpm.dts
index 67152af..8c97823 100644
--- a/arch/arm/boot/dts/apq8026-xpm.dts
+++ b/arch/arm/boot/dts/apq8026-v1-xpm.dts
@@ -12,7 +12,7 @@
 
 
 /dts-v1/;
-/include/ "apq8026.dtsi"
+/include/ "apq8026-v1.dtsi"
 /include/ "msm8226-cdp.dtsi"
 
 / {
diff --git a/arch/arm/boot/dts/apq8026.dtsi b/arch/arm/boot/dts/apq8026-v1.dtsi
similarity index 96%
rename from arch/arm/boot/dts/apq8026.dtsi
rename to arch/arm/boot/dts/apq8026-v1.dtsi
index db6576a..f15a96f 100644
--- a/arch/arm/boot/dts/apq8026.dtsi
+++ b/arch/arm/boot/dts/apq8026-v1.dtsi
@@ -16,7 +16,7 @@
  * file.
  */
 
-/include/ "msm8226.dtsi"
+/include/ "msm8226-v1.dtsi"
 
 / {
 	model = "Qualcomm APQ 8026";
diff --git a/arch/arm/boot/dts/apq8026-mtp.dts b/arch/arm/boot/dts/apq8026-v2-mtp.dts
similarity index 86%
copy from arch/arm/boot/dts/apq8026-mtp.dts
copy to arch/arm/boot/dts/apq8026-v2-mtp.dts
index e14a6856..c6b7f2a 100644
--- a/arch/arm/boot/dts/apq8026-mtp.dts
+++ b/arch/arm/boot/dts/apq8026-v2-mtp.dts
@@ -12,11 +12,11 @@
 
 
 /dts-v1/;
-/include/ "apq8026.dtsi"
+/include/ "apq8026-v2.dtsi"
 /include/ "msm8226-mtp.dtsi"
 
 / {
-	model = "Qualcomm APQ 8026 MTP";
+	model = "Qualcomm APQ 8026v2 MTP";
 	compatible = "qcom,apq8026-mtp", "qcom,apq8026", "qcom,mtp";
-	qcom,msm-id = <199 8 0>;
+	qcom,msm-id = <199 8 0x20000>;
 };
diff --git a/arch/arm/boot/dts/apq8026-xpm.dts b/arch/arm/boot/dts/apq8026-v2-xpm.dts
similarity index 86%
copy from arch/arm/boot/dts/apq8026-xpm.dts
copy to arch/arm/boot/dts/apq8026-v2-xpm.dts
index 67152af..42acd98 100644
--- a/arch/arm/boot/dts/apq8026-xpm.dts
+++ b/arch/arm/boot/dts/apq8026-v2-xpm.dts
@@ -12,11 +12,11 @@
 
 
 /dts-v1/;
-/include/ "apq8026.dtsi"
+/include/ "apq8026-v2.dtsi"
 /include/ "msm8226-cdp.dtsi"
 
 / {
-	model = "Qualcomm APQ 8026 XPM";
+	model = "Qualcomm APQ 8026v2 XPM";
 	compatible = "qcom,apq8026-xpm", "qcom,apq8026", "qcom,xpm";
-	qcom,msm-id = <199 14 0>;
+	qcom,msm-id = <199 14 0x20000>;
 };
diff --git a/arch/arm/boot/dts/apq8026.dtsi b/arch/arm/boot/dts/apq8026-v2.dtsi
similarity index 96%
copy from arch/arm/boot/dts/apq8026.dtsi
copy to arch/arm/boot/dts/apq8026-v2.dtsi
index db6576a..d87b500 100644
--- a/arch/arm/boot/dts/apq8026.dtsi
+++ b/arch/arm/boot/dts/apq8026-v2.dtsi
@@ -16,7 +16,7 @@
  * file.
  */
 
-/include/ "msm8226.dtsi"
+/include/ "msm8226-v2.dtsi"
 
 / {
 	model = "Qualcomm APQ 8026";
diff --git a/arch/arm/boot/dts/apq8074-dragonboard.dtsi b/arch/arm/boot/dts/apq8074-dragonboard.dtsi
index 4b20e9f..32322e3 100644
--- a/arch/arm/boot/dts/apq8074-dragonboard.dtsi
+++ b/arch/arm/boot/dts/apq8074-dragonboard.dtsi
@@ -14,6 +14,10 @@
 /include/ "msm8974-camera-sensor-dragonboard.dtsi"
 /include/ "msm8974-leds.dtsi"
 
+&vph_pwr_vreg {
+	status = "ok";
+};
+
 &soc {
 	serial@f991e000 {
 		status = "ok";
@@ -62,6 +66,10 @@
 		#size-cells = <1>;
 		ranges;
 		smsc,reset-gpio = <&pm8941_gpios 8 0x00>;
+		/* Dragonboard has an always-on VBUS supply for HSIC hub,
+		 * providing a dummy regulator for the hub driver
+		 */
+		hub_vbus-supply = <&vph_pwr_vreg>;
 
 		hsic_host: hsic@f9a00000 {
 			compatible = "qcom,hsic-host";
@@ -484,6 +492,7 @@
 &pm8941_mpps {
 
 	mpp@a000 { /* MPP 1 */
+		status = "disabled";
 	};
 
 	mpp@a100 { /* MPP 2 */
@@ -524,22 +533,7 @@
 };
 
 &spi_epm {
-	epm-adc@0 {
-		compatible = "cy,epm-adc-cy8c5568lti-114";
-		reg = <0>;
-		interrupt-parent = <&msmgpio>;
-		spi-max-frequency = <960000>;
-		qcom,channels = <31>;
-		qcom,gain = <50 50 50 50 50 100 50 50 50 50
-				50 50 50 50 100 50 50 50 50 100
-				50 50 50 100 50 50 50 1 1 1
-				1>;
-		qcom,rsense = <40 10 10 25 10 1000 75 25 10 25
-				33 500 200 10 500 100 33 200 25 100
-				75 500 50 200 5 5 3 1 1 1
-				1>;
-		qcom,channel-type = <0xf0000000>;
-	};
+	status = "disabled";
 };
 
 &spmi_bus {
diff --git a/arch/arm/boot/dts/msm-pm8941.dtsi b/arch/arm/boot/dts/msm-pm8941.dtsi
index b801da8..40f9a7c 100644
--- a/arch/arm/boot/dts/msm-pm8941.dtsi
+++ b/arch/arm/boot/dts/msm-pm8941.dtsi
@@ -555,7 +555,7 @@
 			};
 		};
 
-		vadc@3100 {
+		pm8941_vadc: vadc@3100 {
 			compatible = "qcom,qpnp-vadc";
 			reg = <0x3100 0x100>;
 			#address-cells = <1>;
@@ -797,7 +797,7 @@
 			};
 		};
 
-		iadc@3600 {
+		pm8941_iadc: iadc@3600 {
 			compatible = "qcom,qpnp-iadc";
 			reg = <0x3600 0x100>;
 			#address-cells = <1>;
@@ -819,7 +819,7 @@
 			};
 		};
 
-		qcom,vadc@3400 {
+		pm8941_adc_tm: qcom,vadc@3400 {
 			compatible = "qcom,qpnp-adc-tm";
 			reg = <0x3400 0x100>;
 			#address-cells = <1>;
diff --git a/arch/arm/boot/dts/msm8226-v1-qrd-evt.dts b/arch/arm/boot/dts/msm8226-v1-qrd-evt.dts
index bf94d04..a081308 100644
--- a/arch/arm/boot/dts/msm8226-v1-qrd-evt.dts
+++ b/arch/arm/boot/dts/msm8226-v1-qrd-evt.dts
@@ -28,5 +28,6 @@
 &soc {
         qcom,mdss_dsi_nt35590_720p_video {
                 status = "ok";
+		qcom,cont-splash-enabled;
         };
 };
diff --git a/arch/arm/boot/dts/msm8226-v2-qrd-evt.dts b/arch/arm/boot/dts/msm8226-v2-qrd-evt.dts
index 3b09d92..a2ad682 100644
--- a/arch/arm/boot/dts/msm8226-v2-qrd-evt.dts
+++ b/arch/arm/boot/dts/msm8226-v2-qrd-evt.dts
@@ -29,5 +29,6 @@
 &soc {
         qcom,mdss_dsi_nt35590_720p_video {
                 status = "ok";
+		qcom,cont-splash-enabled;
         };
 };
diff --git a/arch/arm/boot/dts/msm8226.dtsi b/arch/arm/boot/dts/msm8226.dtsi
index 6dfe15d..39e0c27 100644
--- a/arch/arm/boot/dts/msm8226.dtsi
+++ b/arch/arm/boot/dts/msm8226.dtsi
@@ -509,6 +509,11 @@
                         compatible = "qcom,msm-dai-q6-dev";
                         qcom,msm-dai-q6-dev-id = <32773>;
                 };
+
+                qcom,msm-dai-q6-incall-music-2-rx {
+                        compatible = "qcom,msm-dai-q6-dev";
+                        qcom,msm-dai-q6-dev-id = <32770>;
+                };
 	};
 
 	qcom,msm-pcm-hostless {
@@ -886,6 +891,9 @@
 		qcom,temp-hysteresis = <10>;
 		qcom,freq-step = <2>;
 		qcom,freq-control-mask = <0xf>;
+		qcom,core-limit-temp = <80>;
+		qcom,core-temp-hysteresis = <10>;
+		qcom,core-control-mask = <0xe>;
 	};
 
 	spi_0: spi@f9923000 { /* BLSP1 QUP1 */
diff --git a/arch/arm/boot/dts/msm8610-coresight.dtsi b/arch/arm/boot/dts/msm8610-coresight.dtsi
index 516522e..7cf6c4f 100644
--- a/arch/arm/boot/dts/msm8610-coresight.dtsi
+++ b/arch/arm/boot/dts/msm8610-coresight.dtsi
@@ -345,8 +345,9 @@
 		compatible = "qcom,coresight-hwevent";
 		reg = <0xfd820018 0x80>,
 		      <0xf9011080 0x80>,
-		      <0xfd4ab160 0x80>;
-		reg-names = "mmss-mux", "apcs-mux", "ppss-mux";
+		      <0xfd4ab160 0x80>,
+		      <0xfc401600 0x80>;
+		reg-names = "mmss-mux", "apcs-mux", "ppss-mux", "gcc-mux";
 
 		coresight-id = <27>;
 		coresight-name = "coresight-hwevent";
diff --git a/arch/arm/boot/dts/msm8610-qrd.dts b/arch/arm/boot/dts/msm8610-qrd.dts
index 4a2c57c..86294df 100644
--- a/arch/arm/boot/dts/msm8610-qrd.dts
+++ b/arch/arm/boot/dts/msm8610-qrd.dts
@@ -12,7 +12,7 @@
 
 /dts-v1/;
 
-/include/ "msm8610.dtsi"
+/include/ "msm8610-qrd.dtsi"
 /include/ "dsi-v2-panel-hx8379a-wvga-video.dtsi"
 /include/ "msm8610-qrd-camera-sensor.dtsi"
 
@@ -23,308 +23,3 @@
 				  <163 11 0>, <164 11 0>, <166 11 0>;
 };
 
-&soc {
-	i2c@f9923000{
-		focaltech@38{
-			compatible = "focaltech,5x06";
-			reg = <0x38>;
-			interrupt-parent = <&msmgpio>;
-			interrupts = <1 0x2>;
-			vdd-supply = <&pm8110_l19>;
-			vcc_i2c-supply = <&pm8110_l14>;
-			focaltech,family-id = <0x06>;
-			focaltech,reset-gpio = <&msmgpio 0 0x00>;
-			focaltech,irq-gpio = <&msmgpio 1 0x00>;
-			focaltech,display-coords = <0 0 480 800>;
-			focaltech,panel-coords = <0 0 480 800>;
-			focaltech,button-map= <139 102 158>;
-			focaltech,no-force-update;
-			focaltech,i2c-pull-up;
-		};
-	};
-
-	gen-vkeys {
-		compatible = "qcom,gen-vkeys";
-		label = "ft5x06_ts";
-		qcom,disp-maxx = <480>;
-		qcom,disp-maxy = <800>;
-		qcom,panel-maxx = <481>;
-		qcom,panel-maxy = <940>;
-		qcom,key-codes = <139 0 102 158 0 0 0>;
-		qcom,y-offset = <0>;
-	};
-	serial@f991e000 {
-		status = "ok";
-	};
-
-	i2c@f9925000 { /* BLSP-1 QUP-3 */
-		kionix@f {
-			compatible = "kionix,kxtj9";
-			reg = <0x0f>;
-			interrupt-parent = <&msmgpio>;
-			interrupts = <81 0x2>;
-			vdd-supply = <&pm8110_l19>;
-			vio-supply = <&pm8110_l14>;
-			kionix,min-interval = <5>;
-			kionix,init-interval = <200>;
-			kionix,axis-map-x = <1>;
-			kionix,axis-map-y = <0>;
-			kionix,axis-map-z = <2>;
-			kionix,g-range = <2>;
-			kionix,negate-x;
-			kionix,negate-y;
-			kionix,negate-z;
-			kionix,res-12bit;
-		};
-	};
-
-	flashlight {
-		compatible = "qcom,leds-gpio-flash";
-		status = "okay";
-		qcom,flash-en = <&msmgpio 18 0>;
-		qcom,flash-now = <&msmgpio 19 0>;
-		linux,name = "flashlight";
-		linux,default-trigger = "flashlight-trigger";
-	};
-
-	gpio_keys {
-                compatible = "gpio-keys";
-                input-name = "gpio-keys";
-
-                camera_snapshot {
-                        label = "camera_snapshot";
-                        gpios = <&msmgpio 73 0x1>;
-                        linux,input-type = <1>;
-                        linux,code = <0x2fe>;
-                        gpio-key,wakeup;
-                        debounce-interval = <15>;
-                };
-
-                camera_focus {
-                        label = "camera_focus";
-                        gpios = <&msmgpio 74 0x1>;
-                        linux,input-type = <1>;
-                        linux,code = <0x210>;
-                        gpio-key,wakeup;
-                        debounce-interval = <15>;
-                };
-
-                vol_up {
-                        label = "volume_up";
-                        gpios = <&msmgpio 72 0x1>;
-                        linux,input-type = <1>;
-                        linux,code = <115>;
-                        gpio-key,wakeup;
-                        debounce-interval = <15>;
-		};
-	};
-
-	i2c@f9927000  {
-                        msm8x10_wcd_codec@0d{
-                        compatible = "qcom,msm8x10-wcd-i2c";
-                        reg = <0x0d>;
-                        cdc-vdda-cp-supply = <&pm8110_s4>;
-                        qcom,cdc-vdda-cp-voltage = <2150000 2150000>;
-                        qcom,cdc-vdda-cp-current = <650000>;
-
-                        cdc-vdda-h-supply = <&pm8110_l6>;
-                        qcom,cdc-vdda-h-voltage = <1800000 1800000>;
-                        qcom,cdc-vdda-h-current = <250000>;
-
-                        cdc-vdd-px-supply = <&pm8110_l6>;
-                        qcom,cdc-vdd-px-voltage = <1800000 1800000>;
-                        qcom,cdc-vdd-px-current = <10000>;
-
-                        cdc-vdd-1p2v-supply = <&pm8110_l4>;
-                        qcom,cdc-vdd-1p2v-voltage = <1200000 1200000>;
-                        qcom,cdc-vdd-1p2v-current = <5000>;
-
-                        cdc-vdd-mic-bias-supply = <&pm8110_l20>;
-                        qcom,cdc-vdd-mic-bias-voltage = <3075000 3075000>;
-                        qcom,cdc-vdd-mic-bias-current = <25000>;
-
-                        qcom,cdc-micbias-cfilt-sel = <0x0>;
-                        qcom,cdc-micbias-cfilt-mv = <1800000>;
-                        qcom,cdc-mclk-clk-rate = <12288000>;
-                };
-
-                msm8x10_wcd_codec@77{
-                        compatible = "qcom,msm8x10-wcd-i2c";
-                        reg = <0x77>;
-                };
-
-                msm8x10_wcd_codec@66{
-                        compatible = "qcom,msm8x10-wcd-i2c";
-                        reg = <0x66>;
-                };
-
-                msm8x10_wcd_codec@55{
-                        compatible = "qcom,msm8x10-wcd-i2c";
-                        reg = <0x55>;
-                };
-	};
-
-    sound {
-        qcom,audio-routing =
-            "RX_BIAS", "MCLK",
-            "INT_LDO_H", "MCLK",
-            "MIC BIAS Internal1", "Handset Mic",
-            "MIC BIAS Internal2", "Headset Mic",
-            "AMIC1", "MIC BIAS Internal1",
-            "AMIC2", "MIC BIAS Internal2";
-    };
-};
-
-&spmi_bus {
-	qcom,pm8110@0 {
-		qcom,leds@a100 {
-			status = "okay";
-			qcom,led_mpp_2 {
-				label = "mpp";
-				linux,name = "wled-homerow";
-				linux-default-trigger = "hr-trigger";
-				qcom,default-state = "off";
-				qcom,max-current = <40>;
-				qcom,id = <6>;
-				qcom,source-sel = <1>;
-				qcom,mode-ctrl = <0x61>;
-				qcom,mode = "manual";
-			};
-		};
-
-		qcom,leds@a200 {
-			status = "okay";
-			qcom,led_mpp_3 {
-				label = "mpp";
-				linux,name = "wled-backlight";
-				linux,default-trigger = "bkl-trigger";
-				qcom,default-state = "on";
-				qcom,max-current = <40>;
-				qcom,id = <6>;
-				qcom,source-sel = <1>;
-				qcom,mode-ctrl = <0x10>;
-				qcom,mode = "manual";
-			};
-		};
-	};
-};
-
-&spmi_bus {
-	qcom,pm8110@1 {
-		qcom,vibrator@c000 {
-			status = "okay";
-			qcom,vib-timeout-ms = <15000>;
-			qcom,vib-vtg-level-mV = <3100>;
-		};
-	};
-};
-
-&sdhc_1 {
-	vdd-supply = <&pm8110_l17>;
-	qcom,vdd-always-on;
-	qcom,vdd-lpm-sup;
-	qcom,vdd-voltage-level = <2900000 2900000>;
-	qcom,vdd-current-level = <200 400000>;
-
-	vdd-io-supply = <&pm8110_l6>;
-	qcom,vdd-io-always-on;
-	qcom,vdd-io-voltage-level = <1800000 1800000>;
-	qcom,vdd-io-current-level = <200 60000>;
-
-	qcom,pad-pull-on = <0x0 0x3 0x3>; /* no-pull, pull-up, pull-up */
-	qcom,pad-pull-off = <0x0 0x3 0x3>; /* no-pull, pull-up, pull-up */
-	qcom,pad-drv-on = <0x4 0x4 0x4>; /* 10mA, 10mA, 10mA */
-	qcom,pad-drv-off = <0x0 0x0 0x0>; /* 2mA, 2mA, 2mA */
-
-	qcom,clk-rates = <400000 25000000 50000000 100000000 200000000>;
-	qcom,bus-speed-mode = "HS200_1p8v", "DDR_1p8v";
-	qcom,nonremovable;
-
-	status = "ok";
-};
-
-&sdhc_2 {
-	vdd-supply = <&pm8110_l18>;
-	qcom,vdd-voltage-level = <2950000 2950000>;
-	qcom,vdd-current-level = <15000 400000>;
-
-	vdd-io-supply = <&pm8110_l21>;
-	qcom,vdd-io-always-on;
-	qcom,vdd-io-lpm-sup;
-	qcom,vdd-io-voltage-level = <1800000 2950000>;
-	qcom,vdd-io-current-level = <200 50000>;
-
-	qcom,pad-pull-on = <0x0 0x3 0x3>; /* no-pull, pull-up, pull-up */
-	qcom,pad-pull-off = <0x0 0x3 0x3>; /* no-pull, pull-up, pull-up */
-	qcom,pad-drv-on = <0x4 0x4 0x4>; /* 10mA, 10mA, 10mA */
-	qcom,pad-drv-off = <0x0 0x0 0x0>; /* 2mA, 2mA, 2mA */
-
-	qcom,clk-rates = <400000 25000000 50000000 100000000 200000000>;
-
-	#address-cells = <0>;
-	interrupt-parent = <&sdhc_2>;
-	interrupts = <0 1 2>;
-	#interrupt-cells = <1>;
-	interrupt-map-mask = <0xffffffff>;
-	interrupt-map = <0 &intc 0 125 0
-			1 &intc 0 221 0
-			2 &msmgpio 42 0x3>;
-	interrupt-names = "hc_irq", "pwr_irq", "status_irq";
-	cd-gpios = <&msmgpio 42 0x1>;
-
-	status = "ok";
-};
-
-&pm8110_chg {
-	status = "ok";
-
-	qcom,chgr@1000 {
-		status = "ok";
-	};
-
-	qcom,buck@1100 {
-		status = "ok";
-	};
-
-	qcom,bat-if@1200 {
-		status = "ok";
-	};
-
-	qcom,usb-chgpth@1300 {
-		status = "ok";
-	};
-
-	qcom,chg-misc@1600 {
-		status = "ok";
-	};
-};
-
-&pm8110_gpios {
-	gpio@c000 { /* GPIO 1 */
-	};
-
-	gpio@c100 { /* GPIO 2 */
-	};
-
-	gpio@c200 { /* GPIO 3 */
-	};
-
-	gpio@c300 { /* GPIO 4 */
-	};
-};
-
-&pm8110_mpps {
-	mpp@a000 { /* MPP 1 */
-	};
-
-	mpp@a100 { /* MPP 2 */
-		status = "disabled";
-	};
-
-	mpp@a200 { /* MPP 3 */
-		status = "disabled";
-	};
-
-	mpp@a300 { /* MPP 4 */
-	};
-};
diff --git a/arch/arm/boot/dts/msm8610-qrd.dtsi b/arch/arm/boot/dts/msm8610-qrd.dtsi
new file mode 100644
index 0000000..7a93c49
--- /dev/null
+++ b/arch/arm/boot/dts/msm8610-qrd.dtsi
@@ -0,0 +1,335 @@
+/* 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.
+ */
+
+/* This is a QRD reference design common file. The common device
+ * tree approach would help OEM during development of their extended
+ * device tree. Each new QRD OEM target can select its own include
+ * files and provide board specific overrides in the top level DTS
+ * file.
+ *
+ * For example:
+ * msm8xxx-qrd.dtsi: QRD reference common node
+ * msm8xxx-qrd-skuxx.dts:
+ * /include/ "msm8610-qrd.dtsi"
+ * / {
+ *      List skuxx specific node which is different with QRD
+ *      reference design.
+ * };
+ */
+
+/include/ "msm8610.dtsi"
+
+&soc {
+	i2c@f9923000{
+		focaltech@38{
+			compatible = "focaltech,5x06";
+			reg = <0x38>;
+			interrupt-parent = <&msmgpio>;
+			interrupts = <1 0x2>;
+			vdd-supply = <&pm8110_l19>;
+			vcc_i2c-supply = <&pm8110_l14>;
+			focaltech,family-id = <0x06>;
+			focaltech,reset-gpio = <&msmgpio 0 0x00>;
+			focaltech,irq-gpio = <&msmgpio 1 0x00>;
+			focaltech,display-coords = <0 0 480 800>;
+			focaltech,panel-coords = <0 0 480 800>;
+			focaltech,button-map= <139 102 158>;
+			focaltech,no-force-update;
+			focaltech,i2c-pull-up;
+		};
+	};
+
+	gen-vkeys {
+		compatible = "qcom,gen-vkeys";
+		label = "ft5x06_ts";
+		qcom,disp-maxx = <480>;
+		qcom,disp-maxy = <800>;
+		qcom,panel-maxx = <481>;
+		qcom,panel-maxy = <940>;
+		qcom,key-codes = <139 0 102 158 0 0 0>;
+		qcom,y-offset = <0>;
+	};
+	serial@f991e000 {
+		status = "ok";
+	};
+
+	i2c@f9925000 { /* BLSP-1 QUP-3 */
+		kionix@f {
+			compatible = "kionix,kxtj9";
+			reg = <0x0f>;
+			interrupt-parent = <&msmgpio>;
+			interrupts = <81 0x2>;
+			vdd-supply = <&pm8110_l19>;
+			vio-supply = <&pm8110_l14>;
+			kionix,min-interval = <5>;
+			kionix,init-interval = <200>;
+			kionix,axis-map-x = <1>;
+			kionix,axis-map-y = <0>;
+			kionix,axis-map-z = <2>;
+			kionix,g-range = <2>;
+			kionix,negate-x;
+			kionix,negate-y;
+			kionix,negate-z;
+			kionix,res-12bit;
+		};
+	};
+
+	flashlight {
+		compatible = "qcom,leds-gpio-flash";
+		status = "okay";
+		qcom,flash-en = <&msmgpio 18 0>;
+		qcom,flash-now = <&msmgpio 19 0>;
+		linux,name = "flashlight";
+		linux,default-trigger = "flashlight-trigger";
+	};
+
+	gpio_keys {
+                compatible = "gpio-keys";
+                input-name = "gpio-keys";
+
+                camera_snapshot {
+                        label = "camera_snapshot";
+                        gpios = <&msmgpio 73 0x1>;
+                        linux,input-type = <1>;
+                        linux,code = <0x2fe>;
+                        gpio-key,wakeup;
+                        debounce-interval = <15>;
+                };
+
+                camera_focus {
+                        label = "camera_focus";
+                        gpios = <&msmgpio 74 0x1>;
+                        linux,input-type = <1>;
+                        linux,code = <0x210>;
+                        gpio-key,wakeup;
+                        debounce-interval = <15>;
+                };
+
+                vol_up {
+                        label = "volume_up";
+                        gpios = <&msmgpio 72 0x1>;
+                        linux,input-type = <1>;
+                        linux,code = <115>;
+                        gpio-key,wakeup;
+                        debounce-interval = <15>;
+		};
+	};
+
+	i2c@f9927000  {
+                        msm8x10_wcd_codec@0d{
+                        compatible = "qcom,msm8x10-wcd-i2c";
+                        reg = <0x0d>;
+                        cdc-vdda-cp-supply = <&pm8110_s4>;
+                        qcom,cdc-vdda-cp-voltage = <2150000 2150000>;
+                        qcom,cdc-vdda-cp-current = <650000>;
+
+                        cdc-vdda-h-supply = <&pm8110_l6>;
+                        qcom,cdc-vdda-h-voltage = <1800000 1800000>;
+                        qcom,cdc-vdda-h-current = <250000>;
+
+                        cdc-vdd-px-supply = <&pm8110_l6>;
+                        qcom,cdc-vdd-px-voltage = <1800000 1800000>;
+                        qcom,cdc-vdd-px-current = <10000>;
+
+                        cdc-vdd-1p2v-supply = <&pm8110_l4>;
+                        qcom,cdc-vdd-1p2v-voltage = <1200000 1200000>;
+                        qcom,cdc-vdd-1p2v-current = <5000>;
+
+                        cdc-vdd-mic-bias-supply = <&pm8110_l20>;
+                        qcom,cdc-vdd-mic-bias-voltage = <3075000 3075000>;
+                        qcom,cdc-vdd-mic-bias-current = <25000>;
+
+                        qcom,cdc-micbias-cfilt-sel = <0x0>;
+                        qcom,cdc-micbias-cfilt-mv = <1800000>;
+                        qcom,cdc-mclk-clk-rate = <12288000>;
+                };
+
+                msm8x10_wcd_codec@77{
+                        compatible = "qcom,msm8x10-wcd-i2c";
+                        reg = <0x77>;
+                };
+
+                msm8x10_wcd_codec@66{
+                        compatible = "qcom,msm8x10-wcd-i2c";
+                        reg = <0x66>;
+                };
+
+                msm8x10_wcd_codec@55{
+                        compatible = "qcom,msm8x10-wcd-i2c";
+                        reg = <0x55>;
+                };
+	};
+
+    sound {
+        qcom,audio-routing =
+            "RX_BIAS", "MCLK",
+            "INT_LDO_H", "MCLK",
+            "MIC BIAS Internal1", "Handset Mic",
+            "MIC BIAS Internal2", "Headset Mic",
+            "AMIC1", "MIC BIAS Internal1",
+            "AMIC2", "MIC BIAS Internal2";
+    };
+};
+
+&spmi_bus {
+	qcom,pm8110@0 {
+		qcom,leds@a100 {
+			status = "okay";
+			qcom,led_mpp_2 {
+				label = "mpp";
+				linux,name = "wled-homerow";
+				linux-default-trigger = "hr-trigger";
+				qcom,default-state = "off";
+				qcom,max-current = <40>;
+				qcom,id = <6>;
+				qcom,source-sel = <1>;
+				qcom,mode-ctrl = <0x61>;
+				qcom,mode = "manual";
+			};
+		};
+
+		qcom,leds@a200 {
+			status = "okay";
+			qcom,led_mpp_3 {
+				label = "mpp";
+				linux,name = "wled-backlight";
+				linux,default-trigger = "bkl-trigger";
+				qcom,default-state = "on";
+				qcom,max-current = <40>;
+				qcom,id = <6>;
+				qcom,source-sel = <1>;
+				qcom,mode-ctrl = <0x10>;
+				qcom,mode = "manual";
+			};
+		};
+	};
+};
+
+&spmi_bus {
+	qcom,pm8110@1 {
+		qcom,vibrator@c000 {
+			status = "okay";
+			qcom,vib-timeout-ms = <15000>;
+			qcom,vib-vtg-level-mV = <3100>;
+		};
+	};
+};
+
+&sdhc_1 {
+	vdd-supply = <&pm8110_l17>;
+	qcom,vdd-always-on;
+	qcom,vdd-lpm-sup;
+	qcom,vdd-voltage-level = <2900000 2900000>;
+	qcom,vdd-current-level = <200 400000>;
+
+	vdd-io-supply = <&pm8110_l6>;
+	qcom,vdd-io-always-on;
+	qcom,vdd-io-voltage-level = <1800000 1800000>;
+	qcom,vdd-io-current-level = <200 60000>;
+
+	qcom,pad-pull-on = <0x0 0x3 0x3>; /* no-pull, pull-up, pull-up */
+	qcom,pad-pull-off = <0x0 0x3 0x3>; /* no-pull, pull-up, pull-up */
+	qcom,pad-drv-on = <0x4 0x4 0x4>; /* 10mA, 10mA, 10mA */
+	qcom,pad-drv-off = <0x0 0x0 0x0>; /* 2mA, 2mA, 2mA */
+
+	qcom,clk-rates = <400000 25000000 50000000 100000000 200000000>;
+	qcom,bus-speed-mode = "HS200_1p8v", "DDR_1p8v";
+	qcom,nonremovable;
+
+	status = "ok";
+};
+
+&sdhc_2 {
+	vdd-supply = <&pm8110_l18>;
+	qcom,vdd-voltage-level = <2950000 2950000>;
+	qcom,vdd-current-level = <15000 400000>;
+
+	vdd-io-supply = <&pm8110_l21>;
+	qcom,vdd-io-always-on;
+	qcom,vdd-io-lpm-sup;
+	qcom,vdd-io-voltage-level = <1800000 2950000>;
+	qcom,vdd-io-current-level = <200 50000>;
+
+	qcom,pad-pull-on = <0x0 0x3 0x3>; /* no-pull, pull-up, pull-up */
+	qcom,pad-pull-off = <0x0 0x3 0x3>; /* no-pull, pull-up, pull-up */
+	qcom,pad-drv-on = <0x4 0x4 0x4>; /* 10mA, 10mA, 10mA */
+	qcom,pad-drv-off = <0x0 0x0 0x0>; /* 2mA, 2mA, 2mA */
+
+	qcom,clk-rates = <400000 25000000 50000000 100000000 200000000>;
+
+	#address-cells = <0>;
+	interrupt-parent = <&sdhc_2>;
+	interrupts = <0 1 2>;
+	#interrupt-cells = <1>;
+	interrupt-map-mask = <0xffffffff>;
+	interrupt-map = <0 &intc 0 125 0
+			1 &intc 0 221 0
+			2 &msmgpio 42 0x3>;
+	interrupt-names = "hc_irq", "pwr_irq", "status_irq";
+	cd-gpios = <&msmgpio 42 0x1>;
+
+	status = "ok";
+};
+
+&pm8110_chg {
+	status = "ok";
+
+	qcom,chgr@1000 {
+		status = "ok";
+	};
+
+	qcom,buck@1100 {
+		status = "ok";
+	};
+
+	qcom,bat-if@1200 {
+		status = "ok";
+	};
+
+	qcom,usb-chgpth@1300 {
+		status = "ok";
+	};
+
+	qcom,chg-misc@1600 {
+		status = "ok";
+	};
+};
+
+&pm8110_gpios {
+	gpio@c000 { /* GPIO 1 */
+	};
+
+	gpio@c100 { /* GPIO 2 */
+	};
+
+	gpio@c200 { /* GPIO 3 */
+	};
+
+	gpio@c300 { /* GPIO 4 */
+	};
+};
+
+&pm8110_mpps {
+	mpp@a000 { /* MPP 1 */
+	};
+
+	mpp@a100 { /* MPP 2 */
+		status = "disabled";
+	};
+
+	mpp@a200 { /* MPP 3 */
+		status = "disabled";
+	};
+
+	mpp@a300 { /* MPP 4 */
+	};
+};
diff --git a/arch/arm/boot/dts/msm8610.dtsi b/arch/arm/boot/dts/msm8610.dtsi
index ad0980c..4eca5bb 100644
--- a/arch/arm/boot/dts/msm8610.dtsi
+++ b/arch/arm/boot/dts/msm8610.dtsi
@@ -219,6 +219,8 @@
 		HSUSB_1p8-supply = <&pm8110_l10>;
 		HSUSB_3p3-supply = <&pm8110_l20>;
 
+		qcom,hsusb-otg-phy-init-seq =
+			<0x44 0x80 0x68 0x81 0x24 0x82 0x13 0x83 0xffffffff>;
 		qcom,hsusb-otg-phy-type = <2>;
 		qcom,hsusb-otg-mode = <1>;
 		qcom,hsusb-otg-otg-control = <2>;
@@ -772,6 +774,21 @@
 		qcom,core-limit-temp = <80>;
 		qcom,core-temp-hysteresis = <10>;
 		qcom,core-control-mask = <0xe>;
+		qcom,vdd-restriction-temp = <5>;
+		qcom,vdd-restriction-temp-hysteresis = <10>;
+		vdd_dig-supply = <&pm8110_s1_floor_corner>;
+
+		qcom,vdd-dig-rstr{
+			qcom,vdd-rstr-reg = "vdd_dig";
+			qcom,levels = <5 7 7>; /* Nominal, Super Turbo, Super Turbo */
+			qcom,min-level = <1>; /* No Request */
+		};
+
+		qcom,vdd-apps-rstr{
+			qcom,vdd-rstr-reg = "vdd_apps";
+			qcom,levels = <600000 787200 998400>;
+			qcom,freq-req;
+		};
 	};
 
 	qcom,ipc-spinlock@fd484000 {
diff --git a/arch/arm/boot/dts/msm8974-coresight.dtsi b/arch/arm/boot/dts/msm8974-coresight.dtsi
index 9fee2e5..e41adac 100644
--- a/arch/arm/boot/dts/msm8974-coresight.dtsi
+++ b/arch/arm/boot/dts/msm8974-coresight.dtsi
@@ -379,4 +379,14 @@
 
 		qcom,hwevent-clks = "core_mmss_clk";
 	};
+
+	fuse: fuse@fc4be024 {
+		compatible = "arm,coresight-fuse";
+		reg = <0xfc4be024 0x8>;
+		reg-names = "fuse-base";
+
+		coresight-id = <30>;
+		coresight-name = "coresight-fuse";
+		coresight-nr-inports = <0>;
+	};
 };
diff --git a/arch/arm/boot/dts/msm8974-liquid.dtsi b/arch/arm/boot/dts/msm8974-liquid.dtsi
index 2dc52b6..ddf5b60 100644
--- a/arch/arm/boot/dts/msm8974-liquid.dtsi
+++ b/arch/arm/boot/dts/msm8974-liquid.dtsi
@@ -813,7 +813,7 @@
 	};
 
 	qcom,dc-chgpth@1400 {
-		status = "ok";
+		status = "disabled";
 	};
 
 	qcom,boost@1500 {
diff --git a/arch/arm/boot/dts/msm8974-mdss.dtsi b/arch/arm/boot/dts/msm8974-mdss.dtsi
index 6b8d600..46bb71a 100644
--- a/arch/arm/boot/dts/msm8974-mdss.dtsi
+++ b/arch/arm/boot/dts/msm8974-mdss.dtsi
@@ -41,6 +41,7 @@
 		qcom,mdss-intf-off = <0x00021100 0x00021300
 					   0x00021500 0x00021700>;
 
+		qcom,mdss-has-wfd-blk;
 		qcom,vbif-settings = <0x0004 0x00000001>,
 				     <0x00D8 0x00000707>,
 				     <0x00F0 0x00000030>,
diff --git a/arch/arm/boot/dts/msm8974.dtsi b/arch/arm/boot/dts/msm8974.dtsi
index 0029752..0e720c7 100644
--- a/arch/arm/boot/dts/msm8974.dtsi
+++ b/arch/arm/boot/dts/msm8974.dtsi
@@ -648,6 +648,8 @@
 		reg-names = "slimbus_physical", "slimbus_bam_physical";
 		interrupts = <0 163 0 0 164 0>;
 		interrupt-names = "slimbus_irq", "slimbus_bam_irq";
+		qcom,apps-ch-pipes = <0x60000000>;
+		qcom,ea-pc = <0x30>;
 
 		taiko_codec {
 			compatible = "qcom,taiko-slim-pgd";
@@ -1369,6 +1371,12 @@
 		qcom,calib-mode = "fuse_map1";
 	};
 
+	jtag_fuse: jtagfuse@fc4be024 {
+		compatible = "qcom,jtag-fuse";
+		reg = <0xfc4be024 0x8>;
+		reg-names = "fuse-base";
+	};
+
 	qcom,msm-rtb {
 		compatible = "qcom,msm-rtb";
 		qcom,memory-reservation-type = "EBI1";
diff --git a/arch/arm/boot/dts/msm9625-pm.dtsi b/arch/arm/boot/dts/msm9625-pm.dtsi
index 8eb1119..24c6143 100644
--- a/arch/arm/boot/dts/msm9625-pm.dtsi
+++ b/arch/arm/boot/dts/msm9625-pm.dtsi
@@ -294,4 +294,10 @@
 		reg-names = "phys_addr_base";
 		qcom,sleep-stats-version = <2>;
 	};
+
+	qcom,rpm-rbcpr-stats@fc000000 {
+		compatible = "qcom,rpmrbcpr-stats";
+		reg = <0xfc000000 0x1a0000>;
+		qcom,start-offset = <0x190010>;
+	};
 };
diff --git a/arch/arm/boot/dts/msmsamarium-smp2p.dtsi b/arch/arm/boot/dts/msmsamarium-smp2p.dtsi
new file mode 100644
index 0000000..3d8441b
--- /dev/null
+++ b/arch/arm/boot/dts/msmsamarium-smp2p.dtsi
@@ -0,0 +1,160 @@
+/* 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.
+ */
+&soc {
+	qcom,smp2p-modem {
+		compatible = "qcom,smp2p";
+		reg = <0xf9011008 0x4>;
+		qcom,remote-pid = <1>;
+		qcom,irq-bitmask = <0x4000>;
+		interrupts = <0 27 1>;
+	};
+
+	qcom,smp2p-adsp {
+		compatible = "qcom,smp2p";
+		reg = <0xf9011008 0x4>;
+		qcom,remote-pid = <2>;
+		qcom,irq-bitmask = <0x400>;
+		interrupts = <0 158 1>;
+	};
+
+	qcom,smp2p-wcnss {
+		compatible = "qcom,smp2p";
+		reg = <0xf9011008 0x4>;
+		qcom,remote-pid = <4>;
+		qcom,irq-bitmask = <0x40000>;
+		interrupts = <0 143 1>;
+	};
+
+	smp2pgpio_smp2p_7_in: qcom,smp2pgpio-smp2p-7-in {
+		compatible = "qcom,smp2pgpio";
+		qcom,entry-name = "smp2p";
+		qcom,remote-pid = <7>;
+		qcom,is-inbound;
+		gpio-controller;
+		#gpio-cells = <2>;
+		interrupt-controller;
+		#interrupt-cells = <2>;
+	};
+
+	qcom,smp2pgpio_test_smp2p_7_in {
+		compatible = "qcom,smp2pgpio_test_smp2p_7_in";
+		gpios = <&smp2pgpio_smp2p_7_in 0 0>;
+	};
+
+	smp2pgpio_smp2p_7_out: qcom,smp2pgpio-smp2p-7-out {
+		compatible = "qcom,smp2pgpio";
+		qcom,entry-name = "smp2p";
+		qcom,remote-pid = <7>;
+		gpio-controller;
+		#gpio-cells = <2>;
+		interrupt-controller;
+		#interrupt-cells = <2>;
+	};
+
+	qcom,smp2pgpio_test_smp2p_7_out {
+		compatible = "qcom,smp2pgpio_test_smp2p_7_out";
+		gpios = <&smp2pgpio_smp2p_7_out 0 0>;
+	};
+
+	smp2pgpio_smp2p_1_in: qcom,smp2pgpio-smp2p-1-in {
+		compatible = "qcom,smp2pgpio";
+		qcom,entry-name = "smp2p";
+		qcom,remote-pid = <1>;
+		qcom,is-inbound;
+		gpio-controller;
+		#gpio-cells = <2>;
+		interrupt-controller;
+		#interrupt-cells = <2>;
+	};
+
+	qcom,smp2pgpio_test_smp2p_1_in {
+		compatible = "qcom,smp2pgpio_test_smp2p_1_in";
+		gpios = <&smp2pgpio_smp2p_1_in 0 0>;
+	};
+
+	smp2pgpio_smp2p_1_out: qcom,smp2pgpio-smp2p-1-out {
+		compatible = "qcom,smp2pgpio";
+		qcom,entry-name = "smp2p";
+		qcom,remote-pid = <1>;
+		gpio-controller;
+		#gpio-cells = <2>;
+		interrupt-controller;
+		#interrupt-cells = <2>;
+	};
+
+	qcom,smp2pgpio_test_smp2p_1_out {
+		compatible = "qcom,smp2pgpio_test_smp2p_1_out";
+		gpios = <&smp2pgpio_smp2p_1_out 0 0>;
+	};
+
+	smp2pgpio_smp2p_2_in: qcom,smp2pgpio-smp2p-2-in {
+		compatible = "qcom,smp2pgpio";
+		qcom,entry-name = "smp2p";
+		qcom,remote-pid = <2>;
+		qcom,is-inbound;
+		gpio-controller;
+		#gpio-cells = <2>;
+		interrupt-controller;
+		#interrupt-cells = <2>;
+	};
+
+	qcom,smp2pgpio_test_smp2p_2_in {
+		compatible = "qcom,smp2pgpio_test_smp2p_2_in";
+		gpios = <&smp2pgpio_smp2p_2_in 0 0>;
+	};
+
+	smp2pgpio_smp2p_2_out: qcom,smp2pgpio-smp2p-2-out {
+		compatible = "qcom,smp2pgpio";
+		qcom,entry-name = "smp2p";
+		qcom,remote-pid = <2>;
+		gpio-controller;
+		#gpio-cells = <2>;
+		interrupt-controller;
+		#interrupt-cells = <2>;
+	};
+
+	qcom,smp2pgpio_test_smp2p_2_out {
+		compatible = "qcom,smp2pgpio_test_smp2p_2_out";
+		gpios = <&smp2pgpio_smp2p_2_out 0 0>;
+	};
+
+	smp2pgpio_smp2p_4_in: qcom,smp2pgpio-smp2p-4-in {
+		compatible = "qcom,smp2pgpio";
+		qcom,entry-name = "smp2p";
+		qcom,remote-pid = <4>;
+		qcom,is-inbound;
+		gpio-controller;
+		#gpio-cells = <2>;
+		interrupt-controller;
+		#interrupt-cells = <2>;
+	};
+
+	qcom,smp2pgpio_test_smp2p_4_in {
+		compatible = "qcom,smp2pgpio_test_smp2p_4_in";
+		gpios = <&smp2pgpio_smp2p_4_in 0 0>;
+	};
+
+	smp2pgpio_smp2p_4_out: qcom,smp2pgpio-smp2p-4-out {
+		compatible = "qcom,smp2pgpio";
+		qcom,entry-name = "smp2p";
+		qcom,remote-pid = <4>;
+		gpio-controller;
+		#gpio-cells = <2>;
+		interrupt-controller;
+		#interrupt-cells = <2>;
+	};
+
+	qcom,smp2pgpio_test_smp2p_4_out {
+		compatible = "qcom,smp2pgpio_test_smp2p_4_out";
+		gpios = <&smp2pgpio_smp2p_4_out 0 0>;
+	};
+};
diff --git a/arch/arm/boot/dts/msmsamarium.dtsi b/arch/arm/boot/dts/msmsamarium.dtsi
index 8a66920..e743989 100644
--- a/arch/arm/boot/dts/msmsamarium.dtsi
+++ b/arch/arm/boot/dts/msmsamarium.dtsi
@@ -20,6 +20,7 @@
 };
 
 /include/ "msmsamarium-ion.dtsi"
+/include/ "msmsamarium-smp2p.dtsi"
 
 &soc {
 	#address-cells = <1>;
@@ -107,4 +108,79 @@
 		reg = <0xfd484000 0x400>;
 		qcom,num-locks = <8>;
 	};
+
+	qcom,smem@fa00000 {
+		compatible = "qcom,smem";
+		reg = <0xfa00000 0x200000>,
+			<0xf9011000 0x1000>,
+			<0xfc428000 0x4000>;
+		reg-names = "smem", "irq-reg-base", "aux-mem1";
+
+		qcom,smd-modem {
+			compatible = "qcom,smd";
+			qcom,smd-edge = <0>;
+			qcom,smd-irq-offset = <0x8>;
+			qcom,smd-irq-bitmask = <0x1000>;
+			qcom,pil-string = "modem";
+			interrupts = <0 25 1>;
+		};
+
+		qcom,smsm-modem {
+			compatible = "qcom,smsm";
+			qcom,smsm-edge = <0>;
+			qcom,smsm-irq-offset = <0x8>;
+			qcom,smsm-irq-bitmask = <0x2000>;
+			interrupts = <0 26 1>;
+		};
+
+		qcom,smd-adsp {
+			compatible = "qcom,smd";
+			qcom,smd-edge = <1>;
+			qcom,smd-irq-offset = <0x8>;
+			qcom,smd-irq-bitmask = <0x100>;
+			qcom,pil-string = "adsp";
+			interrupts = <0 156 1>;
+		};
+
+		qcom,smsm-adsp {
+			compatible = "qcom,smsm";
+			qcom,smsm-edge = <1>;
+			qcom,smsm-irq-offset = <0x8>;
+			qcom,smsm-irq-bitmask = <0x200>;
+			interrupts = <0 157 1>;
+		};
+
+		qcom,smd-wcnss {
+			compatible = "qcom,smd";
+			qcom,smd-edge = <6>;
+			qcom,smd-irq-offset = <0x8>;
+			qcom,smd-irq-bitmask = <0x20000>;
+			qcom,pil-string = "wcnss";
+			interrupts = <0 142 1>;
+		};
+
+		qcom,smsm-wcnss {
+			compatible = "qcom,smsm";
+			qcom,smsm-edge = <6>;
+			qcom,smsm-irq-offset = <0x8>;
+			qcom,smsm-irq-bitmask = <0x80000>;
+			interrupts = <0 144 1>;
+		};
+
+		qcom,smd-rpm {
+			compatible = "qcom,smd";
+			qcom,smd-edge = <15>;
+			qcom,smd-irq-offset = <0x8>;
+			qcom,smd-irq-bitmask = <0x1>;
+			interrupts = <0 168 1>;
+			qcom,irq-no-suspend;
+		};
+	};
+
+	qcom,bam_dmux@fc834000 {
+		compatible = "qcom,bam_dmux";
+		reg = <0xfc834000 0x7000>;
+		interrupts = <0 29 1>;
+		qcom,rx-ring-size = <64>;
+	};
 };
diff --git a/arch/arm/configs/msm8610-perf_defconfig b/arch/arm/configs/msm8610-perf_defconfig
index 010bc10..29ef385 100644
--- a/arch/arm/configs/msm8610-perf_defconfig
+++ b/arch/arm/configs/msm8610-perf_defconfig
@@ -385,3 +385,4 @@
 CONFIG_INPUT_KXTJ9=y
 CONFIG_MSM_RPM_RBCPR_STATS_V2_LOG=y
 CONFIG_SENSORS_STK3X1X=y
+CONFIG_SENSORS_MMA8X5X=y
diff --git a/arch/arm/configs/msm8610_defconfig b/arch/arm/configs/msm8610_defconfig
index 7225ec5..77a1048 100644
--- a/arch/arm/configs/msm8610_defconfig
+++ b/arch/arm/configs/msm8610_defconfig
@@ -428,3 +428,4 @@
 CONFIG_INPUT_KXTJ9=y
 CONFIG_MSM_RPM_RBCPR_STATS_V2_LOG=y
 CONFIG_SENSORS_STK3X1X=y
+CONFIG_SENSORS_MMA8X5X=y
diff --git a/arch/arm/configs/msm8974_defconfig b/arch/arm/configs/msm8974_defconfig
index c680c55..8447dd55 100644
--- a/arch/arm/configs/msm8974_defconfig
+++ b/arch/arm/configs/msm8974_defconfig
@@ -454,6 +454,7 @@
 CONFIG_MOBICORE_SUPPORT=m
 CONFIG_MOBICORE_API=m
 CONFIG_CORESIGHT=y
+CONFIG_CORESIGHT_FUSE=y
 CONFIG_CORESIGHT_TMC=y
 CONFIG_CORESIGHT_TPIU=y
 CONFIG_CORESIGHT_FUNNEL=y
diff --git a/arch/arm/configs/msm9625-perf_defconfig b/arch/arm/configs/msm9625-perf_defconfig
index d02f5da..6471673 100644
--- a/arch/arm/configs/msm9625-perf_defconfig
+++ b/arch/arm/configs/msm9625-perf_defconfig
@@ -317,3 +317,4 @@
 CONFIG_CRYPTO_DEV_QCEDEV=m
 CONFIG_CRC_CCITT=y
 CONFIG_LIBCRC32C=y
+CONFIG_MSM_RPM_RBCPR_STATS_V2_LOG=y
diff --git a/arch/arm/configs/msm9625_defconfig b/arch/arm/configs/msm9625_defconfig
index 64c8535..0ff4efa 100644
--- a/arch/arm/configs/msm9625_defconfig
+++ b/arch/arm/configs/msm9625_defconfig
@@ -327,3 +327,4 @@
 CONFIG_CRYPTO_DEFLATE=y
 CONFIG_CRC_CCITT=y
 CONFIG_LIBCRC32C=y
+CONFIG_MSM_RPM_RBCPR_STATS_V2_LOG=y
diff --git a/arch/arm/mach-msm/Kconfig b/arch/arm/mach-msm/Kconfig
index e0f9e8a..174a576 100644
--- a/arch/arm/mach-msm/Kconfig
+++ b/arch/arm/mach-msm/Kconfig
@@ -528,6 +528,7 @@
 	select ARM_HAS_SG_CHAIN
 	select MSM_RUN_QUEUE_STATS
 	select ARCH_WANT_KMAP_ATOMIC_FLUSH
+	select QMI_ENCDEC
 endmenu
 
 choice
diff --git a/arch/arm/mach-msm/Makefile b/arch/arm/mach-msm/Makefile
index 300b2da..68e9282 100644
--- a/arch/arm/mach-msm/Makefile
+++ b/arch/arm/mach-msm/Makefile
@@ -62,8 +62,8 @@
 obj-$(CONFIG_MSM_AVS_HW) += avs.o
 obj-$(CONFIG_CPU_V6) += idle-v6.o
 obj-$(CONFIG_CPU_V7) += idle-v7.o
-obj-$(CONFIG_MSM_JTAG) += jtag.o
-obj-$(CONFIG_MSM_JTAG_MM) +=  jtag-mm.o
+obj-$(CONFIG_MSM_JTAG) += jtag-fuse.o jtag.o
+obj-$(CONFIG_MSM_JTAG_MM) +=  jtag-fuse.o jtag-mm.o
 
 msm-etm-objs := etm.o
 obj-$(CONFIG_MSM_ETM) += msm-etm.o
diff --git a/arch/arm/mach-msm/Makefile.boot b/arch/arm/mach-msm/Makefile.boot
index 24b68bc..1ec850f 100644
--- a/arch/arm/mach-msm/Makefile.boot
+++ b/arch/arm/mach-msm/Makefile.boot
@@ -95,10 +95,12 @@
         dtb-$(CONFIG_ARCH_MSM8226)	+= msm8926-cdp.dtb
         dtb-$(CONFIG_ARCH_MSM8226)	+= msm8926-mtp.dtb
         dtb-$(CONFIG_ARCH_MSM8226)	+= msm8926-qrd.dtb
-        dtb-$(CONFIG_ARCH_MSM8226)	+= apq8026-xpm.dtb
-        dtb-$(CONFIG_ARCH_MSM8226)	+= apq8026-mtp.dtb
         dtb-$(CONFIG_ARCH_MSM8226)	+= msm8226-v1-qrd-skuf.dtb
         dtb-$(CONFIG_ARCH_MSM8226)	+= msm8226-v2-qrd-skuf.dtb
+        dtb-$(CONFIG_ARCH_MSM8226)	+= apq8026-v1-xpm.dtb
+        dtb-$(CONFIG_ARCH_MSM8226)	+= apq8026-v1-mtp.dtb
+        dtb-$(CONFIG_ARCH_MSM8226)	+= apq8026-v2-xpm.dtb
+        dtb-$(CONFIG_ARCH_MSM8226)	+= apq8026-v2-mtp.dtb
 
 # FSM9XXX
    zreladdr-$(CONFIG_ARCH_FSM9XXX)	:= 0x10008000
@@ -117,6 +119,7 @@
    zreladdr-$(CONFIG_ARCH_MSM8610)	:= 0x00008000
         dtb-$(CONFIG_ARCH_MSM8610)	+= msm8610-rumi.dtb
         dtb-$(CONFIG_ARCH_MSM8610)	+= msm8610-sim.dtb
+        dtb-$(CONFIG_ARCH_MSM8610)	+= msm8610-qrd.dtb
 
 # MSMSAMARIUM
    zreladdr-$(CONFIG_ARCH_MSMSAMARIUM)	:= 0x00008000
diff --git a/arch/arm/mach-msm/board-samarium.c b/arch/arm/mach-msm/board-samarium.c
index a8d6420..be09b54 100644
--- a/arch/arm/mach-msm/board-samarium.c
+++ b/arch/arm/mach-msm/board-samarium.c
@@ -27,10 +27,12 @@
 #include <mach/socinfo.h>
 #include <mach/clk-provider.h>
 #include <mach/msm_smem.h>
+#include <mach/msm_smd.h>
 #include "board-dt.h"
 #include "clock.h"
 #include "devices.h"
 #include "platsmp.h"
+#include "modem_notifier.h"
 
 static struct clk_lookup msm_clocks_dummy[] = {
 	CLK_DUMMY("core_clk",   BLSP1_UART_CLK, "f991f000.serial", OFF),
@@ -102,6 +104,8 @@
 void __init msmsamarium_add_drivers(void)
 {
 	msm_smem_init();
+	msm_init_modem_notifier_list();
+	msm_smd_init();
 	msm_clock_init(&msm_dummy_clock_init_data);
 }
 
diff --git a/arch/arm/mach-msm/clock-8084.c b/arch/arm/mach-msm/clock-8084.c
index ef8b5bb..605a7ae 100644
--- a/arch/arm/mach-msm/clock-8084.c
+++ b/arch/arm/mach-msm/clock-8084.c
@@ -307,8 +307,9 @@
 	CLK_DUMMY("",	camss_vfe_vfe1_clk.c,	"", OFF),
 	CLK_DUMMY("",	camss_vfe_vfe_ahb_clk.c,	"", OFF),
 	CLK_DUMMY("",	camss_vfe_vfe_axi_clk.c,	"", OFF),
-	CLK_DUMMY("",	mdss_ahb_clk.c,	"", OFF),
-	CLK_DUMMY("",	mdss_axi_clk.c,	"", OFF),
+	CLK_DUMMY("iface_clk", mdss_ahb_clk.c, "fd900000.qcom,mdss_mdp", OFF),
+	CLK_DUMMY("bus_clk", mdss_axi_clk.c, "fd900000.qcom,mdss_mdp", OFF),
+	CLK_DUMMY("core_clk_src", mdp_clk_src.c, "fd900000.qcom,mdss_mdp", OFF),
 	CLK_DUMMY("",	mdss_byte0_clk.c,	"", OFF),
 	CLK_DUMMY("",	mdss_byte1_clk.c,	"", OFF),
 	CLK_DUMMY("",	mdss_edpaux_clk.c,	"", OFF),
@@ -319,11 +320,11 @@
 	CLK_DUMMY("",	mdss_extpclk_clk.c,	"", OFF),
 	CLK_DUMMY("",	mdss_hdmi_ahb_clk.c,	"", OFF),
 	CLK_DUMMY("",	mdss_hdmi_clk.c,	"", OFF),
-	CLK_DUMMY("",	mdss_mdp_clk.c,	"", OFF),
-	CLK_DUMMY("",	mdss_mdp_lut_clk.c,	"", OFF),
+	CLK_DUMMY("core_clk", mdss_mdp_clk.c, "fd900000.qcom,mdss_mdp", OFF),
+	CLK_DUMMY("lut_clk", mdss_mdp_lut_clk.c, "fd900000.qcom,mdss_mdp", OFF),
 	CLK_DUMMY("",	mdss_pclk0_clk.c,	"", OFF),
 	CLK_DUMMY("",	mdss_pclk1_clk.c,	"", OFF),
-	CLK_DUMMY("",	mdss_vsync_clk.c,	"", OFF),
+	CLK_DUMMY("vsync_clk", mdss_vsync_clk.c, "fd900000.qcom,mdss_mdp", OFF),
 	CLK_DUMMY("",	mmss_misc_ahb_clk.c,	"", OFF),
 	CLK_DUMMY("",	mmss_mmssnoc_ahb_clk.c,	"", OFF),
 	CLK_DUMMY("",	mmss_mmssnoc_axi_clk.c,	"", OFF),
diff --git a/arch/arm/mach-msm/clock-8974.c b/arch/arm/mach-msm/clock-8974.c
index a1f24d8..4b8fb45 100644
--- a/arch/arm/mach-msm/clock-8974.c
+++ b/arch/arm/mach-msm/clock-8974.c
@@ -812,7 +812,6 @@
 static DEFINE_CLK_VOTER(snoc_msmbus_clk, &snoc_clk.c, LONG_MAX);
 static DEFINE_CLK_VOTER(cnoc_msmbus_clk, &cnoc_clk.c, LONG_MAX);
 static DEFINE_CLK_VOTER(pnoc_msmbus_a_clk, &pnoc_a_clk.c, LONG_MAX);
-static DEFINE_CLK_VOTER(pnoc_pm_clk, &pnoc_clk.c, LONG_MAX);
 static DEFINE_CLK_VOTER(snoc_msmbus_a_clk, &snoc_a_clk.c, LONG_MAX);
 static DEFINE_CLK_VOTER(cnoc_msmbus_a_clk, &cnoc_a_clk.c, LONG_MAX);
 
@@ -824,6 +823,7 @@
 static DEFINE_CLK_VOTER(ocmemgx_msmbus_a_clk, &ocmemgx_a_clk.c, LONG_MAX);
 static DEFINE_CLK_VOTER(ocmemgx_core_clk, &ocmemgx_clk.c, LONG_MAX);
 
+static DEFINE_CLK_VOTER(pnoc_keepalive_a_clk, &pnoc_a_clk.c, LONG_MAX);
 static DEFINE_CLK_VOTER(pnoc_sps_clk, &pnoc_clk.c, 0);
 
 static DEFINE_CLK_BRANCH_VOTER(cxo_otg_clk, &cxo_clk_src.c);
@@ -5290,6 +5290,7 @@
 	CLK_LOOKUP("core_clk", gcc_prng_ahb_clk.c, "msm_rng"),
 
 	CLK_LOOKUP("dfab_clk", pnoc_sps_clk.c, "msm_sps"),
+	CLK_LOOKUP("bus_clk", pnoc_keepalive_a_clk.c, ""),
 
 	CLK_LOOKUP("bus_clk", snoc_clk.c, ""),
 	CLK_LOOKUP("bus_clk", pnoc_clk.c, ""),
@@ -5307,7 +5308,6 @@
 	CLK_LOOKUP("bus_clk",	snoc_msmbus_clk.c,	"msm_sys_noc"),
 	CLK_LOOKUP("bus_a_clk",	snoc_msmbus_a_clk.c,	"msm_sys_noc"),
 	CLK_LOOKUP("bus_clk",	pnoc_msmbus_clk.c,	"msm_periph_noc"),
-	CLK_LOOKUP("bus_clk",   pnoc_pm_clk.c,      "pm_8x60"),
 	CLK_LOOKUP("bus_a_clk",	pnoc_msmbus_a_clk.c,	"msm_periph_noc"),
 	CLK_LOOKUP("mem_clk",	bimc_msmbus_clk.c,	"msm_bimc"),
 	CLK_LOOKUP("mem_a_clk",	bimc_msmbus_a_clk.c,	"msm_bimc"),
@@ -5563,6 +5563,12 @@
 	clk_prepare_enable(&mmssnoc_ahb_a_clk.c);
 
 	/*
+	 * Hold an active set vote for the PNOC AHB source. Sleep set vote is 0.
+	 */
+	clk_set_rate(&pnoc_keepalive_a_clk.c, 19200000);
+	clk_prepare_enable(&pnoc_keepalive_a_clk.c);
+
+	/*
 	 * Hold an active set vote for CXO; this is because CXO is expected
 	 * to remain on whenever CPUs aren't power collapsed.
 	 */
diff --git a/arch/arm/mach-msm/clock-mdss-8974.c b/arch/arm/mach-msm/clock-mdss-8974.c
index 6877b4d9..70b6bea 100644
--- a/arch/arm/mach-msm/clock-mdss-8974.c
+++ b/arch/arm/mach-msm/clock-mdss-8974.c
@@ -854,11 +854,24 @@
 	return div;
 }
 
+static void dsi_pll_toggle_lock_detect(void)
+{
+	DSS_REG_W(mdss_dsi_base, DSI_0_PHY_PLL_UNIPHY_PLL_LKDET_CFG2,
+		0x05);
+	DSS_REG_W(mdss_dsi_base, DSI_0_PHY_PLL_UNIPHY_PLL_LKDET_CFG2,
+		0x04);
+	udelay(1);
+	DSS_REG_W(mdss_dsi_base, DSI_0_PHY_PLL_UNIPHY_PLL_LKDET_CFG2,
+		0x05);
+}
+
 static int dsi_pll_lock_status(void)
 {
 	u32 status;
 	int pll_locked = 0;
 
+	dsi_pll_toggle_lock_detect();
+
 	/* poll for PLL ready status */
 	if (readl_poll_timeout_noirq((mdss_dsi_base +
 			DSI_0_PHY_PLL_UNIPHY_PLL_STATUS),
diff --git a/arch/arm/mach-msm/include/mach/jtag.h b/arch/arm/mach-msm/include/mach/jtag.h
index 2131be6..ae006be 100644
--- a/arch/arm/mach-msm/include/mach/jtag.h
+++ b/arch/arm/mach-msm/include/mach/jtag.h
@@ -16,9 +16,11 @@
 #if defined(CONFIG_MSM_JTAG) || defined(CONFIG_MSM_JTAG_MM)
 extern void msm_jtag_save_state(void);
 extern void msm_jtag_restore_state(void);
+extern bool msm_jtag_fuse_apps_access_disabled(void);
 #else
 static inline void msm_jtag_save_state(void) {}
 static inline void msm_jtag_restore_state(void) {}
+static inline bool msm_jtag_fuse_apps_access_disabled(void) { return false; }
 #endif
 
 #endif
diff --git a/arch/arm/mach-msm/include/mach/msm_ipc_logging.h b/arch/arm/mach-msm/include/mach/msm_ipc_logging.h
index 0a91719..b3bf07c 100644
--- a/arch/arm/mach-msm/include/mach/msm_ipc_logging.h
+++ b/arch/arm/mach-msm/include/mach/msm_ipc_logging.h
@@ -115,6 +115,20 @@
  */
 int ipc_log_string(void *ilctxt, const char *fmt, ...) __printf(2, 3);
 
+/**
+ * ipc_log_extract - Reads and deserializes log
+ *
+ * @ilctxt:  logging context
+ * @buff:    buffer to receive the data
+ * @size:    size of the buffer
+ * @returns: 0 if no data read; >0 number of bytes read; < 0 error
+ *
+ * If no data is available to be read, then the ilctxt::read_avail
+ * completion is reinitialized.  This allows clients to block
+ * until new log data is save.
+ */
+int ipc_log_extract(void *ilctxt, char *buff, int size);
+
 /*
  * Print a string to decode context.
  * @dctxt   Decode context
@@ -220,6 +234,9 @@
 static inline int ipc_log_string(void *ilctxt, const char *fmt, ...)
 { return -EINVAL; }
 
+static inline int ipc_log_extract(void *ilctxt, char *buff, int size)
+{ return -EINVAL; }
+
 #define IPC_SPRINTF_DECODE(dctxt, args...) do { } while (0)
 
 static inline void tsv_timestamp_read(struct encode_context *ectxt,
diff --git a/arch/arm/mach-msm/include/mach/socinfo.h b/arch/arm/mach-msm/include/mach/socinfo.h
index 52102e3..830992c 100644
--- a/arch/arm/mach-msm/include/mach/socinfo.h
+++ b/arch/arm/mach-msm/include/mach/socinfo.h
@@ -32,6 +32,7 @@
 #define SOCINFO_VERSION_MINOR(ver) (ver & 0x0000ffff)
 
 #ifdef CONFIG_OF
+#define of_board_is_cdp()	of_machine_is_compatible("qcom,cdp")
 #define of_board_is_sim()	of_machine_is_compatible("qcom,sim")
 #define of_board_is_rumi()	of_machine_is_compatible("qcom,rumi")
 #define of_board_is_fluid()	of_machine_is_compatible("qcom,fluid")
diff --git a/arch/arm/mach-msm/ipc_logging.c b/arch/arm/mach-msm/ipc_logging.c
index 43214cc..bad861d 100644
--- a/arch/arm/mach-msm/ipc_logging.c
+++ b/arch/arm/mach-msm/ipc_logging.c
@@ -34,6 +34,8 @@
 static LIST_HEAD(ipc_log_context_list);
 DEFINE_RWLOCK(ipc_log_context_list_lock);
 static atomic_t next_log_id = ATOMIC_INIT(0);
+static void *get_deserialization_func(struct ipc_log_context *ilctxt,
+				      int type);
 
 static struct ipc_log_page *get_first_page(struct ipc_log_context *ilctxt)
 {
@@ -339,6 +341,59 @@
 	ipc_log_write(ilctxt, &ectxt);
 	return 0;
 }
+EXPORT_SYMBOL(ipc_log_string);
+
+/**
+ * ipc_log_extract - Reads and deserializes log
+ *
+ * @ctxt:  logging context
+ * @buff:    buffer to receive the data
+ * @size:    size of the buffer
+ * @returns: 0 if no data read; >0 number of bytes read; < 0 error
+ *
+ * If no data is available to be read, then the ilctxt::read_avail
+ * completion is reinitialized.  This allows clients to block
+ * until new log data is save.
+ */
+int ipc_log_extract(void *ctxt, char *buff, int size)
+{
+	struct encode_context ectxt;
+	struct decode_context dctxt;
+	void (*deserialize_func)(struct encode_context *ectxt,
+				 struct decode_context *dctxt);
+	struct ipc_log_context *ilctxt = (struct ipc_log_context *)ctxt;
+	unsigned long flags;
+
+	if (size < MAX_MSG_DECODED_SIZE)
+		return -EINVAL;
+
+	dctxt.output_format = OUTPUT_DEBUGFS;
+	dctxt.buff = buff;
+	dctxt.size = size;
+	read_lock_irqsave(&ipc_log_context_list_lock, flags);
+	spin_lock(&ilctxt->ipc_log_context_lock);
+	while (dctxt.size >= MAX_MSG_DECODED_SIZE &&
+	       !is_ilctxt_empty(ilctxt)) {
+		msg_read(ilctxt, &ectxt);
+		deserialize_func = get_deserialization_func(ilctxt,
+							ectxt.hdr.type);
+		spin_unlock(&ilctxt->ipc_log_context_lock);
+		read_unlock_irqrestore(&ipc_log_context_list_lock, flags);
+		if (deserialize_func)
+			deserialize_func(&ectxt, &dctxt);
+		else
+			pr_err("%s: unknown message 0x%x\n",
+				__func__, ectxt.hdr.type);
+		read_lock_irqsave(&ipc_log_context_list_lock, flags);
+		spin_lock(&ilctxt->ipc_log_context_lock);
+	}
+	if ((size - dctxt.size) == 0)
+		init_completion(&ilctxt->read_avail);
+	spin_unlock(&ilctxt->ipc_log_context_lock);
+	read_unlock_irqrestore(&ipc_log_context_list_lock, flags);
+	return size - dctxt.size;
+}
+EXPORT_SYMBOL(ipc_log_extract);
 
 /*
  * Helper funtion used to read data from a message context.
@@ -482,6 +537,21 @@
 }
 EXPORT_SYMBOL(add_deserialization_func);
 
+static void *get_deserialization_func(struct ipc_log_context *ilctxt,
+				      int type)
+{
+	struct dfunc_info *df_info = NULL;
+
+	if (!ilctxt)
+		return NULL;
+
+	list_for_each_entry(df_info, &ilctxt->dfunc_info_list, list) {
+		if (df_info->type == type)
+			return df_info->dfunc;
+	}
+	return NULL;
+}
+
 void *ipc_log_context_create(int max_num_pages,
 			     const char *mod_name)
 {
diff --git a/arch/arm/mach-msm/ipc_logging.h b/arch/arm/mach-msm/ipc_logging.h
index 36b4171..ddf194b 100644
--- a/arch/arm/mach-msm/ipc_logging.h
+++ b/arch/arm/mach-msm/ipc_logging.h
@@ -13,6 +13,8 @@
 #ifndef _IPC_LOGGING_H
 #define _IPC_LOGGING_H
 
+#include <mach/msm_ipc_logging.h>
+
 struct ipc_log_page_header {
 	uint32_t magic;
 	uint32_t nmagic; /* inverse of magic number */
@@ -64,6 +66,7 @@
 #define MIN(x, y) ((x) < (y) ? (x) : (y))
 #define IS_MSG_TYPE(x) (((x) > TSV_TYPE_MSG_START) && \
 			((x) < TSV_TYPE_MSG_END))
+#define MAX_MSG_DECODED_SIZE (MAX_MSG_SIZE*4)
 
 extern rwlock_t ipc_log_context_list_lock;
 
diff --git a/arch/arm/mach-msm/ipc_logging_debug.c b/arch/arm/mach-msm/ipc_logging_debug.c
index 246fb99..8a5957c 100644
--- a/arch/arm/mach-msm/ipc_logging_debug.c
+++ b/arch/arm/mach-msm/ipc_logging_debug.c
@@ -33,58 +33,6 @@
 
 static DEFINE_MUTEX(ipc_log_debugfs_init_lock);
 static struct dentry *root_dent;
-#define MAX_MSG_DECODED_SIZE (MAX_MSG_SIZE*4)
-
-static void *get_deserialization_func(struct ipc_log_context *ilctxt,
-				      int type)
-{
-	struct dfunc_info *df_info = NULL;
-
-	if (!ilctxt)
-		return NULL;
-
-	list_for_each_entry(df_info, &ilctxt->dfunc_info_list, list) {
-		if (df_info->type == type)
-			return df_info->dfunc;
-	}
-	return NULL;
-}
-
-static int deserialize_log(struct ipc_log_context *ilctxt,
-			   char *buff, int size)
-{
-	struct encode_context ectxt;
-	struct decode_context dctxt;
-	void (*deserialize_func)(struct encode_context *ectxt,
-				 struct decode_context *dctxt);
-	unsigned long flags;
-
-	dctxt.output_format = OUTPUT_DEBUGFS;
-	dctxt.buff = buff;
-	dctxt.size = size;
-	read_lock_irqsave(&ipc_log_context_list_lock, flags);
-	spin_lock(&ilctxt->ipc_log_context_lock);
-	while (dctxt.size >= MAX_MSG_DECODED_SIZE &&
-	       !is_ilctxt_empty(ilctxt)) {
-		msg_read(ilctxt, &ectxt);
-		deserialize_func = get_deserialization_func(ilctxt,
-							ectxt.hdr.type);
-		spin_unlock(&ilctxt->ipc_log_context_lock);
-		read_unlock_irqrestore(&ipc_log_context_list_lock, flags);
-		if (deserialize_func)
-			deserialize_func(&ectxt, &dctxt);
-		else
-			pr_err("%s: unknown message 0x%x\n",
-				__func__, ectxt.hdr.type);
-		read_lock_irqsave(&ipc_log_context_list_lock, flags);
-		spin_lock(&ilctxt->ipc_log_context_lock);
-	}
-	if ((size - dctxt.size) == 0)
-		init_completion(&ilctxt->read_avail);
-	spin_unlock(&ilctxt->ipc_log_context_lock);
-	read_unlock_irqrestore(&ipc_log_context_list_lock, flags);
-	return size - dctxt.size;
-}
 
 static int debug_log(struct ipc_log_context *ilctxt,
 		     char *buff, int size, int cont)
@@ -97,7 +45,7 @@
 		return -ENOMEM;
 	}
 	do {
-		i = deserialize_log(ilctxt, buff, size - 1);
+		i = ipc_log_extract(ilctxt, buff, size - 1);
 		if (cont && i == 0) {
 			wait_for_completion_interruptible(&ilctxt->read_avail);
 			if (signal_pending(current))
diff --git a/arch/arm/mach-msm/jtag-fuse.c b/arch/arm/mach-msm/jtag-fuse.c
new file mode 100644
index 0000000..ccefc41
--- /dev/null
+++ b/arch/arm/mach-msm/jtag-fuse.c
@@ -0,0 +1,140 @@
+/* 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/kernel.h>
+#include <linux/module.h>
+#include <linux/export.h>
+#include <linux/init.h>
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+#include <linux/err.h>
+#include <linux/slab.h>
+#include <mach/jtag.h>
+
+#define fuse_writel(drvdata, val, off)	__raw_writel((val), drvdata->base + off)
+#define fuse_readl(drvdata, off)	__raw_readl(drvdata->base + off)
+
+#define OEM_CONFIG0		(0x000)
+#define OEM_CONFIG1		(0x004)
+
+#define ALL_DEBUG_DISABLE	BIT(21)
+#define APPS_DBGEN_DISABLE	BIT(0)
+#define APPS_NIDEN_DISABLE	BIT(1)
+#define APPS_SPIDEN_DISABLE	BIT(2)
+#define APPS_SPNIDEN_DISABLE	BIT(3)
+#define DAP_DEVICEEN_DISABLE	BIT(8)
+
+struct fuse_drvdata {
+	void __iomem		*base;
+	struct device		*dev;
+};
+
+static struct fuse_drvdata *fusedrvdata;
+
+bool msm_jtag_fuse_apps_access_disabled(void)
+{
+	struct fuse_drvdata *drvdata = fusedrvdata;
+	uint32_t config0, config1;
+	bool ret;
+
+	if (!drvdata)
+		return false;
+
+	config0 = fuse_readl(drvdata, OEM_CONFIG0);
+	config1 = fuse_readl(drvdata, OEM_CONFIG1);
+
+	dev_dbg(drvdata->dev, "apps config0: %lx\n", (unsigned long)config0);
+	dev_dbg(drvdata->dev, "apps config1: %lx\n", (unsigned long)config1);
+
+	if (config0 & ALL_DEBUG_DISABLE)
+		ret = true;
+	else if (config1 & APPS_DBGEN_DISABLE)
+		ret = true;
+	else if (config1 & APPS_NIDEN_DISABLE)
+		ret = true;
+	else if (config1 & APPS_SPIDEN_DISABLE)
+		ret = true;
+	else if (config1 & APPS_SPNIDEN_DISABLE)
+		ret = true;
+	else if (config1 & DAP_DEVICEEN_DISABLE)
+		ret = true;
+	else
+		ret = false;
+
+	if (ret)
+		dev_dbg(drvdata->dev, "apps fuse disabled\n");
+
+	return ret;
+}
+EXPORT_SYMBOL(msm_jtag_fuse_apps_access_disabled);
+
+static int __devinit jtag_fuse_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct fuse_drvdata *drvdata;
+	struct resource *res;
+
+	drvdata = devm_kzalloc(dev, sizeof(*drvdata), GFP_KERNEL);
+	if (!drvdata)
+		return -ENOMEM;
+	/* Store the driver data pointer for use in exported functions */
+	fusedrvdata = drvdata;
+	drvdata->dev = &pdev->dev;
+	platform_set_drvdata(pdev, drvdata);
+
+	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "fuse-base");
+	if (!res)
+		return -ENODEV;
+
+	drvdata->base = devm_ioremap(dev, res->start, resource_size(res));
+	if (!drvdata->base)
+		return -ENOMEM;
+
+	dev_info(dev, "JTag Fuse initialized\n");
+	return 0;
+}
+
+static int __devexit jtag_fuse_remove(struct platform_device *pdev)
+{
+	return 0;
+}
+
+static struct of_device_id jtag_fuse_match[] = {
+	{.compatible = "qcom,jtag-fuse"},
+	{}
+};
+
+static struct platform_driver jtag_fuse_driver = {
+	.probe          = jtag_fuse_probe,
+	.remove         = __devexit_p(jtag_fuse_remove),
+	.driver         = {
+		.name   = "msm-jtag-fuse",
+		.owner	= THIS_MODULE,
+		.of_match_table = jtag_fuse_match,
+	},
+};
+
+static int __init jtag_fuse_init(void)
+{
+	return platform_driver_register(&jtag_fuse_driver);
+}
+arch_initcall(jtag_fuse_init);
+
+static void __exit jtag_fuse_exit(void)
+{
+	platform_driver_unregister(&jtag_fuse_driver);
+}
+module_exit(jtag_fuse_exit);
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("JTag Fuse driver");
diff --git a/arch/arm/mach-msm/jtag-mm.c b/arch/arm/mach-msm/jtag-mm.c
index 8a67614..55c5a7e 100644
--- a/arch/arm/mach-msm/jtag-mm.c
+++ b/arch/arm/mach-msm/jtag-mm.c
@@ -787,6 +787,9 @@
 	static uint32_t count;
 	struct device *dev = &pdev->dev;
 
+	if (msm_jtag_fuse_apps_access_disabled())
+		return -EPERM;
+
 	cpu = count;
 	count++;
 
diff --git a/arch/arm/mach-msm/jtag.c b/arch/arm/mach-msm/jtag.c
index 24e1c41..840449c 100644
--- a/arch/arm/mach-msm/jtag.c
+++ b/arch/arm/mach-msm/jtag.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
@@ -1105,6 +1105,9 @@
 	int ret;
 	uint32_t dbgdidr;
 
+	if (msm_jtag_fuse_apps_access_disabled())
+		return -EPERM;
+
 	/* This will run on core0 so use it to populate parameters */
 
 	/* Populate dbg_ctx data */
@@ -1146,6 +1149,9 @@
 	uint32_t etmidr;
 	uint32_t etmccr;
 
+	if (msm_jtag_fuse_apps_access_disabled())
+		return -EPERM;
+
 	/* Vote for ETM power/clock enable */
 	etm_clk_enable();
 
diff --git a/arch/arm/mach-msm/pm-8x60.c b/arch/arm/mach-msm/pm-8x60.c
index be32e82..dd0599b 100644
--- a/arch/arm/mach-msm/pm-8x60.c
+++ b/arch/arm/mach-msm/pm-8x60.c
@@ -31,7 +31,6 @@
 #include <linux/of_platform.h>
 #include <linux/regulator/krait-regulator.h>
 #include <linux/cpu.h>
-#include <linux/clk.h>
 #include <mach/msm_iomap.h>
 #include <mach/socinfo.h>
 #include <mach/system.h>
@@ -134,7 +133,6 @@
 static bool msm_no_ramp_down_pc;
 static struct msm_pm_sleep_status_data *msm_pm_slp_sts;
 static bool msm_pm_pc_reset_timer;
-static struct clk *pnoc_clk;
 
 static int msm_pm_get_pc_mode(struct device_node *node,
 		const char *key, uint32_t *pc_mode_val)
@@ -1134,24 +1132,9 @@
 		pm_sleep_ops = *ops;
 }
 
-int msm_suspend_prepare(void)
-{
-	if (pnoc_clk != NULL)
-		clk_disable_unprepare(pnoc_clk);
-	return 0;
-}
-
-void msm_suspend_wake(void)
-{
-	if (pnoc_clk != NULL)
-		clk_prepare_enable(pnoc_clk);
-}
-
 static const struct platform_suspend_ops msm_pm_ops = {
 	.enter = msm_pm_enter,
 	.valid = suspend_valid_only_mem,
-	.prepare_late = msm_suspend_prepare,
-	.wake = msm_suspend_wake,
 };
 
 static int __devinit msm_pm_snoc_client_probe(struct platform_device *pdev)
@@ -1715,18 +1698,6 @@
 		return rc;
 	}
 
-	pnoc_clk = clk_get_sys("pm_8x60", "bus_clk");
-
-	if (IS_ERR(pnoc_clk))
-		pnoc_clk = NULL;
-	else {
-		clk_set_rate(pnoc_clk, 19200000);
-		rc = clk_prepare_enable(pnoc_clk);
-
-		if (rc)
-			pr_err("%s: PNOC clock enable failed\n", __func__);
-	}
-
 	return platform_driver_register(&msm_pm_8x60_driver);
 }
 device_initcall(msm_pm_8x60_init);
diff --git a/arch/arm/mach-msm/qdsp6v2/msm_audio_ion.c b/arch/arm/mach-msm/qdsp6v2/msm_audio_ion.c
index f4c381d..0c71659 100644
--- a/arch/arm/mach-msm/qdsp6v2/msm_audio_ion.c
+++ b/arch/arm/mach-msm/qdsp6v2/msm_audio_ion.c
@@ -151,8 +151,12 @@
 		goto err_ion_handle;
 	}
 
-	if (bufsz != 0)
-		memset((void *)*vaddr, 0, bufsz);
+	*vaddr = ion_map_kernel(*client, *handle);
+	if (IS_ERR_OR_NULL((void *)*vaddr)) {
+		pr_err("%s: ION memory mapping for AUDIO failed\n", __func__);
+		goto err_ion_handle;
+	}
+	pr_debug("%s: mapped address = %p, size=%d\n", __func__, *vaddr, bufsz);
 
 	return 0;
 
diff --git a/block/blk-core.c b/block/blk-core.c
index 153240e..8e12c45 100644
--- a/block/blk-core.c
+++ b/block/blk-core.c
@@ -30,6 +30,7 @@
 #include <linux/list_sort.h>
 #include <linux/delay.h>
 #include <linux/ratelimit.h>
+#include <linux/pm_runtime.h>
 
 #define CREATE_TRACE_POINTS
 #include <trace/events/block.h>
@@ -1195,6 +1196,16 @@
 }
 EXPORT_SYMBOL_GPL(part_round_stats);
 
+#ifdef CONFIG_PM_RUNTIME
+static void blk_pm_put_request(struct request *rq)
+{
+	if (rq->q->dev && !(rq->cmd_flags & REQ_PM) && !--rq->q->nr_pending)
+		pm_runtime_mark_last_busy(rq->q->dev);
+}
+#else
+static inline void blk_pm_put_request(struct request *rq) {}
+#endif
+
 /*
  * queue lock must be held
  */
@@ -1205,6 +1216,8 @@
 	if (unlikely(--req->ref_count))
 		return;
 
+	blk_pm_put_request(req);
+
 	elv_completed_request(q, req);
 
 	/* this is a bio leak */
@@ -1981,6 +1994,28 @@
 	}
 }
 
+#ifdef CONFIG_PM_RUNTIME
+/*
+ * Don't process normal requests when queue is suspended
+ * or in the process of suspending/resuming
+ */
+static struct request *blk_pm_peek_request(struct request_queue *q,
+					   struct request *rq)
+{
+	if (q->dev && (q->rpm_status == RPM_SUSPENDED ||
+	    (q->rpm_status != RPM_ACTIVE && !(rq->cmd_flags & REQ_PM))))
+		return NULL;
+	else
+		return rq;
+}
+#else
+static inline struct request *blk_pm_peek_request(struct request_queue *q,
+						  struct request *rq)
+{
+	return rq;
+}
+#endif
+
 /**
  * blk_peek_request - peek at the top of a request queue
  * @q: request queue to peek at
@@ -2003,6 +2038,11 @@
 	int ret;
 
 	while ((rq = __elv_next_request(q)) != NULL) {
+
+		rq = blk_pm_peek_request(q, rq);
+		if (!rq)
+			break;
+
 		if (!(rq->cmd_flags & REQ_STARTED)) {
 			/*
 			 * This is the first time the device driver
@@ -2979,6 +3019,149 @@
 }
 EXPORT_SYMBOL(blk_finish_plug);
 
+#ifdef CONFIG_PM_RUNTIME
+/**
+ * blk_pm_runtime_init - Block layer runtime PM initialization routine
+ * @q: the queue of the device
+ * @dev: the device the queue belongs to
+ *
+ * Description:
+ *    Initialize runtime-PM-related fields for @q and start auto suspend for
+ *    @dev. Drivers that want to take advantage of request-based runtime PM
+ *    should call this function after @dev has been initialized, and its
+ *    request queue @q has been allocated, and runtime PM for it can not happen
+ *    yet(either due to disabled/forbidden or its usage_count > 0). In most
+ *    cases, driver should call this function before any I/O has taken place.
+ *
+ *    This function takes care of setting up using auto suspend for the device,
+ *    the autosuspend delay is set to -1 to make runtime suspend impossible
+ *    until an updated value is either set by user or by driver. Drivers do
+ *    not need to touch other autosuspend settings.
+ *
+ *    The block layer runtime PM is request based, so only works for drivers
+ *    that use request as their IO unit instead of those directly use bio's.
+ */
+void blk_pm_runtime_init(struct request_queue *q, struct device *dev)
+{
+	q->dev = dev;
+	q->rpm_status = RPM_ACTIVE;
+	pm_runtime_set_autosuspend_delay(q->dev, -1);
+	pm_runtime_use_autosuspend(q->dev);
+}
+EXPORT_SYMBOL(blk_pm_runtime_init);
+
+/**
+ * blk_pre_runtime_suspend - Pre runtime suspend check
+ * @q: the queue of the device
+ *
+ * Description:
+ *    This function will check if runtime suspend is allowed for the device
+ *    by examining if there are any requests pending in the queue. If there
+ *    are requests pending, the device can not be runtime suspended; otherwise,
+ *    the queue's status will be updated to SUSPENDING and the driver can
+ *    proceed to suspend the device.
+ *
+ *    For the not allowed case, we mark last busy for the device so that
+ *    runtime PM core will try to autosuspend it some time later.
+ *
+ *    This function should be called near the start of the device's
+ *    runtime_suspend callback.
+ *
+ * Return:
+ *    0		- OK to runtime suspend the device
+ *    -EBUSY	- Device should not be runtime suspended
+ */
+int blk_pre_runtime_suspend(struct request_queue *q)
+{
+	int ret = 0;
+
+	spin_lock_irq(q->queue_lock);
+	if (q->nr_pending) {
+		ret = -EBUSY;
+		pm_runtime_mark_last_busy(q->dev);
+	} else {
+		q->rpm_status = RPM_SUSPENDING;
+	}
+	spin_unlock_irq(q->queue_lock);
+	return ret;
+}
+EXPORT_SYMBOL(blk_pre_runtime_suspend);
+
+/**
+ * blk_post_runtime_suspend - Post runtime suspend processing
+ * @q: the queue of the device
+ * @err: return value of the device's runtime_suspend function
+ *
+ * Description:
+ *    Update the queue's runtime status according to the return value of the
+ *    device's runtime suspend function and mark last busy for the device so
+ *    that PM core will try to auto suspend the device at a later time.
+ *
+ *    This function should be called near the end of the device's
+ *    runtime_suspend callback.
+ */
+void blk_post_runtime_suspend(struct request_queue *q, int err)
+{
+	spin_lock_irq(q->queue_lock);
+	if (!err) {
+		q->rpm_status = RPM_SUSPENDED;
+	} else {
+		q->rpm_status = RPM_ACTIVE;
+		pm_runtime_mark_last_busy(q->dev);
+	}
+	spin_unlock_irq(q->queue_lock);
+}
+EXPORT_SYMBOL(blk_post_runtime_suspend);
+
+/**
+ * blk_pre_runtime_resume - Pre runtime resume processing
+ * @q: the queue of the device
+ *
+ * Description:
+ *    Update the queue's runtime status to RESUMING in preparation for the
+ *    runtime resume of the device.
+ *
+ *    This function should be called near the start of the device's
+ *    runtime_resume callback.
+ */
+void blk_pre_runtime_resume(struct request_queue *q)
+{
+	spin_lock_irq(q->queue_lock);
+	q->rpm_status = RPM_RESUMING;
+	spin_unlock_irq(q->queue_lock);
+}
+EXPORT_SYMBOL(blk_pre_runtime_resume);
+
+/**
+ * blk_post_runtime_resume - Post runtime resume processing
+ * @q: the queue of the device
+ * @err: return value of the device's runtime_resume function
+ *
+ * Description:
+ *    Update the queue's runtime status according to the return value of the
+ *    device's runtime_resume function. If it is successfully resumed, process
+ *    the requests that are queued into the device's queue when it is resuming
+ *    and then mark last busy and initiate autosuspend for it.
+ *
+ *    This function should be called near the end of the device's
+ *    runtime_resume callback.
+ */
+void blk_post_runtime_resume(struct request_queue *q, int err)
+{
+	spin_lock_irq(q->queue_lock);
+	if (!err) {
+		q->rpm_status = RPM_ACTIVE;
+		__blk_run_queue(q);
+		pm_runtime_mark_last_busy(q->dev);
+		pm_runtime_autosuspend(q->dev);
+	} else {
+		q->rpm_status = RPM_SUSPENDED;
+	}
+	spin_unlock_irq(q->queue_lock);
+}
+EXPORT_SYMBOL(blk_post_runtime_resume);
+#endif
+
 int __init blk_dev_init(void)
 {
 	BUILD_BUG_ON(__REQ_NR_BITS > 8 *
diff --git a/block/elevator.c b/block/elevator.c
index 27adf7c..44193a8 100644
--- a/block/elevator.c
+++ b/block/elevator.c
@@ -34,6 +34,7 @@
 #include <linux/blktrace_api.h>
 #include <linux/hash.h>
 #include <linux/uaccess.h>
+#include <linux/pm_runtime.h>
 
 #include <trace/events/block.h>
 
@@ -568,6 +569,27 @@
 		e->type->ops.elevator_bio_merged_fn(q, rq, bio);
 }
 
+#ifdef CONFIG_PM_RUNTIME
+static void blk_pm_requeue_request(struct request *rq)
+{
+	if (rq->q->dev && !(rq->cmd_flags & REQ_PM))
+		rq->q->nr_pending--;
+}
+
+static void blk_pm_add_request(struct request_queue *q, struct request *rq)
+{
+	if (q->dev && !(rq->cmd_flags & REQ_PM) && q->nr_pending++ == 0 &&
+	    (q->rpm_status == RPM_SUSPENDED || q->rpm_status == RPM_SUSPENDING))
+		pm_request_resume(q->dev);
+}
+#else
+static inline void blk_pm_requeue_request(struct request *rq) {}
+static inline void blk_pm_add_request(struct request_queue *q,
+				      struct request *rq)
+{
+}
+#endif
+
 void elv_requeue_request(struct request_queue *q, struct request *rq)
 {
 	/*
@@ -582,6 +604,8 @@
 
 	rq->cmd_flags &= ~REQ_STARTED;
 
+	blk_pm_requeue_request(rq);
+
 	__elv_add_request(q, rq, ELEVATOR_INSERT_REQUEUE);
 }
 
@@ -658,6 +682,8 @@
 {
 	trace_block_rq_insert(q, rq);
 
+	blk_pm_add_request(q, rq);
+
 	rq->q = q;
 
 	if (rq->cmd_flags & REQ_SOFTBARRIER) {
diff --git a/block/test-iosched.c b/block/test-iosched.c
index b1e5492..07b36b8 100644
--- a/block/test-iosched.c
+++ b/block/test-iosched.c
@@ -101,8 +101,8 @@
 		goto exit;
 	}
 
-	ptd->test_info.test_duration = jiffies -
-				ptd->test_info.test_duration;
+	ptd->test_info.test_duration = ktime_sub(ktime_get(),
+				ptd->test_info.test_duration);
 
 	test_pr_info("%s: Test is completed, test_count=%d, reinsert_count=%d,",
 			__func__, ptd->test_count, ptd->reinsert_count);
@@ -774,7 +774,7 @@
 			goto error;
 		}
 
-		ptd->test_info.test_duration = jiffies;
+		ptd->test_info.test_duration = ktime_get();
 		ret = run_test(ptd);
 		if (ret) {
 			test_pr_err("%s: failed to run the test\n", __func__);
@@ -784,10 +784,10 @@
 		test_pr_info("%s: Waiting for the test completion", __func__);
 
 		wait_event(ptd->wait_q, ptd->test_state == TEST_COMPLETED);
-		t_info->test_duration = ptd->test_info.test_duration;
-		t_info->test_byte_count = ptd->test_info.test_byte_count;
 		del_timer_sync(&ptd->timeout_timer);
 
+		memcpy(t_info, &ptd->test_info, sizeof(struct test_info));
+
 		ret = check_test_result(ptd);
 		if (ret) {
 			test_pr_err("%s: check_test_result failed\n",
diff --git a/drivers/char/diag/diag_dci.c b/drivers/char/diag/diag_dci.c
index 1af9399..d01496e 100644
--- a/drivers/char/diag/diag_dci.c
+++ b/drivers/char/diag/diag_dci.c
@@ -515,6 +515,7 @@
 
 	if (!temp) {
 		pr_err("diag: Invalid buffer in %s\n", __func__);
+		return -ENOMEM;
 	}
 
 	/* This is Pkt request/response transaction */
diff --git a/drivers/char/diag/diagmem.c b/drivers/char/diag/diagmem.c
index f22b4c2..a6ef3ca 100644
--- a/drivers/char/diag/diagmem.c
+++ b/drivers/char/diag/diagmem.c
@@ -151,8 +151,9 @@
 		if (diag_hsic[index].diag_hsic_pool &&
 				(diag_hsic[index].hsic_inited == 0)) {
 			if (diag_hsic[index].count_hsic_pool == 0) {
-				mempool_destroy(driver->diag_hdlc_pool);
-				driver->diag_hdlc_pool = NULL;
+				mempool_destroy(
+					diag_hsic[index].diag_hsic_pool);
+				diag_hsic[index].diag_hsic_pool = NULL;
 			} else if (pool_type == POOL_TYPE_ALL)
 				pr_err("Unable to destroy HDLC mempool for ch %d"
 								, index);
diff --git a/drivers/coresight/Kconfig b/drivers/coresight/Kconfig
index 7ec83dd..5e2acfb 100644
--- a/drivers/coresight/Kconfig
+++ b/drivers/coresight/Kconfig
@@ -24,6 +24,15 @@
 config HAVE_CORESIGHT_SINK
 	bool
 
+config CORESIGHT_FUSE
+	bool "CoreSight Fuse driver"
+	help
+	  This driver provides support for CoreSight Fuse state checks that
+	  other CoreSight drivers can query to determine existence of
+	  Hardware functionality they support. Drivers can then take necessary
+	  actions like failing the probe if the Hardware they manage is
+	  functionally disabled.
+
 config CORESIGHT_CTI
 	bool "CoreSight Cross Trigger Interface driver"
 	help
diff --git a/drivers/coresight/Makefile b/drivers/coresight/Makefile
index 2b14f86..23352a7 100644
--- a/drivers/coresight/Makefile
+++ b/drivers/coresight/Makefile
@@ -2,6 +2,7 @@
 # Makefile for CoreSight drivers.
 #
 obj-$(CONFIG_CORESIGHT) += coresight.o
+obj-$(CONFIG_CORESIGHT_FUSE) += coresight-fuse.o
 obj-$(CONFIG_CORESIGHT_CTI) += coresight-cti.o
 obj-$(CONFIG_CORESIGHT_CSR) += coresight-csr.o
 obj-$(CONFIG_CORESIGHT_TMC) += coresight-tmc.o
diff --git a/drivers/coresight/coresight-csr.c b/drivers/coresight/coresight-csr.c
index 8195184..132df90 100644
--- a/drivers/coresight/coresight-csr.c
+++ b/drivers/coresight/coresight-csr.c
@@ -168,6 +168,9 @@
 	struct resource *res;
 	struct coresight_desc *desc;
 
+	if (coresight_fuse_access_disabled())
+		return -EPERM;
+
 	if (pdev->dev.of_node) {
 		pdata = of_get_coresight_platform_data(dev, pdev->dev.of_node);
 		if (IS_ERR(pdata))
diff --git a/drivers/coresight/coresight-cti.c b/drivers/coresight/coresight-cti.c
index 6a8d412..d0900d1 100644
--- a/drivers/coresight/coresight-cti.c
+++ b/drivers/coresight/coresight-cti.c
@@ -388,6 +388,9 @@
 	struct resource *res;
 	struct coresight_desc *desc;
 
+	if (coresight_fuse_access_disabled())
+		return -EPERM;
+
 	if (pdev->dev.of_node) {
 		pdata = of_get_coresight_platform_data(dev, pdev->dev.of_node);
 		if (IS_ERR(pdata))
diff --git a/drivers/coresight/coresight-etb.c b/drivers/coresight/coresight-etb.c
index 31f85dc..473b4cb 100644
--- a/drivers/coresight/coresight-etb.c
+++ b/drivers/coresight/coresight-etb.c
@@ -362,6 +362,9 @@
 	struct resource *res;
 	struct coresight_desc *desc;
 
+	if (coresight_fuse_access_disabled())
+		return -EPERM;
+
 	if (pdev->dev.of_node) {
 		pdata = of_get_coresight_platform_data(dev, pdev->dev.of_node);
 		if (IS_ERR(pdata))
diff --git a/drivers/coresight/coresight-etm.c b/drivers/coresight/coresight-etm.c
index de86622..52f3027 100644
--- a/drivers/coresight/coresight-etm.c
+++ b/drivers/coresight/coresight-etm.c
@@ -2113,6 +2113,10 @@
 	struct msm_client_dump dump;
 	struct coresight_desc *desc;
 
+	if (coresight_fuse_access_disabled() ||
+	    coresight_fuse_apps_access_disabled())
+		return -EPERM;
+
 	if (pdev->dev.of_node) {
 		pdata = of_get_coresight_platform_data(dev, pdev->dev.of_node);
 		if (IS_ERR(pdata))
diff --git a/drivers/coresight/coresight-funnel.c b/drivers/coresight/coresight-funnel.c
index 625f481..771321d 100644
--- a/drivers/coresight/coresight-funnel.c
+++ b/drivers/coresight/coresight-funnel.c
@@ -174,6 +174,9 @@
 	struct resource *res;
 	struct coresight_desc *desc;
 
+	if (coresight_fuse_access_disabled())
+		return -EPERM;
+
 	if (pdev->dev.of_node) {
 		pdata = of_get_coresight_platform_data(dev, pdev->dev.of_node);
 		if (IS_ERR(pdata))
diff --git a/drivers/coresight/coresight-fuse.c b/drivers/coresight/coresight-fuse.c
new file mode 100644
index 0000000..7af5c6c8
--- /dev/null
+++ b/drivers/coresight/coresight-fuse.c
@@ -0,0 +1,202 @@
+/* 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/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+#include <linux/err.h>
+#include <linux/slab.h>
+#include <linux/of.h>
+#include <linux/of_coresight.h>
+#include <linux/coresight.h>
+
+#include "coresight-priv.h"
+
+#define fuse_writel(drvdata, val, off)	__raw_writel((val), drvdata->base + off)
+#define fuse_readl(drvdata, off)	__raw_readl(drvdata->base + off)
+
+#define OEM_CONFIG0		(0x000)
+#define OEM_CONFIG1		(0x004)
+
+#define ALL_DEBUG_DISABLE	BIT(21)
+#define APPS_DBGEN_DISABLE	BIT(0)
+#define APPS_NIDEN_DISABLE	BIT(1)
+#define APPS_SPIDEN_DISABLE	BIT(2)
+#define APPS_SPNIDEN_DISABLE	BIT(3)
+#define DAP_DBGEN_DISABLE	BIT(4)
+#define DAP_NIDEN_DISABLE	BIT(5)
+#define DAP_SPIDEN_DISABLE	BIT(6)
+#define DAP_SPNIDEN_DISABLE	BIT(7)
+#define DAP_DEVICEEN_DISABLE	BIT(8)
+
+struct fuse_drvdata {
+	void __iomem		*base;
+	struct device		*dev;
+	struct coresight_device	*csdev;
+};
+
+static struct fuse_drvdata *fusedrvdata;
+
+bool coresight_fuse_access_disabled(void)
+{
+	struct fuse_drvdata *drvdata = fusedrvdata;
+	uint32_t config0, config1;
+	bool ret;
+
+	config0 = fuse_readl(drvdata, OEM_CONFIG0);
+	config1 = fuse_readl(drvdata, OEM_CONFIG1);
+
+	dev_dbg(drvdata->dev, "config0: %lx\n", (unsigned long)config0);
+	dev_dbg(drvdata->dev, "config1: %lx\n", (unsigned long)config1);
+
+	if (config0 & ALL_DEBUG_DISABLE)
+		ret = true;
+	else if (config1 & DAP_DBGEN_DISABLE)
+		ret = true;
+	else if (config1 & DAP_NIDEN_DISABLE)
+		ret = true;
+	else if (config1 & DAP_SPIDEN_DISABLE)
+		ret = true;
+	else if (config1 & DAP_SPNIDEN_DISABLE)
+		ret = true;
+	else if (config1 & DAP_DEVICEEN_DISABLE)
+		ret = true;
+	else
+		ret = false;
+
+	if (ret)
+		dev_dbg(drvdata->dev, "coresight fuse disabled\n");
+
+	return ret;
+}
+EXPORT_SYMBOL(coresight_fuse_access_disabled);
+
+bool coresight_fuse_apps_access_disabled(void)
+{
+	struct fuse_drvdata *drvdata = fusedrvdata;
+	uint32_t config0, config1;
+	bool ret;
+
+	config0 = fuse_readl(drvdata, OEM_CONFIG0);
+	config1 = fuse_readl(drvdata, OEM_CONFIG1);
+
+	dev_dbg(drvdata->dev, "apps config0: %lx\n", (unsigned long)config0);
+	dev_dbg(drvdata->dev, "apps config1: %lx\n", (unsigned long)config1);
+
+	if (config0 & ALL_DEBUG_DISABLE)
+		ret = true;
+	else if (config1 & APPS_DBGEN_DISABLE)
+		ret = true;
+	else if (config1 & APPS_NIDEN_DISABLE)
+		ret = true;
+	else if (config1 & APPS_SPIDEN_DISABLE)
+		ret = true;
+	else if (config1 & APPS_SPNIDEN_DISABLE)
+		ret = true;
+	else if (config1 & DAP_DEVICEEN_DISABLE)
+		ret = true;
+	else
+		ret = false;
+
+	if (ret)
+		dev_dbg(drvdata->dev, "apps fuse disabled\n");
+
+	return ret;
+}
+EXPORT_SYMBOL(coresight_fuse_apps_access_disabled);
+
+static int __devinit fuse_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct coresight_platform_data *pdata;
+	struct fuse_drvdata *drvdata;
+	struct resource *res;
+	struct coresight_desc *desc;
+
+	if (pdev->dev.of_node) {
+		pdata = of_get_coresight_platform_data(dev, pdev->dev.of_node);
+		if (IS_ERR(pdata))
+			return PTR_ERR(pdata);
+		pdev->dev.platform_data = pdata;
+	}
+
+	drvdata = devm_kzalloc(dev, sizeof(*drvdata), GFP_KERNEL);
+	if (!drvdata)
+		return -ENOMEM;
+	/* Store the driver data pointer for use in exported functions */
+	fusedrvdata = drvdata;
+	drvdata->dev = &pdev->dev;
+	platform_set_drvdata(pdev, drvdata);
+
+	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "fuse-base");
+	if (!res)
+		return -ENODEV;
+
+	drvdata->base = devm_ioremap(dev, res->start, resource_size(res));
+	if (!drvdata->base)
+		return -ENOMEM;
+
+	desc = devm_kzalloc(dev, sizeof(*desc), GFP_KERNEL);
+	if (!desc)
+		return -ENOMEM;
+	desc->type = CORESIGHT_DEV_TYPE_NONE;
+	desc->pdata = pdev->dev.platform_data;
+	desc->dev = &pdev->dev;
+	desc->owner = THIS_MODULE;
+	drvdata->csdev = coresight_register(desc);
+	if (IS_ERR(drvdata->csdev))
+		return PTR_ERR(drvdata->csdev);
+
+	dev_info(dev, "Fuse initialized\n");
+	return 0;
+}
+
+static int __devexit fuse_remove(struct platform_device *pdev)
+{
+	struct fuse_drvdata *drvdata = platform_get_drvdata(pdev);
+
+	coresight_unregister(drvdata->csdev);
+	return 0;
+}
+
+static struct of_device_id fuse_match[] = {
+	{.compatible = "arm,coresight-fuse"},
+	{}
+};
+
+static struct platform_driver fuse_driver = {
+	.probe          = fuse_probe,
+	.remove         = __devexit_p(fuse_remove),
+	.driver         = {
+		.name   = "coresight-fuse",
+		.owner	= THIS_MODULE,
+		.of_match_table = fuse_match,
+	},
+};
+
+static int __init fuse_init(void)
+{
+	return platform_driver_register(&fuse_driver);
+}
+module_init(fuse_init);
+
+static void __exit fuse_exit(void)
+{
+	platform_driver_unregister(&fuse_driver);
+}
+module_exit(fuse_exit);
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("CoreSight Fuse driver");
diff --git a/drivers/coresight/coresight-hwevent.c b/drivers/coresight/coresight-hwevent.c
index 777484d..269d56e 100644
--- a/drivers/coresight/coresight-hwevent.c
+++ b/drivers/coresight/coresight-hwevent.c
@@ -211,6 +211,9 @@
 	int ret, i;
 	const char *hmux_name, *hclk_name;
 
+	if (coresight_fuse_access_disabled())
+		return -EPERM;
+
 	if (pdev->dev.of_node) {
 		pdata = of_get_coresight_platform_data(dev, pdev->dev.of_node);
 		if (IS_ERR(pdata))
diff --git a/drivers/coresight/coresight-priv.h b/drivers/coresight/coresight-priv.h
index f208185..b570252 100644
--- a/drivers/coresight/coresight-priv.h
+++ b/drivers/coresight/coresight-priv.h
@@ -36,6 +36,13 @@
 #define BMVAL(val, lsb, msb)	((val & BM(lsb, msb)) >> lsb)
 #define BVAL(val, n)		((val & BIT(n)) >> n)
 
+#ifdef CONFIG_CORESIGHT_FUSE
+extern bool coresight_fuse_access_disabled(void);
+extern bool coresight_fuse_apps_access_disabled(void);
+#else
+static inline bool coresight_fuse_access_disabled(void) { return false; }
+static inline bool coresight_fuse_apps_access_disabled(void) { return false; }
+#endif
 #ifdef CONFIG_CORESIGHT_CSR
 extern void msm_qdss_csr_enable_bam_to_usb(void);
 extern void msm_qdss_csr_disable_bam_to_usb(void);
diff --git a/drivers/coresight/coresight-replicator.c b/drivers/coresight/coresight-replicator.c
index d4afa42..9f70dc7 100644
--- a/drivers/coresight/coresight-replicator.c
+++ b/drivers/coresight/coresight-replicator.c
@@ -126,6 +126,9 @@
 	struct resource *res;
 	struct coresight_desc *desc;
 
+	if (coresight_fuse_access_disabled())
+		return -EPERM;
+
 	if (pdev->dev.of_node) {
 		pdata = of_get_coresight_platform_data(dev, pdev->dev.of_node);
 		if (IS_ERR(pdata))
diff --git a/drivers/coresight/coresight-stm.c b/drivers/coresight/coresight-stm.c
index 7d4dabe..085f721 100644
--- a/drivers/coresight/coresight-stm.c
+++ b/drivers/coresight/coresight-stm.c
@@ -791,6 +791,9 @@
 	size_t res_size, bitmap_size;
 	struct coresight_desc *desc;
 
+	if (coresight_fuse_access_disabled())
+		return -EPERM;
+
 	if (pdev->dev.of_node) {
 		pdata = of_get_coresight_platform_data(dev, pdev->dev.of_node);
 		if (IS_ERR(pdata))
diff --git a/drivers/coresight/coresight-tmc.c b/drivers/coresight/coresight-tmc.c
index f39334a..4186abe 100644
--- a/drivers/coresight/coresight-tmc.c
+++ b/drivers/coresight/coresight-tmc.c
@@ -1134,6 +1134,9 @@
 	struct coresight_cti_data *ctidata;
 	struct coresight_desc *desc;
 
+	if (coresight_fuse_access_disabled())
+		return -EPERM;
+
 	if (pdev->dev.of_node) {
 		pdata = of_get_coresight_platform_data(dev, pdev->dev.of_node);
 		if (IS_ERR(pdata))
diff --git a/drivers/coresight/coresight-tpiu.c b/drivers/coresight/coresight-tpiu.c
index 53df0f9..032327c 100644
--- a/drivers/coresight/coresight-tpiu.c
+++ b/drivers/coresight/coresight-tpiu.c
@@ -717,6 +717,9 @@
 	struct resource *res;
 	struct coresight_desc *desc;
 
+	if (coresight_fuse_access_disabled())
+		return -EPERM;
+
 	if (pdev->dev.of_node) {
 		pdata = of_get_coresight_platform_data(dev, pdev->dev.of_node);
 		if (IS_ERR(pdata))
diff --git a/drivers/cpufreq/cpufreq_ondemand.c b/drivers/cpufreq/cpufreq_ondemand.c
index 2fd8bef..96e759b 100644
--- a/drivers/cpufreq/cpufreq_ondemand.c
+++ b/drivers/cpufreq/cpufreq_ondemand.c
@@ -610,6 +610,9 @@
 				if (dbs_info->cur_policy) {
 					/* restart dbs timer */
 					dbs_timer_init(dbs_info);
+					/* Enable frequency synchronization
+					 * of CPUs */
+					atomic_set(&dbs_info->sync_enabled, 1);
 				}
 skip_this_cpu:
 				unlock_policy_rwsem_write(cpu);
@@ -639,15 +642,19 @@
 
 			if (dbs_info->cur_policy) {
 				/* cpu using ondemand, cancel dbs timer */
-				mutex_lock(&dbs_info->timer_mutex);
 				dbs_timer_exit(dbs_info);
+				/* Disable frequency synchronization of
+				 * CPUs to avoid re-queueing of work from
+				 * sync_thread */
+				atomic_set(&dbs_info->sync_enabled, 0);
 
+				mutex_lock(&dbs_info->timer_mutex);
 				ondemand_powersave_bias_setspeed(
 					dbs_info->cur_policy,
 					NULL,
 					input);
-
 				mutex_unlock(&dbs_info->timer_mutex);
+
 			}
 skip_this_cpu_bypass:
 			unlock_policy_rwsem_write(cpu);
@@ -1075,18 +1082,6 @@
 
 		get_online_cpus();
 
-		/* TODO: cur_policy is currently set for all CPUs when
-		 * a policy is started but cleared only on the current
-		 * CPU when the policy is stopped. If/when this is
-		 * resolved, sync_enabled can be removed and
-		 * cur_policy can be used instead.
-		 */
-		if (!atomic_read(&this_dbs_info->sync_enabled)) {
-			atomic_set(&this_dbs_info->src_sync_cpu, -1);
-			put_online_cpus();
-			continue;
-		}
-
 		src_cpu = atomic_read(&this_dbs_info->src_sync_cpu);
 		src_dbs_info = &per_cpu(od_cpu_dbs_info, src_cpu);
 		if (src_dbs_info != NULL &&
@@ -1101,6 +1096,13 @@
 		if (lock_policy_rwsem_write(cpu) < 0)
 			goto bail_acq_sema_failed;
 
+		if (!atomic_read(&this_dbs_info->sync_enabled)) {
+			atomic_set(&this_dbs_info->src_sync_cpu, -1);
+			put_online_cpus();
+			unlock_policy_rwsem_write(cpu);
+			continue;
+		}
+
 		policy = this_dbs_info->cur_policy;
 		if (!policy) {
 			/* CPU not using ondemand governor */
@@ -1238,7 +1240,8 @@
 						kcpustat_cpu(j).cpustat[CPUTIME_NICE];
 			set_cpus_allowed(j_dbs_info->sync_thread,
 					 *cpumask_of(j));
-			atomic_set(&j_dbs_info->sync_enabled, 1);
+			if (!dbs_tuners_ins.powersave_bias)
+				atomic_set(&j_dbs_info->sync_enabled, 1);
 		}
 		this_dbs_info->cpu = cpu;
 		this_dbs_info->rate_mult = 1;
diff --git a/drivers/gpu/msm/adreno.c b/drivers/gpu/msm/adreno.c
index da453a5..95eabcd 100644
--- a/drivers/gpu/msm/adreno.c
+++ b/drivers/gpu/msm/adreno.c
@@ -256,7 +256,9 @@
 		/* countable iter */
 		for (j = 0; j < group->reg_count; j++) {
 			if (group->regs[j].countable ==
-					KGSL_PERFCOUNTER_NOT_USED)
+					KGSL_PERFCOUNTER_NOT_USED ||
+					group->regs[j].countable ==
+					KGSL_PERFCOUNTER_BROKEN)
 				continue;
 
 			if (adreno_dev->gpudev->perfcounter_enable)
@@ -1041,9 +1043,9 @@
 	if (pdata->chipid != 0)
 		return pdata->chipid;
 
-	adreno_regread(device, REG_RBBM_PERIPHID1, &coreid);
-	adreno_regread(device, REG_RBBM_PERIPHID2, &majorid);
-	adreno_regread(device, REG_RBBM_PATCH_RELEASE, &revid);
+	kgsl_regread(device, REG_RBBM_PERIPHID1, &coreid);
+	kgsl_regread(device, REG_RBBM_PERIPHID2, &majorid);
+	kgsl_regread(device, REG_RBBM_PATCH_RELEASE, &revid);
 
 	/*
 	* adreno 22x gpus are indicated by coreid 2,
@@ -3136,6 +3138,7 @@
 	return memdesc ? kgsl_gpuaddr_to_vaddr(memdesc, gpuaddr) : NULL;
 }
 
+
 /**
  * adreno_read - General read function to read adreno device memory
  * @device - Pointer to the GPU device struct (for adreno device)
@@ -3168,7 +3171,7 @@
  * @offsetwords - Word (4 Bytes) offset to the register to be read
  * @value - Value read from device register
  */
-void adreno_regread(struct kgsl_device *device, unsigned int offsetwords,
+static void adreno_regread(struct kgsl_device *device, unsigned int offsetwords,
 	unsigned int *value)
 {
 	adreno_read(device, device->reg_virt, offsetwords, value,
@@ -3188,7 +3191,8 @@
 					device->shader_mem_len);
 }
 
-void adreno_regwrite(struct kgsl_device *device, unsigned int offsetwords,
+static void adreno_regwrite(struct kgsl_device *device,
+				unsigned int offsetwords,
 				unsigned int value)
 {
 	unsigned int *reg;
@@ -3394,7 +3398,7 @@
 	for (i = 0; i < FT_DETECT_REGS_COUNT; i++) {
 		if (ft_detect_regs[i] == 0)
 			continue;
-		adreno_regread(device, ft_detect_regs[i],
+		kgsl_regread(device, ft_detect_regs[i],
 			&curr_reg_val[i]);
 	}
 
diff --git a/drivers/gpu/msm/adreno.h b/drivers/gpu/msm/adreno.h
index 27e72d9..b53d16f 100644
--- a/drivers/gpu/msm/adreno.h
+++ b/drivers/gpu/msm/adreno.h
@@ -373,10 +373,6 @@
 int adreno_coresight_init(struct platform_device *pdev);
 
 int adreno_idle(struct kgsl_device *device);
-void adreno_regread(struct kgsl_device *device, unsigned int offsetwords,
-				unsigned int *value);
-void adreno_regwrite(struct kgsl_device *device, unsigned int offsetwords,
-				unsigned int value);
 
 void adreno_shadermem_regread(struct kgsl_device *device,
 						unsigned int offsetwords,
@@ -664,7 +660,7 @@
 {
 	struct kgsl_device *device = &adreno_dev->dev;
 	if (adreno_checkreg_off(adreno_dev, offset_name))
-		adreno_regread(device,
+		kgsl_regread(device,
 			adreno_dev->gpudev->reg_offsets->offsets[offset_name],
 								val);
 }
@@ -681,7 +677,7 @@
 {
 	struct kgsl_device *device = &adreno_dev->dev;
 	if (adreno_checkreg_off(adreno_dev, offset_name))
-		adreno_regwrite(device,
+		kgsl_regwrite(device,
 		adreno_dev->gpudev->reg_offsets->offsets[offset_name], val);
 }
 
diff --git a/drivers/gpu/msm/adreno_a2xx.c b/drivers/gpu/msm/adreno_a2xx.c
index 1fcd600..42137fe 100644
--- a/drivers/gpu/msm/adreno_a2xx.c
+++ b/drivers/gpu/msm/adreno_a2xx.c
@@ -1707,11 +1707,11 @@
 	struct adreno_ringbuffer *rb = &adreno_dev->ringbuffer;
 	int i;
 
-	adreno_regread(device, REG_MASTER_INT_SIGNAL, &master_status);
+	kgsl_regread(device, REG_MASTER_INT_SIGNAL, &master_status);
 	while (!status && (num_reads < VALID_STATUS_COUNT_MAX) &&
 		(master_status & MASTER_INT_SIGNAL__CP_INT_STAT)) {
-		adreno_regread(device, REG_CP_INT_STATUS, &status);
-		adreno_regread(device, REG_MASTER_INT_SIGNAL,
+		kgsl_regread(device, REG_CP_INT_STATUS, &status);
+		kgsl_regread(device, REG_MASTER_INT_SIGNAL,
 					&master_status);
 		num_reads++;
 	}
@@ -1752,7 +1752,7 @@
 
 	/* only ack bits we understand */
 	status &= CP_INT_MASK;
-	adreno_regwrite(device, REG_CP_INT_ACK, status);
+	kgsl_regwrite(device, REG_CP_INT_ACK, status);
 
 	if (status & (CP_INT_CNTL__IB1_INT_MASK | CP_INT_CNTL__RB_INT_MASK)) {
 		queue_work(device->work_queue, &device->ts_expired_ws);
@@ -1767,10 +1767,10 @@
 	unsigned int addr = 0;
 	const char *source;
 
-	adreno_regread(device, REG_RBBM_INT_STATUS, &status);
+	kgsl_regread(device, REG_RBBM_INT_STATUS, &status);
 
 	if (status & RBBM_INT_CNTL__RDERR_INT_MASK) {
-		adreno_regread(device, REG_RBBM_READ_ERROR, &rderr);
+		kgsl_regread(device, REG_RBBM_READ_ERROR, &rderr);
 		source = (rderr & RBBM_READ_ERROR_REQUESTER)
 			 ? "host" : "cp";
 		/* convert to dword address */
@@ -1794,7 +1794,7 @@
 	}
 
 	status &= RBBM_INT_MASK;
-	adreno_regwrite(device, REG_RBBM_INT_ACK, status);
+	kgsl_regwrite(device, REG_RBBM_INT_ACK, status);
 }
 
 irqreturn_t a2xx_irq_handler(struct adreno_device *adreno_dev)
@@ -1803,7 +1803,7 @@
 	irqreturn_t result = IRQ_NONE;
 	unsigned int status;
 
-	adreno_regread(device, REG_MASTER_INT_SIGNAL, &status);
+	kgsl_regread(device, REG_MASTER_INT_SIGNAL, &status);
 
 	if (status & MASTER_INT_SIGNAL__MH_INT_STAT) {
 		kgsl_mh_intrcallback(device);
@@ -1828,14 +1828,14 @@
 	struct kgsl_device *device = &adreno_dev->dev;
 
 	if (state) {
-		adreno_regwrite(device, REG_RBBM_INT_CNTL, RBBM_INT_MASK);
-		adreno_regwrite(device, REG_CP_INT_CNTL, CP_INT_MASK);
-		adreno_regwrite(device, MH_INTERRUPT_MASK,
+		kgsl_regwrite(device, REG_RBBM_INT_CNTL, RBBM_INT_MASK);
+		kgsl_regwrite(device, REG_CP_INT_CNTL, CP_INT_MASK);
+		kgsl_regwrite(device, MH_INTERRUPT_MASK,
 			kgsl_mmu_get_int_mask());
 	} else {
-		adreno_regwrite(device, REG_RBBM_INT_CNTL, 0);
-		adreno_regwrite(device, REG_CP_INT_CNTL, 0);
-		adreno_regwrite(device, MH_INTERRUPT_MASK, 0);
+		kgsl_regwrite(device, REG_RBBM_INT_CNTL, 0);
+		kgsl_regwrite(device, REG_CP_INT_CNTL, 0);
+		kgsl_regwrite(device, MH_INTERRUPT_MASK, 0);
 	}
 
 	/* Force the writes to post before touching the IRQ line */
@@ -1847,7 +1847,7 @@
 	struct kgsl_device *device = &adreno_dev->dev;
 	unsigned int status;
 
-	adreno_regread(device, REG_MASTER_INT_SIGNAL, &status);
+	kgsl_regread(device, REG_MASTER_INT_SIGNAL, &status);
 
 	return (status &
 		(MASTER_INT_SIGNAL__MH_INT_STAT |
@@ -1929,21 +1929,21 @@
 	unsigned int reg, val;
 
 	/* Freeze the counter */
-	adreno_regwrite(device, REG_CP_PERFMON_CNTL,
+	kgsl_regwrite(device, REG_CP_PERFMON_CNTL,
 		REG_PERF_MODE_CNT | REG_PERF_STATE_FREEZE);
 
 	/* Get the value */
-	adreno_regread(device, REG_RBBM_PERFCOUNTER1_LO, &val);
+	kgsl_regread(device, REG_RBBM_PERFCOUNTER1_LO, &val);
 
 	/* Reset the counter */
-	adreno_regwrite(device, REG_CP_PERFMON_CNTL,
+	kgsl_regwrite(device, REG_CP_PERFMON_CNTL,
 		REG_PERF_MODE_CNT | REG_PERF_STATE_RESET);
 
 	/* Re-Enable the performance monitors */
-	adreno_regread(device, REG_RBBM_PM_OVERRIDE2, &reg);
-	adreno_regwrite(device, REG_RBBM_PM_OVERRIDE2, (reg | 0x40));
-	adreno_regwrite(device, REG_RBBM_PERFCOUNTER1_SELECT, 0x1);
-	adreno_regwrite(device, REG_CP_PERFMON_CNTL,
+	kgsl_regread(device, REG_RBBM_PM_OVERRIDE2, &reg);
+	kgsl_regwrite(device, REG_RBBM_PM_OVERRIDE2, (reg | 0x40));
+	kgsl_regwrite(device, REG_RBBM_PERFCOUNTER1_SELECT, 0x1);
+	kgsl_regwrite(device, REG_CP_PERFMON_CNTL,
 		REG_PERF_MODE_CNT | REG_PERF_STATE_ENABLE);
 
 	return val;
@@ -1969,7 +1969,7 @@
 	/* must be aligned to size */
 	rb_edram_info.f.edram_range = (adreno_dev->gmem_base >> 14);
 
-	adreno_regwrite(device, REG_RB_EDRAM_INFO, rb_edram_info.val);
+	kgsl_regwrite(device, REG_RB_EDRAM_INFO, rb_edram_info.val);
 }
 
 static void a2xx_start(struct adreno_device *adreno_dev)
@@ -1981,8 +1981,8 @@
 	 * before issuing a soft reset.  The overrides will then be
 	 * turned off (set to 0)
 	 */
-	adreno_regwrite(device, REG_RBBM_PM_OVERRIDE1, 0xfffffffe);
-	adreno_regwrite(device, REG_RBBM_PM_OVERRIDE2, 0xffffffff);
+	kgsl_regwrite(device, REG_RBBM_PM_OVERRIDE1, 0xfffffffe);
+	kgsl_regwrite(device, REG_RBBM_PM_OVERRIDE2, 0xffffffff);
 
 	/*
 	 * Only reset CP block if all blocks have previously been
@@ -1990,11 +1990,11 @@
 	 */
 	if (!(device->flags & KGSL_FLAGS_SOFT_RESET) ||
 		!adreno_is_a22x(adreno_dev)) {
-		adreno_regwrite(device, REG_RBBM_SOFT_RESET,
+		kgsl_regwrite(device, REG_RBBM_SOFT_RESET,
 			0xFFFFFFFF);
 		device->flags |= KGSL_FLAGS_SOFT_RESET;
 	} else {
-		adreno_regwrite(device, REG_RBBM_SOFT_RESET,
+		kgsl_regwrite(device, REG_RBBM_SOFT_RESET,
 			0x00000001);
 	}
 	/*
@@ -2003,11 +2003,11 @@
 	 */
 	msleep(30);
 
-	adreno_regwrite(device, REG_RBBM_SOFT_RESET, 0x00000000);
+	kgsl_regwrite(device, REG_RBBM_SOFT_RESET, 0x00000000);
 
 	if (adreno_is_a225(adreno_dev)) {
 		/* Enable large instruction store for A225 */
-		adreno_regwrite(device, REG_SQ_FLOW_CONTROL,
+		kgsl_regwrite(device, REG_SQ_FLOW_CONTROL,
 			0x18000000);
 	}
 
@@ -2015,29 +2015,29 @@
 		/* For A20X based targets increase number of clocks
 		 * that RBBM will wait before de-asserting Register
 		 * Clock Active signal */
-		adreno_regwrite(device, REG_RBBM_CNTL, 0x0000FFFF);
+		kgsl_regwrite(device, REG_RBBM_CNTL, 0x0000FFFF);
 	else
-		adreno_regwrite(device, REG_RBBM_CNTL, 0x00004442);
+		kgsl_regwrite(device, REG_RBBM_CNTL, 0x00004442);
 
-	adreno_regwrite(device, REG_SQ_VS_PROGRAM, 0x00000000);
-	adreno_regwrite(device, REG_SQ_PS_PROGRAM, 0x00000000);
+	kgsl_regwrite(device, REG_SQ_VS_PROGRAM, 0x00000000);
+	kgsl_regwrite(device, REG_SQ_PS_PROGRAM, 0x00000000);
 
 	if (cpu_is_msm8960())
-		adreno_regwrite(device, REG_RBBM_PM_OVERRIDE1, 0x200);
+		kgsl_regwrite(device, REG_RBBM_PM_OVERRIDE1, 0x200);
 	else
-		adreno_regwrite(device, REG_RBBM_PM_OVERRIDE1, 0);
+		kgsl_regwrite(device, REG_RBBM_PM_OVERRIDE1, 0);
 
 	if (!adreno_is_a22x(adreno_dev))
-		adreno_regwrite(device, REG_RBBM_PM_OVERRIDE2, 0);
+		kgsl_regwrite(device, REG_RBBM_PM_OVERRIDE2, 0);
 	else
-		adreno_regwrite(device, REG_RBBM_PM_OVERRIDE2, 0x80);
+		kgsl_regwrite(device, REG_RBBM_PM_OVERRIDE2, 0x80);
 
-	adreno_regwrite(device, REG_RBBM_DEBUG, 0x00080000);
+	kgsl_regwrite(device, REG_RBBM_DEBUG, 0x00080000);
 
 	/* Make sure interrupts are disabled */
-	adreno_regwrite(device, REG_RBBM_INT_CNTL, 0);
-	adreno_regwrite(device, REG_CP_INT_CNTL, 0);
-	adreno_regwrite(device, REG_SQ_INT_CNTL, 0);
+	kgsl_regwrite(device, REG_RBBM_INT_CNTL, 0);
+	kgsl_regwrite(device, REG_CP_INT_CNTL, 0);
+	kgsl_regwrite(device, REG_SQ_INT_CNTL, 0);
 
 	a2xx_gmeminit(adreno_dev);
 }
diff --git a/drivers/gpu/msm/adreno_a2xx_snapshot.c b/drivers/gpu/msm/adreno_a2xx_snapshot.c
index 2c86f82..5134ed6 100644
--- a/drivers/gpu/msm/adreno_a2xx_snapshot.c
+++ b/drivers/gpu/msm/adreno_a2xx_snapshot.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
@@ -38,11 +38,11 @@
 	header->size = SXDEBUG_COUNT;
 
 	for (i = 0; i < SXDEBUG_COUNT; i++) {
-		adreno_regwrite(device, REG_RBBM_DEBUG_CNTL, 0x1B00 | i);
-		adreno_regread(device, REG_RBBM_DEBUG_OUT, &data[i]);
+		kgsl_regwrite(device, REG_RBBM_DEBUG_CNTL, 0x1B00 | i);
+		kgsl_regread(device, REG_RBBM_DEBUG_OUT, &data[i]);
 	}
 
-	adreno_regwrite(device, REG_RBBM_DEBUG_CNTL, 0);
+	kgsl_regwrite(device, REG_RBBM_DEBUG_CNTL, 0);
 
 	return DEBUG_SECTION_SZ(SXDEBUG_COUNT);
 }
@@ -65,11 +65,11 @@
 	header->size = CPDEBUG_COUNT;
 
 	for (i = 0; i < CPDEBUG_COUNT; i++) {
-		adreno_regwrite(device, REG_RBBM_DEBUG_CNTL, 0x1628);
-		adreno_regread(device, REG_RBBM_DEBUG_OUT, &data[i]);
+		kgsl_regwrite(device, REG_RBBM_DEBUG_CNTL, 0x1628);
+		kgsl_regread(device, REG_RBBM_DEBUG_OUT, &data[i]);
 	}
 
-	adreno_regwrite(device, REG_RBBM_DEBUG_CNTL, 0);
+	kgsl_regwrite(device, REG_RBBM_DEBUG_CNTL, 0);
 
 	return DEBUG_SECTION_SZ(CPDEBUG_COUNT);
 }
@@ -82,7 +82,8 @@
 
 #define SQ_DEBUG_WRITE(_device, _reg, _data, _offset) \
 	do { _data[(_offset)++] = (_reg); \
-	adreno_regread(_device, (_reg), &_data[(_offset)++]); } while (0)
+		kgsl_regread(_device, (_reg), &_data[(_offset)++]);	\
+	} while (0)
 
 #define SQ_DEBUG_BANK_SIZE 23
 
@@ -175,7 +176,7 @@
 	header->size = size;
 
 	for (i = 0; i < 16; i++) {
-		adreno_regwrite(device, REG_SQ_DEBUG_TB_STATUS_SEL,
+		kgsl_regwrite(device, REG_SQ_DEBUG_TB_STATUS_SEL,
 				i | (6<<4) | (i<<7) | (1<<11) | (1<<12)
 				| (i<<16) | (6<<20) | (i<<23));
 		SQ_DEBUG_WRITE(device, REG_SQ_DEBUG_VTX_TB_STATE_MEM,
@@ -215,11 +216,11 @@
 	header->size = MIUDEBUG_COUNT;
 
 	for (i = 0; i < MIUDEBUG_COUNT; i++) {
-		adreno_regwrite(device, REG_RBBM_DEBUG_CNTL, 0x1600 | i);
-		adreno_regread(device, REG_RBBM_DEBUG_OUT, &data[i]);
+		kgsl_regwrite(device, REG_RBBM_DEBUG_CNTL, 0x1600 | i);
+		kgsl_regread(device, REG_RBBM_DEBUG_OUT, &data[i]);
 	}
 
-	adreno_regwrite(device, REG_RBBM_DEBUG_CNTL, 0);
+	kgsl_regwrite(device, REG_RBBM_DEBUG_CNTL, 0);
 
 	return DEBUG_SECTION_SZ(MIUDEBUG_COUNT);
 }
@@ -297,8 +298,8 @@
 	 * work
 	 */
 
-	adreno_regread(device, REG_RBBM_PM_OVERRIDE2, &pmoverride);
-	adreno_regwrite(device, REG_RBBM_PM_OVERRIDE2, 0xFF);
+	kgsl_regread(device, REG_RBBM_PM_OVERRIDE2, &pmoverride);
+	kgsl_regwrite(device, REG_RBBM_PM_OVERRIDE2, 0xFF);
 
 	/* SX debug registers */
 	snapshot = kgsl_snapshot_add_section(device,
@@ -376,7 +377,7 @@
 
 
 	/* Reset the clock gating */
-	adreno_regwrite(device, REG_RBBM_PM_OVERRIDE2, pmoverride);
+	kgsl_regwrite(device, REG_RBBM_PM_OVERRIDE2, pmoverride);
 
 	return snapshot;
 }
diff --git a/drivers/gpu/msm/adreno_a3xx.c b/drivers/gpu/msm/adreno_a3xx.c
index 0ae8db6..7e5638c 100644
--- a/drivers/gpu/msm/adreno_a3xx.c
+++ b/drivers/gpu/msm/adreno_a3xx.c
@@ -2545,7 +2545,7 @@
 	case A3XX_INT_RBBM_AHB_ERROR: {
 		unsigned int reg;
 
-		adreno_regread(device, A3XX_RBBM_AHB_ERROR_STATUS, &reg);
+		kgsl_regread(device, A3XX_RBBM_AHB_ERROR_STATUS, &reg);
 
 		/*
 		 * Return the word address of the erroring register so that it
@@ -2559,7 +2559,7 @@
 			(reg >> 24) & 0x3);
 
 		/* Clear the error */
-		adreno_regwrite(device, A3XX_RBBM_AHB_CMD, (1 << 3));
+		kgsl_regwrite(device, A3XX_RBBM_AHB_CMD, (1 << 3));
 		return;
 	}
 	case A3XX_INT_RBBM_REG_TIMEOUT:
@@ -2738,21 +2738,21 @@
 	if (countable > 1)
 		return;
 
-	adreno_regread(device, A3XX_RBBM_RBBM_CTL, &in);
+	kgsl_regread(device, A3XX_RBBM_RBBM_CTL, &in);
 
 	if (countable == 0)
 		out = in | RBBM_RBBM_CTL_RESET_PWR_CTR0;
 	else
 		out = in | RBBM_RBBM_CTL_RESET_PWR_CTR1;
 
-	adreno_regwrite(device, A3XX_RBBM_RBBM_CTL, out);
+	kgsl_regwrite(device, A3XX_RBBM_RBBM_CTL, out);
 
 	if (countable == 0)
 		out = in | RBBM_RBBM_CTL_ENABLE_PWR_CTR0;
 	else
 		out = in | RBBM_RBBM_CTL_ENABLE_PWR_CTR1;
 
-	adreno_regwrite(device, A3XX_RBBM_RBBM_CTL, out);
+	kgsl_regwrite(device, A3XX_RBBM_RBBM_CTL, out);
 
 	return;
 }
@@ -2766,8 +2766,8 @@
 	if (counter > 1 || countable > 0x7f)
 		return;
 
-	adreno_regread(device, A3XX_VBIF_PERF_CNT_EN, &in);
-	adreno_regread(device, A3XX_VBIF_PERF_CNT_SEL, &sel);
+	kgsl_regread(device, A3XX_VBIF_PERF_CNT_EN, &in);
+	kgsl_regread(device, A3XX_VBIF_PERF_CNT_SEL, &sel);
 
 	if (counter == 0) {
 		bit = VBIF_PERF_CNT_0;
@@ -2780,12 +2780,12 @@
 
 	out = in | bit;
 
-	adreno_regwrite(device, A3XX_VBIF_PERF_CNT_SEL, sel);
+	kgsl_regwrite(device, A3XX_VBIF_PERF_CNT_SEL, sel);
 
-	adreno_regwrite(device, A3XX_VBIF_PERF_CNT_CLR, bit);
-	adreno_regwrite(device, A3XX_VBIF_PERF_CNT_CLR, 0);
+	kgsl_regwrite(device, A3XX_VBIF_PERF_CNT_CLR, bit);
+	kgsl_regwrite(device, A3XX_VBIF_PERF_CNT_CLR, 0);
 
-	adreno_regwrite(device, A3XX_VBIF_PERF_CNT_EN, out);
+	kgsl_regwrite(device, A3XX_VBIF_PERF_CNT_EN, out);
 }
 
 static void a3xx_perfcounter_enable_vbif_pwr(struct kgsl_device *device,
@@ -2796,7 +2796,7 @@
 	if (countable > 2)
 		return;
 
-	adreno_regread(device, A3XX_VBIF_PERF_CNT_EN, &in);
+	kgsl_regread(device, A3XX_VBIF_PERF_CNT_EN, &in);
 	if (countable == 0)
 		bit = VBIF_PERF_PWR_CNT_0;
 	else if (countable == 1)
@@ -2806,10 +2806,10 @@
 
 	out = in | bit;
 
-	adreno_regwrite(device, A3XX_VBIF_PERF_CNT_CLR, bit);
-	adreno_regwrite(device, A3XX_VBIF_PERF_CNT_CLR, 0);
+	kgsl_regwrite(device, A3XX_VBIF_PERF_CNT_CLR, bit);
+	kgsl_regwrite(device, A3XX_VBIF_PERF_CNT_CLR, 0);
 
-	adreno_regwrite(device, A3XX_VBIF_PERF_CNT_EN, out);
+	kgsl_regwrite(device, A3XX_VBIF_PERF_CNT_EN, out);
 }
 
 /*
@@ -2846,14 +2846,14 @@
 	reg = &(a3xx_perfcounter_reglist[group].regs[counter]);
 
 	/* Select the desired perfcounter */
-	adreno_regwrite(device, reg->select, countable);
+	kgsl_regwrite(device, reg->select, countable);
 
 	if (reg->load_bit < 32) {
 		val = 1 << reg->load_bit;
-		adreno_regwrite(device, A3XX_RBBM_PERFCTR_LOAD_CMD0, val);
+		kgsl_regwrite(device, A3XX_RBBM_PERFCTR_LOAD_CMD0, val);
 	} else {
 		val  = 1 << (reg->load_bit - 32);
-		adreno_regwrite(device, A3XX_RBBM_PERFCTR_LOAD_CMD1, val);
+		kgsl_regwrite(device, A3XX_RBBM_PERFCTR_LOAD_CMD1, val);
 	}
 }
 
@@ -2875,17 +2875,17 @@
 	reg = &(a3xx_perfcounter_reglist[group].regs[counter]);
 
 	/* Freeze the counter */
-	adreno_regread(device, A3XX_RBBM_PERFCTR_CTL, &val);
+	kgsl_regread(device, A3XX_RBBM_PERFCTR_CTL, &val);
 	val &= ~reg->load_bit;
-	adreno_regwrite(device, A3XX_RBBM_PERFCTR_CTL, val);
+	kgsl_regwrite(device, A3XX_RBBM_PERFCTR_CTL, val);
 
 	/* Read the values */
-	adreno_regread(device, offset, &lo);
-	adreno_regread(device, offset + 1, &hi);
+	kgsl_regread(device, offset, &lo);
+	kgsl_regread(device, offset + 1, &hi);
 
 	/* Re-Enable the counter */
 	val |= reg->load_bit;
-	adreno_regwrite(device, A3XX_RBBM_PERFCTR_CTL, val);
+	kgsl_regwrite(device, A3XX_RBBM_PERFCTR_CTL, val);
 
 	return (((uint64_t) hi) << 32) | lo;
 }
@@ -2945,7 +2945,7 @@
 	unsigned int status, tmp;
 	int i;
 
-	adreno_regread(&adreno_dev->dev, A3XX_RBBM_INT_0_STATUS, &status);
+	kgsl_regread(&adreno_dev->dev, A3XX_RBBM_INT_0_STATUS, &status);
 
 	for (tmp = status, i = 0; tmp && i < ARRAY_SIZE(a3xx_irq_funcs); i++) {
 		if (tmp & 1) {
@@ -2964,7 +2964,7 @@
 	trace_kgsl_a3xx_irq_status(device, status);
 
 	if (status)
-		adreno_regwrite(&adreno_dev->dev, A3XX_RBBM_INT_CLEAR_CMD,
+		kgsl_regwrite(&adreno_dev->dev, A3XX_RBBM_INT_CLEAR_CMD,
 			status);
 	return ret;
 }
@@ -2974,16 +2974,16 @@
 	struct kgsl_device *device = &adreno_dev->dev;
 
 	if (state)
-		adreno_regwrite(device, A3XX_RBBM_INT_0_MASK, A3XX_INT_MASK);
+		kgsl_regwrite(device, A3XX_RBBM_INT_0_MASK, A3XX_INT_MASK);
 	else
-		adreno_regwrite(device, A3XX_RBBM_INT_0_MASK, 0);
+		kgsl_regwrite(device, A3XX_RBBM_INT_0_MASK, 0);
 }
 
 static unsigned int a3xx_irq_pending(struct adreno_device *adreno_dev)
 {
 	unsigned int status;
 
-	adreno_regread(&adreno_dev->dev, A3XX_RBBM_INT_0_STATUS, &status);
+	kgsl_regread(&adreno_dev->dev, A3XX_RBBM_INT_0_STATUS, &status);
 
 	return (status & A3XX_INT_MASK) ? 1 : 0;
 }
@@ -2995,7 +2995,7 @@
 	unsigned int ret = 0;
 
 	/* Read the value */
-	adreno_regread(device, A3XX_RBBM_PERFCTR_PWR_1_LO, &val);
+	kgsl_regread(device, A3XX_RBBM_PERFCTR_PWR_1_LO, &val);
 
 	/* Return 0 for the first read */
 	if (adreno_dev->gpu_cycles != 0) {
@@ -3136,215 +3136,6 @@
 	{ adreno_is_a305b, a305b_vbif },
 };
 
-static void a3xx_perfcounter_init(struct adreno_device *adreno_dev)
-{
-	/*
-	 * Set SP to count SP_ALU_ACTIVE_CYCLES, it includes
-	 * all ALU instruction execution regardless precision or shader ID.
-	 * Set SP to count SP0_ICL1_MISSES, It counts
-	 * USP L1 instruction miss request.
-	 * Set SP to count SP_FS_FULL_ALU_INSTRUCTIONS, it
-	 * counts USP flow control instruction execution.
-	 * we will use this to augment our hang detection
-	 */
-	if (adreno_dev->fast_hang_detect) {
-		adreno_perfcounter_get(adreno_dev, KGSL_PERFCOUNTER_GROUP_SP,
-			SP_ALU_ACTIVE_CYCLES, &ft_detect_regs[6],
-			PERFCOUNTER_FLAG_KERNEL);
-		ft_detect_regs[7] = ft_detect_regs[6] + 1;
-		adreno_perfcounter_get(adreno_dev, KGSL_PERFCOUNTER_GROUP_SP,
-			SP0_ICL1_MISSES, &ft_detect_regs[8],
-			PERFCOUNTER_FLAG_KERNEL);
-		ft_detect_regs[9] = ft_detect_regs[8] + 1;
-		adreno_perfcounter_get(adreno_dev, KGSL_PERFCOUNTER_GROUP_SP,
-			SP_FS_CFLOW_INSTRUCTIONS, &ft_detect_regs[10],
-			PERFCOUNTER_FLAG_KERNEL);
-		ft_detect_regs[11] = ft_detect_regs[10] + 1;
-	}
-
-	adreno_perfcounter_get(adreno_dev, KGSL_PERFCOUNTER_GROUP_SP,
-		SP_FS_FULL_ALU_INSTRUCTIONS, NULL, PERFCOUNTER_FLAG_KERNEL);
-
-	/* Reserve and start countable 1 in the PWR perfcounter group */
-	adreno_perfcounter_get(adreno_dev, KGSL_PERFCOUNTER_GROUP_PWR, 1,
-			NULL, PERFCOUNTER_FLAG_KERNEL);
-}
-
-static void a3xx_start(struct adreno_device *adreno_dev)
-{
-	struct kgsl_device *device = &adreno_dev->dev;
-	struct a3xx_vbif_data *vbif = NULL;
-	int i;
-
-	for (i = 0; i < ARRAY_SIZE(a3xx_vbif_platforms); i++) {
-		if (a3xx_vbif_platforms[i].devfunc(adreno_dev)) {
-			vbif = a3xx_vbif_platforms[i].vbif;
-			break;
-		}
-	}
-
-	BUG_ON(vbif == NULL);
-
-	while (vbif->reg != 0) {
-		adreno_regwrite(device, vbif->reg, vbif->val);
-		vbif++;
-	}
-
-	/* Make all blocks contribute to the GPU BUSY perf counter */
-	adreno_regwrite(device, A3XX_RBBM_GPU_BUSY_MASKED, 0xFFFFFFFF);
-
-	/* Tune the hystersis counters for SP and CP idle detection */
-	adreno_regwrite(device, A3XX_RBBM_SP_HYST_CNT, 0x10);
-	adreno_regwrite(device, A3XX_RBBM_WAIT_IDLE_CLOCKS_CTL, 0x10);
-
-	/* Enable the RBBM error reporting bits.  This lets us get
-	   useful information on failure */
-
-	adreno_regwrite(device, A3XX_RBBM_AHB_CTL0, 0x00000001);
-
-	/* Enable AHB error reporting */
-	adreno_regwrite(device, A3XX_RBBM_AHB_CTL1, 0xA6FFFFFF);
-
-	/* Turn on the power counters */
-	adreno_regwrite(device, A3XX_RBBM_RBBM_CTL, 0x00030000);
-
-	/* Turn on hang detection - this spews a lot of useful information
-	 * into the RBBM registers on a hang */
-
-	adreno_regwrite(device, A3XX_RBBM_INTERFACE_HANG_INT_CTL,
-			(1 << 16) | 0xFFF);
-
-	/* Enable 64-byte cacheline size. HW Default is 32-byte (0x000000E0). */
-	adreno_regwrite(device, A3XX_UCHE_CACHE_MODE_CONTROL_REG, 0x00000001);
-
-	/* Enable Clock gating */
-	adreno_regwrite(device, A3XX_RBBM_CLOCK_CTL,
-		adreno_a3xx_rbbm_clock_ctl_default(adreno_dev));
-
-	if (adreno_is_a330v2(adreno_dev))
-		adreno_regwrite(device, A3XX_RBBM_GPR0_CTL,
-			A330v2_RBBM_GPR0_CTL_DEFAULT);
-	else if (adreno_is_a330(adreno_dev))
-		adreno_regwrite(device, A3XX_RBBM_GPR0_CTL,
-			A330_RBBM_GPR0_CTL_DEFAULT);
-
-	/* Set the OCMEM base address for A330 */
-	if (adreno_is_a330(adreno_dev) ||
-		adreno_is_a305b(adreno_dev)) {
-		adreno_regwrite(device, A3XX_RB_GMEM_BASE_ADDR,
-			(unsigned int)(adreno_dev->ocmem_base >> 14));
-	}
-
-	/* Turn on performance counters */
-	adreno_regwrite(device, A3XX_RBBM_PERFCTR_CTL, 0x01);
-
-	/* Turn on the GPU busy counter and let it run free */
-
-	adreno_dev->gpu_cycles = 0;
-}
-
-/**
- * a3xx_coresight_enable() - Enables debugging through coresight
- * debug bus for adreno a3xx devices.
- * @device: Pointer to GPU device structure
- */
-int a3xx_coresight_enable(struct kgsl_device *device)
-{
-	mutex_lock(&device->mutex);
-	if (!kgsl_active_count_get(device)) {
-		adreno_regwrite(device, A3XX_RBBM_DEBUG_BUS_CTL, 0x0001093F);
-		adreno_regwrite(device, A3XX_RBBM_DEBUG_BUS_STB_CTL0,
-				0x00000000);
-		adreno_regwrite(device, A3XX_RBBM_DEBUG_BUS_STB_CTL1,
-				0xFFFFFFFE);
-		adreno_regwrite(device, A3XX_RBBM_INT_TRACE_BUS_CTL,
-				0x00201111);
-		adreno_regwrite(device, A3XX_RBBM_EXT_TRACE_BUS_CTL,
-				0x89100010);
-		adreno_regwrite(device, A3XX_RBBM_EXT_TRACE_STOP_CNT,
-				0x00017fff);
-		adreno_regwrite(device, A3XX_RBBM_EXT_TRACE_START_CNT,
-				0x0001000f);
-		adreno_regwrite(device, A3XX_RBBM_EXT_TRACE_PERIOD_CNT ,
-				0x0001ffff);
-		adreno_regwrite(device, A3XX_RBBM_EXT_TRACE_CMD,
-				0x00000001);
-		kgsl_active_count_put(device);
-	}
-	mutex_unlock(&device->mutex);
-	return 0;
-}
-
-/**
- * a3xx_coresight_disable() - Disables debugging through coresight
- * debug bus for adreno a3xx devices.
- * @device: Pointer to GPU device structure
- */
-void a3xx_coresight_disable(struct kgsl_device *device)
-{
-	mutex_lock(&device->mutex);
-	if (!kgsl_active_count_get(device)) {
-		adreno_regwrite(device, A3XX_RBBM_DEBUG_BUS_CTL, 0x0);
-		adreno_regwrite(device, A3XX_RBBM_DEBUG_BUS_STB_CTL0, 0x0);
-		adreno_regwrite(device, A3XX_RBBM_DEBUG_BUS_STB_CTL1, 0x0);
-		adreno_regwrite(device, A3XX_RBBM_INT_TRACE_BUS_CTL, 0x0);
-		adreno_regwrite(device, A3XX_RBBM_EXT_TRACE_BUS_CTL, 0x0);
-		adreno_regwrite(device, A3XX_RBBM_EXT_TRACE_STOP_CNT, 0x0);
-		adreno_regwrite(device, A3XX_RBBM_EXT_TRACE_START_CNT, 0x0);
-		adreno_regwrite(device, A3XX_RBBM_EXT_TRACE_PERIOD_CNT , 0x0);
-		adreno_regwrite(device, A3XX_RBBM_EXT_TRACE_CMD, 0x0);
-		kgsl_active_count_put(device);
-	}
-	mutex_unlock(&device->mutex);
-}
-
-static void a3xx_coresight_write_reg(struct kgsl_device *device,
-		unsigned int wordoffset, unsigned int val)
-{
-	mutex_lock(&device->mutex);
-	if (!kgsl_active_count_get(device)) {
-		adreno_regwrite(device, wordoffset, val);
-		kgsl_active_count_put(device);
-	}
-	mutex_unlock(&device->mutex);
-}
-
-void a3xx_coresight_config_debug_reg(struct kgsl_device *device,
-		int debug_reg, unsigned int val)
-{
-	switch (debug_reg) {
-
-	case DEBUG_BUS_CTL:
-		a3xx_coresight_write_reg(device, A3XX_RBBM_DEBUG_BUS_CTL, val);
-		break;
-
-	case TRACE_STOP_CNT:
-		a3xx_coresight_write_reg(device, A3XX_RBBM_EXT_TRACE_STOP_CNT,
-				val);
-		break;
-
-	case TRACE_START_CNT:
-		a3xx_coresight_write_reg(device, A3XX_RBBM_EXT_TRACE_START_CNT,
-				val);
-		break;
-
-	case TRACE_PERIOD_CNT:
-		a3xx_coresight_write_reg(device, A3XX_RBBM_EXT_TRACE_PERIOD_CNT,
-				val);
-		break;
-
-	case TRACE_CMD:
-		a3xx_coresight_write_reg(device, A3XX_RBBM_EXT_TRACE_CMD, val);
-		break;
-
-	case TRACE_BUS_CTL:
-		a3xx_coresight_write_reg(device, A3XX_RBBM_EXT_TRACE_BUS_CTL,
-				val);
-		break;
-	}
-
-}
-
 /*
  * Define the available perfcounter groups - these get used by
  * adreno_perfcounter_get and adreno_perfcounter_put
@@ -3467,6 +3258,219 @@
 	ARRAY_SIZE(a3xx_perfcounter_groups),
 };
 
+static void a3xx_perfcounter_init(struct adreno_device *adreno_dev)
+{
+	/* SP[3] counter is broken on a330 so disable it if a330 device */
+	if (adreno_is_a330(adreno_dev))
+		a3xx_perfcounters_sp[3].countable = KGSL_PERFCOUNTER_BROKEN;
+
+	/*
+	 * Set SP to count SP_ALU_ACTIVE_CYCLES, it includes
+	 * all ALU instruction execution regardless precision or shader ID.
+	 * Set SP to count SP0_ICL1_MISSES, It counts
+	 * USP L1 instruction miss request.
+	 * Set SP to count SP_FS_FULL_ALU_INSTRUCTIONS, it
+	 * counts USP flow control instruction execution.
+	 * we will use this to augment our hang detection
+	 */
+	if (adreno_dev->fast_hang_detect) {
+		adreno_perfcounter_get(adreno_dev, KGSL_PERFCOUNTER_GROUP_SP,
+			SP_ALU_ACTIVE_CYCLES, &ft_detect_regs[6],
+			PERFCOUNTER_FLAG_KERNEL);
+		ft_detect_regs[7] = ft_detect_regs[6] + 1;
+		adreno_perfcounter_get(adreno_dev, KGSL_PERFCOUNTER_GROUP_SP,
+			SP0_ICL1_MISSES, &ft_detect_regs[8],
+			PERFCOUNTER_FLAG_KERNEL);
+		ft_detect_regs[9] = ft_detect_regs[8] + 1;
+		adreno_perfcounter_get(adreno_dev, KGSL_PERFCOUNTER_GROUP_SP,
+			SP_FS_CFLOW_INSTRUCTIONS, &ft_detect_regs[10],
+			PERFCOUNTER_FLAG_KERNEL);
+		ft_detect_regs[11] = ft_detect_regs[10] + 1;
+	}
+
+	adreno_perfcounter_get(adreno_dev, KGSL_PERFCOUNTER_GROUP_SP,
+		SP_FS_FULL_ALU_INSTRUCTIONS, NULL, PERFCOUNTER_FLAG_KERNEL);
+
+	/* Reserve and start countable 1 in the PWR perfcounter group */
+	adreno_perfcounter_get(adreno_dev, KGSL_PERFCOUNTER_GROUP_PWR, 1,
+			NULL, PERFCOUNTER_FLAG_KERNEL);
+}
+
+static void a3xx_start(struct adreno_device *adreno_dev)
+{
+	struct kgsl_device *device = &adreno_dev->dev;
+	struct a3xx_vbif_data *vbif = NULL;
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(a3xx_vbif_platforms); i++) {
+		if (a3xx_vbif_platforms[i].devfunc(adreno_dev)) {
+			vbif = a3xx_vbif_platforms[i].vbif;
+			break;
+		}
+	}
+
+	BUG_ON(vbif == NULL);
+
+	while (vbif->reg != 0) {
+		kgsl_regwrite(device, vbif->reg, vbif->val);
+		vbif++;
+	}
+
+	/* Make all blocks contribute to the GPU BUSY perf counter */
+	kgsl_regwrite(device, A3XX_RBBM_GPU_BUSY_MASKED, 0xFFFFFFFF);
+
+	/* Tune the hystersis counters for SP and CP idle detection */
+	kgsl_regwrite(device, A3XX_RBBM_SP_HYST_CNT, 0x10);
+	kgsl_regwrite(device, A3XX_RBBM_WAIT_IDLE_CLOCKS_CTL, 0x10);
+
+	/* Enable the RBBM error reporting bits.  This lets us get
+	   useful information on failure */
+
+	kgsl_regwrite(device, A3XX_RBBM_AHB_CTL0, 0x00000001);
+
+	/* Enable AHB error reporting */
+	kgsl_regwrite(device, A3XX_RBBM_AHB_CTL1, 0xA6FFFFFF);
+
+	/* Turn on the power counters */
+	kgsl_regwrite(device, A3XX_RBBM_RBBM_CTL, 0x00030000);
+
+	/* Turn on hang detection - this spews a lot of useful information
+	 * into the RBBM registers on a hang */
+
+	kgsl_regwrite(device, A3XX_RBBM_INTERFACE_HANG_INT_CTL,
+			(1 << 16) | 0xFFF);
+
+	/* Enable 64-byte cacheline size. HW Default is 32-byte (0x000000E0). */
+	kgsl_regwrite(device, A3XX_UCHE_CACHE_MODE_CONTROL_REG, 0x00000001);
+
+	/* Enable Clock gating */
+	kgsl_regwrite(device, A3XX_RBBM_CLOCK_CTL,
+		adreno_a3xx_rbbm_clock_ctl_default(adreno_dev));
+
+	if (adreno_is_a330v2(adreno_dev))
+		kgsl_regwrite(device, A3XX_RBBM_GPR0_CTL,
+			A330v2_RBBM_GPR0_CTL_DEFAULT);
+	else if (adreno_is_a330(adreno_dev))
+		kgsl_regwrite(device, A3XX_RBBM_GPR0_CTL,
+			A330_RBBM_GPR0_CTL_DEFAULT);
+
+	/* Set the OCMEM base address for A330 */
+	if (adreno_is_a330(adreno_dev) ||
+		adreno_is_a305b(adreno_dev)) {
+		kgsl_regwrite(device, A3XX_RB_GMEM_BASE_ADDR,
+			(unsigned int)(adreno_dev->ocmem_base >> 14));
+	}
+
+	/* Turn on performance counters */
+	kgsl_regwrite(device, A3XX_RBBM_PERFCTR_CTL, 0x01);
+
+	/* Turn on the GPU busy counter and let it run free */
+
+	adreno_dev->gpu_cycles = 0;
+}
+
+/**
+ * a3xx_coresight_enable() - Enables debugging through coresight
+ * debug bus for adreno a3xx devices.
+ * @device: Pointer to GPU device structure
+ */
+int a3xx_coresight_enable(struct kgsl_device *device)
+{
+	mutex_lock(&device->mutex);
+	if (!kgsl_active_count_get(device)) {
+		kgsl_regwrite(device, A3XX_RBBM_DEBUG_BUS_CTL, 0x0001093F);
+		kgsl_regwrite(device, A3XX_RBBM_DEBUG_BUS_STB_CTL0,
+				0x00000000);
+		kgsl_regwrite(device, A3XX_RBBM_DEBUG_BUS_STB_CTL1,
+				0xFFFFFFFE);
+		kgsl_regwrite(device, A3XX_RBBM_INT_TRACE_BUS_CTL,
+				0x00201111);
+		kgsl_regwrite(device, A3XX_RBBM_EXT_TRACE_BUS_CTL,
+				0x89100010);
+		kgsl_regwrite(device, A3XX_RBBM_EXT_TRACE_STOP_CNT,
+				0x00017fff);
+		kgsl_regwrite(device, A3XX_RBBM_EXT_TRACE_START_CNT,
+				0x0001000f);
+		kgsl_regwrite(device, A3XX_RBBM_EXT_TRACE_PERIOD_CNT ,
+				0x0001ffff);
+		kgsl_regwrite(device, A3XX_RBBM_EXT_TRACE_CMD,
+				0x00000001);
+		kgsl_active_count_put(device);
+	}
+	mutex_unlock(&device->mutex);
+	return 0;
+}
+
+/**
+ * a3xx_coresight_disable() - Disables debugging through coresight
+ * debug bus for adreno a3xx devices.
+ * @device: Pointer to GPU device structure
+ */
+void a3xx_coresight_disable(struct kgsl_device *device)
+{
+	mutex_lock(&device->mutex);
+	if (!kgsl_active_count_get(device)) {
+		kgsl_regwrite(device, A3XX_RBBM_DEBUG_BUS_CTL, 0x0);
+		kgsl_regwrite(device, A3XX_RBBM_DEBUG_BUS_STB_CTL0, 0x0);
+		kgsl_regwrite(device, A3XX_RBBM_DEBUG_BUS_STB_CTL1, 0x0);
+		kgsl_regwrite(device, A3XX_RBBM_INT_TRACE_BUS_CTL, 0x0);
+		kgsl_regwrite(device, A3XX_RBBM_EXT_TRACE_BUS_CTL, 0x0);
+		kgsl_regwrite(device, A3XX_RBBM_EXT_TRACE_STOP_CNT, 0x0);
+		kgsl_regwrite(device, A3XX_RBBM_EXT_TRACE_START_CNT, 0x0);
+		kgsl_regwrite(device, A3XX_RBBM_EXT_TRACE_PERIOD_CNT , 0x0);
+		kgsl_regwrite(device, A3XX_RBBM_EXT_TRACE_CMD, 0x0);
+		kgsl_active_count_put(device);
+	}
+	mutex_unlock(&device->mutex);
+}
+
+static void a3xx_coresight_write_reg(struct kgsl_device *device,
+		unsigned int wordoffset, unsigned int val)
+{
+	mutex_lock(&device->mutex);
+	if (!kgsl_active_count_get(device)) {
+		kgsl_regwrite(device, wordoffset, val);
+		kgsl_active_count_put(device);
+	}
+	mutex_unlock(&device->mutex);
+}
+
+void a3xx_coresight_config_debug_reg(struct kgsl_device *device,
+		int debug_reg, unsigned int val)
+{
+	switch (debug_reg) {
+
+	case DEBUG_BUS_CTL:
+		a3xx_coresight_write_reg(device, A3XX_RBBM_DEBUG_BUS_CTL, val);
+		break;
+
+	case TRACE_STOP_CNT:
+		a3xx_coresight_write_reg(device, A3XX_RBBM_EXT_TRACE_STOP_CNT,
+				val);
+		break;
+
+	case TRACE_START_CNT:
+		a3xx_coresight_write_reg(device, A3XX_RBBM_EXT_TRACE_START_CNT,
+				val);
+		break;
+
+	case TRACE_PERIOD_CNT:
+		a3xx_coresight_write_reg(device, A3XX_RBBM_EXT_TRACE_PERIOD_CNT,
+				val);
+		break;
+
+	case TRACE_CMD:
+		a3xx_coresight_write_reg(device, A3XX_RBBM_EXT_TRACE_CMD, val);
+		break;
+
+	case TRACE_BUS_CTL:
+		a3xx_coresight_write_reg(device, A3XX_RBBM_EXT_TRACE_BUS_CTL,
+				val);
+		break;
+	}
+
+}
+
 /*
  * a3xx_soft_reset() - Soft reset GPU
  * @adreno_dev: Pointer to adreno device
@@ -3482,13 +3486,13 @@
 	struct kgsl_device *device = &adreno_dev->dev;
 	unsigned int reg;
 
-	adreno_regwrite(device, A3XX_RBBM_SW_RESET_CMD, 1);
+	kgsl_regwrite(device, A3XX_RBBM_SW_RESET_CMD, 1);
 	/*
 	 * Do a dummy read to get a brief read cycle delay for the reset to take
 	 * effect
 	 */
-	adreno_regread(device, A3XX_RBBM_SW_RESET_CMD, &reg);
-	adreno_regwrite(device, A3XX_RBBM_SW_RESET_CMD, 0);
+	kgsl_regread(device, A3XX_RBBM_SW_RESET_CMD, &reg);
+	kgsl_regwrite(device, A3XX_RBBM_SW_RESET_CMD, 0);
 }
 
 /* Defined in adreno_a3xx_snapshot.c */
diff --git a/drivers/gpu/msm/adreno_a3xx_snapshot.c b/drivers/gpu/msm/adreno_a3xx_snapshot.c
index 58e3126..56c4305 100644
--- a/drivers/gpu/msm/adreno_a3xx_snapshot.c
+++ b/drivers/gpu/msm/adreno_a3xx_snapshot.c
@@ -35,8 +35,8 @@
 	unsigned int block_id, unsigned int index, unsigned int *val)
 {
 	unsigned int block = (block_id << 8) | 1 << 16;
-	adreno_regwrite(device, A3XX_RBBM_DEBUG_BUS_CTL, block | index);
-	adreno_regread(device, A3XX_RBBM_DEBUG_BUS_DATA_STATUS, val);
+	kgsl_regwrite(device, A3XX_RBBM_DEBUG_BUS_CTL, block | index);
+	kgsl_regread(device, A3XX_RBBM_DEBUG_BUS_DATA_STATUS, val);
 }
 
 /**
@@ -108,9 +108,9 @@
 	for (bank = 0; bank < VPC_MEMORY_BANKS; bank++) {
 		for (addr = 0; addr < VPC_MEMORY_SIZE; addr++) {
 			unsigned int val = bank | (addr << 4);
-			adreno_regwrite(device,
+			kgsl_regwrite(device,
 				A3XX_VPC_VPC_DEBUG_RAM_SEL, val);
-			adreno_regread(device,
+			kgsl_regread(device,
 				A3XX_VPC_VPC_DEBUG_RAM_READ, &data[i++]);
 		}
 	}
@@ -134,9 +134,9 @@
 	header->type = SNAPSHOT_DEBUG_CP_MEQ;
 	header->size = CP_MEQ_SIZE;
 
-	adreno_regwrite(device, A3XX_CP_MEQ_ADDR, 0x0);
+	kgsl_regwrite(device, A3XX_CP_MEQ_ADDR, 0x0);
 	for (i = 0; i < CP_MEQ_SIZE; i++)
-		adreno_regread(device, A3XX_CP_MEQ_DATA, &data[i]);
+		kgsl_regread(device, A3XX_CP_MEQ_DATA, &data[i]);
 
 	return DEBUG_SECTION_SZ(CP_MEQ_SIZE);
 }
@@ -164,9 +164,9 @@
 	 * maintain always changing hardcoded constants
 	 */
 
-	adreno_regwrite(device, REG_CP_ME_RAM_RADDR, 0x0);
+	kgsl_regwrite(device, REG_CP_ME_RAM_RADDR, 0x0);
 	for (i = 0; i < size; i++)
-		adreno_regread(device, REG_CP_ME_RAM_DATA, &data[i]);
+		kgsl_regread(device, REG_CP_ME_RAM_DATA, &data[i]);
 
 	return DEBUG_SECTION_SZ(size);
 }
@@ -195,7 +195,7 @@
 	 */
 	kgsl_regwrite(device, A3XX_CP_PFP_UCODE_ADDR, 0x0);
 	for (i = 0; i < size; i++)
-		adreno_regread(device, A3XX_CP_PFP_UCODE_DATA, &data[i]);
+		kgsl_regread(device, A3XX_CP_PFP_UCODE_DATA, &data[i]);
 
 	return DEBUG_SECTION_SZ(size);
 }
@@ -226,9 +226,9 @@
 	header->type = SNAPSHOT_DEBUG_CP_ROQ;
 	header->size = size;
 
-	adreno_regwrite(device, A3XX_CP_ROQ_ADDR, 0x0);
+	kgsl_regwrite(device, A3XX_CP_ROQ_ADDR, 0x0);
 	for (i = 0; i < size; i++)
-		adreno_regread(device, A3XX_CP_ROQ_DATA, &data[i]);
+		kgsl_regread(device, A3XX_CP_ROQ_DATA, &data[i]);
 
 	return DEBUG_SECTION_SZ(size);
 }
@@ -253,12 +253,12 @@
 	header->type = SNAPSHOT_DEBUG_CP_MERCIU;
 	header->size = size;
 
-	adreno_regwrite(device, A3XX_CP_MERCIU_ADDR, 0x0);
+	kgsl_regwrite(device, A3XX_CP_MERCIU_ADDR, 0x0);
 
 	for (i = 0; i < A330_CP_MERCIU_QUEUE_SIZE; i++) {
-		adreno_regread(device, A3XX_CP_MERCIU_DATA,
+		kgsl_regread(device, A3XX_CP_MERCIU_DATA,
 			&data[(i * 2)]);
-		adreno_regread(device, A3XX_CP_MERCIU_DATA2,
+		kgsl_regread(device, A3XX_CP_MERCIU_DATA2,
 			&data[(i * 2) + 1]);
 	}
 
@@ -444,7 +444,7 @@
 	list.count = 0;
 
 	/* Disable Clock gating temporarily for the debug bus to work */
-	adreno_regwrite(device, A3XX_RBBM_CLOCK_CTL, 0x00);
+	kgsl_regwrite(device, A3XX_RBBM_CLOCK_CTL, 0x00);
 
 	/* Store relevant registers in list to snapshot */
 	_snapshot_a3xx_regs(regs, &list);
@@ -516,7 +516,7 @@
 	snapshot = a3xx_snapshot_debugbus(device, snapshot, remain);
 
 	/* Enable Clock gating */
-	adreno_regwrite(device, A3XX_RBBM_CLOCK_CTL,
+	kgsl_regwrite(device, A3XX_RBBM_CLOCK_CTL,
 		adreno_a3xx_rbbm_clock_ctl_default(adreno_dev));
 
 	return snapshot;
diff --git a/drivers/gpu/msm/adreno_coresight.c b/drivers/gpu/msm/adreno_coresight.c
index e18568d..1b827ff 100644
--- a/drivers/gpu/msm/adreno_coresight.c
+++ b/drivers/gpu/msm/adreno_coresight.c
@@ -109,7 +109,7 @@
 
 	mutex_lock(&device->mutex);
 	if (!kgsl_active_count_get(device)) {
-		adreno_regread(device, offset, &regval);
+		kgsl_regread(device, offset, &regval);
 		kgsl_active_count_put(device);
 	}
 	mutex_unlock(&device->mutex);
diff --git a/drivers/gpu/msm/adreno_ringbuffer.c b/drivers/gpu/msm/adreno_ringbuffer.c
index 32b26ae..fcef296 100644
--- a/drivers/gpu/msm/adreno_ringbuffer.c
+++ b/drivers/gpu/msm/adreno_ringbuffer.c
@@ -367,12 +367,12 @@
 			   (rb->sizedwords << 2));
 
 	if (adreno_is_a2xx(adreno_dev)) {
-		adreno_regwrite(device, REG_CP_RB_WPTR_BASE,
+		kgsl_regwrite(device, REG_CP_RB_WPTR_BASE,
 			(rb->memptrs_desc.gpuaddr
 			+ GSL_RB_MEMPTRS_WPTRPOLL_OFFSET));
 
 		/* setup WPTR delay */
-		adreno_regwrite(device, REG_CP_RB_WPTR_DELAY,
+		kgsl_regwrite(device, REG_CP_RB_WPTR_DELAY,
 			0 /*0x70000010 */);
 	}
 
@@ -412,33 +412,33 @@
 
 	if (adreno_is_a3xx(adreno_dev)) {
 		/* enable access protection to privileged registers */
-		adreno_regwrite(device, A3XX_CP_PROTECT_CTRL, 0x00000007);
+		kgsl_regwrite(device, A3XX_CP_PROTECT_CTRL, 0x00000007);
 
 		/* RBBM registers */
-		adreno_regwrite(device, A3XX_CP_PROTECT_REG_0, 0x63000040);
-		adreno_regwrite(device, A3XX_CP_PROTECT_REG_1, 0x62000080);
-		adreno_regwrite(device, A3XX_CP_PROTECT_REG_2, 0x600000CC);
-		adreno_regwrite(device, A3XX_CP_PROTECT_REG_3, 0x60000108);
-		adreno_regwrite(device, A3XX_CP_PROTECT_REG_4, 0x64000140);
-		adreno_regwrite(device, A3XX_CP_PROTECT_REG_5, 0x66000400);
+		kgsl_regwrite(device, A3XX_CP_PROTECT_REG_0, 0x63000040);
+		kgsl_regwrite(device, A3XX_CP_PROTECT_REG_1, 0x62000080);
+		kgsl_regwrite(device, A3XX_CP_PROTECT_REG_2, 0x600000CC);
+		kgsl_regwrite(device, A3XX_CP_PROTECT_REG_3, 0x60000108);
+		kgsl_regwrite(device, A3XX_CP_PROTECT_REG_4, 0x64000140);
+		kgsl_regwrite(device, A3XX_CP_PROTECT_REG_5, 0x66000400);
 
 		/* CP registers */
-		adreno_regwrite(device, A3XX_CP_PROTECT_REG_6, 0x65000700);
-		adreno_regwrite(device, A3XX_CP_PROTECT_REG_7, 0x610007D8);
-		adreno_regwrite(device, A3XX_CP_PROTECT_REG_8, 0x620007E0);
-		adreno_regwrite(device, A3XX_CP_PROTECT_REG_9, 0x61001178);
-		adreno_regwrite(device, A3XX_CP_PROTECT_REG_A, 0x64001180);
+		kgsl_regwrite(device, A3XX_CP_PROTECT_REG_6, 0x65000700);
+		kgsl_regwrite(device, A3XX_CP_PROTECT_REG_7, 0x610007D8);
+		kgsl_regwrite(device, A3XX_CP_PROTECT_REG_8, 0x620007E0);
+		kgsl_regwrite(device, A3XX_CP_PROTECT_REG_9, 0x61001178);
+		kgsl_regwrite(device, A3XX_CP_PROTECT_REG_A, 0x64001180);
 
 		/* RB registers */
-		adreno_regwrite(device, A3XX_CP_PROTECT_REG_B, 0x60003300);
+		kgsl_regwrite(device, A3XX_CP_PROTECT_REG_B, 0x60003300);
 
 		/* VBIF registers */
-		adreno_regwrite(device, A3XX_CP_PROTECT_REG_C, 0x6B00C000);
+		kgsl_regwrite(device, A3XX_CP_PROTECT_REG_C, 0x6B00C000);
 	}
 
 	if (adreno_is_a2xx(adreno_dev)) {
 		/* explicitly clear all cp interrupts */
-		adreno_regwrite(device, REG_CP_INT_ACK, 0xFFFFFFFF);
+		kgsl_regwrite(device, REG_CP_INT_ACK, 0xFFFFFFFF);
 	}
 
 	/* setup scratch/timestamp */
@@ -453,9 +453,9 @@
 	/* CP ROQ queue sizes (bytes) - RB:16, ST:16, IB1:32, IB2:64 */
 	if (adreno_is_a305(adreno_dev) || adreno_is_a305c(adreno_dev) ||
 		adreno_is_a320(adreno_dev))
-		adreno_regwrite(device, REG_CP_QUEUE_THRESHOLDS, 0x000E0602);
+		kgsl_regwrite(device, REG_CP_QUEUE_THRESHOLDS, 0x000E0602);
 	else if (adreno_is_a330(adreno_dev) || adreno_is_a305b(adreno_dev))
-		adreno_regwrite(device, REG_CP_QUEUE_THRESHOLDS, 0x003E2008);
+		kgsl_regwrite(device, REG_CP_QUEUE_THRESHOLDS, 0x003E2008);
 
 	rb->wptr = 0;
 
@@ -531,7 +531,7 @@
 
 	if (rb->flags & KGSL_FLAGS_STARTED) {
 		if (adreno_is_a200(adreno_dev))
-			adreno_regwrite(rb->device, REG_CP_ME_CNTL, 0x10000000);
+			kgsl_regwrite(rb->device, REG_CP_ME_CNTL, 0x10000000);
 
 		rb->flags &= ~KGSL_FLAGS_STARTED;
 	}
diff --git a/drivers/gpu/msm/kgsl_iommu.c b/drivers/gpu/msm/kgsl_iommu.c
index 9113605..aeafb01 100644
--- a/drivers/gpu/msm/kgsl_iommu.c
+++ b/drivers/gpu/msm/kgsl_iommu.c
@@ -1534,6 +1534,7 @@
 				KGSL_IOMMU_SET_CTX_REG(iommu, iommu_unit,
 						iommu_unit->dev[j].ctx_id,
 						V2PUR, v2pxx);
+				mb();
 				vaddr += PAGE_SIZE;
 				for (l = 0; l < iommu_unit->dev_count; l++) {
 					tlblkcr = KGSL_IOMMU_GET_CTX_REG(iommu,
diff --git a/drivers/media/dvb/dvb-core/demux.h b/drivers/media/dvb/dvb-core/demux.h
index 2c2b339..189418a 100644
--- a/drivers/media/dvb/dvb-core/demux.h
+++ b/drivers/media/dvb/dvb-core/demux.h
@@ -246,6 +246,8 @@
 				enum dmx_tsp_format_t tsp_format);
 	int (*set_secure_mode)(struct dmx_ts_feed *feed,
 				struct dmx_secure_mode *sec_mode);
+	int (*set_cipher_ops)(struct dmx_ts_feed *feed,
+				struct dmx_cipher_operations *cipher_ops);
 	int (*oob_command) (struct dmx_ts_feed *feed,
 			struct dmx_oob_command *cmd);
 	int (*ts_insertion_init)(struct dmx_ts_feed *feed);
@@ -301,6 +303,8 @@
 			u32 bytes_num);
 	int (*set_secure_mode)(struct dmx_section_feed *feed,
 				struct dmx_secure_mode *sec_mode);
+	int (*set_cipher_ops)(struct dmx_section_feed *feed,
+				struct dmx_cipher_operations *cipher_ops);
 	int (*oob_command) (struct dmx_section_feed *feed,
 				struct dmx_oob_command *cmd);
 	int (*get_scrambling_bits)(struct dmx_section_feed *feed, u8 *value);
@@ -388,6 +392,7 @@
 	struct dmx_frontend* frontend;    /* Front-end connected to the demux */
 	void* priv;                  /* Pointer to private data of the API client */
 	struct data_buffer dvr_input; /* DVR input buffer */
+	int dvr_input_protected;
 	struct dentry *debugfs_demux_dir; /* debugfs dir */
 
 	int (*open) (struct dmx_demux* demux);
diff --git a/drivers/media/dvb/dvb-core/dmxdev.c b/drivers/media/dvb/dvb-core/dmxdev.c
index 28e8092..a1cac54 100644
--- a/drivers/media/dvb/dvb-core/dmxdev.c
+++ b/drivers/media/dvb/dvb-core/dmxdev.c
@@ -566,6 +566,7 @@
 	int bytes_written = 0;
 	size_t split;
 	size_t tsp_size;
+	u8 *data_start;
 	struct dvb_ringbuffer *src = &dmxdev->dvr_input_buffer;
 	todo = dvr_cmd->cmd.data_feed_count;
 
@@ -578,15 +579,15 @@
 		/* wait for input */
 		ret = wait_event_interruptible(
 			src->queue,
-			(dvb_ringbuffer_avail(src) >= tsp_size) || (!src->data)
-			|| (dmxdev->dvr_in_exit) || (src->error));
+			(dvb_ringbuffer_avail(src) >= tsp_size) ||
+			dmxdev->dvr_in_exit || src->error);
 
 		if (ret < 0)
 			break;
 
 		spin_lock(&dmxdev->dvr_in_lock);
 
-		if (!src->data || dmxdev->exit || dmxdev->dvr_in_exit) {
+		if (dmxdev->exit || dmxdev->dvr_in_exit) {
 			spin_unlock(&dmxdev->dvr_in_lock);
 			ret = -ENODEV;
 			break;
@@ -609,12 +610,20 @@
 		 * Lock on DVR buffer is released before calling to
 		 * write, if DVR was released meanwhile, dvr_in_exit is
 		 * prompted. Lock is acquired when updating the read pointer
-		 * again to preserve read/write pointers consistency
+		 * again to preserve read/write pointers consistency.
+		 *
+		 * In protected input mode, DVR input buffer is not mapped
+		 * to kernel memory. Underlying demux implementation
+		 * should trigger HW to read from DVR input buffer
+		 * based on current read offset.
 		 */
 		if (split > 0) {
+			data_start = (dmxdev->demux->dvr_input_protected) ?
+						NULL : (src->data + src->pread);
+
 			spin_unlock(&dmxdev->dvr_in_lock);
 			ret = dmxdev->demux->write(dmxdev->demux,
-						src->data + src->pread,
+						data_start,
 						split);
 
 			if (ret < 0) {
@@ -641,9 +650,12 @@
 			}
 		}
 
+		data_start = (dmxdev->demux->dvr_input_protected) ?
+			NULL : (src->data + src->pread);
+
 		spin_unlock(&dmxdev->dvr_in_lock);
 		ret = dmxdev->demux->write(dmxdev->demux,
-			src->data + src->pread, todo);
+			data_start, todo);
 
 		if (ret < 0) {
 			printk(KERN_ERR "dmxdev: dvr write error %d\n",
@@ -708,8 +720,7 @@
 
 			ret = dvb_dvr_feed_cmd(dmxdev, &dvr_cmd);
 			if (ret < 0) {
-				printk(KERN_ERR
-					"%s: DVR data feed failed, ret=%d\n",
+				dprintk("%s: DVR data feed failed, ret=%d\n",
 					__func__, ret);
 				continue;
 			}
@@ -825,6 +836,7 @@
 
 		dmxdev->demux->dvr_input.priv_handle = NULL;
 		dmxdev->demux->dvr_input.ringbuff = &dmxdev->dvr_input_buffer;
+		dmxdev->demux->dvr_input_protected = 0;
 		mem = vmalloc(DVR_CMDS_BUFFER_SIZE);
 		if (!mem) {
 			vfree(dmxdev->dvr_input_buffer.data);
@@ -936,7 +948,8 @@
 		if ((dmxdev->dvr_input_buffer_mode ==
 			DMX_BUFFER_MODE_EXTERNAL) &&
 			(dmxdev->demux->dvr_input.priv_handle)) {
-			dmxdev->demux->unmap_buffer(dmxdev->demux,
+			if (!dmxdev->demux->dvr_input_protected)
+				dmxdev->demux->unmap_buffer(dmxdev->demux,
 					dmxdev->demux->dvr_input.priv_handle);
 			dmxdev->demux->dvr_input.priv_handle = NULL;
 		}
@@ -1130,8 +1143,8 @@
 	for (todo = count; todo > 0; todo -= ret) {
 		ret = wait_event_interruptible(src->queue,
 			(dvb_ringbuffer_free(src)) ||
-			(!src->data) || (!cmdbuf->data) ||
-			(src->error != 0) || (dmxdev->dvr_in_exit));
+			!src->data || !cmdbuf->data ||
+			(src->error != 0) || dmxdev->dvr_in_exit);
 
 		if (ret < 0)
 			return ret;
@@ -1314,6 +1327,7 @@
 	enum dmx_buffer_mode *buffer_mode;
 	void **buff_handle;
 	void *oldmem;
+	int *is_protected;
 
 	if ((mode != DMX_BUFFER_MODE_INTERNAL) &&
 		(mode != DMX_BUFFER_MODE_EXTERNAL))
@@ -1328,11 +1342,13 @@
 		lock = &dmxdev->lock;
 		buffer_mode = &dmxdev->dvr_buffer_mode;
 		buff_handle = &dmxdev->dvr_priv_buff_handle;
+		is_protected = NULL;
 	} else {
 		buf = &dmxdev->dvr_input_buffer;
 		lock = &dmxdev->dvr_in_lock;
 		buffer_mode = &dmxdev->dvr_input_buffer_mode;
 		buff_handle = &dmxdev->demux->dvr_input.priv_handle;
+		is_protected = &dmxdev->demux->dvr_input_protected;
 	}
 
 	if (mode == *buffer_mode)
@@ -1353,6 +1369,9 @@
 			*buff_handle = NULL;
 		}
 
+		if (is_protected)
+			*is_protected = 0;
+
 		/* set default internal buffer */
 		dvb_dvr_set_buffer_size(dmxdev, f_flags, DVR_BUFFER_SIZE);
 	} else if (oldmem) {
@@ -1372,31 +1391,56 @@
 	void **buff_handle;
 	void *newmem;
 	void *oldmem;
+	int *is_protected;
+	struct dmx_caps caps;
+
+	if (dmxdev->demux->get_caps)
+		dmxdev->demux->get_caps(dmxdev->demux, &caps);
+	else
+		caps.caps = 0;
 
 	if ((f_flags & O_ACCMODE) == O_RDONLY) {
 		buf = &dmxdev->dvr_buffer;
 		lock = &dmxdev->lock;
 		buffer_mode = dmxdev->dvr_buffer_mode;
 		buff_handle = &dmxdev->dvr_priv_buff_handle;
+		is_protected = NULL;
 	} else {
 		buf = &dmxdev->dvr_input_buffer;
 		lock = &dmxdev->dvr_in_lock;
 		buffer_mode = dmxdev->dvr_input_buffer_mode;
 		buff_handle = &dmxdev->demux->dvr_input.priv_handle;
+		is_protected = &dmxdev->demux->dvr_input_protected;
+		if (!(caps.caps & DMX_CAP_SECURED_INPUT_PLAYBACK) &&
+			dmx_buffer->is_protected)
+			return -EINVAL;
 	}
 
-	if ((!dmx_buffer->size) ||
+	if (!dmx_buffer->size ||
 		(buffer_mode == DMX_BUFFER_MODE_INTERNAL))
 		return -EINVAL;
 
 	oldmem = *buff_handle;
-	if (dmxdev->demux->map_buffer(dmxdev->demux, dmx_buffer,
-				buff_handle, &newmem))
-		return -ENOMEM;
+
+	/*
+	 * Protected buffer is relevant only for DVR input buffer
+	 * when DVR device is opened for write. In such case,
+	 * buffer is mapped only if the buffer is not protected one.
+	 */
+	if (!is_protected || !dmx_buffer->is_protected) {
+		if (dmxdev->demux->map_buffer(dmxdev->demux, dmx_buffer,
+					buff_handle, &newmem))
+			return -ENOMEM;
+	} else {
+		newmem = NULL;
+		*buff_handle = NULL;
+	}
 
 	spin_lock_irq(lock);
 	buf->data = newmem;
 	buf->size = dmx_buffer->size;
+	if (is_protected)
+		*is_protected = dmx_buffer->is_protected;
 	dvb_ringbuffer_reset(buf);
 	spin_unlock_irq(lock);
 
@@ -1717,19 +1761,20 @@
 static int dvb_dmxdev_set_source(struct dmxdev_filter *dmxdevfilter,
 					dmx_source_t *source)
 {
+	int ret = 0;
 	struct dmxdev *dev;
 
 	if (dmxdevfilter->state == DMXDEV_STATE_GO)
 		return -EBUSY;
 
 	dev = dmxdevfilter->dev;
-
-	dev->source = *source;
-
 	if (dev->demux->set_source)
-		return dev->demux->set_source(dev->demux, source);
+		ret = dev->demux->set_source(dev->demux, source);
 
-	return 0;
+	if (!ret)
+		dev->source = *source;
+
+	return ret;
 }
 
 static int dvb_dmxdev_reuse_decoder_buf(struct dmxdev_filter *dmxdevfilter,
@@ -3105,7 +3150,10 @@
 		tsfeed->set_tsp_out_format(tsfeed, filter->dmx_tsp_format);
 
 	if (tsfeed->set_secure_mode)
-		tsfeed->set_secure_mode(tsfeed, &feed->sec_mode);
+		tsfeed->set_secure_mode(tsfeed, &filter->sec_mode);
+
+	if (tsfeed->set_cipher_ops)
+		tsfeed->set_cipher_ops(tsfeed, &feed->cipher_ops);
 
 	if ((para->pes_type == DMX_PES_VIDEO0) ||
 	    (para->pes_type == DMX_PES_VIDEO1) ||
@@ -3265,7 +3313,11 @@
 
 			if ((*secfeed)->set_secure_mode)
 				(*secfeed)->set_secure_mode(*secfeed,
-					&filter->feed.sec.sec_mode);
+					&filter->sec_mode);
+
+			if ((*secfeed)->set_cipher_ops)
+				(*secfeed)->set_cipher_ops(*secfeed,
+					&filter->feed.sec.cipher_ops);
 		} else {
 			dvb_dmxdev_feed_stop(filter);
 		}
@@ -3434,6 +3486,8 @@
 	dvb_dmxdev_filter_state_set(dmxdevfilter, DMXDEV_STATE_ALLOCATED);
 	init_timer(&dmxdevfilter->timer);
 
+	dmxdevfilter->sec_mode.is_secured = 0;
+
 	INIT_LIST_HEAD(&dmxdevfilter->insertion_buffers);
 
 	dmxdevfilter->dmx_tsp_format = DMX_TSP_FORMAT_188;
@@ -3513,7 +3567,7 @@
 		return -ENOMEM;
 
 	feed->pid = pid;
-	feed->sec_mode.is_secured = 0;
+	feed->cipher_ops.operations_count = 0;
 	feed->idx_params.enable = 0;
 	list_add(&feed->next, &filter->feed.ts);
 
@@ -3568,7 +3622,7 @@
 	memcpy(&dmxdevfilter->params.sec,
 	       params, sizeof(struct dmx_sct_filter_params));
 	invert_mode(&dmxdevfilter->params.sec.filter);
-	dmxdevfilter->feed.sec.sec_mode.is_secured = 0;
+	dmxdevfilter->feed.sec.cipher_ops.operations_count = 0;
 	dvb_dmxdev_filter_state_set(dmxdevfilter, DMXDEV_STATE_SET);
 
 	if (params->flags & DMX_IMMEDIATE_START)
@@ -3582,43 +3636,78 @@
 	struct dmxdev_filter *filter,
 	struct dmx_secure_mode *sec_mode)
 {
+	if (!dmxdev || !filter || !sec_mode)
+		return -EINVAL;
+
+	if (filter->state == DMXDEV_STATE_GO) {
+		printk(KERN_ERR "%s: invalid filter state\n", __func__);
+		return -EBUSY;
+	}
+
+	dprintk(KERN_DEBUG "%s: secure=%d\n", __func__, sec_mode->is_secured);
+
+	filter->sec_mode = *sec_mode;
+
+	return 0;
+}
+
+static int dvb_dmxdev_set_cipher(struct dmxdev *dmxdev,
+	struct dmxdev_filter *filter,
+	struct dmx_cipher_operations *cipher_ops)
+{
 	struct dmxdev_feed *feed;
 	struct dmxdev_feed *ts_feed = NULL;
 	struct dmxdev_sec_feed *sec_feed = NULL;
+	struct dmx_caps caps;
 
-	if (NULL == dmxdev || NULL == filter || NULL == sec_mode)
+	if (!dmxdev || !dmxdev->demux->get_caps)
 		return -EINVAL;
 
+	dmxdev->demux->get_caps(dmxdev->demux, &caps);
+
+	if (!filter || !cipher_ops ||
+		(cipher_ops->operations_count > caps.num_cipher_ops) ||
+		(cipher_ops->operations_count >
+		 DMX_MAX_CIPHER_OPERATIONS_COUNT))
+		return -EINVAL;
+
+	dprintk(KERN_DEBUG "%s: pid=%d, operations=%d\n", __func__,
+		cipher_ops->pid, cipher_ops->operations_count);
+
 	if (filter->state < DMXDEV_STATE_SET ||
 		filter->state > DMXDEV_STATE_GO) {
 		printk(KERN_ERR "%s: invalid filter state\n", __func__);
 		return -EPERM;
 	}
-	dprintk(KERN_DEBUG "%s: key_id=%d, secure=%d, looking for pid=%d\n",
-		__func__, sec_mode->key_ladder_id, sec_mode->is_secured,
-		sec_mode->pid);
+
+	if (!filter->sec_mode.is_secured && cipher_ops->operations_count) {
+		printk(KERN_ERR "%s: secure mode must be enabled to set cipher ops\n",
+			__func__);
+		return -EPERM;
+	}
+
 	switch (filter->type) {
 	case DMXDEV_TYPE_PES:
 		list_for_each_entry(feed, &filter->feed.ts, next) {
-			if (feed->pid == sec_mode->pid) {
+			if (feed->pid == cipher_ops->pid) {
 				ts_feed = feed;
-				ts_feed->sec_mode = *sec_mode;
+				ts_feed->cipher_ops = *cipher_ops;
 				if (filter->state == DMXDEV_STATE_GO &&
-					ts_feed->ts->set_secure_mode)
-					ts_feed->ts->set_secure_mode(
-						ts_feed->ts, sec_mode);
+					ts_feed->ts->set_cipher_ops)
+					ts_feed->ts->set_cipher_ops(
+						ts_feed->ts, cipher_ops);
 				break;
 			}
 		}
 		break;
 	case DMXDEV_TYPE_SEC:
-		if (filter->params.sec.pid == sec_mode->pid) {
+		if (filter->params.sec.pid == cipher_ops->pid) {
 			sec_feed = &filter->feed.sec;
-			sec_feed->sec_mode = *sec_mode;
+			sec_feed->cipher_ops = *cipher_ops;
 			if (filter->state == DMXDEV_STATE_GO &&
-				sec_feed->feed->set_secure_mode)
-				sec_feed->feed->set_secure_mode(sec_feed->feed,
-						sec_mode);
+				sec_feed->feed->set_cipher_ops)
+				sec_feed->feed->set_cipher_ops(sec_feed->feed,
+						cipher_ops);
 		}
 		break;
 
@@ -3628,7 +3717,7 @@
 
 	if (!ts_feed && !sec_feed) {
 		printk(KERN_ERR "%s: pid %d is undefined for this filter\n",
-			__func__, sec_mode->pid);
+			__func__, cipher_ops->pid);
 		return -EINVAL;
 	}
 
@@ -4029,6 +4118,15 @@
 		mutex_unlock(&dmxdevfilter->mutex);
 		break;
 
+	case DMX_SET_CIPHER:
+		if (mutex_lock_interruptible(&dmxdevfilter->mutex)) {
+			ret = -ERESTARTSYS;
+			break;
+		}
+		ret = dvb_dmxdev_set_cipher(dmxdev, dmxdevfilter, parg);
+		mutex_unlock(&dmxdevfilter->mutex);
+		break;
+
 	case DMX_REUSE_DECODER_BUFFER:
 		if (mutex_lock_interruptible(&dmxdevfilter->mutex)) {
 			mutex_unlock(&dmxdev->mutex);
@@ -4384,13 +4482,12 @@
 					buffer_status.fullness);
 				seq_printf(s, "error: %d, ",
 					buffer_status.error);
-				seq_printf(s, "scramble: %d\n",
-					scrambling_bits.value);
-
-			} else {
-				seq_printf(s, "scramble: %d\n",
-					scrambling_bits.value);
 			}
+
+			seq_printf(s, "scramble: %d, ",
+				scrambling_bits.value);
+			seq_printf(s, "secured: %d\n",
+				filter->sec_mode.is_secured);
 		}
 	}
 
@@ -4425,6 +4522,7 @@
 		return -ENOMEM;
 
 	dmxdev->playback_mode = DMX_PB_MODE_PUSH;
+	dmxdev->demux->dvr_input_protected = 0;
 
 	mutex_init(&dmxdev->mutex);
 	spin_lock_init(&dmxdev->lock);
diff --git a/drivers/media/dvb/dvb-core/dmxdev.h b/drivers/media/dvb/dvb-core/dmxdev.h
index 4e306e8..6747ca7 100644
--- a/drivers/media/dvb/dvb-core/dmxdev.h
+++ b/drivers/media/dvb/dvb-core/dmxdev.h
@@ -58,15 +58,15 @@
 
 struct dmxdev_feed {
 	u16 pid;
-	struct dmx_secure_mode sec_mode;
 	struct dmx_indexing_params idx_params;
+	struct dmx_cipher_operations cipher_ops;
 	struct dmx_ts_feed *ts;
 	struct list_head next;
 };
 
 struct dmxdev_sec_feed {
-	struct dmx_secure_mode sec_mode;
 	struct dmx_section_feed *feed;
+	struct dmx_cipher_operations cipher_ops;
 };
 
 #define DMX_EVENT_QUEUE_SIZE	500 /* number of events */
@@ -182,6 +182,8 @@
 	int todo;
 	u8 secheader[3];
 
+	struct dmx_secure_mode sec_mode;
+
 	/* Decoder buffer(s) related */
 	struct dmx_decoder_buffers decoder_buffers;
 };
diff --git a/drivers/media/dvb/dvb-core/dvb_demux.c b/drivers/media/dvb/dvb-core/dvb_demux.c
index bbf2470..692a04e 100644
--- a/drivers/media/dvb/dvb-core/dvb_demux.c
+++ b/drivers/media/dvb/dvb-core/dvb_demux.c
@@ -2262,19 +2262,36 @@
 {
 	struct dvb_demux_feed *dvbdmxfeed = (struct dvb_demux_feed *)feed;
 	struct dvb_demux *dvbdmx = dvbdmxfeed->demux;
+
+	if (mutex_lock_interruptible(&dvbdmx->mutex))
+		return -ERESTARTSYS;
+
+	if (dvbdmxfeed->state == DMX_STATE_GO) {
+		mutex_unlock(&dvbdmx->mutex);
+		return -EBUSY;
+	}
+
+	dvbdmxfeed->secure_mode = *secure_mode;
+	mutex_unlock(&dvbdmx->mutex);
+	return 0;
+}
+
+static int dmx_ts_set_cipher_ops(struct dmx_ts_feed *feed,
+				struct dmx_cipher_operations *cipher_ops)
+{
+	struct dvb_demux_feed *dvbdmxfeed = (struct dvb_demux_feed *)feed;
+	struct dvb_demux *dvbdmx = dvbdmxfeed->demux;
 	int ret = 0;
 
-	mutex_lock(&dvbdmx->mutex);
+	if (mutex_lock_interruptible(&dvbdmx->mutex))
+		return -ERESTARTSYS;
 
 	if ((dvbdmxfeed->state == DMX_STATE_GO) &&
-		dvbdmxfeed->demux->set_secure_mode) {
-		ret = dvbdmxfeed->demux->set_secure_mode(dvbdmxfeed,
-			secure_mode);
-		if (!ret)
-			dvbdmxfeed->secure_mode = *secure_mode;
-	} else {
-		dvbdmxfeed->secure_mode = *secure_mode;
-	}
+		dvbdmx->set_cipher_op)
+		ret = dvbdmx->set_cipher_op(dvbdmxfeed, cipher_ops);
+
+	if (!ret)
+		dvbdmxfeed->cipher_ops = *cipher_ops;
 
 	mutex_unlock(&dvbdmx->mutex);
 	return ret;
@@ -2481,6 +2498,7 @@
 	(*ts_feed)->data_ready_cb = dmx_ts_feed_data_ready_cb;
 	(*ts_feed)->notify_data_read = NULL;
 	(*ts_feed)->set_secure_mode = dmx_ts_set_secure_mode;
+	(*ts_feed)->set_cipher_ops = dmx_ts_set_cipher_ops;
 	(*ts_feed)->oob_command = dvbdmx_ts_feed_oob_cmd;
 	(*ts_feed)->get_scrambling_bits = dvbdmx_ts_get_scrambling_bits;
 	(*ts_feed)->ts_insertion_init = NULL;
@@ -2724,15 +2742,38 @@
 
 	mutex_lock(&dvbdmx->mutex);
 
-	dvbdmxfeed->secure_mode = *secure_mode;
-	if ((dvbdmxfeed->state == DMX_STATE_GO) &&
-		dvbdmxfeed->demux->set_secure_mode)
-		dvbdmxfeed->demux->set_secure_mode(dvbdmxfeed, secure_mode);
+	if (dvbdmxfeed->state == DMX_STATE_GO) {
+		mutex_unlock(&dvbdmx->mutex);
+		return -EBUSY;
+	}
 
+	dvbdmxfeed->secure_mode = *secure_mode;
 	mutex_unlock(&dvbdmx->mutex);
 	return 0;
 }
 
+static int dmx_section_set_cipher_ops(struct dmx_section_feed *feed,
+				struct dmx_cipher_operations *cipher_ops)
+{
+	struct dvb_demux_feed *dvbdmxfeed = (struct dvb_demux_feed *)feed;
+	struct dvb_demux *dvbdmx = dvbdmxfeed->demux;
+	int ret = 0;
+
+	if (mutex_lock_interruptible(&dvbdmx->mutex))
+		return -ERESTARTSYS;
+
+	if ((dvbdmxfeed->state == DMX_STATE_GO) &&
+		dvbdmx->set_cipher_op) {
+		ret = dvbdmx->set_cipher_op(dvbdmxfeed, cipher_ops);
+	}
+
+	if (!ret)
+		dvbdmxfeed->cipher_ops = *cipher_ops;
+
+	mutex_unlock(&dvbdmx->mutex);
+	return ret;
+}
+
 static int dmx_section_feed_release_filter(struct dmx_section_feed *feed,
 					   struct dmx_section_filter *filter)
 {
@@ -2875,6 +2916,7 @@
 	(*feed)->data_ready_cb = dmx_section_feed_data_ready_cb;
 	(*feed)->notify_data_read = NULL;
 	(*feed)->set_secure_mode = dmx_section_set_secure_mode;
+	(*feed)->set_cipher_ops = dmx_section_set_cipher_ops;
 	(*feed)->oob_command = dvbdmx_section_feed_oob_cmd;
 	(*feed)->get_scrambling_bits = dvbdmx_section_get_scrambling_bits;
 
@@ -2939,8 +2981,10 @@
 {
 	struct dvb_demux *dvbdemux = (struct dvb_demux *)demux;
 
-	if ((!demux->frontend) || (demux->frontend->source != DMX_MEMORY_FE))
+	if (!demux->frontend || !buf || demux->dvr_input_protected ||
+		(demux->frontend->source != DMX_MEMORY_FE)) {
 		return -EINVAL;
+	}
 
 	dvb_dmx_swfilter_format(dvbdemux, buf, count, dvbdemux->tsp_format);
 
diff --git a/drivers/media/dvb/dvb-core/dvb_demux.h b/drivers/media/dvb/dvb-core/dvb_demux.h
index aeafa57..835e7b8 100644
--- a/drivers/media/dvb/dvb-core/dvb_demux.h
+++ b/drivers/media/dvb/dvb-core/dvb_demux.h
@@ -176,6 +176,7 @@
 	int buffer_size;
 	enum dmx_tsp_format_t tsp_out_format;
 	struct dmx_secure_mode secure_mode;
+	struct dmx_cipher_operations cipher_ops;
 
 	struct timespec timeout;
 	struct dvb_demux_filter *filter;
@@ -233,8 +234,8 @@
 				struct dmx_buffer_status *dmx_buffer_status);
 	int (*reuse_decoder_buffer)(struct dvb_demux_feed *feed,
 				int cookie);
-	int (*set_secure_mode)(struct dvb_demux_feed *feed,
-				struct dmx_secure_mode *secure_mode);
+	int (*set_cipher_op)(struct dvb_demux_feed *feed,
+				struct dmx_cipher_operations *cipher_ops);
 	u32 (*check_crc32)(struct dvb_demux_feed *feed,
 			    const u8 *buf, size_t len);
 	void (*memcopy)(struct dvb_demux_feed *feed, u8 *dst,
diff --git a/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_common.c b/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_common.c
index 85fdff6..75b75ea 100644
--- a/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_common.c
+++ b/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_common.c
@@ -692,6 +692,7 @@
 			memset(feed, 0, sizeof(*feed));
 			feed->sdmx_filter_handle = SDMX_INVALID_FILTER_HANDLE;
 			feed->mpq_demux = mpq_demux;
+			feed->session_id = 0;
 		}
 
 		/*
@@ -3649,16 +3650,18 @@
 	 * If pid has a key ladder id associated, we need to
 	 * set it to SDMX.
 	 */
-	if (dvbdmx_feed->secure_mode.is_secured)  {
+	if (dvbdmx_feed->secure_mode.is_secured &&
+		dvbdmx_feed->cipher_ops.operations_count) {
 		MPQ_DVB_DBG_PRINT(
-				"%s: set key-ladder %d to PID %d\n",
-				__func__,
-				dvbdmx_feed->secure_mode.key_ladder_id,
-				dvbdmx_feed->secure_mode.pid);
-		ret = sdmx_set_kl_ind(
-			mpq_demux->sdmx_session_handle,
-			dvbdmx_feed->secure_mode.pid,
-			dvbdmx_feed->secure_mode.key_ladder_id);
+			"%s: set key-ladder %d to PID %d\n",
+			__func__,
+			dvbdmx_feed->cipher_ops.operations[0].key_ladder_id,
+			dvbdmx_feed->cipher_ops.pid);
+
+		ret = sdmx_set_kl_ind(mpq_demux->sdmx_session_handle,
+			dvbdmx_feed->cipher_ops.pid,
+			dvbdmx_feed->cipher_ops.operations[0].key_ladder_id);
+
 		if (ret) {
 			MPQ_DVB_ERR_PRINT(
 				"%s: FAILED to set key ladder, ret=%d\n",
@@ -3776,8 +3779,10 @@
 	}
 
 init_mpq_feed_end:
-	if (!ret)
+	if (!ret) {
 		mpq_demux->num_active_feeds++;
+		mpq_feed->session_id++;
+	}
 	mutex_unlock(&mpq_demux->mutex);
 	return ret;
 }
@@ -3786,14 +3791,14 @@
 /**
  * Note: Called only when filter is in "GO" state - after feed has been started.
  */
-int mpq_dmx_set_secure_mode(struct dvb_demux_feed *feed,
-	struct dmx_secure_mode *sec_mode)
+int mpq_dmx_set_cipher_ops(struct dvb_demux_feed *feed,
+		struct dmx_cipher_operations *cipher_ops)
 {
 	struct mpq_feed *mpq_feed;
 	struct mpq_demux *mpq_demux;
 	int ret = 0;
 
-	if (!feed || !feed->priv || !sec_mode) {
+	if (!feed || !feed->priv || !cipher_ops) {
 		MPQ_DVB_ERR_PRINT(
 			"%s: invalid parameters\n",
 			__func__);
@@ -3801,37 +3806,45 @@
 	}
 
 	MPQ_DVB_DBG_PRINT("%s(%d, %d, %d)\n",
-		__func__, sec_mode->pid,
-		sec_mode->is_secured,
-		sec_mode->key_ladder_id);
+		__func__, cipher_ops->pid,
+		cipher_ops->operations_count,
+		cipher_ops->operations[0].key_ladder_id);
+
+	if ((cipher_ops->operations_count > 1) ||
+		(cipher_ops->operations_count &&
+		 cipher_ops->operations[0].encrypt)) {
+		MPQ_DVB_ERR_PRINT(
+			"%s: Invalid cipher operations, count=%d, encrypt=%d\n",
+			__func__, cipher_ops->operations_count,
+			cipher_ops->operations[0].encrypt);
+		return -EINVAL;
+	}
+
+	if (!feed->secure_mode.is_secured) {
+		/*
+		 * Filter is not configured as secured, setting cipher
+		 * operations is not allowed.
+		 */
+		MPQ_DVB_ERR_PRINT(
+			"%s: Cannot set cipher operations to non-secure filter\n",
+			__func__);
+		return -EPERM;
+	}
 
 	mpq_feed = feed->priv;
 	mpq_demux = mpq_feed->mpq_demux;
 
 	mutex_lock(&mpq_demux->mutex);
 
-	if (feed->secure_mode.is_secured != sec_mode->is_secured) {
-		/*
-		 * Switching between secure & non-secure mode is not allowed
-		 * while filter is running
-		 */
-		MPQ_DVB_ERR_PRINT(
-			"%s: Cannot switch between secure mode while filter is running\n",
-			__func__);
-		mutex_unlock(&mpq_demux->mutex);
-		return -EPERM;
-	}
-
 	/*
 	 * Feed is running in secure mode, this secure mode request is to
 	 * update the key ladder id
 	 */
-	if (feed->secure_mode.pid == sec_mode->pid && sec_mode->is_secured &&
-		feed->secure_mode.key_ladder_id != sec_mode->key_ladder_id &&
-		mpq_demux->sdmx_session_handle != SDMX_INVALID_SESSION_HANDLE) {
+	if ((mpq_demux->sdmx_session_handle != SDMX_INVALID_SESSION_HANDLE) &&
+		cipher_ops->operations_count) {
 		ret = sdmx_set_kl_ind(mpq_demux->sdmx_session_handle,
-			sec_mode->pid,
-			sec_mode->key_ladder_id);
+			cipher_ops->pid,
+			cipher_ops->operations[0].key_ladder_id);
 		if (ret) {
 			MPQ_DVB_ERR_PRINT(
 				"%s: FAILED to set key ladder, ret=%d\n",
@@ -3844,7 +3857,7 @@
 
 	return ret;
 }
-EXPORT_SYMBOL(mpq_dmx_set_secure_mode);
+EXPORT_SYMBOL(mpq_dmx_set_cipher_ops);
 
 static void mpq_sdmx_prepare_filter_status(struct mpq_demux *mpq_demux,
 	struct sdmx_filter_status *filter_sts,
@@ -4525,19 +4538,14 @@
 static void mpq_sdmx_process_results(struct mpq_demux *mpq_demux)
 {
 	int i;
-	int j;
 	int sdmx_filters;
 	struct sdmx_filter_status *sts;
 	struct mpq_feed *mpq_feed;
+	u8 mpq_feed_idx;
 
 	sdmx_filters = mpq_demux->sdmx_filter_count;
 	for (i = 0; i < sdmx_filters; i++) {
-		/*
-		 * MPQ_TODO: review lookup optimization
-		 * Can have the related mpq_feed index already associated with
-		 * the filter status.
-		 */
-		sts = &mpq_demux->filters_status[i];
+		sts = &mpq_demux->sdmx_filters_state.status[i];
 		MPQ_DVB_DBG_PRINT(
 			"%s: Filter: handle=%d, status=0x%x, errors=0x%x\n",
 			__func__, sts->filter_handle, sts->status_indicators,
@@ -4548,16 +4556,13 @@
 		MPQ_DVB_DBG_PRINT("%s: Data fill count=%d (write=%d)\n",
 			__func__, sts->data_fill_count, sts->data_write_offset);
 
-		for (j = 0; j < MPQ_MAX_DMX_FILES; j++) {
-			mpq_feed = &mpq_demux->feeds[j];
-			if ((mpq_feed->dvb_demux_feed->state == DMX_STATE_GO) &&
-				(sts->filter_handle ==
-					mpq_feed->sdmx_filter_handle) &&
-				(!mpq_feed->secondary_feed))
-				break;
-		}
-
-		if (j == MPQ_MAX_DMX_FILES)
+		mpq_feed_idx = mpq_demux->sdmx_filters_state.mpq_feed_idx[i];
+		mpq_feed = &mpq_demux->feeds[mpq_feed_idx];
+		if ((mpq_feed->dvb_demux_feed->state != DMX_STATE_GO) ||
+			(sts->filter_handle != mpq_feed->sdmx_filter_handle) ||
+			mpq_feed->secondary_feed ||
+			(mpq_demux->sdmx_filters_state.session_id[i] !=
+			 mpq_feed->session_id))
 			continue;
 
 		if (sts->error_indicators & SDMX_FILTER_ERR_MD_BUF_FULL)
@@ -4636,9 +4641,14 @@
 		if ((mpq_feed->sdmx_filter_handle != SDMX_INVALID_FILTER_HANDLE)
 			&& (mpq_feed->dvb_demux_feed->state == DMX_STATE_GO)
 			&& (!mpq_feed->secondary_feed)) {
-			sts = &mpq_demux->filters_status[filter_index];
+			sts = mpq_demux->sdmx_filters_state.status +
+				filter_index;
 			mpq_sdmx_prepare_filter_status(mpq_demux, sts,
 				mpq_feed);
+			mpq_demux->sdmx_filters_state.mpq_feed_idx[filter_index]
+				 = i;
+			mpq_demux->sdmx_filters_state.session_id[filter_index] =
+				mpq_feed->session_id;
 			filter_index++;
 		}
 	}
@@ -4662,7 +4672,8 @@
 	prev_fill_count = fill_count;
 	sdmx_res = sdmx_process(mpq_demux->sdmx_session_handle, flags, input,
 		&fill_count, &read_offset, &errors, &status,
-		mpq_demux->sdmx_filter_count, mpq_demux->filters_status);
+		mpq_demux->sdmx_filter_count,
+		mpq_demux->sdmx_filters_state.status);
 
 	process_end_time = current_kernel_time();
 	bytes_read = prev_fill_count - fill_count;
diff --git a/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_common.h b/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_common.h
index ca7c15a..f095e00 100644
--- a/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_common.h
+++ b/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_common.h
@@ -322,6 +322,8 @@
  * other feeds
  * @metadata_buf: Ring buffer object for managing the metadata buffer
  * @metadata_buf_handle: Allocation handle for the metadata buffer
+ * @session_id: Counter that is incremented every time feed is initialized
+ * through mpq_dmx_init_mpq_feed
  * @sdmx_buf: Ring buffer object for intermediate output data from the sdmx
  * @sdmx_buf_handle: Allocation handle for the sdmx intermediate data buffer
  * @video_info: Video feed specific information
@@ -338,6 +340,7 @@
 	struct dvb_ringbuffer metadata_buf;
 	struct ion_handle *metadata_buf_handle;
 
+	u8 session_id;
 	struct dvb_ringbuffer sdmx_buf;
 	struct ion_handle *sdmx_buf_handle;
 
@@ -355,23 +358,24 @@
  * @ion_client: ION demux client used to allocate memory from ION.
  * @mutex: Lock used to protect against private feed data
  * @feeds: mpq common feed object pool
+ * @plugin_priv: Underlying plugin's own private data
  * @num_active_feeds: Number of active mpq feeds
  * @num_secure_feeds: Number of secure feeds (have a sdmx filter associated)
  * currently allocated.
- * @filters_status: Array holding buffers status for each secure demux filter.
  * Used before each call to sdmx_process() to build up to date state.
  * @sdmx_session_handle: Secure demux open session handle
  * @sdmx_filter_count: Number of active secure demux filters
  * @sdmx_eos: End-of-stream indication flag for current sdmx session
- * @plugin_priv: Underlying plugin's own private data
+ * @sdmx_filters_state: Array holding buffers status for each secure
+ * demux filter.
  * @hw_notification_interval: Notification interval in msec,
- *                            exposed in debugfs.
+ * exposed in debugfs.
  * @hw_notification_min_interval: Minimum notification internal in msec,
  * exposed in debugfs.
  * @hw_notification_count: Notification count, exposed in debugfs.
  * @hw_notification_size: Notification size in bytes, exposed in debugfs.
  * @hw_notification_min_size: Minimum notification size in bytes,
- *                            exposed in debugfs.
+ * exposed in debugfs.
  * @decoder_drop_count: Accumulated number of bytes dropped due to decoder
  * buffer fullness, exposed in debugfs.
  * @decoder_out_count: Counter incremeneted for each video frame output by
@@ -403,14 +407,31 @@
 	struct ion_client *ion_client;
 	struct mutex mutex;
 	struct mpq_feed feeds[MPQ_MAX_DMX_FILES];
+	void *plugin_priv;
+
 	u32 num_active_feeds;
 	u32 num_secure_feeds;
-	struct sdmx_filter_status filters_status[MPQ_MAX_DMX_FILES];
 	int sdmx_session_handle;
 	int sdmx_session_ref_count;
 	int sdmx_filter_count;
 	int sdmx_eos;
-	void *plugin_priv;
+	struct {
+		/* SDMX filters status */
+		struct sdmx_filter_status status[MPQ_MAX_DMX_FILES];
+
+		/* Index of the feed respective to SDMX filter */
+		u8 mpq_feed_idx[MPQ_MAX_DMX_FILES];
+
+		/*
+		 * Snapshot of session_id of the feed
+		 * when SDMX process was called. This is used
+		 * to identify whether the feed has been
+		 * restarted when processing SDMX results.
+		 * May happen when demux is stalled in playback
+		 * from memory with PULL mode.
+		 */
+		u8 session_id[MPQ_MAX_DMX_FILES];
+	} sdmx_filters_state;
 
 	/* debug-fs */
 	u32 hw_notification_interval;
@@ -633,15 +654,19 @@
 void mpq_dmx_update_hw_statistics(struct mpq_demux *mpq_demux);
 
 /**
- * mpq_dmx_set_secure_mode - Handles set secure mode command from demux device
+ * mpq_dmx_set_cipher_ops - Handles setting of cipher operations
  *
- * @feed: The feed to set its secure mode
- * @sec_mode: Secure mode details (key ladder info)
+ * @feed: The feed to set its cipher operations
+ * @cipher_ops: Cipher operations to be set
+ *
+ * This common function handles only the case when working with
+ * secure-demux. When working with secure demux a single decrypt cipher
+ * operation is allowed.
  *
  * Return error code
-*/
-int mpq_dmx_set_secure_mode(struct dvb_demux_feed *feed,
-		struct dmx_secure_mode *secure_mode);
+ */
+int mpq_dmx_set_cipher_ops(struct dvb_demux_feed *feed,
+		struct dmx_cipher_operations *cipher_ops);
 
 /**
  * mpq_dmx_convert_tts - Convert timestamp attached by HW to each TS
@@ -652,7 +677,7 @@
  * @timestampIn27Mhz: Timestamp result in 27MHz
  *
  * Return error code
-*/
+ */
 void mpq_dmx_convert_tts(struct dvb_demux_feed *feed,
 		const u8 timestamp[TIMESTAMP_LEN],
 		u64 *timestampIn27Mhz);
diff --git a/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_tsif.c b/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_tsif.c
index 5daa842..40445b0 100644
--- a/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_tsif.c
+++ b/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_tsif.c
@@ -561,6 +561,7 @@
 	caps->max_bitrate = 144;
 	caps->demod_input_max_bitrate = 72;
 	caps->memory_input_max_bitrate = 72;
+	caps->num_cipher_ops = 0;
 
 	/* TSIF reports 3 bytes STC at unit of 27MHz/256 */
 	caps->max_stc = (u64)0xFFFFFF * 256;
diff --git a/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_tspp_v1.c b/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_tspp_v1.c
index 5bd008d..940a4bc 100644
--- a/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_tspp_v1.c
+++ b/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_tspp_v1.c
@@ -1627,6 +1627,7 @@
 	caps->max_bitrate = 192;
 	caps->demod_input_max_bitrate = 96;
 	caps->memory_input_max_bitrate = 96;
+	caps->num_cipher_ops = 1;
 
 	/* TSIF reports 3 bytes STC at unit of 27MHz/256 */
 	caps->max_stc = (u64)0xFFFFFF * 256;
@@ -1747,7 +1748,7 @@
 		mpq_dmx_decoder_fullness_abort;
 	mpq_demux->demux.decoder_buffer_status = mpq_dmx_decoder_buffer_status;
 	mpq_demux->demux.reuse_decoder_buffer = mpq_dmx_reuse_decoder_buffer;
-	mpq_demux->demux.set_secure_mode = mpq_dmx_set_secure_mode;
+	mpq_demux->demux.set_cipher_op = mpq_dmx_set_cipher_ops;
 	mpq_demux->demux.oob_command = mpq_dmx_oob_command;
 	mpq_demux->demux.convert_ts = mpq_dmx_convert_tts;
 
diff --git a/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_tspp_v2.c b/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_tspp_v2.c
index 9837e9f..c2e37a4 100644
--- a/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_tspp_v2.c
+++ b/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_tspp_v2.c
@@ -73,7 +73,8 @@
 	}
 
 	caps->caps = DMX_CAP_PULL_MODE | DMX_CAP_VIDEO_INDEXING |
-		DMX_CAP_VIDEO_DECODER_DATA | DMX_CAP_TS_INSERTION;
+		DMX_CAP_VIDEO_DECODER_DATA | DMX_CAP_TS_INSERTION |
+		DMX_CAP_SECURED_INPUT_PLAYBACK;
 	caps->num_decoders = MPQ_ADAPTER_MAX_NUM_OF_INTERFACES;
 	caps->num_demux_devices = CONFIG_DVB_MPQ_NUM_DMX_DEVICES;
 	caps->num_pid_filters = TSPP_MAX_PID_FILTER_NUM;
@@ -85,6 +86,7 @@
 	caps->max_bitrate = 320;
 	caps->demod_input_max_bitrate = 96;
 	caps->memory_input_max_bitrate = 80;
+	caps->num_cipher_ops = DMX_MAX_CIPHER_OPERATIONS_COUNT;
 
 	/* TSIF reports 7 bytes STC at unit of 27MHz */
 	caps->max_stc = 0x00FFFFFFFFFFFFFF;
diff --git a/drivers/media/platform/msm/vidc/Makefile b/drivers/media/platform/msm/vidc/Makefile
index 6977165..ff6274c 100644
--- a/drivers/media/platform/msm/vidc/Makefile
+++ b/drivers/media/platform/msm/vidc/Makefile
@@ -5,6 +5,7 @@
 				msm_venc.o \
 				msm_smem.o \
 				msm_vidc_debug.o \
+				msm_vidc_res_parse.o \
 				venus_hfi.o \
 				hfi_response_handler.o \
 				hfi_packetization.o \
diff --git a/drivers/media/platform/msm/vidc/msm_v4l2_vidc.c b/drivers/media/platform/msm/vidc/msm_v4l2_vidc.c
index 687bd71..96d95989 100644
--- a/drivers/media/platform/msm/vidc/msm_v4l2_vidc.c
+++ b/drivers/media/platform/msm/vidc/msm_v4l2_vidc.c
@@ -20,7 +20,6 @@
 #include <linux/debugfs.h>
 #include <linux/version.h>
 #include <linux/slab.h>
-#include <linux/of.h>
 #include <mach/board.h>
 #include <mach/iommu.h>
 #include <mach/iommu_domains.h>
@@ -31,6 +30,7 @@
 #include "msm_smem.h"
 #include "vidc_hfi_api.h"
 #include "msm_vidc_resources.h"
+#include "msm_vidc_res_parse.h"
 
 #define BASE_DEVICE_NUMBER 32
 
@@ -54,50 +54,6 @@
 	struct list_head registered_bufs;
 };
 
-struct master_slave {
-	int masters_ocmem[2];
-	int masters_ddr[2];
-	int slaves_ocmem[2];
-	int slaves_ddr[2];
-};
-
-struct bus_pdata_config {
-	int *masters;
-	int *slaves;
-	char *name;
-};
-
-static struct master_slave bus_vectors_masters_slaves = {
-	.masters_ocmem = {MSM_BUS_MASTER_VIDEO_P0_OCMEM,
-				MSM_BUS_MASTER_VIDEO_P1_OCMEM},
-	.masters_ddr = {MSM_BUS_MASTER_VIDEO_P0, MSM_BUS_MASTER_VIDEO_P1},
-	.slaves_ocmem = {MSM_BUS_SLAVE_OCMEM, MSM_BUS_SLAVE_OCMEM},
-	.slaves_ddr = {MSM_BUS_SLAVE_EBI_CH0, MSM_BUS_SLAVE_EBI_CH0},
-};
-
-static struct bus_pdata_config bus_pdata_config_vector[] = {
-{
-	.masters = bus_vectors_masters_slaves.masters_ocmem,
-	.slaves = bus_vectors_masters_slaves.slaves_ocmem,
-	.name = "qcom,enc-ocmem-ab-ib",
-},
-{
-	.masters = bus_vectors_masters_slaves.masters_ocmem,
-	.slaves = bus_vectors_masters_slaves.slaves_ocmem,
-	.name = "qcom,dec-ocmem-ab-ib",
-},
-{
-	.masters = bus_vectors_masters_slaves.masters_ddr,
-	.slaves = bus_vectors_masters_slaves.slaves_ddr,
-	.name = "qcom,enc-ddr-ab-ib",
-},
-{
-	.masters = bus_vectors_masters_slaves.masters_ddr,
-	.slaves = bus_vectors_masters_slaves.slaves_ddr,
-	.name = "qcom,dec-ddr-ab-ib",
-},
-};
-
 static inline struct msm_vidc_inst *get_vidc_inst(struct file *filp, void *fh)
 {
 	return container_of(filp->private_data,
@@ -736,578 +692,6 @@
 {
 }
 
-static size_t get_u32_array_num_elements(struct platform_device *pdev,
-					char *name)
-{
-	struct device_node *np = pdev->dev.of_node;
-	int len;
-	size_t num_elements = 0;
-	if (!of_get_property(np, name, &len)) {
-		dprintk(VIDC_ERR, "Failed to read %s from device tree\n",
-			name);
-		goto fail_read;
-	}
-
-	num_elements = len / sizeof(u32);
-	if (num_elements <= 0) {
-		dprintk(VIDC_ERR, "%s not specified in device tree\n",
-			name);
-		goto fail_read;
-	}
-	return num_elements / 2;
-
-fail_read:
-	return 0;
-}
-
-static int read_hfi_type(struct platform_device *pdev)
-{
-	struct device_node *np = pdev->dev.of_node;
-	int rc = 0;
-	const char *hfi_name = NULL;
-
-	if (np) {
-		rc = of_property_read_string(np, "qcom,hfi", &hfi_name);
-		if (rc) {
-			dprintk(VIDC_ERR,
-				"Failed to read hfi from device tree\n");
-			goto err_hfi_read;
-		}
-		if (!strcmp(hfi_name, "venus"))
-			rc = VIDC_HFI_VENUS;
-		else if (!strcmp(hfi_name, "q6"))
-			rc = VIDC_HFI_Q6;
-		else
-			rc = -EINVAL;
-	} else
-		rc = VIDC_HFI_Q6;
-
-err_hfi_read:
-	return rc;
-}
-
-static inline void msm_vidc_free_freq_table(
-		struct msm_vidc_platform_resources *res)
-{
-	kfree(res->load_freq_tbl);
-	res->load_freq_tbl = NULL;
-}
-
-static inline void msm_vidc_free_reg_table(
-			struct msm_vidc_platform_resources *res)
-{
-	kfree(res->reg_set.reg_tbl);
-	res->reg_set.reg_tbl = NULL;
-}
-
-static inline void msm_vidc_free_bus_vectors(
-			struct msm_vidc_platform_resources *res)
-{
-	int i, j;
-	if (res->bus_pdata) {
-		for (i = 0; i < ARRAY_SIZE(bus_pdata_config_vector); i++) {
-			for (j = 0; j < res->bus_pdata[i].num_usecases; j++) {
-				kfree(res->bus_pdata[i].usecase[j].vectors);
-				res->bus_pdata[i].usecase[j].vectors = NULL;
-			}
-			kfree(res->bus_pdata[i].usecase);
-			res->bus_pdata[i].usecase = NULL;
-		}
-		kfree(res->bus_pdata);
-		res->bus_pdata = NULL;
-	}
-}
-
-static inline void msm_vidc_free_iommu_groups(
-			struct msm_vidc_platform_resources *res)
-{
-	kfree(res->iommu_group_set.iommu_maps);
-	res->iommu_group_set.iommu_maps = NULL;
-}
-
-static inline void msm_vidc_free_buffer_usage_table(
-			struct msm_vidc_platform_resources *res)
-{
-	kfree(res->buffer_usage_set.buffer_usage_tbl);
-	res->buffer_usage_set.buffer_usage_tbl = NULL;
-}
-
-static int msm_vidc_load_freq_table(struct msm_vidc_platform_resources *res)
-{
-	int rc = 0;
-	int num_elements = 0;
-	struct platform_device *pdev = res->pdev;
-
-	num_elements = get_u32_array_num_elements(pdev, "qcom,load-freq-tbl");
-	if (num_elements == 0) {
-		dprintk(VIDC_ERR, "no elements in frequency table\n");
-		return rc;
-	}
-
-	res->load_freq_tbl = kzalloc(num_elements * sizeof(*res->load_freq_tbl),
-			GFP_KERNEL);
-	if (!res->load_freq_tbl) {
-		dprintk(VIDC_ERR,
-				"%s Failed to alloc load_freq_tbl\n",
-				__func__);
-		return -ENOMEM;
-	}
-
-	if (of_property_read_u32_array(pdev->dev.of_node,
-		"qcom,load-freq-tbl", (u32 *)res->load_freq_tbl,
-		num_elements * 2)) {
-		dprintk(VIDC_ERR, "Failed to read frequency table\n");
-		msm_vidc_free_freq_table(res);
-		return -EINVAL;
-	}
-
-	res->load_freq_tbl_size = num_elements;
-	return rc;
-}
-
-static int msm_vidc_load_reg_table(struct msm_vidc_platform_resources *res)
-{
-	struct reg_set *reg_set;
-	struct platform_device *pdev = res->pdev;
-	int i;
-	int rc = 0;
-
-	reg_set = &res->reg_set;
-	reg_set->count = get_u32_array_num_elements(pdev, "qcom,reg-presets");
-	if (reg_set->count == 0) {
-		dprintk(VIDC_DBG, "no elements in reg set\n");
-		return rc;
-	}
-
-	reg_set->reg_tbl = kzalloc(reg_set->count *
-			sizeof(*(reg_set->reg_tbl)), GFP_KERNEL);
-	if (!reg_set->reg_tbl) {
-		dprintk(VIDC_ERR, "%s Failed to alloc register table\n",
-			__func__);
-		return -ENOMEM;
-	}
-
-	if (of_property_read_u32_array(pdev->dev.of_node, "qcom,reg-presets",
-		(u32 *)reg_set->reg_tbl, reg_set->count * 2)) {
-		dprintk(VIDC_ERR, "Failed to read register table\n");
-		msm_vidc_free_reg_table(res);
-		return -EINVAL;
-	}
-	for (i = 0; i < reg_set->count; i++) {
-		dprintk(VIDC_DBG,
-			"reg = %x, value = %x\n",
-			reg_set->reg_tbl[i].reg,
-			reg_set->reg_tbl[i].value
-		);
-	}
-	return rc;
-}
-
-static void msm_vidc_free_bus_vector(struct msm_bus_scale_pdata *bus_pdata)
-{
-	int i;
-	for (i = 0; i < bus_pdata->num_usecases; i++) {
-		kfree(bus_pdata->usecase[i].vectors);
-		bus_pdata->usecase[i].vectors = NULL;
-	}
-
-	kfree(bus_pdata->usecase);
-	bus_pdata->usecase = NULL;
-}
-
-static int msm_vidc_load_bus_vector(struct platform_device *pdev,
-			struct msm_bus_scale_pdata *bus_pdata, u32 num_ports,
-			struct bus_pdata_config *bus_pdata_config)
-{
-	struct bus_values {
-	    u32 ab;
-	    u32 ib;
-	};
-	struct bus_values *values;
-	int i, j;
-	int rc = 0;
-
-	values = kzalloc(sizeof(*values) * bus_pdata->num_usecases, GFP_KERNEL);
-	if (!values) {
-		dprintk(VIDC_ERR, "%s Failed to alloc bus_values\n", __func__);
-		rc = -ENOMEM;
-		goto err_mem_alloc;
-	}
-
-	if (of_property_read_u32_array(pdev->dev.of_node,
-		    bus_pdata_config->name, (u32 *)values,
-		    bus_pdata->num_usecases * (sizeof(*values)/sizeof(u32)))) {
-		dprintk(VIDC_ERR, "%s Failed to read bus values\n", __func__);
-		rc = -EINVAL;
-		goto err_parse_dt;
-	}
-
-	bus_pdata->usecase = kzalloc(sizeof(*bus_pdata->usecase) *
-		    bus_pdata->num_usecases, GFP_KERNEL);
-	if (!bus_pdata->usecase) {
-		dprintk(VIDC_ERR,
-			"%s Failed to alloc bus_pdata usecase\n", __func__);
-		rc = -ENOMEM;
-		goto err_parse_dt;
-	}
-	bus_pdata->name = bus_pdata_config->name;
-	for (i = 0; i < bus_pdata->num_usecases; i++) {
-		bus_pdata->usecase[i].vectors = kzalloc(
-			sizeof(*bus_pdata->usecase[i].vectors) * num_ports,
-			GFP_KERNEL);
-		if (!bus_pdata->usecase) {
-			dprintk(VIDC_ERR,
-				"%s Failed to alloc bus_pdata usecase\n",
-				__func__);
-			break;
-		}
-		for (j = 0; j < num_ports; j++) {
-			bus_pdata->usecase[i].vectors[j].ab = (u64)values[i].ab
-									* 1000;
-			bus_pdata->usecase[i].vectors[j].ib = (u64)values[i].ib
-									* 1000;
-			bus_pdata->usecase[i].vectors[j].src =
-						bus_pdata_config->masters[j];
-			bus_pdata->usecase[i].vectors[j].dst =
-						bus_pdata_config->slaves[j];
-			dprintk(VIDC_DBG,
-				"ab = %llu, ib = %llu, src = %d, dst = %d\n",
-				bus_pdata->usecase[i].vectors[j].ab,
-				bus_pdata->usecase[i].vectors[j].ib,
-				bus_pdata->usecase[i].vectors[j].src,
-				bus_pdata->usecase[i].vectors[j].dst);
-		}
-		bus_pdata->usecase[i].num_paths = num_ports;
-	}
-	if (i < bus_pdata->num_usecases) {
-		for (--i; i >= 0; i--) {
-			kfree(bus_pdata->usecase[i].vectors);
-			bus_pdata->usecase[i].vectors = NULL;
-		}
-		kfree(bus_pdata->usecase);
-		bus_pdata->usecase = NULL;
-		rc = -EINVAL;
-	}
-err_parse_dt:
-	kfree(values);
-err_mem_alloc:
-	return rc;
-}
-
-static int msm_vidc_load_bus_vectors(struct msm_vidc_platform_resources *res)
-{
-	u32 num_ports = 0;
-	int rc = 0;
-	int i;
-	struct platform_device *pdev = res->pdev;
-	u32 num_bus_pdata = ARRAY_SIZE(bus_pdata_config_vector);
-
-	if (of_property_read_u32_array(pdev->dev.of_node, "qcom,bus-ports",
-			(u32 *)&num_ports, 1) || (num_ports == 0))
-		goto err_mem_alloc;
-
-	res->bus_pdata = kzalloc(sizeof(*res->bus_pdata) * num_bus_pdata,
-				GFP_KERNEL);
-	if (!res->bus_pdata) {
-		dprintk(VIDC_ERR, "Failed to alloc memory\n");
-		rc = -ENOMEM;
-		goto err_mem_alloc;
-	}
-	for (i = 0; i < num_bus_pdata; i++) {
-		if (!res->has_ocmem &&
-			(!strcmp(bus_pdata_config_vector[i].name,
-				"qcom,enc-ocmem-ab-ib")
-			|| !strcmp(bus_pdata_config_vector[i].name,
-				"qcom,dec-ocmem-ab-ib"))) {
-			continue;
-		}
-		res->bus_pdata[i].num_usecases = get_u32_array_num_elements(
-					pdev, bus_pdata_config_vector[i].name);
-		if (res->bus_pdata[i].num_usecases == 0) {
-			dprintk(VIDC_ERR, "no elements in %s\n",
-				bus_pdata_config_vector[i].name);
-			rc = -EINVAL;
-			break;
-		}
-
-		rc = msm_vidc_load_bus_vector(pdev, &res->bus_pdata[i],
-				num_ports, &bus_pdata_config_vector[i]);
-		if (rc) {
-			dprintk(VIDC_ERR,
-				"Failed to load bus vector: %d\n", i);
-			break;
-		}
-	}
-	if (i < num_bus_pdata) {
-		for (--i; i >= 0; i--)
-			msm_vidc_free_bus_vector(&res->bus_pdata[i]);
-		kfree(res->bus_pdata);
-		res->bus_pdata = NULL;
-	}
-err_mem_alloc:
-	return rc;
-}
-
-static int msm_vidc_load_iommu_groups(struct msm_vidc_platform_resources *res)
-{
-	int rc = 0;
-	struct platform_device *pdev = res->pdev;
-	struct device_node *ctx_node;
-	struct iommu_set *iommu_group_set = &res->iommu_group_set;
-	int array_size;
-	int i;
-	struct iommu_info *iommu_map;
-	u32 *buffer_types = NULL;
-
-	if (!of_get_property(pdev->dev.of_node, "qcom,iommu-groups",
-				&array_size)) {
-		dprintk(VIDC_DBG, "iommu_groups property not present\n");
-		iommu_group_set->count = 0;
-		return 0;
-	}
-
-	iommu_group_set->count = array_size / sizeof(u32);
-	if (iommu_group_set->count == 0) {
-		dprintk(VIDC_ERR, "No group present in iommu_groups\n");
-		rc = -ENOENT;
-		goto err_no_of_node;
-	}
-
-	iommu_group_set->iommu_maps = kzalloc(iommu_group_set->count *
-			sizeof(*(iommu_group_set->iommu_maps)), GFP_KERNEL);
-	if (!iommu_group_set->iommu_maps) {
-		dprintk(VIDC_ERR, "%s Failed to alloc iommu_maps\n",
-			__func__);
-		rc = -ENOMEM;
-		goto err_no_of_node;
-	}
-
-	buffer_types = kzalloc(iommu_group_set->count * sizeof(*buffer_types),
-				GFP_KERNEL);
-	if (!buffer_types) {
-		dprintk(VIDC_ERR,
-			"%s Failed to alloc iommu group buffer types\n",
-			__func__);
-		rc = -ENOMEM;
-		goto err_load_groups;
-	}
-
-	rc = of_property_read_u32_array(pdev->dev.of_node,
-			"qcom,iommu-group-buffer-types", buffer_types,
-			iommu_group_set->count);
-	if (rc) {
-		dprintk(VIDC_ERR,
-		    "%s Failed to read iommu group buffer types\n", __func__);
-		goto err_load_groups;
-	}
-
-	for (i = 0; i < iommu_group_set->count; i++) {
-		iommu_map = &iommu_group_set->iommu_maps[i];
-		ctx_node = of_parse_phandle(pdev->dev.of_node,
-				"qcom,iommu-groups", i);
-		if (!ctx_node) {
-			dprintk(VIDC_ERR, "Unable to parse phandle : %u\n", i);
-			rc = -EBADHANDLE;
-			goto err_load_groups;
-		}
-
-		rc = of_property_read_string(ctx_node, "label",
-				&(iommu_map->name));
-		if (rc) {
-			dprintk(VIDC_ERR, "Could not find label property\n");
-			goto err_load_groups;
-		}
-
-		if (!of_get_property(ctx_node, "qcom,virtual-addr-pool",
-				&array_size)) {
-			dprintk(VIDC_ERR,
-				"Could not find any addr pool for group : %s\n",
-				iommu_map->name);
-			rc = -EBADHANDLE;
-			goto err_load_groups;
-		}
-
-		iommu_map->npartitions = array_size / sizeof(u32) / 2;
-
-		rc = of_property_read_u32_array(ctx_node,
-				"qcom,virtual-addr-pool",
-				(u32 *)iommu_map->addr_range,
-				iommu_map->npartitions * 2);
-		if (rc) {
-			dprintk(VIDC_ERR,
-				"Could not read addr pool for group : %s\n",
-				iommu_map->name);
-			goto err_load_groups;
-		}
-
-		iommu_map->buffer_type = buffer_types[i];
-		iommu_map->is_secure =
-			of_property_read_bool(ctx_node,	"qcom,secure-domain");
-	}
-	kfree(buffer_types);
-	return 0;
-err_load_groups:
-	kfree(buffer_types);
-	msm_vidc_free_iommu_groups(res);
-err_no_of_node:
-	return rc;
-}
-
-static int msm_vidc_load_buffer_usage_table(
-		struct msm_vidc_platform_resources *res)
-{
-	int rc = 0;
-	struct platform_device *pdev = res->pdev;
-	struct buffer_usage_set *buffer_usage_set = &res->buffer_usage_set;
-
-	buffer_usage_set->count = get_u32_array_num_elements(
-				    pdev, "qcom,buffer-type-tz-usage-table");
-	if (buffer_usage_set->count == 0) {
-		dprintk(VIDC_DBG, "no elements in buffer usage set\n");
-		return 0;
-	}
-
-	buffer_usage_set->buffer_usage_tbl = kzalloc(buffer_usage_set->count *
-			sizeof(*(buffer_usage_set->buffer_usage_tbl)),
-			GFP_KERNEL);
-	if (!buffer_usage_set->buffer_usage_tbl) {
-		dprintk(VIDC_ERR, "%s Failed to alloc buffer usage table\n",
-			__func__);
-		rc = -ENOMEM;
-		goto err_load_buf_usage;
-	}
-
-	rc = of_property_read_u32_array(pdev->dev.of_node,
-		    "qcom,buffer-type-tz-usage-table",
-		(u32 *)buffer_usage_set->buffer_usage_tbl,
-		buffer_usage_set->count *
-		(sizeof(*buffer_usage_set->buffer_usage_tbl)/sizeof(u32)));
-	if (rc) {
-		dprintk(VIDC_ERR, "Failed to read buffer usage table\n");
-		goto err_load_buf_usage;
-	}
-
-	return 0;
-err_load_buf_usage:
-	msm_vidc_free_buffer_usage_table(res);
-	return rc;
-}
-
-
-static int read_platform_resources_from_dt(
-		struct msm_vidc_platform_resources *res)
-{
-	struct platform_device *pdev = res->pdev;
-	struct resource *kres = NULL;
-	int rc = 0;
-
-	if (!pdev->dev.of_node) {
-		dprintk(VIDC_ERR, "DT node not found\n");
-		return -ENOENT;
-	}
-
-	res->fw_base_addr = 0x0;
-
-	kres = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	res->register_base = kres ? kres->start : -1;
-	res->register_size = kres ? (kres->end + 1 - kres->start) : -1;
-
-	kres = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
-	res->irq = kres ? kres->start : -1;
-
-	res->has_ocmem = of_property_read_bool(pdev->dev.of_node,
-						"qcom,has-ocmem");
-
-	rc = msm_vidc_load_freq_table(res);
-	if (rc) {
-		dprintk(VIDC_ERR, "Failed to load freq table: %d\n", rc);
-		goto err_load_freq_table;
-	}
-	rc = msm_vidc_load_reg_table(res);
-	if (rc) {
-		dprintk(VIDC_ERR, "Failed to load reg table: %d\n", rc);
-		goto err_load_reg_table;
-	}
-	rc = msm_vidc_load_bus_vectors(res);
-	if (rc) {
-		dprintk(VIDC_ERR, "Failed to load bus vectors: %d\n", rc);
-		goto err_load_bus_vectors;
-	}
-	rc = msm_vidc_load_iommu_groups(res);
-	if (rc) {
-		dprintk(VIDC_ERR, "Failed to load iommu groups: %d\n", rc);
-		goto err_load_iommu_groups;
-	}
-	rc = msm_vidc_load_buffer_usage_table(res);
-	if (rc) {
-		dprintk(VIDC_ERR,
-			"Failed to load buffer usage table: %d\n", rc);
-		goto err_load_buffer_usage_table;
-	}
-
-	rc = of_property_read_u32(pdev->dev.of_node, "qcom,max-hw-load",
-			&res->max_load);
-	if (rc) {
-		dprintk(VIDC_ERR,
-			"Failed to determine max load supported: %d\n", rc);
-		goto err_load_buffer_usage_table;
-	}
-
-	return rc;
-
-err_load_buffer_usage_table:
-	msm_vidc_free_iommu_groups(res);
-err_load_iommu_groups:
-	msm_vidc_free_bus_vectors(res);
-err_load_bus_vectors:
-	msm_vidc_free_reg_table(res);
-err_load_reg_table:
-	msm_vidc_free_freq_table(res);
-err_load_freq_table:
-	return rc;
-}
-
-static int read_platform_resources_from_board(
-		struct msm_vidc_platform_resources *res)
-{
-	struct resource *kres = NULL;
-	struct platform_device *pdev = res->pdev;
-	struct msm_vidc_v4l2_platform_data *pdata = pdev->dev.platform_data;
-	int c = 0, rc = 0;
-
-	if (!pdata) {
-		dprintk(VIDC_ERR, "Platform data not found\n");
-		return -ENOENT;
-	}
-
-	res->fw_base_addr = 0x0;
-
-	kres = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	res->register_base = kres ? kres->start : -1;
-	res->register_size = kres ? (kres->end + 1 - kres->start) : -1;
-
-	kres = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
-	res->irq = kres ? kres->start : -1;
-
-	res->load_freq_tbl = kzalloc(pdata->num_load_table *
-			sizeof(*res->load_freq_tbl), GFP_KERNEL);
-
-	if (!res->load_freq_tbl) {
-		dprintk(VIDC_ERR, "%s Failed to alloc load_freq_tbl\n",
-				__func__);
-		return -ENOMEM;
-	}
-
-	res->load_freq_tbl_size = pdata->num_load_table;
-	for (c = 0; c > pdata->num_load_table; ++c) {
-		res->load_freq_tbl[c].load = pdata->load_table[c][0];
-		res->load_freq_tbl[c].freq = pdata->load_table[c][1];
-	}
-
-	res->max_load = pdata->max_load;
-	return rc;
-}
-
 static int read_platform_resources(struct msm_vidc_core *core,
 		struct platform_device *pdev)
 {
@@ -1521,11 +905,7 @@
 	video_unregister_device(&core->vdev[MSM_VIDC_DECODER].vdev);
 	v4l2_device_unregister(&core->v4l2_dev);
 
-	msm_vidc_free_freq_table(&core->resources);
-	msm_vidc_free_reg_table(&core->resources);
-	msm_vidc_free_bus_vectors(&core->resources);
-	msm_vidc_free_iommu_groups(&core->resources);
-	msm_vidc_free_buffer_usage_table(&core->resources);
+	msm_vidc_free_platform_resources(&core->resources);
 	kfree(core);
 	return rc;
 }
diff --git a/drivers/media/platform/msm/vidc/msm_vidc_res_parse.c b/drivers/media/platform/msm/vidc/msm_vidc_res_parse.c
new file mode 100644
index 0000000..cb08da7
--- /dev/null
+++ b/drivers/media/platform/msm/vidc/msm_vidc_res_parse.c
@@ -0,0 +1,642 @@
+/* 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
+ * 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/of.h>
+#include <mach/board.h>
+#include "msm_vidc_resources.h"
+#include "msm_vidc_debug.h"
+#include "msm_vidc_res_parse.h"
+
+struct master_slave {
+	int masters_ocmem[2];
+	int masters_ddr[2];
+	int slaves_ocmem[2];
+	int slaves_ddr[2];
+};
+
+static struct master_slave bus_vectors_masters_slaves = {
+	.masters_ocmem = {MSM_BUS_MASTER_VIDEO_P0_OCMEM,
+				MSM_BUS_MASTER_VIDEO_P1_OCMEM},
+	.masters_ddr = {MSM_BUS_MASTER_VIDEO_P0, MSM_BUS_MASTER_VIDEO_P1},
+	.slaves_ocmem = {MSM_BUS_SLAVE_OCMEM, MSM_BUS_SLAVE_OCMEM},
+	.slaves_ddr = {MSM_BUS_SLAVE_EBI_CH0, MSM_BUS_SLAVE_EBI_CH0},
+};
+
+struct bus_pdata_config {
+	int *masters;
+	int *slaves;
+	char *name;
+};
+
+static struct bus_pdata_config bus_pdata_config_vector[] = {
+	{
+		.masters = bus_vectors_masters_slaves.masters_ocmem,
+		.slaves = bus_vectors_masters_slaves.slaves_ocmem,
+		.name = "qcom,enc-ocmem-ab-ib",
+	},
+	{
+		.masters = bus_vectors_masters_slaves.masters_ocmem,
+		.slaves = bus_vectors_masters_slaves.slaves_ocmem,
+		.name = "qcom,dec-ocmem-ab-ib",
+	},
+	{
+		.masters = bus_vectors_masters_slaves.masters_ddr,
+		.slaves = bus_vectors_masters_slaves.slaves_ddr,
+		.name = "qcom,enc-ddr-ab-ib",
+	},
+	{
+		.masters = bus_vectors_masters_slaves.masters_ddr,
+		.slaves = bus_vectors_masters_slaves.slaves_ddr,
+		.name = "qcom,dec-ddr-ab-ib",
+	},
+};
+
+static size_t get_u32_array_num_elements(struct platform_device *pdev,
+					char *name)
+{
+	struct device_node *np = pdev->dev.of_node;
+	int len;
+	size_t num_elements = 0;
+	if (!of_get_property(np, name, &len)) {
+		dprintk(VIDC_ERR, "Failed to read %s from device tree\n",
+			name);
+		goto fail_read;
+	}
+
+	num_elements = len / sizeof(u32);
+	if (num_elements <= 0) {
+		dprintk(VIDC_ERR, "%s not specified in device tree\n",
+			name);
+		goto fail_read;
+	}
+	return num_elements / 2;
+
+fail_read:
+	return 0;
+}
+
+int read_hfi_type(struct platform_device *pdev)
+{
+	struct device_node *np = pdev->dev.of_node;
+	int rc = 0;
+	const char *hfi_name = NULL;
+
+	if (np) {
+		rc = of_property_read_string(np, "qcom,hfi", &hfi_name);
+		if (rc) {
+			dprintk(VIDC_ERR,
+				"Failed to read hfi from device tree\n");
+			goto err_hfi_read;
+		}
+		if (!strcmp(hfi_name, "venus"))
+			rc = VIDC_HFI_VENUS;
+		else if (!strcmp(hfi_name, "q6"))
+			rc = VIDC_HFI_Q6;
+		else
+			rc = -EINVAL;
+	} else
+		rc = VIDC_HFI_Q6;
+
+err_hfi_read:
+	return rc;
+}
+
+static inline void msm_vidc_free_freq_table(
+		struct msm_vidc_platform_resources *res)
+{
+	kfree(res->load_freq_tbl);
+	res->load_freq_tbl = NULL;
+}
+
+static inline void msm_vidc_free_reg_table(
+			struct msm_vidc_platform_resources *res)
+{
+	kfree(res->reg_set.reg_tbl);
+	res->reg_set.reg_tbl = NULL;
+}
+
+static inline void msm_vidc_free_bus_vectors(
+			struct msm_vidc_platform_resources *res)
+{
+	int i, j;
+	if (res->bus_pdata) {
+		for (i = 0; i < ARRAY_SIZE(bus_pdata_config_vector); i++) {
+			for (j = 0; j < res->bus_pdata[i].num_usecases; j++) {
+				kfree(res->bus_pdata[i].usecase[j].vectors);
+				res->bus_pdata[i].usecase[j].vectors = NULL;
+			}
+			kfree(res->bus_pdata[i].usecase);
+			res->bus_pdata[i].usecase = NULL;
+		}
+		kfree(res->bus_pdata);
+		res->bus_pdata = NULL;
+	}
+}
+
+static inline void msm_vidc_free_iommu_groups(
+			struct msm_vidc_platform_resources *res)
+{
+	kfree(res->iommu_group_set.iommu_maps);
+	res->iommu_group_set.iommu_maps = NULL;
+}
+
+static inline void msm_vidc_free_buffer_usage_table(
+			struct msm_vidc_platform_resources *res)
+{
+	kfree(res->buffer_usage_set.buffer_usage_tbl);
+	res->buffer_usage_set.buffer_usage_tbl = NULL;
+}
+
+void msm_vidc_free_platform_resources(
+			struct msm_vidc_platform_resources *res)
+{
+	msm_vidc_free_freq_table(res);
+	msm_vidc_free_reg_table(res);
+	msm_vidc_free_bus_vectors(res);
+	msm_vidc_free_iommu_groups(res);
+	msm_vidc_free_buffer_usage_table(res);
+}
+
+static void msm_vidc_free_bus_vector(struct msm_bus_scale_pdata *bus_pdata)
+{
+	int i;
+	for (i = 0; i < bus_pdata->num_usecases; i++) {
+		kfree(bus_pdata->usecase[i].vectors);
+		bus_pdata->usecase[i].vectors = NULL;
+	}
+
+	kfree(bus_pdata->usecase);
+	bus_pdata->usecase = NULL;
+}
+
+static int msm_vidc_load_reg_table(struct msm_vidc_platform_resources *res)
+{
+	struct reg_set *reg_set;
+	struct platform_device *pdev = res->pdev;
+	int i;
+	int rc = 0;
+
+	reg_set = &res->reg_set;
+	reg_set->count = get_u32_array_num_elements(pdev, "qcom,reg-presets");
+	if (reg_set->count == 0) {
+		dprintk(VIDC_DBG, "no elements in reg set\n");
+		return rc;
+	}
+
+	reg_set->reg_tbl = kzalloc(reg_set->count *
+			sizeof(*(reg_set->reg_tbl)), GFP_KERNEL);
+	if (!reg_set->reg_tbl) {
+		dprintk(VIDC_ERR, "%s Failed to alloc register table\n",
+			__func__);
+		return -ENOMEM;
+	}
+
+	if (of_property_read_u32_array(pdev->dev.of_node, "qcom,reg-presets",
+		(u32 *)reg_set->reg_tbl, reg_set->count * 2)) {
+		dprintk(VIDC_ERR, "Failed to read register table\n");
+		msm_vidc_free_reg_table(res);
+		return -EINVAL;
+	}
+	for (i = 0; i < reg_set->count; i++) {
+		dprintk(VIDC_DBG,
+			"reg = %x, value = %x\n",
+			reg_set->reg_tbl[i].reg,
+			reg_set->reg_tbl[i].value
+		);
+	}
+	return rc;
+}
+static int msm_vidc_load_freq_table(struct msm_vidc_platform_resources *res)
+{
+	int rc = 0;
+	int num_elements = 0;
+	struct platform_device *pdev = res->pdev;
+
+	num_elements = get_u32_array_num_elements(pdev, "qcom,load-freq-tbl");
+	if (num_elements == 0) {
+		dprintk(VIDC_ERR, "no elements in frequency table\n");
+		return rc;
+	}
+
+	res->load_freq_tbl = kzalloc(num_elements * sizeof(*res->load_freq_tbl),
+			GFP_KERNEL);
+	if (!res->load_freq_tbl) {
+		dprintk(VIDC_ERR,
+				"%s Failed to alloc load_freq_tbl\n",
+				__func__);
+		return -ENOMEM;
+	}
+
+	if (of_property_read_u32_array(pdev->dev.of_node,
+		"qcom,load-freq-tbl", (u32 *)res->load_freq_tbl,
+		num_elements * 2)) {
+		dprintk(VIDC_ERR, "Failed to read frequency table\n");
+		msm_vidc_free_freq_table(res);
+		return -EINVAL;
+	}
+
+	res->load_freq_tbl_size = num_elements;
+	return rc;
+}
+
+static int msm_vidc_load_bus_vector(struct platform_device *pdev,
+			struct msm_bus_scale_pdata *bus_pdata, u32 num_ports,
+			struct bus_pdata_config *bus_pdata_config)
+{
+	struct bus_values {
+	    u32 ab;
+	    u32 ib;
+	};
+	struct bus_values *values;
+	int i, j;
+	int rc = 0;
+
+	values = kzalloc(sizeof(*values) * bus_pdata->num_usecases, GFP_KERNEL);
+	if (!values) {
+		dprintk(VIDC_ERR, "%s Failed to alloc bus_values\n", __func__);
+		rc = -ENOMEM;
+		goto err_mem_alloc;
+	}
+
+	if (of_property_read_u32_array(pdev->dev.of_node,
+		    bus_pdata_config->name, (u32 *)values,
+		    bus_pdata->num_usecases * (sizeof(*values)/sizeof(u32)))) {
+		dprintk(VIDC_ERR, "%s Failed to read bus values\n", __func__);
+		rc = -EINVAL;
+		goto err_parse_dt;
+	}
+
+	bus_pdata->usecase = kzalloc(sizeof(*bus_pdata->usecase) *
+		    bus_pdata->num_usecases, GFP_KERNEL);
+	if (!bus_pdata->usecase) {
+		dprintk(VIDC_ERR,
+			"%s Failed to alloc bus_pdata usecase\n", __func__);
+		rc = -ENOMEM;
+		goto err_parse_dt;
+	}
+	bus_pdata->name = bus_pdata_config->name;
+	for (i = 0; i < bus_pdata->num_usecases; i++) {
+		bus_pdata->usecase[i].vectors = kzalloc(
+			sizeof(*bus_pdata->usecase[i].vectors) * num_ports,
+			GFP_KERNEL);
+		if (!bus_pdata->usecase) {
+			dprintk(VIDC_ERR,
+				"%s Failed to alloc bus_pdata usecase\n",
+				__func__);
+			break;
+		}
+		for (j = 0; j < num_ports; j++) {
+			bus_pdata->usecase[i].vectors[j].ab = (u64)values[i].ab
+									* 1000;
+			bus_pdata->usecase[i].vectors[j].ib = (u64)values[i].ib
+									* 1000;
+			bus_pdata->usecase[i].vectors[j].src =
+						bus_pdata_config->masters[j];
+			bus_pdata->usecase[i].vectors[j].dst =
+						bus_pdata_config->slaves[j];
+			dprintk(VIDC_DBG,
+				"ab = %llu, ib = %llu, src = %d, dst = %d\n",
+				bus_pdata->usecase[i].vectors[j].ab,
+				bus_pdata->usecase[i].vectors[j].ib,
+				bus_pdata->usecase[i].vectors[j].src,
+				bus_pdata->usecase[i].vectors[j].dst);
+		}
+		bus_pdata->usecase[i].num_paths = num_ports;
+	}
+	if (i < bus_pdata->num_usecases) {
+		for (--i; i >= 0; i--) {
+			kfree(bus_pdata->usecase[i].vectors);
+			bus_pdata->usecase[i].vectors = NULL;
+		}
+		kfree(bus_pdata->usecase);
+		bus_pdata->usecase = NULL;
+		rc = -EINVAL;
+	}
+err_parse_dt:
+	kfree(values);
+err_mem_alloc:
+	return rc;
+}
+
+static int msm_vidc_load_bus_vectors(struct msm_vidc_platform_resources *res)
+{
+	u32 num_ports = 0;
+	int rc = 0;
+	int i;
+	struct platform_device *pdev = res->pdev;
+	u32 num_bus_pdata = ARRAY_SIZE(bus_pdata_config_vector);
+
+	if (of_property_read_u32_array(pdev->dev.of_node, "qcom,bus-ports",
+			(u32 *)&num_ports, 1) || (num_ports == 0))
+		goto err_mem_alloc;
+
+	res->bus_pdata = kzalloc(sizeof(*res->bus_pdata) * num_bus_pdata,
+				GFP_KERNEL);
+	if (!res->bus_pdata) {
+		dprintk(VIDC_ERR, "Failed to alloc memory\n");
+		rc = -ENOMEM;
+		goto err_mem_alloc;
+	}
+	for (i = 0; i < num_bus_pdata; i++) {
+		if (!res->has_ocmem &&
+			(!strcmp(bus_pdata_config_vector[i].name,
+				"qcom,enc-ocmem-ab-ib")
+			|| !strcmp(bus_pdata_config_vector[i].name,
+				"qcom,dec-ocmem-ab-ib"))) {
+			continue;
+		}
+		res->bus_pdata[i].num_usecases = get_u32_array_num_elements(
+					pdev, bus_pdata_config_vector[i].name);
+		if (res->bus_pdata[i].num_usecases == 0) {
+			dprintk(VIDC_ERR, "no elements in %s\n",
+				bus_pdata_config_vector[i].name);
+			rc = -EINVAL;
+			break;
+		}
+
+		rc = msm_vidc_load_bus_vector(pdev, &res->bus_pdata[i],
+				num_ports, &bus_pdata_config_vector[i]);
+		if (rc) {
+			dprintk(VIDC_ERR,
+				"Failed to load bus vector: %d\n", i);
+			break;
+		}
+	}
+	if (i < num_bus_pdata) {
+		for (--i; i >= 0; i--)
+			msm_vidc_free_bus_vector(&res->bus_pdata[i]);
+		kfree(res->bus_pdata);
+		res->bus_pdata = NULL;
+	}
+err_mem_alloc:
+	return rc;
+}
+
+static int msm_vidc_load_iommu_groups(struct msm_vidc_platform_resources *res)
+{
+	int rc = 0;
+	struct platform_device *pdev = res->pdev;
+	struct device_node *ctx_node;
+	struct iommu_set *iommu_group_set = &res->iommu_group_set;
+	int array_size;
+	int i;
+	struct iommu_info *iommu_map;
+	u32 *buffer_types = NULL;
+
+	if (!of_get_property(pdev->dev.of_node, "qcom,iommu-groups",
+				&array_size)) {
+		dprintk(VIDC_DBG, "iommu_groups property not present\n");
+		iommu_group_set->count = 0;
+		return 0;
+	}
+
+	iommu_group_set->count = array_size / sizeof(u32);
+	if (iommu_group_set->count == 0) {
+		dprintk(VIDC_ERR, "No group present in iommu_groups\n");
+		rc = -ENOENT;
+		goto err_no_of_node;
+	}
+
+	iommu_group_set->iommu_maps = kzalloc(iommu_group_set->count *
+			sizeof(*(iommu_group_set->iommu_maps)), GFP_KERNEL);
+	if (!iommu_group_set->iommu_maps) {
+		dprintk(VIDC_ERR, "%s Failed to alloc iommu_maps\n",
+			__func__);
+		rc = -ENOMEM;
+		goto err_no_of_node;
+	}
+
+	buffer_types = kzalloc(iommu_group_set->count * sizeof(*buffer_types),
+				GFP_KERNEL);
+	if (!buffer_types) {
+		dprintk(VIDC_ERR,
+			"%s Failed to alloc iommu group buffer types\n",
+			__func__);
+		rc = -ENOMEM;
+		goto err_load_groups;
+	}
+
+	rc = of_property_read_u32_array(pdev->dev.of_node,
+			"qcom,iommu-group-buffer-types", buffer_types,
+			iommu_group_set->count);
+	if (rc) {
+		dprintk(VIDC_ERR,
+		    "%s Failed to read iommu group buffer types\n", __func__);
+		goto err_load_groups;
+	}
+
+	for (i = 0; i < iommu_group_set->count; i++) {
+		iommu_map = &iommu_group_set->iommu_maps[i];
+		ctx_node = of_parse_phandle(pdev->dev.of_node,
+				"qcom,iommu-groups", i);
+		if (!ctx_node) {
+			dprintk(VIDC_ERR, "Unable to parse phandle : %u\n", i);
+			rc = -EBADHANDLE;
+			goto err_load_groups;
+		}
+
+		rc = of_property_read_string(ctx_node, "label",
+				&(iommu_map->name));
+		if (rc) {
+			dprintk(VIDC_ERR, "Could not find label property\n");
+			goto err_load_groups;
+		}
+
+		if (!of_get_property(ctx_node, "qcom,virtual-addr-pool",
+				&array_size)) {
+			dprintk(VIDC_ERR,
+				"Could not find any addr pool for group : %s\n",
+				iommu_map->name);
+			rc = -EBADHANDLE;
+			goto err_load_groups;
+		}
+
+		iommu_map->npartitions = array_size / sizeof(u32) / 2;
+
+		rc = of_property_read_u32_array(ctx_node,
+				"qcom,virtual-addr-pool",
+				(u32 *)iommu_map->addr_range,
+				iommu_map->npartitions * 2);
+		if (rc) {
+			dprintk(VIDC_ERR,
+				"Could not read addr pool for group : %s\n",
+				iommu_map->name);
+			goto err_load_groups;
+		}
+
+		iommu_map->buffer_type = buffer_types[i];
+		iommu_map->is_secure =
+			of_property_read_bool(ctx_node,	"qcom,secure-domain");
+	}
+	kfree(buffer_types);
+	return 0;
+err_load_groups:
+	kfree(buffer_types);
+	msm_vidc_free_iommu_groups(res);
+err_no_of_node:
+	return rc;
+}
+
+static int msm_vidc_load_buffer_usage_table(
+		struct msm_vidc_platform_resources *res)
+{
+	int rc = 0;
+	struct platform_device *pdev = res->pdev;
+	struct buffer_usage_set *buffer_usage_set = &res->buffer_usage_set;
+
+	buffer_usage_set->count = get_u32_array_num_elements(
+				    pdev, "qcom,buffer-type-tz-usage-table");
+	if (buffer_usage_set->count == 0) {
+		dprintk(VIDC_DBG, "no elements in buffer usage set\n");
+		return 0;
+	}
+
+	buffer_usage_set->buffer_usage_tbl = kzalloc(buffer_usage_set->count *
+			sizeof(*(buffer_usage_set->buffer_usage_tbl)),
+			GFP_KERNEL);
+	if (!buffer_usage_set->buffer_usage_tbl) {
+		dprintk(VIDC_ERR, "%s Failed to alloc buffer usage table\n",
+			__func__);
+		rc = -ENOMEM;
+		goto err_load_buf_usage;
+	}
+
+	rc = of_property_read_u32_array(pdev->dev.of_node,
+		    "qcom,buffer-type-tz-usage-table",
+		(u32 *)buffer_usage_set->buffer_usage_tbl,
+		buffer_usage_set->count *
+		(sizeof(*buffer_usage_set->buffer_usage_tbl)/sizeof(u32)));
+	if (rc) {
+		dprintk(VIDC_ERR, "Failed to read buffer usage table\n");
+		goto err_load_buf_usage;
+	}
+
+	return 0;
+err_load_buf_usage:
+	msm_vidc_free_buffer_usage_table(res);
+	return rc;
+}
+
+int read_platform_resources_from_dt(
+		struct msm_vidc_platform_resources *res)
+{
+	struct platform_device *pdev = res->pdev;
+	struct resource *kres = NULL;
+	int rc = 0;
+
+	if (!pdev->dev.of_node) {
+		dprintk(VIDC_ERR, "DT node not found\n");
+		return -ENOENT;
+	}
+
+	res->fw_base_addr = 0x0;
+
+	kres = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	res->register_base = kres ? kres->start : -1;
+	res->register_size = kres ? (kres->end + 1 - kres->start) : -1;
+
+	kres = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+	res->irq = kres ? kres->start : -1;
+
+	res->has_ocmem = of_property_read_bool(pdev->dev.of_node,
+						"qcom,has-ocmem");
+
+	rc = msm_vidc_load_freq_table(res);
+	if (rc) {
+		dprintk(VIDC_ERR, "Failed to load freq table: %d\n", rc);
+		goto err_load_freq_table;
+	}
+	rc = msm_vidc_load_reg_table(res);
+	if (rc) {
+		dprintk(VIDC_ERR, "Failed to load reg table: %d\n", rc);
+		goto err_load_reg_table;
+	}
+	rc = msm_vidc_load_bus_vectors(res);
+	if (rc) {
+		dprintk(VIDC_ERR, "Failed to load bus vectors: %d\n", rc);
+		goto err_load_bus_vectors;
+	}
+	rc = msm_vidc_load_iommu_groups(res);
+	if (rc) {
+		dprintk(VIDC_ERR, "Failed to load iommu groups: %d\n", rc);
+		goto err_load_iommu_groups;
+	}
+	rc = msm_vidc_load_buffer_usage_table(res);
+	if (rc) {
+		dprintk(VIDC_ERR,
+			"Failed to load buffer usage table: %d\n", rc);
+		goto err_load_buffer_usage_table;
+	}
+
+	rc = of_property_read_u32(pdev->dev.of_node, "qcom,max-hw-load",
+			&res->max_load);
+	if (rc) {
+		dprintk(VIDC_ERR,
+			"Failed to determine max load supported: %d\n", rc);
+		goto err_load_buffer_usage_table;
+	}
+
+	return rc;
+
+err_load_buffer_usage_table:
+	msm_vidc_free_iommu_groups(res);
+err_load_iommu_groups:
+	msm_vidc_free_bus_vectors(res);
+err_load_bus_vectors:
+	msm_vidc_free_reg_table(res);
+err_load_reg_table:
+	msm_vidc_free_freq_table(res);
+err_load_freq_table:
+	return rc;
+}
+
+int read_platform_resources_from_board(
+		struct msm_vidc_platform_resources *res)
+{
+	struct resource *kres = NULL;
+	struct platform_device *pdev = res->pdev;
+	struct msm_vidc_v4l2_platform_data *pdata = pdev->dev.platform_data;
+	int c = 0, rc = 0;
+
+	if (!pdata) {
+		dprintk(VIDC_ERR, "Platform data not found\n");
+		return -ENOENT;
+	}
+
+	res->fw_base_addr = 0x0;
+
+	kres = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	res->register_base = kres ? kres->start : -1;
+	res->register_size = kres ? (kres->end + 1 - kres->start) : -1;
+
+	kres = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+	res->irq = kres ? kres->start : -1;
+
+	res->load_freq_tbl = kzalloc(pdata->num_load_table *
+			sizeof(*res->load_freq_tbl), GFP_KERNEL);
+
+	if (!res->load_freq_tbl) {
+		dprintk(VIDC_ERR, "%s Failed to alloc load_freq_tbl\n",
+				__func__);
+		return -ENOMEM;
+	}
+
+	res->load_freq_tbl_size = pdata->num_load_table;
+	for (c = 0; c > pdata->num_load_table; ++c) {
+		res->load_freq_tbl[c].load = pdata->load_table[c][0];
+		res->load_freq_tbl[c].freq = pdata->load_table[c][1];
+	}
+
+	res->max_load = pdata->max_load;
+	return rc;
+}
diff --git a/drivers/media/platform/msm/vidc/msm_vidc_res_parse.h b/drivers/media/platform/msm/vidc/msm_vidc_res_parse.h
new file mode 100644
index 0000000..9fe6b58
--- /dev/null
+++ b/drivers/media/platform/msm/vidc/msm_vidc_res_parse.h
@@ -0,0 +1,30 @@
+
+/* 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
+ * 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 DT_PARSE
+#define DT_PARSE
+#include <linux/of.h>
+#include <mach/board.h>
+#include "msm_vidc_resources.h"
+void msm_vidc_free_platform_resources(
+		struct msm_vidc_platform_resources *res);
+
+int read_hfi_type(struct platform_device *pdev);
+
+int read_platform_resources_from_dt(
+		struct msm_vidc_platform_resources *res);
+
+int read_platform_resources_from_board(
+		struct msm_vidc_platform_resources *res);
+#endif
diff --git a/drivers/media/platform/msm/vidc/venus_hfi.c b/drivers/media/platform/msm/vidc/venus_hfi.c
index 15ac493..28ea41a 100644
--- a/drivers/media/platform/msm/vidc/venus_hfi.c
+++ b/drivers/media/platform/msm/vidc/venus_hfi.c
@@ -2852,8 +2852,8 @@
 	venus_hfi_disable_clks(device);
 fail_enable_clks:
 	subsystem_put(device->resources.fw.cookie);
-	device->resources.fw.cookie = NULL;
 fail_load_fw:
+	device->resources.fw.cookie = NULL;
 	venus_hfi_iommu_detach(device);
 fail_iommu_attach:
 	return rc;
diff --git a/drivers/mmc/card/mmc_block_test.c b/drivers/mmc/card/mmc_block_test.c
index 7a4d19e..e9ac2fc 100644
--- a/drivers/mmc/card/mmc_block_test.c
+++ b/drivers/mmc/card/mmc_block_test.c
@@ -20,7 +20,6 @@
 #include <linux/mmc/host.h>
 #include <linux/delay.h>
 #include <linux/test-iosched.h>
-#include <linux/jiffies.h>
 #include "queue.h"
 #include <linux/mmc/mmc.h>
 
@@ -2787,7 +2786,7 @@
 		if (ret)
 			break;
 
-		mtime = jiffies_to_msecs(mbtd->test_info.test_duration);
+		mtime = ktime_to_ms(mbtd->test_info.test_duration);
 
 		test_pr_info("%s: time is %lu msec, size is %u.%u MiB",
 			__func__, mtime,
@@ -2946,7 +2945,7 @@
 		if (ret)
 			break;
 
-		mtime = jiffies_to_msecs(mbtd->test_info.test_duration);
+		mtime = ktime_to_ms(mbtd->test_info.test_duration);
 		byte_count = mbtd->test_info.test_byte_count;
 
 		test_pr_info("%s: time is %lu msec, size is %lu.%lu MiB",
diff --git a/drivers/mtd/devices/msm_qpic_nand.c b/drivers/mtd/devices/msm_qpic_nand.c
index efa09f6..16012bd 100644
--- a/drivers/mtd/devices/msm_qpic_nand.c
+++ b/drivers/mtd/devices/msm_qpic_nand.c
@@ -694,7 +694,7 @@
 	dma_addr_t dma_addr_param_info = 0;
 	struct onfi_param_page *onfi_param_page_ptr;
 	struct msm_nand_flash_onfi_data data;
-	uint32_t onfi_signature;
+	uint32_t onfi_signature = 0;
 
 	/* SPS command/data descriptors */
 	uint32_t total_cnt = 13;
diff --git a/drivers/platform/msm/ipa/ipa.c b/drivers/platform/msm/ipa/ipa.c
index f5d7b6e..6a16cf3 100644
--- a/drivers/platform/msm/ipa/ipa.c
+++ b/drivers/platform/msm/ipa/ipa.c
@@ -1667,13 +1667,6 @@
 	}
 	/* register IPA with SPS driver */
 	bam_props.phys_addr = resource_p->bam_mem_base;
-	bam_props.virt_addr = ioremap(resource_p->bam_mem_base,
-			resource_p->bam_mem_size);
-	if (!bam_props.virt_addr) {
-		IPAERR(":bam-base ioremap err.\n");
-		result = -EFAULT;
-		goto fail_bam_remap;
-	}
 	bam_props.virt_size = resource_p->bam_mem_size;
 	bam_props.irq = resource_p->bam_irq;
 	bam_props.num_pipes = IPA_NUM_PIPES;
@@ -1685,7 +1678,7 @@
 	if (result) {
 		IPAERR(":bam register err.\n");
 		result = -ENODEV;
-		goto fail_bam_register;
+		goto fail_init_hw;
 	}
 
 	if (ipa_setup_bam_cfg(resource_p)) {
@@ -2006,18 +1999,12 @@
 	kmem_cache_destroy(ipa_ctx->flt_rule_cache);
 fail_flt_rule_cache:
 	sps_deregister_bam_device(ipa_ctx->bam_handle);
-fail_bam_register:
-	iounmap(bam_props.virt_addr);
-fail_bam_remap:
 fail_init_hw:
 	iounmap(ipa_ctx->mmio);
 fail_remap:
 	kfree(ipa_ctx);
 	ipa_ctx = NULL;
 fail_mem:
-	/* gate IPA clocks */
-	if (ipa_ctx->ipa_hw_mode == IPA_HW_MODE_NORMAL)
-		ipa_disable_clks();
 	return result;
 }
 
@@ -2178,8 +2165,12 @@
 
 	/* Proceed to real initialization */
 	result = ipa_init(&ipa_res);
-	if (result)
+	if (result) {
 		IPAERR("ipa_init failed\n");
+		/* gate IPA clocks */
+		if (ipa_res.ipa_hw_mode == IPA_HW_MODE_NORMAL)
+			ipa_disable_clks();
+	}
 
 	result = device_create_file(&pdev_p->dev,
 			&dev_attr_aggregation_type);
diff --git a/drivers/power/qpnp-bms.c b/drivers/power/qpnp-bms.c
index 12aef1c..4df511b 100644
--- a/drivers/power/qpnp-bms.c
+++ b/drivers/power/qpnp-bms.c
@@ -280,6 +280,7 @@
 	POWER_SUPPLY_PROP_CHARGE_COUNTER,
 	POWER_SUPPLY_PROP_CHARGE_COUNTER_SHADOW,
 	POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN,
+	POWER_SUPPLY_PROP_CHARGE_FULL,
 	POWER_SUPPLY_PROP_CYCLE_COUNT,
 };
 
@@ -1413,6 +1414,21 @@
 	return chip->fcc_mah * 1000;
 }
 
+/* Returns the current full charge in uAh */
+static int get_prop_bms_charge_full(struct qpnp_bms_chip *chip)
+{
+	int rc;
+	struct qpnp_vadc_result result;
+
+	rc = qpnp_vadc_read(LR_MUX1_BATT_THERM, &result);
+	if (rc) {
+		pr_err("Unable to read battery temperature\n");
+		return rc;
+	}
+
+	return calculate_fcc(chip, (int)result.physical);
+}
+
 static int calculate_delta_time(unsigned long *time_stamp, int *delta_time_s)
 {
 	unsigned long now_tm_sec = 0;
@@ -2985,6 +3001,9 @@
 	case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN:
 		val->intval = get_prop_bms_charge_full_design(chip);
 		break;
+	case POWER_SUPPLY_PROP_CHARGE_FULL:
+		val->intval = get_prop_bms_charge_full(chip);
+		break;
 	case POWER_SUPPLY_PROP_CYCLE_COUNT:
 		val->intval = chip->charge_cycles;
 		break;
diff --git a/drivers/power/qpnp-charger.c b/drivers/power/qpnp-charger.c
index 85bdd67..e05c866 100644
--- a/drivers/power/qpnp-charger.c
+++ b/drivers/power/qpnp-charger.c
@@ -98,6 +98,7 @@
 #define BOOST_VSET				0x41
 #define BOOST_ENABLE_CONTROL			0x46
 #define COMP_OVR1				0xEA
+#define BAT_IF_BTC_CTRL				0x49
 
 #define REG_OFFSET_PERP_SUBTYPE			0x05
 
@@ -222,6 +223,7 @@
  * @dc_present:			present status of dc
  * @batt_present:		present status of battery
  * @use_default_batt_values:	flag to report default battery properties
+ * @btc_disabled		Flag to disable btc (disables hot and cold irqs)
  * @max_voltage_mv:		the max volts the batt should be charged up to
  * @min_voltage_mv:		min battery voltage before turning the FET on
  * @max_bat_chg_current:	maximum battery charge current in mA
@@ -234,6 +236,8 @@
  * @safe_current:		battery safety current setting
  * @maxinput_usb_ma:		Maximum Input current USB
  * @maxinput_dc_ma:		Maximum Input current DC
+ * @hot_batt_p			Hot battery threshold setting
+ * @cold_batt_p			Cold battery threshold setting
  * @warm_bat_decidegc		Warm battery temperature in degree Celsius
  * @cool_bat_decidegc		Cool battery temperature in degree Celsius
  * @revision:			PMIC revision
@@ -276,6 +280,7 @@
 	bool				dc_present;
 	bool				batt_present;
 	bool				charging_disabled;
+	bool				btc_disabled;
 	bool				use_default_batt_values;
 	bool				duty_cycle_100p;
 	unsigned int			bpd_detection;
@@ -293,6 +298,8 @@
 	int				term_current;
 	unsigned int			maxinput_usb_ma;
 	unsigned int			maxinput_dc_ma;
+	unsigned int			hot_batt_p;
+	unsigned int			cold_batt_p;
 	unsigned int			warm_bat_decidegc;
 	unsigned int			cool_bat_decidegc;
 	unsigned int			safe_current;
@@ -334,7 +341,21 @@
 	[BPD_TYPE_BAT_THM_BAT_ID] = "bpd_thm_id",
 };
 
-static inline int
+enum btc_type {
+	HOT_THD_25_PCT = 25,
+	HOT_THD_35_PCT = 35,
+	COLD_THD_70_PCT = 70,
+	COLD_THD_80_PCT = 80,
+};
+
+static u8 btc_value[] = {
+	[HOT_THD_25_PCT] = 0x0,
+	[HOT_THD_35_PCT] = BIT(0),
+	[COLD_THD_70_PCT] = 0x0,
+	[COLD_THD_80_PCT] = BIT(1),
+};
+
+	static inline int
 get_bpd(const char *name)
 {
 	int i = 0;
@@ -1066,6 +1087,7 @@
 	POWER_SUPPLY_PROP_CAPACITY,
 	POWER_SUPPLY_PROP_CURRENT_NOW,
 	POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN,
+	POWER_SUPPLY_PROP_CHARGE_FULL,
 	POWER_SUPPLY_PROP_TEMP,
 	POWER_SUPPLY_PROP_SYSTEM_TEMP_LEVEL,
 	POWER_SUPPLY_PROP_CYCLE_COUNT,
@@ -1245,6 +1267,22 @@
 	return 0;
 }
 
+static int
+get_prop_charge_full(struct qpnp_chg_chip *chip)
+{
+	union power_supply_propval ret = {0,};
+
+	if (chip->bms_psy) {
+		chip->bms_psy->get_property(chip->bms_psy,
+			  POWER_SUPPLY_PROP_CHARGE_FULL, &ret);
+		return ret.intval;
+	} else {
+		pr_debug("No BMS supply registered return 0\n");
+	}
+
+	return 0;
+}
+
 #define DEFAULT_CAPACITY	50
 static int
 get_prop_capacity(struct qpnp_chg_chip *chip)
@@ -1380,6 +1418,9 @@
 	case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN:
 		val->intval = get_prop_full_design(chip);
 		break;
+	case POWER_SUPPLY_PROP_CHARGE_FULL:
+		val->intval = get_prop_charge_full(chip);
+		break;
 	case POWER_SUPPLY_PROP_CHARGING_ENABLED:
 		val->intval = !(chip->charging_disabled);
 		break;
@@ -1396,7 +1437,39 @@
 	return 0;
 }
 
-#define QPNP_CHG_VINMIN_MIN_MV		3400
+#define BTC_CONFIG_ENABLED	BIT(7)
+#define BTC_COLD		BIT(1)
+#define BTC_HOT			BIT(0)
+static int
+qpnp_chg_bat_if_configure_btc(struct qpnp_chg_chip *chip)
+{
+	u8 btc_cfg = 0, mask = 0;
+
+	/* Do nothing if battery peripheral not present */
+	if (!chip->bat_if_base)
+		return 0;
+
+	if ((chip->hot_batt_p == HOT_THD_25_PCT)
+			|| (chip->hot_batt_p == HOT_THD_35_PCT)) {
+		btc_cfg |= btc_value[chip->hot_batt_p];
+		mask |= BTC_HOT;
+	}
+
+	if ((chip->cold_batt_p == COLD_THD_70_PCT) ||
+			(chip->cold_batt_p == COLD_THD_80_PCT)) {
+		btc_cfg |= btc_value[chip->cold_batt_p];
+		mask |= BTC_COLD;
+	}
+
+	if (chip->btc_disabled)
+		mask |= BTC_CONFIG_ENABLED;
+
+	return qpnp_chg_masked_write(chip,
+			chip->bat_if_base + BAT_IF_BTC_CTRL,
+			mask, btc_cfg, 1);
+}
+
+#define QPNP_CHG_VINMIN_MIN_MV		4200
 #define QPNP_CHG_VINMIN_HIGH_MIN_MV	5600
 #define QPNP_CHG_VINMIN_HIGH_MIN_VAL	0x2B
 #define QPNP_CHG_VINMIN_MAX_MV		9600
@@ -2617,6 +2690,8 @@
 	OF_PROP_READ(chip, warm_bat_decidegc, "warm-bat-decidegc", rc, 1);
 	OF_PROP_READ(chip, cool_bat_decidegc, "cool-bat-decidegc", rc, 1);
 	OF_PROP_READ(chip, tchg_mins, "tchg-mins", rc, 1);
+	OF_PROP_READ(chip, hot_batt_p, "batt-hot-percentage", rc, 1);
+	OF_PROP_READ(chip, cold_batt_p, "batt-cold-percentage", rc, 1);
 	if (rc)
 		return rc;
 
@@ -2649,6 +2724,10 @@
 			return rc;
 	}
 
+	/* Get the btc-disabled property */
+	chip->btc_disabled = of_property_read_bool(chip->spmi->dev.of_node,
+					"qcom,btc-disabled");
+
 	/* Get the charging-disabled property */
 	chip->charging_disabled = of_property_read_bool(chip->spmi->dev.of_node,
 					"qcom,charging-disabled");
@@ -2972,6 +3051,11 @@
 			}
 		}
 	}
+	rc = qpnp_chg_bat_if_configure_btc(chip);
+	if (rc) {
+		pr_err("failed to configure btc %d\n", rc);
+		goto unregister_batt;
+	}
 
 	qpnp_chg_charge_en(chip, !chip->charging_disabled);
 	qpnp_chg_force_run_on_batt(chip, chip->charging_disabled);
diff --git a/drivers/regulator/qpnp-regulator.c b/drivers/regulator/qpnp-regulator.c
index c9d0500..d859651 100644
--- a/drivers/regulator/qpnp-regulator.c
+++ b/drivers/regulator/qpnp-regulator.c
@@ -1535,7 +1535,9 @@
 			&(pdata->init_data), vreg, spmi->dev.of_node);
 	if (IS_ERR(vreg->rdev)) {
 		rc = PTR_ERR(vreg->rdev);
-		vreg_err(vreg, "regulator_register failed, rc=%d\n", rc);
+		if (rc != -EPROBE_DEFER)
+			vreg_err(vreg, "regulator_register failed, rc=%d\n",
+				rc);
 		goto cancel_ocp_work;
 	}
 
@@ -1547,7 +1549,7 @@
 	if (vreg->ocp_irq)
 		cancel_delayed_work_sync(&vreg->ocp_work);
 bail:
-	if (rc)
+	if (rc && rc != -EPROBE_DEFER)
 		vreg_err(vreg, "probe failed, rc=%d\n", rc);
 
 	kfree(vreg->rdesc.name);
diff --git a/drivers/rtc/qpnp-rtc.c b/drivers/rtc/qpnp-rtc.c
index e0bffb9..bfbae78 100644
--- a/drivers/rtc/qpnp-rtc.c
+++ b/drivers/rtc/qpnp-rtc.c
@@ -45,6 +45,11 @@
 #define TO_SECS(arr)		(arr[0] | (arr[1] << 8) | (arr[2] << 16) | \
 							(arr[3] << 24))
 
+/* Module parameter to control power-on-alarm */
+static bool poweron_alarm;
+module_param(poweron_alarm, bool, 0644);
+MODULE_PARM_DESC(poweron_alarm, "Enable/Disable power-on alarm");
+
 /* rtc driver internal structure */
 struct qpnp_rtc {
 	u8  rtc_ctrl_reg;
@@ -586,7 +591,7 @@
 	struct qpnp_rtc *rtc_dd = dev_get_drvdata(&spmi->dev);
 	bool rtc_alarm_powerup = rtc_dd->rtc_alarm_powerup;
 
-	if (!rtc_alarm_powerup) {
+	if (!rtc_alarm_powerup && !poweron_alarm) {
 		spin_lock_irqsave(&rtc_dd->alarm_ctrl_lock, irq_flags);
 		dev_dbg(&spmi->dev, "Disabling alarm interrupts\n");
 
diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
index 5dfd749..1def2dd 100644
--- a/drivers/scsi/scsi_lib.c
+++ b/drivers/scsi/scsi_lib.c
@@ -255,11 +255,10 @@
 }
 EXPORT_SYMBOL(scsi_execute);
 
-
-int scsi_execute_req(struct scsi_device *sdev, const unsigned char *cmd,
+int scsi_execute_req_flags(struct scsi_device *sdev, const unsigned char *cmd,
 		     int data_direction, void *buffer, unsigned bufflen,
 		     struct scsi_sense_hdr *sshdr, int timeout, int retries,
-		     int *resid)
+		     int *resid, int flags)
 {
 	char *sense = NULL;
 	int result;
@@ -270,14 +269,14 @@
 			return DRIVER_ERROR << 24;
 	}
 	result = scsi_execute(sdev, cmd, data_direction, buffer, bufflen,
-			      sense, timeout, retries, 0, resid);
+			      sense, timeout, retries, flags, resid);
 	if (sshdr)
 		scsi_normalize_sense(sense, SCSI_SENSE_BUFFERSIZE, sshdr);
 
 	kfree(sense);
 	return result;
 }
-EXPORT_SYMBOL(scsi_execute_req);
+EXPORT_SYMBOL(scsi_execute_req_flags);
 
 /*
  * Function:    scsi_init_cmd_errh()
diff --git a/drivers/scsi/scsi_pm.c b/drivers/scsi/scsi_pm.c
index c467064..ff78095 100644
--- a/drivers/scsi/scsi_pm.c
+++ b/drivers/scsi/scsi_pm.c
@@ -16,29 +16,28 @@
 
 #include "scsi_priv.h"
 
-static int scsi_dev_type_suspend(struct device *dev, pm_message_t msg)
+static int scsi_dev_type_suspend(struct device *dev, int (*cb)(struct device *))
 {
-	struct device_driver *drv;
 	int err;
 
 	err = scsi_device_quiesce(to_scsi_device(dev));
 	if (err == 0) {
-		drv = dev->driver;
-		if (drv && drv->suspend)
-			err = drv->suspend(dev, msg);
+		if (cb) {
+			err = cb(dev);
+			if (err)
+				scsi_device_resume(to_scsi_device(dev));
+		}
 	}
 	dev_dbg(dev, "scsi suspend: %d\n", err);
 	return err;
 }
 
-static int scsi_dev_type_resume(struct device *dev)
+static int scsi_dev_type_resume(struct device *dev, int (*cb)(struct device *))
 {
-	struct device_driver *drv;
 	int err = 0;
 
-	drv = dev->driver;
-	if (drv && drv->resume)
-		err = drv->resume(dev);
+	if (cb)
+		err = cb(dev);
 	scsi_device_resume(to_scsi_device(dev));
 	dev_dbg(dev, "scsi resume: %d\n", err);
 	return err;
@@ -46,30 +45,28 @@
 
 #ifdef CONFIG_PM_SLEEP
 
-static int scsi_bus_suspend_common(struct device *dev, pm_message_t msg)
+static int
+scsi_bus_suspend_common(struct device *dev, int (*cb)(struct device *))
 {
 	int err = 0;
 
 	if (scsi_is_sdev_device(dev)) {
 		/*
-		 * sd is the only high-level SCSI driver to implement runtime
-		 * PM, and sd treats runtime suspend, system suspend, and
-		 * system hibernate identically (but not system freeze).
+		 * All the high-level SCSI drivers that implement runtime
+		 * PM treat runtime suspend, system suspend, and system
+		 * hibernate identically.
 		 */
-		if (pm_runtime_suspended(dev)) {
-			if (msg.event == PM_EVENT_SUSPEND ||
-			    msg.event == PM_EVENT_HIBERNATE)
-				return 0;	/* already suspended */
+		if (pm_runtime_suspended(dev))
+			return 0;
 
-			/* wake up device so that FREEZE will succeed */
-			pm_runtime_resume(dev);
-		}
-		err = scsi_dev_type_suspend(dev, msg);
+		err = scsi_dev_type_suspend(dev, cb);
 	}
+
 	return err;
 }
 
-static int scsi_bus_resume_common(struct device *dev)
+static int
+scsi_bus_resume_common(struct device *dev, int (*cb)(struct device *))
 {
 	int err = 0;
 
@@ -81,7 +78,7 @@
 		 * Resume it on behalf of child.
 		 */
 		pm_runtime_get_sync(dev->parent);
-		err = scsi_dev_type_resume(dev);
+		err = scsi_dev_type_resume(dev, cb);
 		pm_runtime_put_sync(dev->parent);
 	}
 
@@ -108,55 +105,131 @@
 
 static int scsi_bus_suspend(struct device *dev)
 {
-	return scsi_bus_suspend_common(dev, PMSG_SUSPEND);
+	const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
+	return scsi_bus_suspend_common(dev, pm ? pm->suspend : NULL);
+}
+
+static int scsi_bus_resume(struct device *dev)
+{
+	const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
+	return scsi_bus_resume_common(dev, pm ? pm->resume : NULL);
 }
 
 static int scsi_bus_freeze(struct device *dev)
 {
-	return scsi_bus_suspend_common(dev, PMSG_FREEZE);
+	const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
+	return scsi_bus_suspend_common(dev, pm ? pm->freeze : NULL);
+}
+
+static int scsi_bus_thaw(struct device *dev)
+{
+	const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
+	return scsi_bus_resume_common(dev, pm ? pm->thaw : NULL);
 }
 
 static int scsi_bus_poweroff(struct device *dev)
 {
-	return scsi_bus_suspend_common(dev, PMSG_HIBERNATE);
+	const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
+	return scsi_bus_suspend_common(dev, pm ? pm->poweroff : NULL);
+}
+
+static int scsi_bus_restore(struct device *dev)
+{
+	const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
+	return scsi_bus_resume_common(dev, pm ? pm->restore : NULL);
 }
 
 #else /* CONFIG_PM_SLEEP */
 
-#define scsi_bus_resume_common		NULL
 #define scsi_bus_prepare		NULL
 #define scsi_bus_suspend		NULL
+#define scsi_bus_resume			NULL
 #define scsi_bus_freeze			NULL
+#define scsi_bus_thaw			NULL
 #define scsi_bus_poweroff		NULL
+#define scsi_bus_restore		NULL
 
 #endif /* CONFIG_PM_SLEEP */
 
 #ifdef CONFIG_PM_RUNTIME
 
+static int sdev_blk_runtime_suspend(struct scsi_device *sdev,
+					int (*cb)(struct device *))
+{
+	int err;
+
+	err = blk_pre_runtime_suspend(sdev->request_queue);
+	if (err)
+		return err;
+	if (cb)
+		err = cb(&sdev->sdev_gendev);
+	blk_post_runtime_suspend(sdev->request_queue, err);
+
+	return err;
+}
+
+static int sdev_runtime_suspend(struct device *dev)
+{
+	const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
+	int (*cb)(struct device *) = pm ? pm->runtime_suspend : NULL;
+	struct scsi_device *sdev = to_scsi_device(dev);
+	int err;
+
+	if (sdev->request_queue->dev)
+		return sdev_blk_runtime_suspend(sdev, cb);
+
+	err = scsi_dev_type_suspend(dev, cb);
+	if (err == -EAGAIN)
+		pm_schedule_suspend(dev, jiffies_to_msecs(
+					round_jiffies_up_relative(HZ/10)));
+	return err;
+}
+
 static int scsi_runtime_suspend(struct device *dev)
 {
 	int err = 0;
 
 	dev_dbg(dev, "scsi_runtime_suspend\n");
-	if (scsi_is_sdev_device(dev)) {
-		err = scsi_dev_type_suspend(dev, PMSG_AUTO_SUSPEND);
-		if (err == -EAGAIN)
-			pm_schedule_suspend(dev, jiffies_to_msecs(
-				round_jiffies_up_relative(HZ/10)));
-	}
+	if (scsi_is_sdev_device(dev))
+		err = sdev_runtime_suspend(dev);
 
 	/* Insert hooks here for targets, hosts, and transport classes */
 
 	return err;
 }
 
+static int sdev_blk_runtime_resume(struct scsi_device *sdev,
+					int (*cb)(struct device *))
+{
+	int err = 0;
+
+	blk_pre_runtime_resume(sdev->request_queue);
+	if (cb)
+		err = cb(&sdev->sdev_gendev);
+	blk_post_runtime_resume(sdev->request_queue, err);
+
+	return err;
+}
+
+static int sdev_runtime_resume(struct device *dev)
+{
+	struct scsi_device *sdev = to_scsi_device(dev);
+	const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
+	int (*cb)(struct device *) = pm ? pm->runtime_resume : NULL;
+
+	if (sdev->request_queue->dev)
+		return sdev_blk_runtime_resume(sdev, cb);
+	else
+		return scsi_dev_type_resume(dev, cb);
+}
+
 static int scsi_runtime_resume(struct device *dev)
 {
 	int err = 0;
 
 	dev_dbg(dev, "scsi_runtime_resume\n");
 	if (scsi_is_sdev_device(dev))
-		err = scsi_dev_type_resume(dev);
+		err = sdev_runtime_resume(dev);
 
 	/* Insert hooks here for targets, hosts, and transport classes */
 
@@ -171,10 +244,18 @@
 
 	/* Insert hooks here for targets, hosts, and transport classes */
 
-	if (scsi_is_sdev_device(dev))
-		err = pm_schedule_suspend(dev, 100);
-	else
+	if (scsi_is_sdev_device(dev)) {
+		struct scsi_device *sdev = to_scsi_device(dev);
+
+		if (sdev->request_queue->dev) {
+			pm_runtime_mark_last_busy(dev);
+			err = pm_runtime_autosuspend(dev);
+		} else {
+			err = pm_runtime_suspend(dev);
+		}
+	} else {
 		err = pm_runtime_suspend(dev);
+	}
 	return err;
 }
 
@@ -235,11 +316,11 @@
 const struct dev_pm_ops scsi_bus_pm_ops = {
 	.prepare =		scsi_bus_prepare,
 	.suspend =		scsi_bus_suspend,
-	.resume =		scsi_bus_resume_common,
+	.resume =		scsi_bus_resume,
 	.freeze =		scsi_bus_freeze,
-	.thaw =			scsi_bus_resume_common,
+	.thaw =			scsi_bus_thaw,
 	.poweroff =		scsi_bus_poweroff,
-	.restore =		scsi_bus_resume_common,
+	.restore =		scsi_bus_restore,
 	.runtime_suspend =	scsi_runtime_suspend,
 	.runtime_resume =	scsi_runtime_resume,
 	.runtime_idle =		scsi_runtime_idle,
diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c
index 508c2bb..f454610 100644
--- a/drivers/scsi/sd.c
+++ b/drivers/scsi/sd.c
@@ -966,10 +966,6 @@
 
 	sdev = sdkp->device;
 
-	retval = scsi_autopm_get_device(sdev);
-	if (retval)
-		goto error_autopm;
-
 	/*
 	 * If the device is in error recovery, wait until it is done.
 	 * If the device is offline, then disallow any access to it.
@@ -1014,8 +1010,6 @@
 	return 0;
 
 error_out:
-	scsi_autopm_put_device(sdev);
-error_autopm:
 	scsi_disk_put(sdkp);
 	return retval;	
 }
@@ -1050,7 +1044,6 @@
 	 * XXX is followed by a "rmmod sd_mod"?
 	 */
 
-	scsi_autopm_put_device(sdev);
 	scsi_disk_put(sdkp);
 	return 0;
 }
@@ -1212,14 +1205,9 @@
 	retval = -ENODEV;
 
 	if (scsi_block_when_processing_errors(sdp)) {
-		retval = scsi_autopm_get_device(sdp);
-		if (retval)
-			goto out;
-
 		sshdr  = kzalloc(sizeof(*sshdr), GFP_KERNEL);
 		retval = scsi_test_unit_ready(sdp, SD_TIMEOUT, SD_MAX_RETRIES,
 					      sshdr);
-		scsi_autopm_put_device(sdp);
 	}
 
 	/* failed to execute TUR, assume media not present */
@@ -1269,8 +1257,9 @@
 		 * Leave the rest of the command zero to indicate
 		 * flush everything.
 		 */
-		res = scsi_execute_req(sdp, cmd, DMA_NONE, NULL, 0, &sshdr,
-				       SD_FLUSH_TIMEOUT, SD_MAX_RETRIES, NULL);
+		res = scsi_execute_req_flags(sdp, cmd, DMA_NONE, NULL, 0,
+					     &sshdr, SD_FLUSH_TIMEOUT,
+					     SD_MAX_RETRIES, NULL, REQ_PM);
 		if (res == 0)
 			break;
 	}
@@ -2630,6 +2619,7 @@
 
 	sd_printk(KERN_NOTICE, sdkp, "Attached SCSI %sdisk\n",
 		  sdp->removable ? "removable " : "");
+	blk_pm_runtime_init(sdp->request_queue, dev);
 	scsi_autopm_put_device(sdp);
 	put_device(&sdkp->dev);
 }
@@ -2812,8 +2802,8 @@
 	if (!scsi_device_online(sdp))
 		return -ENODEV;
 
-	res = scsi_execute_req(sdp, cmd, DMA_NONE, NULL, 0, &sshdr,
-			       SD_TIMEOUT, SD_MAX_RETRIES, NULL);
+	res = scsi_execute_req_flags(sdp, cmd, DMA_NONE, NULL, 0, &sshdr,
+			       SD_TIMEOUT, SD_MAX_RETRIES, NULL, REQ_PM);
 	if (res) {
 		sd_printk(KERN_WARNING, sdkp, "START_STOP FAILED\n");
 		sd_print_result(sdkp, res);
diff --git a/drivers/scsi/ufs/ufs_test.c b/drivers/scsi/ufs/ufs_test.c
index 03c58a4..dbab808 100644
--- a/drivers/scsi/ufs/ufs_test.c
+++ b/drivers/scsi/ufs/ufs_test.c
@@ -18,13 +18,27 @@
 #include <scsi/scsi_device.h>
 #include <scsi/scsi_cmnd.h>
 #include <../sd.h>
+#include <linux/delay.h>
 
 #define MODULE_NAME "ufs_test"
 
-#define TEST_MAX_BIOS_PER_REQ		120
+#define TEST_MAX_BIOS_PER_REQ		16
 #define LARGE_PRIME_1	1103515367
 #define LARGE_PRIME_2	35757
-#define DEFAULT_NUM_OF_BIOS	2
+#define DEFAULT_NUM_OF_BIOS		2
+
+/* the amount of requests that will be inserted */
+#define LONG_SEQ_TEST_NUM_REQS  256
+/* request queue limitation is 128 requests, and we leave 10 spare requests */
+#define QUEUE_MAX_REQUESTS 118
+#define MB_MSEC_RATIO_APPROXIMATION ((1024 * 1024) / 1000)
+/* actual number of MiB in test multiplied by 10, for single digit precision*/
+#define BYTE_TO_MB_x_10(x) ((x * 10) / (1024 * 1024))
+/* extract integer value */
+#define LONG_TEST_SIZE_INTEGER(x) (BYTE_TO_MB_x_10(x) / 10)
+/* and calculate the MiB value fraction */
+#define LONG_TEST_SIZE_FRACTION(x) (BYTE_TO_MB_x_10(x) - \
+		(LONG_TEST_SIZE_INTEGER(x) * 10))
 
 #define test_pr_debug(fmt, args...) pr_debug("%s: "fmt"\n", MODULE_NAME, args)
 #define test_pr_info(fmt, args...) pr_info("%s: "fmt"\n", MODULE_NAME, args)
@@ -32,11 +46,16 @@
 
 enum ufs_test_testcases {
 	UFS_TEST_WRITE_READ_TEST,
+
+	TEST_LONG_SEQUENTIAL_READ,
+	TEST_LONG_SEQUENTIAL_WRITE,
 };
 
 struct ufs_test_debug {
 	struct dentry *write_read_test; /* basic test */
 	struct dentry *random_test_seed; /* parameters in utils */
+	struct dentry *long_sequential_read_test;
+	struct dentry *long_sequential_write_test;
 };
 
 struct ufs_test_data {
@@ -60,6 +79,8 @@
 	 * disabled and 2 BIOs are written.
 	 */
 	unsigned int random_test_seed;
+	/* A counter for the number of test requests completed */
+	unsigned int completed_req_count;
 };
 
 static struct ufs_test_data *utd;
@@ -77,6 +98,12 @@
 	case UFS_TEST_WRITE_READ_TEST:
 		return "UFS write read test";
 		break;
+	case TEST_LONG_SEQUENTIAL_READ:
+		return "UFS long sequential read test";
+		break;
+	case TEST_LONG_SEQUENTIAL_WRITE:
+		return "UFS long sequential write test";
+		break;
 	default:
 		return "Unknown test";
 	}
@@ -166,8 +193,9 @@
 		num_bios = DEFAULT_NUM_OF_BIOS;
 
 	/* Adding a write request */
-	test_pr_info("%s: Adding a write requests to Q, first req_id=%d",
-			__func__, td->wr_rd_next_req_id);
+	test_pr_info(
+		"%s: Adding a write request with %d bios to Q, req_id=%d"
+			, __func__, num_bios, td->wr_rd_next_req_id);
 
 	utd->write_completed = false;
 	ret = test_iosched_add_wr_rd_test_req(0, WRITE, start_sec,
@@ -265,21 +293,290 @@
 		.read = ufs_test_write_read_test_read_cb,
 };
 
+static void long_seq_test_free_end_io_fn(struct request *rq, int err)
+{
+	struct test_request *test_rq;
+	struct test_data *ptd = test_get_test_data();
+
+	if (rq)
+		test_rq = (struct test_request *)rq->elv.priv[0];
+	else {
+		test_pr_err("%s: error: NULL request", __func__);
+		return;
+	}
+
+	BUG_ON(!test_rq);
+
+	spin_lock_irq(&ptd->lock);
+	ptd->dispatched_count--;
+	list_del_init(&test_rq->queuelist);
+	__blk_put_request(ptd->req_q, test_rq->rq);
+	spin_unlock_irq(&ptd->lock);
+
+	kfree(test_rq->bios_buffer);
+	kfree(test_rq);
+	utd->completed_req_count++;
+
+	test_pr_err("%s: request %d completed, err=%d",
+	       __func__, test_rq->req_id, err);
+
+	check_test_completion();
+
+}
+
+static int run_long_seq_test(struct test_data *td)
+{
+	int ret = 0;
+	int direction;
+	static unsigned int inserted_requests;
+
+	BUG_ON(!td);
+	td->test_count = 0;
+	utd->completed_req_count = 0;
+	inserted_requests = 0;
+
+	if (td->test_info.testcase == TEST_LONG_SEQUENTIAL_READ)
+		direction = READ;
+	else
+		direction = WRITE;
+
+	test_pr_info("%s: Adding %d requests, first req_id=%d",
+		     __func__, LONG_SEQ_TEST_NUM_REQS,
+		     td->wr_rd_next_req_id);
+
+	do {
+		/*
+		* since our requests come from a pool containing 128
+		* requests, we don't want to exhaust this quantity,
+		* therefore we add up to QUEUE_MAX_REQUESTS (which
+		* includes a safety margin) and then call the mmc layer
+		* to fetch them
+		*/
+		if (td->test_count >= QUEUE_MAX_REQUESTS) {
+			blk_run_queue(td->req_q);
+			continue;
+		}
+
+		ret = test_iosched_add_wr_rd_test_req(0, direction,
+			td->start_sector, TEST_MAX_BIOS_PER_REQ,
+			TEST_PATTERN_5A,
+			long_seq_test_free_end_io_fn);
+		if (ret) {
+			test_pr_err("%s: failed to create request" , __func__);
+			break;
+		}
+		inserted_requests++;
+		td->test_info.test_byte_count +=
+			(TEST_MAX_BIOS_PER_REQ * sizeof(unsigned int) *
+			BIO_U32_SIZE);
+
+	} while (inserted_requests < LONG_SEQ_TEST_NUM_REQS);
+
+	/* in this case the queue will not run in the above loop */
+	if (LONG_SEQ_TEST_NUM_REQS < QUEUE_MAX_REQUESTS)
+		blk_run_queue(td->req_q);
+
+	return ret;
+}
+
+
+void long_seq_test_calc_throughput(unsigned long mtime,
+				   unsigned long byte_count)
+{
+	unsigned long fraction, integer;
+
+	test_pr_info("%s: time is %lu msec, size is %lu.%lu MiB",
+			__func__, mtime, LONG_TEST_SIZE_INTEGER(byte_count),
+				LONG_TEST_SIZE_FRACTION(byte_count));
+
+	/* we first multiply in order not to lose precision */
+	mtime *= MB_MSEC_RATIO_APPROXIMATION;
+	/* divide values to get a MiB/sec integer value with one
+	   digit of precision
+	   */
+	fraction = integer = (byte_count * 10) / mtime;
+	integer /= 10;
+	/* and calculate the MiB value fraction */
+	fraction -= integer * 10;
+
+	test_pr_info("%s: Throughput: %lu.%lu MiB/sec\n",
+		__func__, integer, fraction);
+}
+
+static ssize_t long_sequential_read_test_write(struct file *file,
+				const char __user *buf,
+				size_t count,
+				loff_t *ppos)
+{
+	int ret = 0;
+	int i = 0;
+	int number = -1;
+	unsigned long mtime, byte_count;
+
+	test_pr_info("%s: -- UFS Long Sequential Read TEST --", __func__);
+
+	sscanf(buf, "%d", &number);
+
+	if (number <= 0)
+		number = 1;
+
+	memset(&utd->test_info, 0, sizeof(struct test_info));
+
+	utd->test_info.data = utd;
+	utd->test_info.get_rq_disk_fn = ufs_test_get_rq_disk;
+	utd->test_info.run_test_fn = run_long_seq_test;
+	utd->test_info.get_test_case_str_fn = ufs_test_get_test_case_str;
+	utd->test_info.testcase = TEST_LONG_SEQUENTIAL_READ;
+
+	for (i = 0 ; i < number ; ++i) {
+		test_pr_info("%s: Cycle # %d / %d", __func__, i+1, number);
+		test_pr_info("%s: ====================", __func__);
+
+		ret = test_iosched_start_test(&utd->test_info);
+		if (ret)
+			break;
+
+		mtime = ktime_to_ms(utd->test_info.test_duration);
+		byte_count = utd->test_info.test_byte_count;
+
+		long_seq_test_calc_throughput(mtime, byte_count);
+
+		/* Allow FS requests to be dispatched */
+		msleep(1000);
+	}
+
+	return count;
+}
+
+static ssize_t long_sequential_read_test_read(struct file *file,
+			       char __user *buffer,
+			       size_t count,
+			       loff_t *offset)
+{
+	memset((void *)buffer, 0, count);
+
+	snprintf(buffer, count,
+		 "\nufs_long_sequential_read_test\n"
+		 "=========\n"
+		 "Description:\n"
+		 "This test runs the following scenarios\n"
+		 "- Long Sequential Read Test: this test measures read "
+		 "throughput at the driver level by sequentially reading many "
+		 "large requests.\n");
+
+	if (message_repeat == 1) {
+		message_repeat = 0;
+		return strnlen(buffer, count);
+	} else
+		return 0;
+}
+
+static bool message_repeat;
+static int test_open(struct inode *inode, struct file *file)
+{
+	file->private_data = inode->i_private;
+	message_repeat = 1;
+	return 0;
+}
+
+const struct file_operations long_sequential_read_test_ops = {
+	.open = test_open,
+	.write = long_sequential_read_test_write,
+	.read = long_sequential_read_test_read,
+};
+
+static ssize_t long_sequential_write_test_write(struct file *file,
+				const char __user *buf,
+				size_t count,
+				loff_t *ppos)
+{
+	int ret = 0;
+	int i = 0;
+	int number = -1;
+	unsigned long mtime, byte_count;
+
+	test_pr_info("%s: -- UFS Long Sequential Write TEST --", __func__);
+
+	sscanf(buf, "%d", &number);
+
+	if (number <= 0)
+		number = 1;
+
+	memset(&utd->test_info, 0, sizeof(struct test_info));
+
+	utd->test_info.data = utd;
+	utd->test_info.get_rq_disk_fn = ufs_test_get_rq_disk;
+	utd->test_info.get_test_case_str_fn = ufs_test_get_test_case_str;
+	utd->test_info.run_test_fn = run_long_seq_test;
+	utd->test_info.testcase = TEST_LONG_SEQUENTIAL_WRITE;
+
+	for (i = 0 ; i < number ; ++i) {
+		test_pr_info("%s: Cycle # %d / %d", __func__, i+1, number);
+		test_pr_info("%s: ====================", __func__);
+
+		utd->test_info.test_byte_count = 0;
+		ret = test_iosched_start_test(&utd->test_info);
+		if (ret)
+			break;
+
+		mtime = ktime_to_ms(utd->test_info.test_duration);
+		byte_count = utd->test_info.test_byte_count;
+
+		long_seq_test_calc_throughput(mtime, byte_count);
+
+		/* Allow FS requests to be dispatched */
+		msleep(1000);
+	}
+
+	return count;
+}
+
+static ssize_t long_sequential_write_test_read(struct file *file,
+			       char __user *buffer,
+			       size_t count,
+			       loff_t *offset)
+{
+	memset((void *)buffer, 0, count);
+
+	snprintf(buffer, count,
+		 "\nufs_long_sequential_write_test\n"
+		 "=========\n"
+		 "Description:\n"
+		 "This test runs the following scenarios\n"
+		 "- Long Sequential Write Test: this test measures write "
+		 "throughput at the driver level by sequentially writing many "
+		 "large requests\n");
+
+	if (message_repeat == 1) {
+		message_repeat = 0;
+		return strnlen(buffer, count);
+	} else
+		return 0;
+}
+
+const struct file_operations long_sequential_write_test_ops = {
+	.open = test_open,
+	.write = long_sequential_write_test_write,
+	.read = long_sequential_write_test_read,
+};
+
 static void ufs_test_debugfs_cleanup(void)
 {
-	debugfs_remove(utd->debug.write_read_test);
+	debugfs_remove_recursive(test_iosched_get_debugfs_tests_root());
 }
 
 static int ufs_test_debugfs_init(void)
 {
 	struct dentry *utils_root, *tests_root;
+	int ret = 0;
 
 	utils_root = test_iosched_get_debugfs_utils_root();
 	tests_root = test_iosched_get_debugfs_tests_root();
 
 	if (!utils_root || !tests_root) {
 		test_pr_err("%s: Failed to create debugfs root.", __func__);
-		return -EINVAL;
+		ret = -EINVAL;
+		goto exit;
 	}
 
 	utd->debug.random_test_seed = debugfs_create_u32("random_test_seed",
@@ -288,21 +585,49 @@
 	if (!utd->debug.random_test_seed) {
 		test_pr_err("%s: Could not create debugfs random_test_seed.",
 				__func__);
-		return -ENOMEM;
+		ret = -ENOMEM;
+		goto exit;
 	}
 
-	utd->debug.write_read_test = debugfs_create_file("write_read_test",
+	utd->debug.write_read_test = debugfs_create_file("ufs_write_read_test",
 					S_IRUGO | S_IWUGO, tests_root,
 					NULL, &write_read_test_ops);
 
 	if (!utd->debug.write_read_test) {
-		debugfs_remove(utd->debug.random_test_seed);
-		test_pr_err("%s: Could not create debugfs write_read_test.",
-				__func__);
-		return -ENOMEM;
+		ret = -ENOMEM;
+		goto exit_err;
 	}
 
-	return 0;
+	utd->debug.long_sequential_read_test = debugfs_create_file(
+					"ufs_long_sequential_read_test",
+					S_IRUGO | S_IWUGO,
+					tests_root,
+					NULL,
+					&long_sequential_read_test_ops);
+
+	if (!utd->debug.long_sequential_read_test) {
+		ret = -ENOMEM;
+		goto exit_err;
+	}
+
+	utd->debug.long_sequential_write_test = debugfs_create_file(
+					"ufs_long_sequential_write_test",
+					S_IRUGO | S_IWUGO,
+					tests_root,
+					NULL,
+					&long_sequential_write_test_ops);
+
+	if (!utd->debug.long_sequential_write_test) {
+		ret = -ENOMEM;
+		goto exit_err;
+	}
+
+	goto exit;
+
+exit_err:
+	debugfs_remove_recursive(tests_root);
+exit:
+	return ret;
 }
 
 static void ufs_test_probe(void)
diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index c32a478..48a7645 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -33,8 +33,16 @@
  * this program.
  */
 
+#include <linux/async.h>
+
 #include "ufshcd.h"
 
+#define UFSHCD_ENABLE_INTRS	(UTP_TRANSFER_REQ_COMPL |\
+				 UTP_TASK_REQ_COMPL |\
+				 UFSHCD_ERROR_MASK)
+/* UIC command timeout, unit: ms */
+#define UIC_CMD_TIMEOUT	500
+
 enum {
 	UFSHCD_MAX_CHANNEL	= 0,
 	UFSHCD_MAX_ID		= 1,
@@ -64,6 +72,20 @@
 };
 
 /**
+ * ufshcd_get_intr_mask - Get the interrupt bit mask
+ * @hba - Pointer to adapter instance
+ *
+ * Returns interrupt bit mask per version
+ */
+static inline u32 ufshcd_get_intr_mask(struct ufs_hba *hba)
+{
+	if (hba->ufs_version == UFSHCI_VERSION_10)
+		return INTERRUPT_MASK_ALL_VER_10;
+	else
+		return INTERRUPT_MASK_ALL_VER_11;
+}
+
+/**
  * ufshcd_get_ufs_version - Get the UFS version supported by the HBA
  * @hba - Pointer to adapter instance
  *
@@ -71,7 +93,7 @@
  */
 static inline u32 ufshcd_get_ufs_version(struct ufs_hba *hba)
 {
-	return readl(hba->mmio_base + REG_UFS_VERSION);
+	return ufshcd_readl(hba, REG_UFS_VERSION);
 }
 
 /**
@@ -130,8 +152,7 @@
  */
 static inline void ufshcd_utrl_clear(struct ufs_hba *hba, u32 pos)
 {
-	writel(~(1 << pos),
-		(hba->mmio_base + REG_UTP_TRANSFER_REQ_LIST_CLEAR));
+	ufshcd_writel(hba, ~(1 << pos), REG_UTP_TRANSFER_REQ_LIST_CLEAR);
 }
 
 /**
@@ -165,7 +186,7 @@
  */
 static inline int ufshcd_get_uic_cmd_result(struct ufs_hba *hba)
 {
-	return readl(hba->mmio_base + REG_UIC_COMMAND_ARG_2) &
+	return ufshcd_readl(hba, REG_UIC_COMMAND_ARG_2) &
 	       MASK_UIC_COMMAND_RESULT;
 }
 
@@ -243,18 +264,15 @@
 {
 	switch (option) {
 	case INT_AGGR_RESET:
-		writel((INT_AGGR_ENABLE |
-			INT_AGGR_COUNTER_AND_TIMER_RESET),
-			(hba->mmio_base +
-			 REG_UTP_TRANSFER_REQ_INT_AGG_CONTROL));
+		ufshcd_writel(hba, INT_AGGR_ENABLE |
+			      INT_AGGR_COUNTER_AND_TIMER_RESET,
+			      REG_UTP_TRANSFER_REQ_INT_AGG_CONTROL);
 		break;
 	case INT_AGGR_CONFIG:
-		writel((INT_AGGR_ENABLE |
-			INT_AGGR_PARAM_WRITE |
-			INT_AGGR_COUNTER_THRESHOLD_VALUE |
-			INT_AGGR_TIMEOUT_VALUE),
-			(hba->mmio_base +
-			 REG_UTP_TRANSFER_REQ_INT_AGG_CONTROL));
+		ufshcd_writel(hba, INT_AGGR_ENABLE | INT_AGGR_PARAM_WRITE |
+			      INT_AGGR_COUNTER_THRESHOLD_VALUE |
+			      INT_AGGR_TIMEOUT_VALUE,
+			      REG_UTP_TRANSFER_REQ_INT_AGG_CONTROL);
 		break;
 	}
 }
@@ -267,12 +285,10 @@
  */
 static void ufshcd_enable_run_stop_reg(struct ufs_hba *hba)
 {
-	writel(UTP_TASK_REQ_LIST_RUN_STOP_BIT,
-	       (hba->mmio_base +
-		REG_UTP_TASK_REQ_LIST_RUN_STOP));
-	writel(UTP_TRANSFER_REQ_LIST_RUN_STOP_BIT,
-	       (hba->mmio_base +
-		REG_UTP_TRANSFER_REQ_LIST_RUN_STOP));
+	ufshcd_writel(hba, UTP_TASK_REQ_LIST_RUN_STOP_BIT,
+		      REG_UTP_TASK_REQ_LIST_RUN_STOP);
+	ufshcd_writel(hba, UTP_TRANSFER_REQ_LIST_RUN_STOP_BIT,
+		      REG_UTP_TRANSFER_REQ_LIST_RUN_STOP);
 }
 
 /**
@@ -281,7 +297,7 @@
  */
 static inline void ufshcd_hba_start(struct ufs_hba *hba)
 {
-	writel(CONTROLLER_ENABLE , (hba->mmio_base + REG_CONTROLLER_ENABLE));
+	ufshcd_writel(hba, CONTROLLER_ENABLE, REG_CONTROLLER_ENABLE);
 }
 
 /**
@@ -292,7 +308,7 @@
  */
 static inline int ufshcd_is_hba_active(struct ufs_hba *hba)
 {
-	return (readl(hba->mmio_base + REG_CONTROLLER_ENABLE) & 0x1) ? 0 : 1;
+	return (ufshcd_readl(hba, REG_CONTROLLER_ENABLE) & 0x1) ? 0 : 1;
 }
 
 /**
@@ -304,8 +320,7 @@
 void ufshcd_send_command(struct ufs_hba *hba, unsigned int task_tag)
 {
 	__set_bit(task_tag, &hba->outstanding_reqs);
-	writel((1 << task_tag),
-	       (hba->mmio_base + REG_UTP_TRANSFER_REQ_DOOR_BELL));
+	ufshcd_writel(hba, 1 << task_tag, REG_UTP_TRANSFER_REQ_DOOR_BELL);
 }
 
 /**
@@ -329,8 +344,7 @@
  */
 static inline void ufshcd_hba_capabilities(struct ufs_hba *hba)
 {
-	hba->capabilities =
-		readl(hba->mmio_base + REG_CONTROLLER_CAPABILITIES);
+	hba->capabilities = ufshcd_readl(hba, REG_CONTROLLER_CAPABILITIES);
 
 	/* nutrs and nutmrs are 0 based values */
 	hba->nutrs = (hba->capabilities & MASK_TRANSFER_REQUESTS_SLOTS) + 1;
@@ -339,24 +353,119 @@
 }
 
 /**
- * ufshcd_send_uic_command - Send UIC commands to unipro layers
+ * ufshcd_ready_for_uic_cmd - Check if controller is ready
+ *                            to accept UIC commands
  * @hba: per adapter instance
- * @uic_command: UIC command
+ * Return true on success, else false
+ */
+static inline bool ufshcd_ready_for_uic_cmd(struct ufs_hba *hba)
+{
+	if (ufshcd_readl(hba, REG_CONTROLLER_STATUS) & UIC_COMMAND_READY)
+		return true;
+	else
+		return false;
+}
+
+/**
+ * ufshcd_dispatch_uic_cmd - Dispatch UIC commands to unipro layers
+ * @hba: per adapter instance
+ * @uic_cmd: UIC command
+ *
+ * Mutex must be held.
  */
 static inline void
-ufshcd_send_uic_command(struct ufs_hba *hba, struct uic_command *uic_cmnd)
+ufshcd_dispatch_uic_cmd(struct ufs_hba *hba, struct uic_command *uic_cmd)
 {
+	WARN_ON(hba->active_uic_cmd);
+
+	hba->active_uic_cmd = uic_cmd;
+
 	/* Write Args */
-	writel(uic_cmnd->argument1,
-	      (hba->mmio_base + REG_UIC_COMMAND_ARG_1));
-	writel(uic_cmnd->argument2,
-	      (hba->mmio_base + REG_UIC_COMMAND_ARG_2));
-	writel(uic_cmnd->argument3,
-	      (hba->mmio_base + REG_UIC_COMMAND_ARG_3));
+	ufshcd_writel(hba, uic_cmd->argument1, REG_UIC_COMMAND_ARG_1);
+	ufshcd_writel(hba, uic_cmd->argument2, REG_UIC_COMMAND_ARG_2);
+	ufshcd_writel(hba, uic_cmd->argument3, REG_UIC_COMMAND_ARG_3);
 
 	/* Write UIC Cmd */
-	writel((uic_cmnd->command & COMMAND_OPCODE_MASK),
-	       (hba->mmio_base + REG_UIC_COMMAND));
+	ufshcd_writel(hba, uic_cmd->command & COMMAND_OPCODE_MASK,
+		      REG_UIC_COMMAND);
+}
+
+/**
+ * ufshcd_wait_for_uic_cmd - Wait complectioin of UIC command
+ * @hba: per adapter instance
+ * @uic_command: UIC command
+ *
+ * Must be called with mutex held.
+ * Returns 0 only if success.
+ */
+static int
+ufshcd_wait_for_uic_cmd(struct ufs_hba *hba, struct uic_command *uic_cmd)
+{
+	int ret;
+	unsigned long flags;
+
+	if (wait_for_completion_timeout(&uic_cmd->done,
+					msecs_to_jiffies(UIC_CMD_TIMEOUT)))
+		ret = uic_cmd->argument2 & MASK_UIC_COMMAND_RESULT;
+	else
+		ret = -ETIMEDOUT;
+
+	spin_lock_irqsave(hba->host->host_lock, flags);
+	hba->active_uic_cmd = NULL;
+	spin_unlock_irqrestore(hba->host->host_lock, flags);
+
+	return ret;
+}
+
+/**
+ * __ufshcd_send_uic_cmd - Send UIC commands and retrieve the result
+ * @hba: per adapter instance
+ * @uic_cmd: UIC command
+ *
+ * Identical to ufshcd_send_uic_cmd() expect mutex. Must be called
+ * with mutex held.
+ * Returns 0 only if success.
+ */
+static int
+__ufshcd_send_uic_cmd(struct ufs_hba *hba, struct uic_command *uic_cmd)
+{
+	int ret;
+	unsigned long flags;
+
+	if (!ufshcd_ready_for_uic_cmd(hba)) {
+		dev_err(hba->dev,
+			"Controller not ready to accept UIC commands\n");
+		return -EIO;
+	}
+
+	init_completion(&uic_cmd->done);
+
+	spin_lock_irqsave(hba->host->host_lock, flags);
+	ufshcd_dispatch_uic_cmd(hba, uic_cmd);
+	spin_unlock_irqrestore(hba->host->host_lock, flags);
+
+	ret = ufshcd_wait_for_uic_cmd(hba, uic_cmd);
+
+	return ret;
+}
+
+/**
+ * ufshcd_send_uic_cmd - Send UIC commands and retrieve the result
+ * @hba: per adapter instance
+ * @uic_cmd: UIC command
+ *
+ * Returns 0 only if success.
+ */
+static int
+ufshcd_send_uic_cmd(struct ufs_hba *hba, struct uic_command *uic_cmd)
+{
+	int ret;
+
+	mutex_lock(&hba->uic_cmd_mutex);
+	ret = __ufshcd_send_uic_cmd(hba, uic_cmd);
+	mutex_unlock(&hba->uic_cmd_mutex);
+
+	return ret;
 }
 
 /**
@@ -400,26 +509,45 @@
 }
 
 /**
- * ufshcd_int_config - enable/disable interrupts
+ * ufshcd_enable_intr - enable interrupts
  * @hba: per adapter instance
- * @option: interrupt option
+ * @intrs: interrupt bits
  */
-static void ufshcd_int_config(struct ufs_hba *hba, u32 option)
+static void ufshcd_enable_intr(struct ufs_hba *hba, u32 intrs)
 {
-	switch (option) {
-	case UFSHCD_INT_ENABLE:
-		writel(hba->int_enable_mask,
-		      (hba->mmio_base + REG_INTERRUPT_ENABLE));
-		break;
-	case UFSHCD_INT_DISABLE:
-		if (hba->ufs_version == UFSHCI_VERSION_10)
-			writel(INTERRUPT_DISABLE_MASK_10,
-			      (hba->mmio_base + REG_INTERRUPT_ENABLE));
-		else
-			writel(INTERRUPT_DISABLE_MASK_11,
-			       (hba->mmio_base + REG_INTERRUPT_ENABLE));
-		break;
+	u32 set = ufshcd_readl(hba, REG_INTERRUPT_ENABLE);
+
+	if (hba->ufs_version == UFSHCI_VERSION_10) {
+		u32 rw;
+		rw = set & INTERRUPT_MASK_RW_VER_10;
+		set = rw | ((set ^ intrs) & intrs);
+	} else {
+		set |= intrs;
 	}
+
+	ufshcd_writel(hba, set, REG_INTERRUPT_ENABLE);
+}
+
+/**
+ * ufshcd_disable_intr - disable interrupts
+ * @hba: per adapter instance
+ * @intrs: interrupt bits
+ */
+static void ufshcd_disable_intr(struct ufs_hba *hba, u32 intrs)
+{
+	u32 set = ufshcd_readl(hba, REG_INTERRUPT_ENABLE);
+
+	if (hba->ufs_version == UFSHCI_VERSION_10) {
+		u32 rw;
+		rw = (set & INTERRUPT_MASK_RW_VER_10) &
+			~(intrs & INTERRUPT_MASK_RW_VER_10);
+		set = rw | ((set & intrs) & ~INTERRUPT_MASK_RW_VER_10);
+
+	} else {
+		set &= ~intrs;
+	}
+
+	ufshcd_writel(hba, set, REG_INTERRUPT_ENABLE);
 }
 
 /**
@@ -699,35 +827,16 @@
  */
 static int ufshcd_dme_link_startup(struct ufs_hba *hba)
 {
-	struct uic_command *uic_cmd;
-	unsigned long flags;
+	struct uic_command uic_cmd = {0};
+	int ret;
 
-	/* check if controller is ready to accept UIC commands */
-	if (((readl(hba->mmio_base + REG_CONTROLLER_STATUS)) &
-	    UIC_COMMAND_READY) == 0x0) {
+	uic_cmd.command = UIC_CMD_DME_LINK_STARTUP;
+
+	ret = ufshcd_send_uic_cmd(hba, &uic_cmd);
+	if (ret)
 		dev_err(hba->dev,
-			"Controller not ready"
-			" to accept UIC commands\n");
-		return -EIO;
-	}
-
-	spin_lock_irqsave(hba->host->host_lock, flags);
-
-	/* form UIC command */
-	uic_cmd = &hba->active_uic_cmd;
-	uic_cmd->command = UIC_CMD_DME_LINK_STARTUP;
-	uic_cmd->argument1 = 0;
-	uic_cmd->argument2 = 0;
-	uic_cmd->argument3 = 0;
-
-	/* enable UIC related interrupts */
-	hba->int_enable_mask |= UIC_COMMAND_COMPL;
-	ufshcd_int_config(hba, UFSHCD_INT_ENABLE);
-
-	/* sending UIC commands to controller */
-	ufshcd_send_uic_command(hba, uic_cmd);
-	spin_unlock_irqrestore(hba->host->host_lock, flags);
-	return 0;
+			"dme-link-startup: error code %d\n", ret);
+	return ret;
 }
 
 /**
@@ -736,9 +845,10 @@
  *
  * To bring UFS host controller to operational state,
  * 1. Check if device is present
- * 2. Configure run-stop-registers
- * 3. Enable required interrupts
- * 4. Configure interrupt aggregation
+ * 2. Enable required interrupts
+ * 3. Configure interrupt aggregation
+ * 4. Program UTRL and UTMRL base addres
+ * 5. Configure run-stop-registers
  *
  * Returns 0 on success, non-zero value on failure
  */
@@ -748,13 +858,29 @@
 	u32 reg;
 
 	/* check if device present */
-	reg = readl((hba->mmio_base + REG_CONTROLLER_STATUS));
+	reg = ufshcd_readl(hba, REG_CONTROLLER_STATUS);
 	if (!ufshcd_is_device_present(reg)) {
 		dev_err(hba->dev, "cc: Device not present\n");
 		err = -ENXIO;
 		goto out;
 	}
 
+	/* Enable required interrupts */
+	ufshcd_enable_intr(hba, UFSHCD_ENABLE_INTRS);
+
+	/* Configure interrupt aggregation */
+	ufshcd_config_int_aggr(hba, INT_AGGR_CONFIG);
+
+	/* Configure UTRL and UTMRL base address registers */
+	ufshcd_writel(hba, lower_32_bits(hba->utrdl_dma_addr),
+			REG_UTP_TRANSFER_REQ_LIST_BASE_L);
+	ufshcd_writel(hba, upper_32_bits(hba->utrdl_dma_addr),
+			REG_UTP_TRANSFER_REQ_LIST_BASE_H);
+	ufshcd_writel(hba, lower_32_bits(hba->utmrdl_dma_addr),
+			REG_UTP_TASK_REQ_LIST_BASE_L);
+	ufshcd_writel(hba, upper_32_bits(hba->utmrdl_dma_addr),
+			REG_UTP_TASK_REQ_LIST_BASE_H);
+
 	/*
 	 * UCRDY, UTMRLDY and UTRLRDY bits must be 1
 	 * DEI, HEI bits must be 0
@@ -768,23 +894,11 @@
 		goto out;
 	}
 
-	/* Enable required interrupts */
-	hba->int_enable_mask |= (UTP_TRANSFER_REQ_COMPL |
-				 UIC_ERROR |
-				 UTP_TASK_REQ_COMPL |
-				 DEVICE_FATAL_ERROR |
-				 CONTROLLER_FATAL_ERROR |
-				 SYSTEM_BUS_FATAL_ERROR);
-	ufshcd_int_config(hba, UFSHCD_INT_ENABLE);
-
-	/* Configure interrupt aggregation */
-	ufshcd_config_int_aggr(hba, INT_AGGR_CONFIG);
-
 	if (hba->ufshcd_state == UFSHCD_STATE_RESET)
 		scsi_unblock_requests(hba->host);
 
 	hba->ufshcd_state = UFSHCD_STATE_OPERATIONAL;
-	scsi_scan_host(hba->host);
+
 out:
 	return err;
 }
@@ -853,34 +967,28 @@
 }
 
 /**
- * ufshcd_initialize_hba - start the initialization process
+ * ufshcd_link_startup - Initialize unipro link startup
  * @hba: per adapter instance
  *
- * 1. Enable the controller via ufshcd_hba_enable.
- * 2. Program the Transfer Request List Address with the starting address of
- * UTRDL.
- * 3. Program the Task Management Request List Address with starting address
- * of UTMRDL.
- *
- * Returns 0 on success, non-zero value on failure.
+ * Returns 0 for success, non-zero in case of failure
  */
-static int ufshcd_initialize_hba(struct ufs_hba *hba)
+static int ufshcd_link_startup(struct ufs_hba *hba)
 {
-	if (ufshcd_hba_enable(hba))
-		return -EIO;
+	int ret;
 
-	/* Configure UTRL and UTMRL base address registers */
-	writel(lower_32_bits(hba->utrdl_dma_addr),
-	       (hba->mmio_base + REG_UTP_TRANSFER_REQ_LIST_BASE_L));
-	writel(upper_32_bits(hba->utrdl_dma_addr),
-	       (hba->mmio_base + REG_UTP_TRANSFER_REQ_LIST_BASE_H));
-	writel(lower_32_bits(hba->utmrdl_dma_addr),
-	       (hba->mmio_base + REG_UTP_TASK_REQ_LIST_BASE_L));
-	writel(upper_32_bits(hba->utmrdl_dma_addr),
-	       (hba->mmio_base + REG_UTP_TASK_REQ_LIST_BASE_H));
+	/* enable UIC related interrupts */
+	ufshcd_enable_intr(hba, UIC_COMMAND_COMPL);
 
-	/* Initialize unipro link startup procedure */
-	return ufshcd_dme_link_startup(hba);
+	ret = ufshcd_dme_link_startup(hba);
+	if (ret)
+		goto out;
+
+	ret = ufshcd_make_hba_operational(hba);
+
+out:
+	if (ret)
+		dev_err(hba->dev, "link startup failed %d\n", ret);
+	return ret;
 }
 
 /**
@@ -920,12 +1028,19 @@
 	hba->outstanding_reqs = 0;
 	hba->outstanding_tasks = 0;
 
-	/* start the initialization process */
-	if (ufshcd_initialize_hba(hba)) {
+	/* Host controller enable */
+	if (ufshcd_hba_enable(hba)) {
 		dev_err(hba->dev,
 			"Reset: Controller initialization failed\n");
 		return FAILED;
 	}
+
+	if (ufshcd_link_startup(hba)) {
+		dev_err(hba->dev,
+			"Reset: Link start-up failed\n");
+		return FAILED;
+	}
+
 	return SUCCESS;
 }
 
@@ -1157,6 +1272,19 @@
 }
 
 /**
+ * ufshcd_uic_cmd_compl - handle completion of uic command
+ * @hba: per adapter instance
+ */
+static void ufshcd_uic_cmd_compl(struct ufs_hba *hba)
+{
+	if (hba->active_uic_cmd) {
+		hba->active_uic_cmd->argument2 |=
+			ufshcd_get_uic_cmd_result(hba);
+		complete(&hba->active_uic_cmd->done);
+	}
+}
+
+/**
  * ufshcd_transfer_req_compl - handle SCSI and query command completion
  * @hba: per adapter instance
  */
@@ -1169,8 +1297,7 @@
 	int index;
 
 	lrb = hba->lrb;
-	tr_doorbell =
-		readl(hba->mmio_base + REG_UTP_TRANSFER_REQ_DOOR_BELL);
+	tr_doorbell = ufshcd_readl(hba, REG_UTP_TRANSFER_REQ_DOOR_BELL);
 	completed_reqs = tr_doorbell ^ hba->outstanding_reqs;
 
 	for (index = 0; index < hba->nutrs; index++) {
@@ -1197,28 +1324,6 @@
 }
 
 /**
- * ufshcd_uic_cc_handler - handle UIC command completion
- * @work: pointer to a work queue structure
- *
- * Returns 0 on success, non-zero value on failure
- */
-static void ufshcd_uic_cc_handler (struct work_struct *work)
-{
-	struct ufs_hba *hba;
-
-	hba = container_of(work, struct ufs_hba, uic_workq);
-
-	if ((hba->active_uic_cmd.command == UIC_CMD_DME_LINK_STARTUP) &&
-	    !(ufshcd_get_uic_cmd_result(hba))) {
-
-		if (ufshcd_make_hba_operational(hba))
-			dev_err(hba->dev,
-				"cc: hba not operational state\n");
-		return;
-	}
-}
-
-/**
  * ufshcd_fatal_err_handler - handle fatal errors
  * @hba: per adapter instance
  */
@@ -1244,9 +1349,7 @@
 		goto fatal_eh;
 
 	if (hba->errors & UIC_ERROR) {
-
-		reg = readl(hba->mmio_base +
-			    REG_UIC_ERROR_CODE_PHY_ADAPTER_LAYER);
+		reg = ufshcd_readl(hba, REG_UIC_ERROR_CODE_PHY_ADAPTER_LAYER);
 		if (reg & UIC_DATA_LINK_LAYER_ERROR_PA_INIT)
 			goto fatal_eh;
 	}
@@ -1264,7 +1367,7 @@
 {
 	u32 tm_doorbell;
 
-	tm_doorbell = readl(hba->mmio_base + REG_UTP_TASK_REQ_DOOR_BELL);
+	tm_doorbell = ufshcd_readl(hba, REG_UTP_TASK_REQ_DOOR_BELL);
 	hba->tm_condition = tm_doorbell ^ hba->outstanding_tasks;
 	wake_up_interruptible(&hba->ufshcd_tm_wait_queue);
 }
@@ -1281,7 +1384,7 @@
 		ufshcd_err_handler(hba);
 
 	if (intr_status & UIC_COMMAND_COMPL)
-		schedule_work(&hba->uic_workq);
+		ufshcd_uic_cmd_compl(hba);
 
 	if (intr_status & UTP_TASK_REQ_COMPL)
 		ufshcd_tmc_handler(hba);
@@ -1305,15 +1408,11 @@
 	struct ufs_hba *hba = __hba;
 
 	spin_lock(hba->host->host_lock);
-	intr_status = readl(hba->mmio_base + REG_INTERRUPT_STATUS);
+	intr_status = ufshcd_readl(hba, REG_INTERRUPT_STATUS);
 
 	if (intr_status) {
+		ufshcd_writel(hba, intr_status, REG_INTERRUPT_STATUS);
 		ufshcd_sl_intr(hba, intr_status);
-
-		/* If UFSHCI 1.0 then clear interrupt status register */
-		if (hba->ufs_version == UFSHCI_VERSION_10)
-			writel(intr_status,
-			       (hba->mmio_base + REG_INTERRUPT_STATUS));
 		retval = IRQ_HANDLED;
 	}
 	spin_unlock(hba->host->host_lock);
@@ -1378,8 +1477,7 @@
 
 	/* send command to the controller */
 	__set_bit(free_slot, &hba->outstanding_tasks);
-	writel((1 << free_slot),
-	       (hba->mmio_base + REG_UTP_TASK_REQ_DOOR_BELL));
+	ufshcd_writel(hba, 1 << free_slot, REG_UTP_TASK_REQ_DOOR_BELL);
 
 	spin_unlock_irqrestore(host->host_lock, flags);
 
@@ -1509,6 +1607,21 @@
 	return err;
 }
 
+/**
+ * ufshcd_async_scan - asynchronous execution for link startup
+ * @data: data pointer to pass to this function
+ * @cookie: cookie data
+ */
+static void ufshcd_async_scan(void *data, async_cookie_t cookie)
+{
+	struct ufs_hba *hba = (struct ufs_hba *)data;
+	int ret;
+
+	ret = ufshcd_link_startup(hba);
+	if (!ret)
+		scsi_scan_host(hba->host);
+}
+
 static struct scsi_host_template ufshcd_driver_template = {
 	.module			= THIS_MODULE,
 	.name			= UFSHCD,
@@ -1587,7 +1700,7 @@
 void ufshcd_remove(struct ufs_hba *hba)
 {
 	/* disable interrupts */
-	ufshcd_int_config(hba, UFSHCD_INT_DISABLE);
+	ufshcd_disable_intr(hba, hba->intr_mask);
 
 	ufshcd_hba_stop(hba);
 	ufshcd_hba_free(hba);
@@ -1645,6 +1758,9 @@
 	/* Get UFS version supported by the controller */
 	hba->ufs_version = ufshcd_get_ufs_version(hba);
 
+	/* Get Interrupt bit mask per version */
+	hba->intr_mask = ufshcd_get_intr_mask(hba);
+
 	/* Allocate memory for host memory space */
 	err = ufshcd_memory_alloc(hba);
 	if (err) {
@@ -1667,9 +1783,11 @@
 	init_waitqueue_head(&hba->ufshcd_tm_wait_queue);
 
 	/* Initialize work queues */
-	INIT_WORK(&hba->uic_workq, ufshcd_uic_cc_handler);
 	INIT_WORK(&hba->feh_workq, ufshcd_fatal_err_handler);
 
+	/* Initialize UIC command mutex */
+	mutex_init(&hba->uic_cmd_mutex);
+
 	/* IRQ registration */
 	err = request_irq(irq, ufshcd_intr, IRQF_SHARED, UFSHCD, hba);
 	if (err) {
@@ -1690,14 +1808,17 @@
 		goto out_free_irq;
 	}
 
-	/* Initialization routine */
-	err = ufshcd_initialize_hba(hba);
+	/* Host controller enable */
+	err = ufshcd_hba_enable(hba);
 	if (err) {
-		dev_err(hba->dev, "Initialization failed\n");
+		dev_err(hba->dev, "Host controller enable failed\n");
 		goto out_remove_scsi_host;
 	}
+
 	*hba_handle = hba;
 
+	async_schedule(ufshcd_async_scan, hba);
+
 	return 0;
 
 out_remove_scsi_host:
diff --git a/drivers/scsi/ufs/ufshcd.h b/drivers/scsi/ufs/ufshcd.h
index 6b99a42..49590ee 100644
--- a/drivers/scsi/ufs/ufshcd.h
+++ b/drivers/scsi/ufs/ufshcd.h
@@ -51,6 +51,7 @@
 #include <linux/bitops.h>
 #include <linux/pm_runtime.h>
 #include <linux/clk.h>
+#include <linux/completion.h>
 
 #include <asm/irq.h>
 #include <asm/byteorder.h>
@@ -75,6 +76,7 @@
  * @argument3: UIC command argument 3
  * @cmd_active: Indicate if UIC command is outstanding
  * @result: UIC command result
+ * @done: UIC command completion
  */
 struct uic_command {
 	u32 command;
@@ -83,6 +85,7 @@
 	u32 argument3;
 	int cmd_active;
 	int result;
+	struct completion done;
 };
 
 /**
@@ -136,11 +139,11 @@
  * @ufs_version: UFS Version to which controller complies
  * @irq: Irq number of the controller
  * @active_uic_cmd: handle of active UIC command
+ * @uic_cmd_mutex: mutex for uic command
  * @ufshcd_tm_wait_queue: wait queue for task management
  * @tm_condition: condition variable for task management
  * @ufshcd_state: UFSHCD states
- * @int_enable_mask: Interrupt Mask Bits
- * @uic_workq: Work queue for UIC completion handling
+ * @intr_mask: Interrupt Mask Bits
  * @feh_workq: Work queue for fatal controller error handling
  * @errors: HBA errors
  */
@@ -171,21 +174,27 @@
 	u32 ufs_version;
 	unsigned int irq;
 
-	struct uic_command active_uic_cmd;
+	struct uic_command *active_uic_cmd;
+	struct mutex uic_cmd_mutex;
+
 	wait_queue_head_t ufshcd_tm_wait_queue;
 	unsigned long tm_condition;
 
 	u32 ufshcd_state;
-	u32 int_enable_mask;
+	u32 intr_mask;
 
 	/* Work Queues */
-	struct work_struct uic_workq;
 	struct work_struct feh_workq;
 
 	/* HBA Errors */
 	u32 errors;
 };
 
+#define ufshcd_writel(hba, val, reg)	\
+	writel((val), (hba)->mmio_base + (reg))
+#define ufshcd_readl(hba, reg)	\
+	readl((hba)->mmio_base + (reg))
+
 int ufshcd_init(struct device *, struct ufs_hba ** , void __iomem * ,
 			unsigned int);
 void ufshcd_remove(struct ufs_hba *);
@@ -196,7 +205,7 @@
  */
 static inline void ufshcd_hba_stop(struct ufs_hba *hba)
 {
-	writel(CONTROLLER_DISABLE, (hba->mmio_base + REG_CONTROLLER_ENABLE));
+	ufshcd_writel(hba, CONTROLLER_DISABLE,  REG_CONTROLLER_ENABLE);
 }
 
 #endif /* End of Header */
diff --git a/drivers/scsi/ufs/ufshci.h b/drivers/scsi/ufs/ufshci.h
index 0c16484..d5c5f14 100644
--- a/drivers/scsi/ufs/ufshci.h
+++ b/drivers/scsi/ufs/ufshci.h
@@ -232,10 +232,11 @@
 /* Interrupt disable masks */
 enum {
 	/* Interrupt disable mask for UFSHCI v1.0 */
-	INTERRUPT_DISABLE_MASK_10	= 0xFFFF,
+	INTERRUPT_MASK_ALL_VER_10	= 0x30FFF,
+	INTERRUPT_MASK_RW_VER_10	= 0x30000,
 
 	/* Interrupt disable mask for UFSHCI v1.1 */
-	INTERRUPT_DISABLE_MASK_11	= 0x0,
+	INTERRUPT_MASK_ALL_VER_11	= 0x31FFF,
 };
 
 /*
diff --git a/drivers/slimbus/slim-msm-ctrl.c b/drivers/slimbus/slim-msm-ctrl.c
index 97d47db..6e7a815 100644
--- a/drivers/slimbus/slim-msm-ctrl.c
+++ b/drivers/slimbus/slim-msm-ctrl.c
@@ -30,12 +30,6 @@
 #define MSM_SLIM_NAME	"msm_slim_ctrl"
 #define SLIM_ROOT_FREQ 24576000
 
-#define QC_MFGID_LSB	0x2
-#define QC_MFGID_MSB	0x17
-#define QC_CHIPID_SL	0x10
-#define QC_DEVID_SAT1	0x3
-#define QC_DEVID_SAT2	0x4
-#define QC_DEVID_PGD	0x5
 #define QC_MSM_DEVS	5
 
 /* Manager registers */
diff --git a/drivers/slimbus/slim-msm-ngd.c b/drivers/slimbus/slim-msm-ngd.c
index 509c1e8..2f19863 100644
--- a/drivers/slimbus/slim-msm-ngd.c
+++ b/drivers/slimbus/slim-msm-ngd.c
@@ -306,8 +306,26 @@
 			txn->mc = SLIM_USR_MC_CONNECT_SINK;
 		else if (txn->mc == SLIM_MSG_MC_DISCONNECT_PORT)
 			txn->mc = SLIM_USR_MC_DISCONNECT_PORT;
-		if (txn->la == SLIM_LA_MGR)
+		if (txn->la == SLIM_LA_MGR) {
+			if (dev->pgdla == SLIM_LA_MGR) {
+				u8 ea[] = {0, QC_DEVID_PGD, 0, 0, QC_MFGID_MSB,
+						QC_MFGID_LSB};
+				ea[2] = (u8)(dev->pdata.eapc & 0xFF);
+				ea[3] = (u8)((dev->pdata.eapc & 0xFF00) >> 8);
+				mutex_unlock(&dev->tx_lock);
+				ret = dev->ctrl.get_laddr(&dev->ctrl, ea, 6,
+						&dev->pgdla);
+				pr_debug("SLIM PGD LA:0x%x, ret:%d", dev->pgdla,
+						ret);
+				if (ret) {
+					pr_err("Incorrect SLIM-PGD EAPC:0x%x",
+							dev->pdata.eapc);
+					return ret;
+				}
+				mutex_lock(&dev->tx_lock);
+			}
 			txn->la = dev->pgdla;
+		}
 		wbuf[i++] = txn->la;
 		la = SLIM_LA_MGR;
 		wbuf[i++] = txn->wbuf[0];
@@ -380,6 +398,8 @@
 			dev_err(dev->dev, "pipe-port connect err:%d", dev->err);
 			goto ngd_xfer_err;
 		}
+		/* Add port-base to port number if this is manager side port */
+		puc[1] += dev->port_b;
 	}
 	dev->err = 0;
 	dev->wr_comp = &tx_sent;
@@ -1070,9 +1090,18 @@
 		}
 		rxreg_access = of_property_read_bool(pdev->dev.of_node,
 					"qcom,rxreg-access");
+		of_property_read_u32(pdev->dev.of_node, "qcom,apps-ch-pipes",
+					&dev->pdata.apps_pipes);
+		of_property_read_u32(pdev->dev.of_node, "qcom,ea-pc",
+					&dev->pdata.eapc);
 	} else {
 		dev->ctrl.nr = pdev->id;
 	}
+	/*
+	 * Keep PGD's logical address as manager's. Query it when first data
+	 * channel request comes in
+	 */
+	dev->pgdla = SLIM_LA_MGR;
 	dev->ctrl.nchans = MSM_SLIM_NCHANS;
 	dev->ctrl.nports = MSM_SLIM_NPORTS;
 	dev->framer.rootfreq = SLIM_ROOT_FREQ >> 3;
diff --git a/drivers/slimbus/slim-msm.c b/drivers/slimbus/slim-msm.c
index a63ee76..37bc883 100644
--- a/drivers/slimbus/slim-msm.c
+++ b/drivers/slimbus/slim-msm.c
@@ -788,6 +788,10 @@
 	bam_props.options = SPS_O_DESC_DONE | SPS_O_ERROR |
 				SPS_O_ACK_TRANSFERS | SPS_O_AUTO_ENABLE;
 
+	/* override apps channel pipes if specified in platform-data or DT */
+	if (dev->pdata.apps_pipes)
+		sec_props.ees[dev->ee].pipe_mask = dev->pdata.apps_pipes;
+
 	/* First 7 bits are for message Qs */
 	for (i = 7; i < 32; i++) {
 		/* Check what pipes are owned by Apps. */
diff --git a/drivers/slimbus/slim-msm.h b/drivers/slimbus/slim-msm.h
index 896e196..b5c41ed 100644
--- a/drivers/slimbus/slim-msm.h
+++ b/drivers/slimbus/slim-msm.h
@@ -50,6 +50,13 @@
 #define MSM_SLIM_NPORTS			24
 #define MSM_SLIM_NCHANS			32
 
+#define QC_MFGID_LSB	0x2
+#define QC_MFGID_MSB	0x17
+#define QC_CHIPID_SL	0x10
+#define QC_DEVID_SAT1	0x3
+#define QC_DEVID_SAT2	0x4
+#define QC_DEVID_PGD	0x5
+
 #define SLIM_MSG_ASM_FIRST_WORD(l, mt, mc, dt, ad) \
 		((l) | ((mt) << 5) | ((mc) << 8) | ((dt) << 15) | ((ad) << 16))
 
@@ -198,6 +205,11 @@
 	struct work_struct		ssr_up;
 };
 
+struct msm_slim_pdata {
+	u32 apps_pipes;
+	u32 eapc;
+};
+
 struct msm_slim_ctrl {
 	struct slim_controller  ctrl;
 	struct slim_framer	framer;
@@ -240,6 +252,7 @@
 	u32			ver;
 	struct work_struct	slave_notify;
 	struct msm_slim_qmi	qmi;
+	struct msm_slim_pdata	pdata;
 };
 
 struct msm_sat_chan {
diff --git a/drivers/video/msm/mdss/mdss.h b/drivers/video/msm/mdss/mdss.h
index 1311dab..078960b 100644
--- a/drivers/video/msm/mdss/mdss.h
+++ b/drivers/video/msm/mdss/mdss.h
@@ -73,6 +73,7 @@
 	u32 irq_buzy;
 	u32 has_bwc;
 	u32 has_decimation;
+	u8 has_wfd_blk;
 
 	u32 mdp_irq_mask;
 	u32 mdp_hist_irq_mask;
@@ -121,6 +122,7 @@
 	struct early_suspend early_suspend;
 	void *debug_data;
 	int current_bus_idx;
+	bool mixer_switched;
 };
 extern struct mdss_data_type *mdss_res;
 
diff --git a/drivers/video/msm/mdss/mdss_mdp.c b/drivers/video/msm/mdss/mdss_mdp.c
index df81519..56a4ac4 100644
--- a/drivers/video/msm/mdss/mdss_mdp.c
+++ b/drivers/video/msm/mdss/mdss_mdp.c
@@ -1531,6 +1531,8 @@
 					       "qcom,mdss-has-bwc");
 	mdata->has_decimation = of_property_read_bool(pdev->dev.of_node,
 		"qcom,mdss-has-decimation");
+	mdata->has_wfd_blk = of_property_read_bool(pdev->dev.of_node,
+		"qcom,mdss-has-wfd-blk");
 	return 0;
 }
 
diff --git a/drivers/video/msm/mdss/mdss_mdp.h b/drivers/video/msm/mdss/mdss_mdp.h
index 240ba52..8ecc861 100644
--- a/drivers/video/msm/mdss/mdss_mdp.h
+++ b/drivers/video/msm/mdss/mdss_mdp.h
@@ -118,6 +118,11 @@
 	struct list_head list;
 };
 
+enum mdss_mdp_wb_ctl_type {
+	MDSS_MDP_WB_CTL_TYPE_BLOCK = 1,
+	MDSS_MDP_WB_CTL_TYPE_LINE
+};
+
 struct mdss_mdp_ctl {
 	u32 num;
 	char __iomem *base;
@@ -151,6 +156,7 @@
 	struct mdss_mdp_mixer *mixer_left;
 	struct mdss_mdp_mixer *mixer_right;
 	struct mutex lock;
+	struct mutex *shared_lock;
 
 	struct mdss_panel_data *panel_data;
 	struct mdss_mdp_vsync_handler vsync_handler;
@@ -168,6 +174,7 @@
 					struct mdss_mdp_vsync_handler *);
 
 	void *priv_data;
+	u32 wb_type;
 };
 
 struct mdss_mdp_mixer {
@@ -560,8 +567,13 @@
 int mdss_panel_register_done(struct mdss_panel_data *pdata);
 int mdss_mdp_limited_lut_igc_config(struct mdss_mdp_ctl *ctl);
 int mdss_mdp_calib_config(struct mdp_calib_config_data *cfg, u32 *copyback);
+int mdss_mdp_calib_config_buffer(struct mdp_calib_config_buffer *cfg,
+						u32 *copyback);
 
 int mdss_mdp_pipe_is_staged(struct mdss_mdp_pipe *pipe);
+int mdss_mdp_writeback_display_commit(struct mdss_mdp_ctl *ctl, void *arg);
+struct mdss_mdp_ctl *mdss_mdp_ctl_mixer_switch(struct mdss_mdp_ctl *ctl,
+					       u32 return_type);
 
 #define mfd_to_mdp5_data(mfd) (mfd->mdp.private1)
 #define mfd_to_mdata(mfd) (((struct mdss_overlay_private *)\
diff --git a/drivers/video/msm/mdss/mdss_mdp_ctl.c b/drivers/video/msm/mdss/mdss_mdp_ctl.c
index fe76b4b..e656131 100644
--- a/drivers/video/msm/mdss/mdss_mdp_ctl.c
+++ b/drivers/video/msm/mdss/mdss_mdp_ctl.c
@@ -299,9 +299,13 @@
 {
 	struct mdss_mdp_ctl *ctl = NULL;
 	u32 cnum;
+	u32 nctl = mdata->nctl;
 
 	mutex_lock(&mdss_mdp_ctl_lock);
-	for (cnum = off; cnum < mdata->nctl; cnum++) {
+	if (!mdata->has_wfd_blk)
+		nctl++;
+
+	for (cnum = off; cnum < nctl; cnum++) {
 		ctl = mdata->ctl_off + cnum;
 		if (ctl->ref_cnt == 0) {
 			ctl->ref_cnt++;
@@ -399,13 +403,18 @@
 			(mixer_pool[MDSS_MDP_INTF_LAYERMIXER2].ref_cnt == 0))
 		mixer_pool += MDSS_MDP_INTF_LAYERMIXER2;
 
+	/*Allocate virtual wb mixer if no dedicated wfd wb blk is present*/
+	if (!ctl->mdata->has_wfd_blk && (type == MDSS_MDP_MIXER_TYPE_WRITEBACK))
+		nmixers += 1;
+
 	for (i = 0; i < nmixers; i++) {
 		mixer = mixer_pool + i;
 		if (mixer->ref_cnt == 0) {
 			mixer->ref_cnt++;
 			mixer->params_changed++;
 			mixer->ctl = ctl;
-			pr_debug("alloc mixer num%d\n", mixer->num);
+			pr_debug("alloc mixer num %d for ctl=%d\n",
+				 mixer->num, ctl->num);
 			break;
 		}
 		mixer = NULL;
@@ -440,12 +449,16 @@
 	struct mdss_mdp_mixer *mixer = NULL;
 
 	ctl = mdss_mdp_ctl_alloc(mdss_res, mdss_res->nmixers_intf);
-	if (!ctl)
+	if (!ctl) {
+		pr_err("unable to allocate wb ctl\n");
 		return NULL;
+	}
 
 	mixer = mdss_mdp_mixer_alloc(ctl, MDSS_MDP_MIXER_TYPE_WRITEBACK, false);
-	if (!mixer)
+	if (!mixer) {
+		pr_err("unable to allocate wb mixer\n");
 		goto error;
+	}
 
 	mixer->rotator_mode = rotator;
 
@@ -467,6 +480,9 @@
 
 	ctl->start_fnc = mdss_mdp_writeback_start;
 	ctl->power_on = true;
+	ctl->wb_type = (rotator ? MDSS_MDP_WB_CTL_TYPE_BLOCK :
+			MDSS_MDP_WB_CTL_TYPE_LINE);
+	mixer->ctl = ctl;
 
 	if (ctl->start_fnc)
 		ctl->start_fnc(ctl);
@@ -705,6 +721,7 @@
 			mdss_mdp_mixer_free(mixer);
 			return -EINVAL;
 		}
+		ctl->wb_type = MDSS_MDP_WB_CTL_TYPE_LINE;
 	}
 	ctl->mixer_left = mixer;
 
@@ -1212,9 +1229,13 @@
 	struct mdss_mdp_mixer *head;
 	u32 i;
 	int rc = 0;
+	u32 size = len;
+
+	if ((type == MDSS_MDP_MIXER_TYPE_WRITEBACK) && !mdata->has_wfd_blk)
+		size++;
 
 	head = devm_kzalloc(&mdata->pdev->dev, sizeof(struct mdss_mdp_mixer) *
-			len, GFP_KERNEL);
+			size, GFP_KERNEL);
 
 	if (!head) {
 		pr_err("unable to setup mixer type=%d :kzalloc fail\n",
@@ -1234,6 +1255,13 @@
 		}
 	}
 
+	/*
+	 * Duplicate the last writeback mixer for concurrent line and block mode
+	 * operations
+	*/
+	if ((type == MDSS_MDP_MIXER_TYPE_WRITEBACK) && !mdata->has_wfd_blk)
+		head[len] = head[len - 1];
+
 	switch (type) {
 
 	case MDSS_MDP_MIXER_TYPE_INTF:
@@ -1257,10 +1285,24 @@
 	u32 *ctl_offsets, u32 *wb_offsets, u32 len)
 {
 	struct mdss_mdp_ctl *head;
+	struct mutex *shared_lock = NULL;
 	u32 i;
+	u32 size = len;
+
+	if (!mdata->has_wfd_blk) {
+		size++;
+		shared_lock = devm_kzalloc(&mdata->pdev->dev,
+					   sizeof(struct mutex),
+					   GFP_KERNEL);
+		if (!shared_lock) {
+			pr_err("unable to allocate mem for mutex\n");
+			return -ENOMEM;
+		}
+		mutex_init(shared_lock);
+	}
 
 	head = devm_kzalloc(&mdata->pdev->dev, sizeof(struct mdss_mdp_ctl) *
-			len, GFP_KERNEL);
+			size, GFP_KERNEL);
 
 	if (!head) {
 		pr_err("unable to setup ctl and wb: kzalloc fail\n");
@@ -1274,6 +1316,16 @@
 		head[i].ref_cnt = 0;
 	}
 
+	if (!mdata->has_wfd_blk) {
+		head[len - 1].shared_lock = shared_lock;
+		/*
+		 * Allocate a virtual ctl to be able to perform simultaneous
+		 * line mode and block mode operations on the same
+		 * writeback block
+		*/
+		head[len] = head[len - 1];
+		head[len].num = -1;
+	}
 	mdata->ctl_off = head;
 
 	return 0;
@@ -1400,11 +1452,19 @@
 
 static int mdss_mdp_mixer_update(struct mdss_mdp_mixer *mixer)
 {
+	u32 off = 0;
+	if (!mixer)
+		return -EINVAL;
+
 	mixer->params_changed = 0;
 
 	/* skip mixer setup for rotator */
-	if (!mixer->rotator_mode)
+	if (!mixer->rotator_mode) {
 		mdss_mdp_mixer_setup(mixer->ctl, mixer);
+	} else {
+		off = __mdss_mdp_ctl_get_mixer_off(mixer);
+		mdss_mdp_ctl_write(mixer->ctl, off, 0);
+	}
 
 	return 0;
 }
@@ -1533,12 +1593,9 @@
 		return -ENODEV;
 	}
 
+	mutex_lock(&ctl->lock);
 	pr_debug("commit ctl=%d play_cnt=%d\n", ctl->num, ctl->play_cnt);
 
-	ret = mutex_lock_interruptible(&ctl->lock);
-	if (ret)
-		return ret;
-
 	if (!ctl->power_on) {
 		mutex_unlock(&ctl->lock);
 		return 0;
@@ -1633,6 +1690,36 @@
 	return mixer_cnt;
 }
 
+/**
+ * @mdss_mdp_ctl_mixer_switch() - return ctl mixer of @return_type
+ * @ctl: Pointer to ctl structure to be switched.
+ * @return_type: wb_type of the ctl to be switched to.
+ *
+ * Virtual mixer switch should be performed only when there is no
+ * dedicated wfd block and writeback block is shared.
+ */
+struct mdss_mdp_ctl *mdss_mdp_ctl_mixer_switch(struct mdss_mdp_ctl *ctl,
+					       u32 return_type)
+{
+	int i;
+	struct mdss_data_type *mdata = ctl->mdata;
+
+	if (ctl->wb_type == return_type) {
+		mdata->mixer_switched = false;
+		return ctl;
+	}
+	for (i = 0; i <= mdata->nctl; i++) {
+		if (mdata->ctl_off[i].wb_type == return_type) {
+			pr_debug("switching mixer from ctl=%d to ctl=%d\n",
+				 ctl->num, mdata->ctl_off[i].num);
+			mdata->mixer_switched = true;
+			return mdata->ctl_off + i;
+		}
+	}
+	pr_err("unable to switch mixer to type=%d\n", return_type);
+	return NULL;
+}
+
 static inline int __mdss_mdp_ctl_get_mixer_off(struct mdss_mdp_mixer *mixer)
 {
 	if (mixer->type == MDSS_MDP_MIXER_TYPE_INTF)
diff --git a/drivers/video/msm/mdss/mdss_mdp_intf_writeback.c b/drivers/video/msm/mdss/mdss_mdp_intf_writeback.c
index b7fe1bd..0a37573 100644
--- a/drivers/video/msm/mdss/mdss_mdp_intf_writeback.c
+++ b/drivers/video/msm/mdss/mdss_mdp_intf_writeback.c
@@ -219,7 +219,7 @@
 	if (!ctx)
 		return -ENODEV;
 
-	if (ctx->initialized) /* already set */
+	if (ctx->initialized && !ctl->shared_lock) /* already set */
 		return 0;
 
 	pr_debug("wfd setup ctl=%d\n", ctl->num);
@@ -347,6 +347,9 @@
 
 	rc = wait_for_completion_interruptible_timeout(&ctx->wb_comp,
 			KOFF_TIMEOUT);
+	mdss_mdp_set_intr_callback(ctx->intr_type, ctx->intf_num,
+		NULL, NULL);
+
 	if (rc <= 0) {
 		rc = -ENODEV;
 		WARN(1, "writeback kickoff timed out (%d) ctl=%d\n",
@@ -389,6 +392,9 @@
 		return ret;
 	}
 
+	mdss_mdp_set_intr_callback(ctx->intr_type, ctx->intf_num,
+		   mdss_mdp_writeback_intr_done, ctx);
+
 	ctx->callback_fnc = wb_args->callback_fnc;
 	ctx->callback_arg = wb_args->priv_data;
 
@@ -434,9 +440,6 @@
 	ctx->initialized = false;
 	init_completion(&ctx->wb_comp);
 
-	mdss_mdp_set_intr_callback(ctx->intr_type, ctx->intf_num,
-				   mdss_mdp_writeback_intr_done, ctx);
-
 	if (ctx->type == MDSS_MDP_WRITEBACK_TYPE_ROTATOR)
 		ctl->prepare_fnc = mdss_mdp_writeback_prepare_rot;
 	else /* wfd or line mode */
@@ -447,3 +450,21 @@
 
 	return ret;
 }
+
+int mdss_mdp_writeback_display_commit(struct mdss_mdp_ctl *ctl, void *arg)
+{
+	if (ctl->shared_lock && !mutex_is_locked(ctl->shared_lock)) {
+		pr_err("shared mutex is not locked before commit on ctl=%d\n",
+			ctl->num);
+		return -EINVAL;
+	}
+
+	if (ctl->mdata->mixer_switched) {
+		if (ctl->mixer_left)
+			ctl->mixer_left->params_changed++;
+		if (ctl->mixer_right)
+			ctl->mixer_right->params_changed++;
+	}
+
+	return mdss_mdp_display_commit(ctl, arg);
+}
diff --git a/drivers/video/msm/mdss/mdss_mdp_overlay.c b/drivers/video/msm/mdss/mdss_mdp_overlay.c
index 780ff94..24b27b4 100644
--- a/drivers/video/msm/mdss/mdss_mdp_overlay.c
+++ b/drivers/video/msm/mdss/mdss_mdp_overlay.c
@@ -494,6 +494,7 @@
 	pipe->overfetch_disable = fmt->is_yuv &&
 			!(pipe->flags & MDP_SOURCE_ROTATED_90);
 
+	req->id = pipe->ndx;
 	pipe->req_data = *req;
 
 	if (pipe->flags & MDP_OVERLAY_PP_CFG_EN) {
@@ -568,6 +569,10 @@
 	if (ret)
 		goto exit_fail;
 
+	if ((mixer->type == MDSS_MDP_MIXER_TYPE_WRITEBACK) &&
+		!mdp5_data->mdata->has_wfd_blk)
+		mdss_mdp_smp_release(pipe);
+
 	ret = mdss_mdp_smp_reserve(pipe);
 	if (ret) {
 		pr_debug("mdss_mdp_smp_reserve failed. ret=%d\n", ret);
@@ -576,7 +581,6 @@
 
 	pipe->params_changed++;
 
-	req->id = pipe->ndx;
 	req->vert_deci = pipe->vert_deci;
 
 	*ppipe = pipe;
@@ -766,8 +770,12 @@
 	struct mdss_overlay_private *mdp5_data = mfd_to_mdp5_data(mfd);
 	struct mdss_mdp_pipe *pipe, *next;
 	struct mdss_mdp_ctl *ctl = mfd_to_ctl(mfd);
+	struct mdss_mdp_ctl *tmp;
 	int ret;
 
+	if (ctl->shared_lock)
+		mutex_lock(ctl->shared_lock);
+
 	mutex_lock(&mdp5_data->ov_lock);
 	mutex_lock(&mfd->lock);
 
@@ -775,12 +783,44 @@
 	if (ret) {
 		mutex_unlock(&mfd->lock);
 		mutex_unlock(&mdp5_data->ov_lock);
+		if (ctl->shared_lock)
+			mutex_unlock(ctl->shared_lock);
 		return ret;
 	}
 
 	list_for_each_entry_safe(pipe, next, &mdp5_data->pipes_used,
 			used_list) {
 		struct mdss_mdp_data *buf;
+		/*
+		 * When external is connected and no dedicated wfd is present,
+		 * reprogram DMA pipe before kickoff to clear out any previous
+		 * block mode configuration.
+		 */
+		if ((pipe->type == MDSS_MDP_PIPE_TYPE_DMA) &&
+		    (ctl->shared_lock && !ctl->mdata->has_wfd_blk)) {
+			if (ctl->mdata->mixer_switched) {
+				ret = mdss_mdp_overlay_pipe_setup(mfd,
+						&pipe->req_data, &pipe);
+				pr_debug("reseting DMA pipe for ctl=%d",
+					 ctl->num);
+			}
+			if (ret) {
+				pr_err("can't reset DMA pipe ret=%d ctl=%d\n",
+					ret, ctl->num);
+				mutex_unlock(&mfd->lock);
+				goto commit_fail;
+			}
+
+			tmp = mdss_mdp_ctl_mixer_switch(ctl,
+					MDSS_MDP_WB_CTL_TYPE_LINE);
+			if (!tmp) {
+				mutex_unlock(&mfd->lock);
+				ret = -EINVAL;
+				goto commit_fail;
+			}
+			pipe->mixer = mdss_mdp_mixer_get(tmp,
+					MDSS_MDP_MIXER_MUX_DEFAULT);
+		}
 		if (pipe->back_buf.num_planes) {
 			buf = &pipe->back_buf;
 		} else if (ctl->play_cnt == 0) {
@@ -831,6 +871,8 @@
 	mdss_mdp_overlay_cleanup(mfd);
 
 	mutex_unlock(&mdp5_data->ov_lock);
+	if (ctl->shared_lock)
+		mutex_unlock(ctl->shared_lock);
 
 	return ret;
 }
@@ -1199,7 +1241,7 @@
 
 static void mdss_mdp_overlay_pan_display(struct msm_fb_data_type *mfd)
 {
-	struct mdss_mdp_data data;
+	struct mdss_mdp_data *buf;
 	struct mdss_mdp_pipe *pipe;
 	struct fb_info *fbi;
 	struct mdss_overlay_private *mdp5_data;
@@ -1229,8 +1271,6 @@
 		return;
 	}
 
-	memset(&data, 0, sizeof(data));
-
 	bpp = fbi->var.bits_per_pixel / 8;
 	offset = fbi->var.xoffset * bpp +
 		 fbi->var.yoffset * fbi->fix.line_length;
@@ -1247,18 +1287,6 @@
 		goto pan_display_error;
 	}
 
-	if (is_mdss_iommu_attached()) {
-		if (!mfd->iova) {
-			pr_err("mfd iova is zero\n");
-			goto pan_display_error;
-		}
-		data.p[0].addr = mfd->iova;
-	} else
-		data.p[0].addr = fbi->fix.smem_start;
-
-	data.p[0].addr += offset;
-	data.p[0].len = fbi->fix.smem_len - offset;
-	data.num_planes = 1;
 
 	ret = mdss_mdp_overlay_get_fb_pipe(mfd, &pipe, MDSS_MDP_MIXER_MUX_LEFT);
 	if (ret) {
@@ -1270,13 +1298,23 @@
 		pr_err("unable to map base pipe\n");
 		goto pan_display_error;
 	}
-	ret = mdss_mdp_pipe_queue_data(pipe, &data);
-	mdss_mdp_pipe_unmap(pipe);
-	if (ret) {
-		pr_err("unable to queue data\n");
-		goto pan_display_error;
+
+	buf = &pipe->back_buf;
+	if (is_mdss_iommu_attached()) {
+		if (!mfd->iova) {
+			pr_err("mfd iova is zero\n");
+			goto pan_display_error;
+		}
+		buf->p[0].addr = mfd->iova;
+	} else {
+		buf->p[0].addr = fbi->fix.smem_start;
 	}
 
+	buf->p[0].addr += offset;
+	buf->p[0].len = fbi->fix.smem_len - offset;
+	buf->num_planes = 1;
+	mdss_mdp_pipe_unmap(pipe);
+
 	if (fbi->var.xres > MAX_MIXER_WIDTH || mfd->split_display) {
 		ret = mdss_mdp_overlay_get_fb_pipe(mfd, &pipe,
 						   MDSS_MDP_MIXER_MUX_RIGHT);
@@ -1288,12 +1326,8 @@
 			pr_err("unable to map right base pipe\n");
 			goto pan_display_error;
 		}
-		ret = mdss_mdp_pipe_queue_data(pipe, &data);
+		pipe->back_buf = *buf;
 		mdss_mdp_pipe_unmap(pipe);
-		if (ret) {
-			pr_err("unable to queue right data\n");
-			goto pan_display_error;
-		}
 	}
 	mutex_unlock(&mdp5_data->ov_lock);
 
@@ -1642,6 +1676,11 @@
 	case mdp_op_calib_mode:
 		ret = mdss_mdp_calib_mode(mfd, &mdp_pp.data.mdss_calib_cfg);
 		break;
+	case mdp_op_calib_buffer:
+		ret = mdss_mdp_calib_config_buffer(
+				(struct mdp_calib_config_buffer *)
+				 &mdp_pp.data.calib_buffer, &copyback);
+		break;
 	default:
 		pr_err("Unsupported request to MDP_PP IOCTL. %d = op\n",
 								mdp_pp.op);
diff --git a/drivers/video/msm/mdss/mdss_mdp_pipe.c b/drivers/video/msm/mdss/mdss_mdp_pipe.c
index c8f0f27..137da66 100644
--- a/drivers/video/msm/mdss/mdss_mdp_pipe.c
+++ b/drivers/video/msm/mdss/mdss_mdp_pipe.c
@@ -269,12 +269,13 @@
 }
 
 static struct mdss_mdp_pipe *mdss_mdp_pipe_init(struct mdss_mdp_mixer *mixer,
-						u32 type)
+						u32 type, u32 off)
 {
 	struct mdss_mdp_pipe *pipe;
 	struct mdss_data_type *mdata;
 	struct mdss_mdp_pipe *pipe_pool = NULL;
 	u32 npipes;
+	bool pipe_share = false;
 	u32 i;
 
 	if (!mixer || !mixer->ctl || !mixer->ctl->mdata)
@@ -296,6 +297,9 @@
 	case MDSS_MDP_PIPE_TYPE_DMA:
 		pipe_pool = mdata->dma_pipes;
 		npipes = mdata->ndma_pipes;
+		if (!mdata->has_wfd_blk &&
+		   (mixer->type == MDSS_MDP_MIXER_TYPE_WRITEBACK))
+			pipe_share = true;
 		break;
 
 	default:
@@ -304,7 +308,7 @@
 		break;
 	}
 
-	for (i = 0; i < npipes; i++) {
+	for (i = off; i < npipes; i++) {
 		pipe = pipe_pool + i;
 		if (atomic_cmpxchg(&pipe->ref_cnt, 0, 1) == 0) {
 			pipe->mixer = mixer;
@@ -317,6 +321,14 @@
 		pr_debug("type=%x   pnum=%d\n", pipe->type, pipe->num);
 		mutex_init(&pipe->pp_res.hist.hist_mutex);
 		spin_lock_init(&pipe->pp_res.hist.hist_lock);
+	} else if (pipe_share) {
+		/*
+		 * when there is no dedicated wfd blk, DMA pipe can be
+		 * shared as long as its attached to a writeback mixer
+		 */
+		pipe = mdata->dma_pipes + mixer->num;
+		mdss_mdp_pipe_map(pipe);
+		pr_debug("pipe sharing for pipe=%d\n", pipe->num);
 	} else {
 		pr_err("no %d type pipes available\n", type);
 	}
@@ -328,20 +340,20 @@
 {
 	struct mdss_mdp_pipe *pipe = NULL;
 	struct mdss_data_type *mdata;
-	u32 pnum;
 
 	mutex_lock(&mdss_mdp_sspp_lock);
 	mdata = mixer->ctl->mdata;
-	pnum = mixer->num;
-
-	if (atomic_cmpxchg(&((mdata->dma_pipes[pnum]).ref_cnt), 0, 1) == 0) {
-		pipe = &mdata->dma_pipes[pnum];
-		pipe->mixer = mixer;
-
+	pipe = mdss_mdp_pipe_init(mixer, MDSS_MDP_PIPE_TYPE_DMA, mixer->num);
+	if (!pipe) {
+		pr_err("DMA pipes not available for mixer=%d\n", mixer->num);
+	} else if (pipe != &mdata->dma_pipes[mixer->num]) {
+		pr_err("Requested DMA pnum=%d not available\n",
+			mdata->dma_pipes[mixer->num].num);
+		mdss_mdp_pipe_unmap(pipe);
+		pipe = NULL;
 	} else {
-		pr_err("DMA pnum%d\t not available\n", pnum);
+		pipe->mixer = mixer;
 	}
-
 	mutex_unlock(&mdss_mdp_sspp_lock);
 	return pipe;
 }
@@ -351,7 +363,7 @@
 {
 	struct mdss_mdp_pipe *pipe;
 	mutex_lock(&mdss_mdp_sspp_lock);
-	pipe = mdss_mdp_pipe_init(mixer, type);
+	pipe = mdss_mdp_pipe_init(mixer, type, 0);
 	mutex_unlock(&mdss_mdp_sspp_lock);
 	return pipe;
 }
@@ -633,13 +645,14 @@
 {
 	int ret = 0;
 	u32 params_changed, opmode;
+	struct mdss_mdp_ctl *ctl;
 
 	if (!pipe) {
 		pr_err("pipe not setup properly for queue\n");
 		return -ENODEV;
 	}
 
-	if (!pipe->mixer) {
+	if (!pipe->mixer || !pipe->mixer->ctl) {
 		pr_err("pipe mixer not setup properly for queue\n");
 		return -ENODEV;
 	}
@@ -648,8 +661,16 @@
 		 pipe->mixer->num, pipe->play_cnt);
 
 	mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_ON, false);
-
-	params_changed = pipe->params_changed;
+	ctl = pipe->mixer->ctl;
+	/*
+	 * Reprogram the pipe when there is no dedicated wfd blk and
+	 * virtual mixer is allocated for the DMA pipe during concurrent
+	 * line and block mode operations
+	 */
+	params_changed = (pipe->params_changed) ||
+			 ((pipe->type == MDSS_MDP_PIPE_TYPE_DMA) &&
+			 (pipe->mixer->type == MDSS_MDP_MIXER_TYPE_WRITEBACK)
+			 && (ctl->mdata->mixer_switched));
 	if (src_data == NULL) {
 		mdss_mdp_pipe_solidfill_setup(pipe);
 		goto update_nobuf;
diff --git a/drivers/video/msm/mdss/mdss_mdp_pp.c b/drivers/video/msm/mdss/mdss_mdp_pp.c
index 4dd9dcb..6cedd98 100644
--- a/drivers/video/msm/mdss/mdss_mdp_pp.c
+++ b/drivers/video/msm/mdss/mdss_mdp_pp.c
@@ -3376,3 +3376,69 @@
 	mutex_unlock(&mdss_pp_mutex);
 	return 0;
 }
+
+int mdss_mdp_calib_config_buffer(struct mdp_calib_config_buffer *cfg,
+						u32 *copyback)
+{
+	int ret = -1;
+	int counter = cfg->size / (sizeof(uint32_t) * 2);
+	uint32_t *buff = NULL, *buff_org = NULL;
+	void *ptr;
+	int i = 0;
+
+	buff_org = buff = kzalloc(cfg->size, GFP_KERNEL);
+	if (buff == NULL) {
+		pr_err("Allocation failed");
+		return ret;
+	}
+
+	if (copy_from_user(buff, cfg->buffer, cfg->size)) {
+		kfree(buff);
+		pr_err("Copy failed");
+		return ret;
+	}
+
+	mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_ON, false);
+
+	if (cfg->ops & MDP_PP_OPS_READ) {
+		for (i = 0 ; i < counter ; i++) {
+			if (is_valid_calib_addr((void *) *buff)) {
+				ret = 0;
+			} else {
+				ret = -1;
+				pr_err("Address validation failed");
+				break;
+			}
+
+			ptr = (void *)(((unsigned int) *buff) +
+					 (mdss_res->mdp_base));
+			buff++;
+			*buff = readl_relaxed(ptr);
+			buff++;
+		}
+		if (!ret)
+			ret = copy_to_user(cfg->buffer, buff_org, cfg->size);
+		*copyback = 1;
+	} else if (cfg->ops & MDP_PP_OPS_WRITE) {
+		for (i = 0 ; i < counter ; i++) {
+			if (is_valid_calib_addr((void *) *buff)) {
+				ret = 0;
+			} else {
+				ret = -1;
+				pr_err("Address validation failed");
+				break;
+			}
+
+			ptr = (void *)(((unsigned int) *buff) +
+					 (mdss_res->mdp_base));
+			buff++;
+			writel_relaxed(*buff, ptr);
+			buff++;
+		}
+	}
+
+	mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_OFF, false);
+
+	kfree(buff_org);
+	return ret;
+}
diff --git a/drivers/video/msm/mdss/mdss_mdp_rotator.c b/drivers/video/msm/mdss/mdss_mdp_rotator.c
index 8c45df8..fcd90e1 100644
--- a/drivers/video/msm/mdss/mdss_mdp_rotator.c
+++ b/drivers/video/msm/mdss/mdss_mdp_rotator.c
@@ -73,13 +73,16 @@
 	struct mdss_mdp_pipe *pipe = NULL;
 
 	mixer = mdss_mdp_wb_mixer_alloc(1);
-	if (!mixer)
+	if (!mixer) {
+		pr_err("wb mixer alloc failed\n");
 		return NULL;
+	}
 
 	pipe = mdss_mdp_pipe_alloc_dma(mixer);
-
-	if (!pipe)
+	if (!pipe) {
 		mdss_mdp_wb_mixer_destroy(mixer);
+		pr_err("dma pipe allocation failed\n");
+	}
 
 	return pipe;
 }
@@ -96,12 +99,12 @@
 	ctl = rot_pipe->mixer->ctl;
 	mutex_lock(&rot->lock);
 	if (rot->busy) {
-		pr_debug("waiting for rot=%d to complete\n", rot->pipe->num);
 		mdss_mdp_display_wait4comp(ctl);
 		rot->busy = false;
-		mdss_mdp_smp_release(rot->pipe);
-
+		if (ctl->shared_lock)
+			mutex_unlock(ctl->shared_lock);
 	}
+	mdss_mdp_smp_release(rot->pipe);
 	mutex_unlock(&rot->lock);
 
 	return 0;
@@ -120,7 +123,7 @@
 
 	mutex_lock(&rot->lock);
 	rot->busy = true;
-	ret = mdss_mdp_display_commit(ctl, &wb_args);
+	ret = mdss_mdp_writeback_display_commit(ctl, &wb_args);
 	if (ret) {
 		rot->busy = false;
 		pr_err("problem with kickoff rot pipe=%d", rot->pipe->num);
@@ -188,8 +191,19 @@
 	pr_debug("queue rotator pnum=%d\n", rot_pipe->num);
 
 	ctl = rot_pipe->mixer->ctl;
+	if (ctl->shared_lock)
+		mutex_lock(ctl->shared_lock);
 
-	if (rot->params_changed) {
+	ctl = mdss_mdp_ctl_mixer_switch(ctl,
+			MDSS_MDP_WB_CTL_TYPE_BLOCK);
+	if (!ctl) {
+		ret = -EINVAL;
+		goto error;
+	} else {
+		rot->pipe->mixer = ctl->mixer_left;
+	}
+
+	if (rot->params_changed || ctl->mdata->mixer_switched) {
 		rot->params_changed = 0;
 		rot_pipe->flags = rot->flags;
 		rot_pipe->src_fmt = mdss_mdp_get_format_params(rot->format);
@@ -205,19 +219,23 @@
 	ret = mdss_mdp_smp_reserve(rot->pipe);
 	if (ret) {
 		pr_err("unable to mdss_mdp_smp_reserve rot data\n");
-		return ret;
+		goto error;
 	}
 
 	ret = mdss_mdp_pipe_queue_data(rot->pipe, src_data);
 	if (ret) {
 		pr_err("unable to queue rot data\n");
 		mdss_mdp_smp_unreserve(rot->pipe);
-		return ret;
+		goto error;
 	}
 
 	ret = mdss_mdp_rotator_kickoff(ctl, rot, dst_data);
 
 	return ret;
+error:
+	if (ctl->shared_lock)
+		mutex_unlock(ctl->shared_lock);
+	return ret;
 }
 
 int mdss_mdp_rotator_queue(struct mdss_mdp_rotator_session *rot,
@@ -342,6 +360,8 @@
 static int mdss_mdp_rotator_finish(struct mdss_mdp_rotator_session *rot)
 {
 	struct mdss_mdp_pipe *rot_pipe;
+	struct mdss_mdp_ctl *tmp;
+	int ret = 0;
 
 	if (!rot)
 		return -ENODEV;
@@ -359,11 +379,16 @@
 	memset(rot, 0, sizeof(*rot));
 	if (rot_pipe) {
 		struct mdss_mdp_mixer *mixer = rot_pipe->mixer;
-		mdss_mdp_pipe_destroy(rot_pipe);
+		mdss_mdp_pipe_unmap(rot_pipe);
+		tmp = mdss_mdp_ctl_mixer_switch(mixer->ctl,
+				MDSS_MDP_WB_CTL_TYPE_BLOCK);
+		if (!tmp)
+			return -EINVAL;
+		else
+			mixer = tmp->mixer_left;
 		mdss_mdp_wb_mixer_destroy(mixer);
 	}
-
-	return 0;
+	return ret;
 }
 
 int mdss_mdp_rotator_release(struct mdss_mdp_rotator_session *rot)
diff --git a/drivers/video/msm/mdss/mdss_mdp_wb.c b/drivers/video/msm/mdss/mdss_mdp_wb.c
index a9deef2..ff54067 100644
--- a/drivers/video/msm/mdss/mdss_mdp_wb.c
+++ b/drivers/video/msm/mdss/mdss_mdp_wb.c
@@ -527,7 +527,7 @@
 		goto kickoff_fail;
 	}
 
-	ret = mdss_mdp_display_commit(ctl, &wb_args);
+	ret = mdss_mdp_writeback_display_commit(ctl, &wb_args);
 	if (ret) {
 		pr_err("error on commit ctl=%d\n", ctl->num);
 		goto kickoff_fail;
diff --git a/include/linux/blk_types.h b/include/linux/blk_types.h
index 2b4542a..130d0fd 100644
--- a/include/linux/blk_types.h
+++ b/include/linux/blk_types.h
@@ -152,6 +152,7 @@
 	__REQ_MIXED_MERGE,	/* merge of different types, fail separately */
 	__REQ_SANITIZE,		/* sanitize */
 	__REQ_URGENT,		/* urgent request */
+	__REQ_PM,		/* runtime pm request */
 	__REQ_NR_BITS,		/* stops here */
 };
 
@@ -196,5 +197,6 @@
 #define REQ_IO_STAT		(1 << __REQ_IO_STAT)
 #define REQ_MIXED_MERGE		(1 << __REQ_MIXED_MERGE)
 #define REQ_SECURE		(1 << __REQ_SECURE)
+#define REQ_PM                 (1 << __REQ_PM)
 
 #endif /* __LINUX_BLK_TYPES_H */
diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h
index 6502841..651a0fc 100644
--- a/include/linux/blkdev.h
+++ b/include/linux/blkdev.h
@@ -340,6 +340,12 @@
 	 */
 	struct kobject kobj;
 
+#ifdef CONFIG_PM_RUNTIME
+	struct device		*dev;
+	int			rpm_status;
+	unsigned int		nr_pending;
+#endif
+
 	/*
 	 * queue settings
 	 */
@@ -883,6 +889,27 @@
 extern void blk_put_queue(struct request_queue *);
 
 /*
+ * block layer runtime pm functions
+ */
+#ifdef CONFIG_PM_RUNTIME
+extern void blk_pm_runtime_init(struct request_queue *q, struct device *dev);
+extern int blk_pre_runtime_suspend(struct request_queue *q);
+extern void blk_post_runtime_suspend(struct request_queue *q, int err);
+extern void blk_pre_runtime_resume(struct request_queue *q);
+extern void blk_post_runtime_resume(struct request_queue *q, int err);
+#else
+static inline void blk_pm_runtime_init(struct request_queue *q,
+	struct device *dev) {}
+static inline int blk_pre_runtime_suspend(struct request_queue *q)
+{
+	return -ENOSYS;
+}
+static inline void blk_post_runtime_suspend(struct request_queue *q, int err) {}
+static inline void blk_pre_runtime_resume(struct request_queue *q) {}
+static inline void blk_post_runtime_resume(struct request_queue *q, int err) {}
+#endif
+
+/*
  * blk_plug permits building a queue of related requests by holding the I/O
  * fragments for a short period. This allows merging of sequential requests
  * into single larger request. As the requests are moved from a per-task list to
diff --git a/include/linux/diagchar.h b/include/linux/diagchar.h
index c8125b9..0739ece 100644
--- a/include/linux/diagchar.h
+++ b/include/linux/diagchar.h
@@ -119,10 +119,10 @@
 /* This needs to be modified manually now, when we add
  a new RANGE of SSIDs to the msg_mask_tbl */
 #define MSG_MASK_TBL_CNT		24
-#define EVENT_LAST_ID			0x09BE
+#define EVENT_LAST_ID			0x09CB
 
 #define MSG_SSID_0			0
-#define MSG_SSID_0_LAST			96
+#define MSG_SSID_0_LAST			97
 #define MSG_SSID_1			500
 #define MSG_SSID_1_LAST			506
 #define MSG_SSID_2			1000
@@ -136,7 +136,7 @@
 #define MSG_SSID_6			4500
 #define MSG_SSID_6_LAST			4526
 #define MSG_SSID_7			4600
-#define MSG_SSID_7_LAST			4613
+#define MSG_SSID_7_LAST			4614
 #define MSG_SSID_8			5000
 #define MSG_SSID_8_LAST			5030
 #define MSG_SSID_9			5500
@@ -271,7 +271,7 @@
 	MSG_LVL_LOW,
 	MSG_LVL_LOW,
 	MSG_LVL_LOW,
-	MSG_LVL_HIGH,
+	MSG_LVL_HIGH | MSG_MASK_21,
 	MSG_LVL_HIGH,
 	MSG_LVL_LOW,
 	MSG_LVL_LOW,
@@ -291,6 +291,7 @@
 	MSG_LVL_LOW,
 	MSG_LVL_LOW,
 	MSG_LVL_LOW|MSG_LVL_MED|MSG_LVL_HIGH|MSG_LVL_ERROR|MSG_LVL_FATAL,
+	MSG_LVL_MED,
 };
 
 static const uint32_t msg_bld_masks_1[] = {
@@ -403,6 +404,7 @@
 	MSG_LVL_MED,
 	MSG_LVL_MED,
 	MSG_LVL_LOW,
+	MSG_LVL_LOW,
 	MSG_LVL_LOW
 };
 
@@ -726,7 +728,7 @@
 /* LOG CODES */
 
 #define LOG_0	0x0
-#define LOG_1	0x1807
+#define LOG_1	0x1808
 #define LOG_2	0x0
 #define LOG_3	0x0
 #define LOG_4	0x4910
diff --git a/include/linux/dvb/dmx.h b/include/linux/dvb/dmx.h
index 3ae83d6..dd675f3 100644
--- a/include/linux/dvb/dmx.h
+++ b/include/linux/dvb/dmx.h
@@ -531,6 +531,9 @@
 /* Indicates whether TS insertion is supported */
 #define DMX_CAP_TS_INSERTION	0x20
 
+/* Indicates whether playback from secured input is supported */
+#define DMX_CAP_SECURED_INPUT_PLAYBACK	0x40
+
 	/* Number of decoders demux can output data to */
 	int num_decoders;
 
@@ -570,6 +573,9 @@
 	/* Max bitrate from single memory input. Mbit/sec */
 	int memory_input_max_bitrate;
 
+	/* Max number of supported cipher operations per PID */
+	int num_cipher_ops;
+
 	/* Max possible value of STC reported by demux, in 27MHz */
 	__u64 max_stc;
 
@@ -660,6 +666,15 @@
 struct dmx_buffer {
 	unsigned int size;
 	int handle;
+
+	/*
+	 * The following indication is relevant only when setting
+	 * DVR input buffer. It indicates whether the input buffer
+	 * being set is secured one or not. Secured (locked) buffers
+	 * are required for playback from secured input. In such case
+	 * write() syscall is not allowed.
+	 */
+	int is_protected;
 };
 
 struct dmx_decoder_buffers {
@@ -684,16 +699,41 @@
 
 struct dmx_secure_mode {
 	/*
-	 * Specifies whether secure mode should be set or not for the filter's
-	 * pid. Note that DMX_OUT_TSDEMUX_TAP filters can have more than 1 pid
+	 * Specifies whether the filter is secure or not.
+	 * Filter should be set as secured if the filter's data *may* include
+	 * encrypted data that would require decryption configured through
+	 * DMX_SET_CIPHER ioctl. The setting may be done while
+	 * filter is in idle state only.
 	 */
 	int is_secured;
+};
 
-	/* PID to associate with key ladder id */
+struct dmx_cipher_operation {
+	/* Indication whether the operation is encryption or decryption */
+	int encrypt;
+
+	/* The ID of the key used for decryption or encryption */
+	__u32 key_ladder_id;
+};
+
+#define DMX_MAX_CIPHER_OPERATIONS_COUNT	5
+struct dmx_cipher_operations {
+	/*
+	 * The PID to perform the cipher operations on.
+	 * In case of recording filter, multiple PIDs may exist in the same
+	 * filter through DMX_ADD_PID ioctl, each may have different
+	 * cipher operations.
+	 */
 	__u16 pid;
 
-	/* key ladder information to associate with the specified pid */
-	__u32 key_ladder_id;
+	/* Total number of operations */
+	__u8 operations_count;
+
+	/*
+	 * Cipher operation to perform on the given PID.
+	 * The operations are performed in the order they are given.
+	 */
+	struct dmx_cipher_operation operations[DMX_MAX_CIPHER_OPERATIONS_COUNT];
 };
 
 struct dmx_events_mask {
@@ -825,5 +865,7 @@
 #define DMX_SET_TS_INSERTION _IOW('o', 70, struct dmx_set_ts_insertion)
 #define DMX_ABORT_TS_INSERTION _IOW('o', 71, struct dmx_abort_ts_insertion)
 #define DMX_GET_SCRAMBLING_BITS _IOWR('o', 72, struct dmx_scrambling_bits)
+#define DMX_SET_CIPHER _IOW('o', 73, struct dmx_cipher_operations)
+
 
 #endif /*_DVBDMX_H_*/
diff --git a/include/linux/msm_kgsl.h b/include/linux/msm_kgsl.h
index ae88807..f8b78a4 100644
--- a/include/linux/msm_kgsl.h
+++ b/include/linux/msm_kgsl.h
@@ -227,6 +227,7 @@
 #define KGSL_PERFCOUNTER_GROUP_VBIF_PWR 0xE
 
 #define KGSL_PERFCOUNTER_NOT_USED 0xFFFFFFFF
+#define KGSL_PERFCOUNTER_BROKEN 0xFFFFFFFE
 
 /* structure holds list of ibs */
 struct kgsl_ibdesc {
diff --git a/include/linux/msm_mdp.h b/include/linux/msm_mdp.h
index 18921a0..c3ff9de 100644
--- a/include/linux/msm_mdp.h
+++ b/include/linux/msm_mdp.h
@@ -606,6 +606,12 @@
 	uint32_t data;
 };
 
+struct mdp_calib_config_buffer {
+	uint32_t ops;
+	uint32_t size;
+	uint32_t *buffer;
+};
+
 #define MDSS_MAX_BL_BRIGHTNESS 255
 #define AD_BL_LIN_LEN (MDSS_MAX_BL_BRIGHTNESS + 1)
 
@@ -697,6 +703,7 @@
 	mdp_op_ad_cfg,
 	mdp_op_ad_input,
 	mdp_op_calib_mode,
+	mdp_op_calib_buffer,
 	mdp_op_max,
 };
 
@@ -724,6 +731,7 @@
 		struct mdss_ad_init_cfg ad_init_cfg;
 		struct mdss_calib_cfg mdss_calib_cfg;
 		struct mdss_ad_input ad_input;
+		struct mdp_calib_config_buffer calib_buffer;
 	} data;
 };
 
diff --git a/include/linux/test-iosched.h b/include/linux/test-iosched.h
index 89d3b30..5b05b7a 100644
--- a/include/linux/test-iosched.h
+++ b/include/linux/test-iosched.h
@@ -130,7 +130,7 @@
  * @check_test_result_fn: Test specific test result checking
  *			callback
  * @get_test_case_str_fn: Test specific function to get the test name
- * @test_duration:	A jiffies value saved for timing
+ * @test_duration:	A ktime value saved for timing
  *			calculations
  * @data:		Test specific private data
  * @test_byte_count:	Total number of bytes dispatched in
@@ -144,7 +144,7 @@
 	check_test_result_fn *check_test_result_fn;
 	post_test_fn *post_test_fn;
 	get_test_case_str_fn *get_test_case_str_fn;
-	unsigned long test_duration;
+	ktime_t test_duration;
 	get_rq_disk_fn *get_rq_disk_fn;
 	void *data;
 	unsigned long test_byte_count;
@@ -263,4 +263,6 @@
 void test_iosched_add_urgent_req(struct test_request *test_rq);
 
 int test_is_req_urgent(struct request *rq);
+
+void check_test_completion(void);
 #endif /* _LINUX_TEST_IOSCHED_H */
diff --git a/include/scsi/scsi_device.h b/include/scsi/scsi_device.h
index 6efb2e1..7c6a558 100644
--- a/include/scsi/scsi_device.h
+++ b/include/scsi/scsi_device.h
@@ -383,10 +383,18 @@
 			int data_direction, void *buffer, unsigned bufflen,
 			unsigned char *sense, int timeout, int retries,
 			int flag, int *resid);
-extern int scsi_execute_req(struct scsi_device *sdev, const unsigned char *cmd,
-			    int data_direction, void *buffer, unsigned bufflen,
-			    struct scsi_sense_hdr *, int timeout, int retries,
-			    int *resid);
+extern int scsi_execute_req_flags(struct scsi_device *sdev,
+	const unsigned char *cmd, int data_direction, void *buffer,
+	unsigned bufflen, struct scsi_sense_hdr *sshdr, int timeout,
+	int retries, int *resid, int flags);
+static inline int scsi_execute_req(struct scsi_device *sdev,
+	const unsigned char *cmd, int data_direction, void *buffer,
+	unsigned bufflen, struct scsi_sense_hdr *sshdr, int timeout,
+	int retries, int *resid)
+{
+	return scsi_execute_req_flags(sdev, cmd, data_direction, buffer,
+		bufflen, sshdr, timeout, retries, resid, 0);
+}
 
 #ifdef CONFIG_PM_RUNTIME
 extern int scsi_autopm_get_device(struct scsi_device *);
diff --git a/include/sound/apr_audio-v2.h b/include/sound/apr_audio-v2.h
index 7e98ef3..364de9a 100644
--- a/include/sound/apr_audio-v2.h
+++ b/include/sound/apr_audio-v2.h
@@ -632,43 +632,44 @@
 
 /* Port ID. Update afe_get_port_index
  *	when a new port is added here. */
-#define PRIMARY_I2S_RX 0		/* index = 0 */
-#define PRIMARY_I2S_TX 1		/* index = 1 */
-#define SECONDARY_I2S_RX 4		/* index = 4 */
-#define SECONDARY_I2S_TX 5		/* index = 5 */
-#define MI2S_RX 6			/* index = 6 */
-#define MI2S_TX 7			/* index = 7 */
-#define HDMI_RX 8			/* index = 8 */
-#define RSVD_2 9			/* index = 9 */
-#define RSVD_3 10			/* index = 10 */
-#define DIGI_MIC_TX 11			/* index = 11 */
-#define VOICE_RECORD_RX 0x8003		/* index = 12 */
-#define VOICE_RECORD_TX 0x8004		/* index = 13 */
-#define VOICE_PLAYBACK_TX 0x8005	/* index = 14 */
+#define PRIMARY_I2S_RX 0
+#define PRIMARY_I2S_TX 1
+#define SECONDARY_I2S_RX 4
+#define SECONDARY_I2S_TX 5
+#define MI2S_RX 6
+#define MI2S_TX 7
+#define HDMI_RX 8
+#define RSVD_2 9
+#define RSVD_3 10
+#define DIGI_MIC_TX 11
+#define VOICE2_PLAYBACK_TX 0x8002
+#define VOICE_RECORD_RX 0x8003
+#define VOICE_RECORD_TX 0x8004
+#define VOICE_PLAYBACK_TX 0x8005
 
 /* Slimbus Multi channel port id pool  */
-#define SLIMBUS_0_RX		0x4000		/* index = 15 */
-#define SLIMBUS_0_TX		0x4001		/* index = 16 */
-#define SLIMBUS_1_RX		0x4002		/* index = 17 */
-#define SLIMBUS_1_TX		0x4003		/* index = 18 */
+#define SLIMBUS_0_RX		0x4000
+#define SLIMBUS_0_TX		0x4001
+#define SLIMBUS_1_RX		0x4002
+#define SLIMBUS_1_TX		0x4003
 #define SLIMBUS_2_RX		0x4004
 #define SLIMBUS_2_TX		0x4005
 #define SLIMBUS_3_RX		0x4006
 #define SLIMBUS_3_TX		0x4007
 #define SLIMBUS_4_RX		0x4008
-#define SLIMBUS_4_TX		0x4009		/* index = 24 */
+#define SLIMBUS_4_TX		0x4009
 #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 */
-#define INT_FM_RX 0x3004		/* index = 28 */
-#define INT_FM_TX 0x3005		/* index = 29 */
-#define RT_PROXY_PORT_001_RX	0x2000    /* index = 30 */
-#define RT_PROXY_PORT_001_TX	0x2001    /* index = 31 */
+#define INT_BT_SCO_RX 0x3000
+#define INT_BT_SCO_TX 0x3001
+#define INT_BT_A2DP_RX 0x3002
+#define INT_FM_RX 0x3004
+#define INT_FM_TX 0x3005
+#define RT_PROXY_PORT_001_RX	0x2000
+#define RT_PROXY_PORT_001_TX	0x2001
 
 #define AFE_PORT_INVALID 0xFFFF
 #define SLIMBUS_INVALID AFE_PORT_INVALID
@@ -818,6 +819,7 @@
  * to this port from where the voice path delivers them on the
  * Rx path.
  */
+#define AFE_PORT_ID_VOICE2_PLAYBACK_TX  0x8002
 #define AFE_PORT_ID_VOICE_PLAYBACK_TX   0x8005
 #define AFE_PORT_ID_INVALID             0xFFFF
 
diff --git a/include/sound/q6afe-v2.h b/include/sound/q6afe-v2.h
index 2e4c7c1..12934aa 100644
--- a/include/sound/q6afe-v2.h
+++ b/include/sound/q6afe-v2.h
@@ -83,6 +83,7 @@
 	IDX_AFE_PORT_ID_PRIMARY_MI2S_TX = 41,
 	IDX_AFE_PORT_ID_SECONDARY_PCM_RX = 42,
 	IDX_AFE_PORT_ID_SECONDARY_PCM_TX = 43,
+	IDX_VOICE2_PLAYBACK_TX = 44,
 	IDX_GLOBAL_CFG,
 	AFE_MAX_PORTS
 };
diff --git a/include/sound/q6asm-v2.h b/include/sound/q6asm-v2.h
index 2138689..4ad1ca9 100644
--- a/include/sound/q6asm-v2.h
+++ b/include/sound/q6asm-v2.h
@@ -191,6 +191,9 @@
 int q6asm_open_read(struct audio_client *ac, uint32_t format
 		/*, uint16_t bits_per_sample*/);
 
+int q6asm_open_read_v2(struct audio_client *ac, uint32_t format,
+			uint16_t bits_per_sample);
+
 int q6asm_open_write(struct audio_client *ac, uint32_t format
 		/*, uint16_t bits_per_sample*/);
 
@@ -252,6 +255,10 @@
 int q6asm_enc_cfg_blk_pcm(struct audio_client *ac,
 			uint32_t rate, uint32_t channels);
 
+int q6asm_enc_cfg_blk_pcm_format_support(struct audio_client *ac,
+			uint32_t rate, uint32_t channels,
+			uint16_t bits_per_sample);
+
 int q6asm_set_encdec_chan_map(struct audio_client *ac,
 		uint32_t num_channels);
 
diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c
index 2356791..d85cf09 100644
--- a/net/netlink/af_netlink.c
+++ b/net/netlink/af_netlink.c
@@ -648,6 +648,9 @@
 	struct sockaddr_nl *nladdr = (struct sockaddr_nl *)addr;
 	int err;
 
+	if (addr_len < sizeof(struct sockaddr_nl))
+		return -EINVAL;
+
 	if (nladdr->nl_family != AF_NETLINK)
 		return -EINVAL;
 
diff --git a/sound/soc/codecs/msm_stub.c b/sound/soc/codecs/msm_stub.c
index 0cbcaf3..bdf1eb4 100644
--- a/sound/soc/codecs/msm_stub.c
+++ b/sound/soc/codecs/msm_stub.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
@@ -36,7 +36,8 @@
 			.channels_min = 1,
 			.channels_max = 8,
 			.rates = SNDRV_PCM_RATE_8000_48000,
-			.formats = SNDRV_PCM_FMTBIT_S16_LE,
+			.formats = (SNDRV_PCM_FMTBIT_S16_LE |
+				    SNDRV_PCM_FMTBIT_S24_LE),
 		},
 	},
 };
diff --git a/sound/soc/msm/msm-dai-fe.c b/sound/soc/msm/msm-dai-fe.c
index 1b51595..a0ed887 100644
--- a/sound/soc/msm/msm-dai-fe.c
+++ b/sound/soc/msm/msm-dai-fe.c
@@ -67,7 +67,8 @@
 			.aif_name = "MM_UL1",
 			.rates = (SNDRV_PCM_RATE_8000_48000|
 					SNDRV_PCM_RATE_KNOT),
-			.formats = SNDRV_PCM_FMTBIT_S16_LE,
+			.formats = (SNDRV_PCM_FMTBIT_S16_LE |
+				    SNDRV_PCM_FMTBIT_S24_LE),
 			.channels_min = 1,
 			.channels_max = 4,
 			.rate_min =     8000,
@@ -713,6 +714,33 @@
 		.ops = &msm_fe_dai_ops,
 		.name = "VOICE2_STUB",
 	},
+	{
+		.playback = {
+			.stream_name = "Multimedia9 Playback",
+			.aif_name = "MM_DL9",
+			.rates = (SNDRV_PCM_RATE_8000_192000|
+				  SNDRV_PCM_RATE_KNOT),
+			.formats = (SNDRV_PCM_FMTBIT_S16_LE |
+				    SNDRV_PCM_FMTBIT_S24_LE),
+			.channels_min = 1,
+			.channels_max = 8,
+			.rate_min =     8000,
+			.rate_max =	192000,
+		},
+		.capture = {
+			.stream_name = "Multimedia9 Capture",
+			.aif_name = "MM_UL9",
+			.rates = (SNDRV_PCM_RATE_8000_48000|
+				  SNDRV_PCM_RATE_KNOT),
+			.formats = SNDRV_PCM_FMTBIT_S16_LE,
+			.channels_min = 1,
+			.channels_max = 8,
+			.rate_min =     8000,
+			.rate_max =	48000,
+		},
+		.ops = &msm_fe_Multimedia_dai_ops,
+		.name = "MultiMedia9",
+	},
 };
 
 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 6a4f825..043a998 100644
--- a/sound/soc/msm/msm8226.c
+++ b/sound/soc/msm/msm8226.c
@@ -1025,6 +1025,21 @@
 		.ignore_pmdown_time = 1,
 		.be_id = MSM_FRONTEND_DAI_MULTIMEDIA5,
 	},
+	{
+		.name = "MSM8226 Media9",
+		.stream_name = "MultiMedia9",
+		.cpu_dai_name   = "MultiMedia9",
+		.platform_name  = "msm-pcm-dsp.0",
+		.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 dailink has playback support */
+		.ignore_pmdown_time = 1,
+		.be_id = MSM_FRONTEND_DAI_MULTIMEDIA9,
+	},
 	/* Backend BT/FM DAI Links */
 	{
 		.name = LPASS_BE_INT_BT_SCO_RX,
@@ -1301,6 +1316,19 @@
 		.be_hw_params_fixup = msm_be_hw_params_fixup,
 		.ignore_suspend = 1,
 	},
+	/* Incall Music 2 BACK END DAI Link */
+	{
+		.name = LPASS_BE_VOICE2_PLAYBACK_TX,
+		.stream_name = "Voice2 Farend Playback",
+		.cpu_dai_name = "msm-dai-q6-dev.32770",
+		.platform_name = "msm-pcm-routing",
+		.codec_name     = "msm-stub-codec.1",
+		.codec_dai_name = "msm-stub-rx",
+		.no_pcm = 1,
+		.be_id = MSM_BACKEND_DAI_VOICE2_PLAYBACK_TX,
+		.be_hw_params_fixup = msm_be_hw_params_fixup,
+		.ignore_suspend = 1,
+	},
 };
 
 struct snd_soc_card snd_soc_card_msm8226 = {
diff --git a/sound/soc/msm/msm8974.c b/sound/soc/msm/msm8974.c
index f67af9b..0b7e7f2 100644
--- a/sound/soc/msm/msm8974.c
+++ b/sound/soc/msm/msm8974.c
@@ -208,6 +208,7 @@
 static int msm_hdmi_rx_ch = 2;
 static int slim0_rx_sample_rate = SAMPLING_RATE_48KHZ;
 static int msm_proxy_rx_ch = 2;
+static int hdmi_rx_sample_rate = SAMPLING_RATE_48KHZ;
 
 static struct mutex cdc_mclk_mutex;
 static struct clk *codec_clk;
@@ -720,6 +721,8 @@
 static const char *const proxy_rx_ch_text[] = {"One", "Two", "Three", "Four",
 	"Five",	"Six", "Seven", "Eight"};
 
+static char const *hdmi_rx_sample_rate_text[] = {"KHZ_48", "KHZ_96",
+					"KHZ_192"};
 static const char *const btsco_rate_text[] = {"8000", "16000"};
 static const struct soc_enum msm_btsco_enum[] = {
 	SOC_ENUM_SINGLE_EXT(2, btsco_rate_text),
@@ -940,6 +943,57 @@
 	return 1;
 }
 
+static int hdmi_rx_sample_rate_get(struct snd_kcontrol *kcontrol,
+	struct snd_ctl_elem_value *ucontrol)
+{
+	int sample_rate_val = 0;
+
+	switch (hdmi_rx_sample_rate) {
+	case SAMPLING_RATE_192KHZ:
+		sample_rate_val = 2;
+		break;
+
+	case SAMPLING_RATE_96KHZ:
+		sample_rate_val = 1;
+		break;
+
+	case SAMPLING_RATE_48KHZ:
+	default:
+		sample_rate_val = 0;
+		break;
+	}
+
+	ucontrol->value.integer.value[0] = sample_rate_val;
+	pr_debug("%s: hdmi_rx_sample_rate = %d\n", __func__,
+				hdmi_rx_sample_rate);
+
+	return 0;
+}
+
+static int hdmi_rx_sample_rate_put(struct snd_kcontrol *kcontrol,
+	struct snd_ctl_elem_value *ucontrol)
+{
+	pr_debug("%s: ucontrol value = %ld\n", __func__,
+			ucontrol->value.integer.value[0]);
+
+	switch (ucontrol->value.integer.value[0]) {
+	case 2:
+		hdmi_rx_sample_rate = SAMPLING_RATE_192KHZ;
+		break;
+	case 1:
+		hdmi_rx_sample_rate = SAMPLING_RATE_96KHZ;
+		break;
+	case 0:
+	default:
+		hdmi_rx_sample_rate = SAMPLING_RATE_48KHZ;
+	}
+
+	pr_debug("%s: hdmi_rx_sample_rate = %d\n", __func__,
+			hdmi_rx_sample_rate);
+
+	return 0;
+}
+
 static int msm_btsco_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
 					struct snd_pcm_hw_params *params)
 {
@@ -1055,7 +1109,7 @@
 				hdmi_rx_bit_format);
 	if (channels->max < 2)
 		channels->min = channels->max = 2;
-	rate->min = rate->max = 48000;
+	rate->min = rate->max = hdmi_rx_sample_rate;
 	channels->min = channels->max = msm_hdmi_rx_ch;
 
 	return 0;
@@ -1324,6 +1378,7 @@
 	SOC_ENUM_SINGLE_EXT(2, rx_bit_format_text),
 	SOC_ENUM_SINGLE_EXT(3, slim0_rx_sample_rate_text),
 	SOC_ENUM_SINGLE_EXT(8, proxy_rx_ch_text),
+	SOC_ENUM_SINGLE_EXT(3, hdmi_rx_sample_rate_text),
 };
 
 static const struct snd_kcontrol_new msm_snd_controls[] = {
@@ -1347,6 +1402,8 @@
 			msm_proxy_rx_ch_get, msm_proxy_rx_ch_put),
 	SOC_ENUM_EXT("Internal BTSCO SampleRate", msm_btsco_enum[0],
 		     msm_btsco_rate_get, msm_btsco_rate_put),
+	SOC_ENUM_EXT("HDMI_RX SampleRate", msm_snd_enum[7],
+			hdmi_rx_sample_rate_get, hdmi_rx_sample_rate_put),
 };
 
 static bool msm8974_swap_gnd_mic(struct snd_soc_codec *codec)
diff --git a/sound/soc/msm/qdsp6/q6voice.c b/sound/soc/msm/qdsp6/q6voice.c
index 60f4669..094c58b 100644
--- a/sound/soc/msm/qdsp6/q6voice.c
+++ b/sound/soc/msm/qdsp6/q6voice.c
@@ -2356,10 +2356,11 @@
 	}
 	if (common.ec_ref_ext == true) {
 		ret = voice_send_set_device_cmd_v2(v);
-		if (ret < 0)
+		if (ret < 0) {
 			pr_err("%s:  set device V2 failed rc =%x\n",
 			       __func__, ret);
 			goto fail;
+		}
 	}
 	/* send cvs cal */
 	ret = voice_send_cvs_map_memory_cmd(v);
@@ -3354,10 +3355,11 @@
 	if (v->voc_state == VOC_CHANGE) {
 		if (common.ec_ref_ext == true) {
 			ret = voice_send_set_device_cmd_v2(v);
-			if (ret < 0)
+			if (ret < 0) {
 				pr_err("%s: set device V2 failed\n"
 				       "rc =%x\n", __func__, ret);
 				goto fail;
+			}
 		} else {
 			ret = voice_send_set_device_cmd(v);
 			if (ret < 0) {
diff --git a/sound/soc/msm/qdsp6v2/audio_acdb.c b/sound/soc/msm/qdsp6v2/audio_acdb.c
index 3b6a415..d6090cf 100644
--- a/sound/soc/msm/qdsp6v2/audio_acdb.c
+++ b/sound/soc/msm/qdsp6v2/audio_acdb.c
@@ -153,15 +153,18 @@
 	atomic_set(&acdb_data.valid_asm_custom_top, 1);
 }
 
-void get_adm_custom_topology(struct acdb_cal_block *cal_block)
+int get_adm_custom_topology(struct acdb_cal_block *cal_block)
 {
+	int result = 0;
 	pr_debug("%s\n", __func__);
 
 	if (cal_block == NULL) {
 		pr_err("ACDB=> NULL pointer sent to %s\n", __func__);
+		result = -EINVAL;
 		goto done;
 	}
 
+	/* Only return allow one access after memory registered */
 	if (atomic_read(&acdb_data.valid_adm_custom_top) == 0) {
 		cal_block->cal_size = 0;
 		goto done;
@@ -175,17 +178,19 @@
 	cal_block->cal_kvaddr =
 		atomic_read(&acdb_data.adm_custom_topology.cal_kvaddr);
 done:
-	return;
+	return result;
 }
 
-void store_adm_custom_topology(struct cal_block *cal_block)
+int store_adm_custom_topology(struct cal_block *cal_block)
 {
+	int result = 0;
 	pr_debug("%s,\n", __func__);
 
 	if (cal_block->cal_offset > atomic64_read(&acdb_data.mem_len)) {
 		pr_err("%s: offset %d is > mem_len %ld\n",
 			__func__, cal_block->cal_offset,
 			(long)atomic64_read(&acdb_data.mem_len));
+		result = -EINVAL;
 		goto done;
 	}
 
@@ -197,18 +202,21 @@
 		cal_block->cal_offset +
 		atomic64_read(&acdb_data.kvaddr));
 done:
-	return;
+	return result;
 }
 
-void get_asm_custom_topology(struct acdb_cal_block *cal_block)
+int get_asm_custom_topology(struct acdb_cal_block *cal_block)
 {
-	pr_debug("%s\n", __func__);
+	int result = 0;
+	pr_debug("%s,\n", __func__);
 
 	if (cal_block == NULL) {
 		pr_err("ACDB=> NULL pointer sent to %s\n", __func__);
+		result = -EINVAL;
 		goto done;
 	}
 
+	/* Only return allow one access after memory registered */
 	if (atomic_read(&acdb_data.valid_asm_custom_top) == 0) {
 		cal_block->cal_size = 0;
 		goto done;
@@ -222,17 +230,19 @@
 	cal_block->cal_kvaddr =
 		atomic_read(&acdb_data.asm_custom_topology.cal_kvaddr);
 done:
-	return;
+	return result;
 }
 
-void store_asm_custom_topology(struct cal_block *cal_block)
+int store_asm_custom_topology(struct cal_block *cal_block)
 {
+	int result = 0;
 	pr_debug("%s,\n", __func__);
 
 	if (cal_block->cal_offset > atomic64_read(&acdb_data.mem_len)) {
 		pr_err("%s: offset %d is > mem_len %ld\n",
 			__func__, cal_block->cal_offset,
 			(long)atomic64_read(&acdb_data.mem_len));
+		result = -EINVAL;
 		goto done;
 	}
 
@@ -244,24 +254,37 @@
 		cal_block->cal_offset +
 		atomic64_read(&acdb_data.kvaddr));
 done:
-	return;
+	return result;
 }
 
-void get_voice_cal_allocation(struct acdb_cal_block *cal_block)
+int get_voice_cal_allocation(struct acdb_cal_block *cal_block)
 {
+	int result = 0;
+	pr_debug("%s,\n", __func__);
+
+	if (cal_block == NULL) {
+		pr_err("ACDB=> NULL pointer sent to %s\n", __func__);
+		result = -EINVAL;
+		goto done;
+	}
+
 	cal_block->cal_size = ACDB_TOTAL_VOICE_ALLOCATION;
 	cal_block->cal_paddr =
 		atomic_read(&acdb_data.vocproc_cal.cal_paddr);
 	cal_block->cal_kvaddr =
 		atomic_read(&acdb_data.vocproc_cal.cal_kvaddr);
+done:
+	return result;
 }
 
-void get_aanc_cal(struct acdb_cal_block *cal_block)
+int get_aanc_cal(struct acdb_cal_block *cal_block)
 {
-	pr_debug("%s\n", __func__);
+	int result = 0;
+	pr_debug("%s,\n", __func__);
 
 	if (cal_block == NULL) {
 		pr_err("ACDB=> NULL pointer sent to %s\n", __func__);
+		result = -EINVAL;
 		goto done;
 	}
 
@@ -272,18 +295,20 @@
 	cal_block->cal_kvaddr =
 		atomic_read(&acdb_data.aanc_cal.cal_kvaddr);
 done:
-	return;
+	return result;
 }
 
-void store_aanc_cal(struct cal_block *cal_block)
+int store_aanc_cal(struct cal_block *cal_block)
 {
+	int result = 0;
 	pr_debug("%s,\n", __func__);
 
 	if (cal_block->cal_offset > atomic64_read(&acdb_data.mem_len)) {
 		pr_err("%s: offset %d is > mem_len %ld\n",
 		 __func__, cal_block->cal_offset,
 		(long)atomic64_read(&acdb_data.mem_len));
-		 goto done;
+		result = -EINVAL;
+		goto done;
 	}
 
 	atomic_set(&acdb_data.aanc_cal.cal_size,
@@ -293,15 +318,17 @@
 	atomic_set(&acdb_data.aanc_cal.cal_kvaddr,
 		cal_block->cal_offset + atomic64_read(&acdb_data.kvaddr));
 done:
-	return;
+	return result;
 }
 
-void get_lsm_cal(struct acdb_cal_block *cal_block)
+int get_lsm_cal(struct acdb_cal_block *cal_block)
 {
-	pr_debug("%s\n", __func__);
+	int result = 0;
+	pr_debug("%s,\n", __func__);
 
 	if (cal_block == NULL) {
 		pr_err("ACDB=> NULL pointer sent to %s\n", __func__);
+		result = -EINVAL;
 		goto done;
 	}
 
@@ -312,17 +339,19 @@
 	cal_block->cal_kvaddr =
 		atomic_read(&acdb_data.lsm_cal.cal_kvaddr);
 done:
-	return;
+	return result;
 }
 
-void store_lsm_cal(struct cal_block *cal_block)
+int store_lsm_cal(struct cal_block *cal_block)
 {
+	int result = 0;
 	pr_debug("%s,\n", __func__);
 
 	if (cal_block->cal_offset > atomic64_read(&acdb_data.mem_len)) {
 		pr_err("%s: offset %d is > mem_len %ld\n",
 			__func__, cal_block->cal_offset,
 			(long)atomic64_read(&acdb_data.mem_len));
+		result = -EINVAL;
 		goto done;
 	}
 
@@ -333,15 +362,17 @@
 	atomic_set(&acdb_data.lsm_cal.cal_kvaddr,
 		cal_block->cal_offset + atomic64_read(&acdb_data.kvaddr));
 done:
-	return;
+	return result;
 }
 
-void get_anc_cal(struct acdb_cal_block *cal_block)
+int get_anc_cal(struct acdb_cal_block *cal_block)
 {
-	pr_debug("%s\n", __func__);
+	int result = 0;
+	pr_debug("%s,\n", __func__);
 
 	if (cal_block == NULL) {
 		pr_err("ACDB=> NULL pointer sent to %s\n", __func__);
+		result = -EINVAL;
 		goto done;
 	}
 
@@ -352,17 +383,19 @@
 	cal_block->cal_kvaddr =
 		atomic_read(&acdb_data.anc_cal.cal_kvaddr);
 done:
-	return;
+	return result;
 }
 
-void store_anc_cal(struct cal_block *cal_block)
+int store_anc_cal(struct cal_block *cal_block)
 {
+	int result = 0;
 	pr_debug("%s,\n", __func__);
 
 	if (cal_block->cal_offset > atomic64_read(&acdb_data.mem_len)) {
 		pr_err("%s: offset %d is > mem_len %ld\n",
 			__func__, cal_block->cal_offset,
 			(long)atomic64_read(&acdb_data.mem_len));
+		result = -EINVAL;
 		goto done;
 	}
 
@@ -373,22 +406,25 @@
 	atomic_set(&acdb_data.anc_cal.cal_kvaddr,
 		cal_block->cal_offset + atomic64_read(&acdb_data.kvaddr));
 done:
-	return;
+	return result;
 }
 
-void store_afe_cal(int32_t path, struct cal_block *cal_block)
+int store_afe_cal(int32_t path, struct cal_block *cal_block)
 {
+	int result = 0;
 	pr_debug("%s, path = %d\n", __func__, path);
 
 	if (cal_block->cal_offset > atomic64_read(&acdb_data.mem_len)) {
 		pr_err("%s: offset %d is > mem_len %ld\n",
 			__func__, cal_block->cal_offset,
 			(long)atomic64_read(&acdb_data.mem_len));
+		result = -EINVAL;
 		goto done;
 	}
 	if ((path >= MAX_AUDPROC_TYPES) || (path < 0)) {
 		pr_err("ACDB=> Bad path sent to %s, path: %d\n",
 			__func__, path);
+		result = -EINVAL;
 		goto done;
 	}
 
@@ -399,20 +435,23 @@
 	atomic_set(&acdb_data.afe_cal[path].cal_kvaddr,
 		cal_block->cal_offset + atomic64_read(&acdb_data.kvaddr));
 done:
-	return;
+	return result;
 }
 
-void get_afe_cal(int32_t path, struct acdb_cal_block *cal_block)
+int get_afe_cal(int32_t path, struct acdb_cal_block *cal_block)
 {
+	int result = 0;
 	pr_debug("%s, path = %d\n", __func__, path);
 
 	if (cal_block == NULL) {
 		pr_err("ACDB=> NULL pointer sent to %s\n", __func__);
+		result = -EINVAL;
 		goto done;
 	}
 	if ((path >= MAX_AUDPROC_TYPES) || (path < 0)) {
 		pr_err("ACDB=> Bad path sent to %s, path: %d\n",
 			__func__, path);
+		result = -EINVAL;
 		goto done;
 	}
 
@@ -423,22 +462,25 @@
 	cal_block->cal_kvaddr =
 		atomic_read(&acdb_data.afe_cal[path].cal_kvaddr);
 done:
-	return;
+	return result;
 }
 
-void store_audproc_cal(int32_t path, struct cal_block *cal_block)
+int store_audproc_cal(int32_t path, struct cal_block *cal_block)
 {
+	int result = 0;
 	pr_debug("%s, path = %d\n", __func__, path);
 
 	if (cal_block->cal_offset > atomic64_read(&acdb_data.mem_len)) {
 		pr_err("%s: offset %d is > mem_len %ld\n",
 			__func__, cal_block->cal_offset,
 			(long)atomic64_read(&acdb_data.mem_len));
+		result = -EINVAL;
 		goto done;
 	}
 	if (path >= MAX_AUDPROC_TYPES) {
 		pr_err("ACDB=> Bad path sent to %s, path: %d\n",
 			__func__, path);
+		result = -EINVAL;
 		goto done;
 	}
 
@@ -449,20 +491,23 @@
 	atomic_set(&acdb_data.audproc_cal[path].cal_kvaddr,
 		cal_block->cal_offset + atomic64_read(&acdb_data.kvaddr));
 done:
-	return;
+	return result;
 }
 
-void get_audproc_cal(int32_t path, struct acdb_cal_block *cal_block)
+int get_audproc_cal(int32_t path, struct acdb_cal_block *cal_block)
 {
+	int result = 0;
 	pr_debug("%s, path = %d\n", __func__, path);
 
 	if (cal_block == NULL) {
 		pr_err("ACDB=> NULL pointer sent to %s\n", __func__);
+		result = -EINVAL;
 		goto done;
 	}
 	if (path >= MAX_AUDPROC_TYPES) {
 		pr_err("ACDB=> Bad path sent to %s, path: %d\n",
 			__func__, path);
+		result = -EINVAL;
 		goto done;
 	}
 
@@ -473,22 +518,25 @@
 	cal_block->cal_kvaddr =
 		atomic_read(&acdb_data.audproc_cal[path].cal_kvaddr);
 done:
-	return;
+	return result;
 }
 
-void store_audstrm_cal(int32_t path, struct cal_block *cal_block)
+int store_audstrm_cal(int32_t path, struct cal_block *cal_block)
 {
+	int result = 0;
 	pr_debug("%s, path = %d\n", __func__, path);
 
 	if (cal_block->cal_offset > atomic64_read(&acdb_data.mem_len)) {
 		pr_err("%s: offset %d is > mem_len %ld\n",
 			__func__, cal_block->cal_offset,
 			(long)atomic64_read(&acdb_data.mem_len));
+		result = -EINVAL;
 		goto done;
 	}
 	if (path >= MAX_AUDPROC_TYPES) {
 		pr_err("ACDB=> Bad path sent to %s, path: %d\n",
 			__func__, path);
+		result = -EINVAL;
 		goto done;
 	}
 
@@ -499,20 +547,23 @@
 	atomic_set(&acdb_data.audstrm_cal[path].cal_kvaddr,
 		cal_block->cal_offset + atomic64_read(&acdb_data.kvaddr));
 done:
-	return;
+	return result;
 }
 
-void get_audstrm_cal(int32_t path, struct acdb_cal_block *cal_block)
+int get_audstrm_cal(int32_t path, struct acdb_cal_block *cal_block)
 {
+	int result = 0;
 	pr_debug("%s, path = %d\n", __func__, path);
 
 	if (cal_block == NULL) {
 		pr_err("ACDB=> NULL pointer sent to %s\n", __func__);
+		result = -EINVAL;
 		goto done;
 	}
 	if (path >= MAX_AUDPROC_TYPES) {
 		pr_err("ACDB=> Bad path sent to %s, path: %d\n",
 			__func__, path);
+		result = -EINVAL;
 		goto done;
 	}
 
@@ -523,22 +574,25 @@
 	cal_block->cal_kvaddr =
 		atomic_read(&acdb_data.audstrm_cal[path].cal_kvaddr);
 done:
-	return;
+	return result;
 }
 
-void store_audvol_cal(int32_t path, struct cal_block *cal_block)
+int store_audvol_cal(int32_t path, struct cal_block *cal_block)
 {
+	int result = 0;
 	pr_debug("%s, path = %d\n", __func__, path);
 
 	if (cal_block->cal_offset > atomic64_read(&acdb_data.mem_len)) {
 		pr_err("%s: offset %d is > mem_len %ld\n",
 			__func__, cal_block->cal_offset,
 			(long)atomic64_read(&acdb_data.mem_len));
+		result = -EINVAL;
 		goto done;
 	}
 	if (path >= MAX_AUDPROC_TYPES) {
 		pr_err("ACDB=> Bad path sent to %s, path: %d\n",
 			__func__, path);
+		result = -EINVAL;
 		goto done;
 	}
 
@@ -549,20 +603,23 @@
 	atomic_set(&acdb_data.audvol_cal[path].cal_kvaddr,
 		cal_block->cal_offset + atomic64_read(&acdb_data.kvaddr));
 done:
-	return;
+	return result;
 }
 
-void get_audvol_cal(int32_t path, struct acdb_cal_block *cal_block)
+int get_audvol_cal(int32_t path, struct acdb_cal_block *cal_block)
 {
+	int result = 0;
 	pr_debug("%s, path = %d\n", __func__, path);
 
 	if (cal_block == NULL) {
 		pr_err("ACDB=> NULL pointer sent to %s\n", __func__);
+		result = -EINVAL;
 		goto done;
 	}
 	if (path >= MAX_AUDPROC_TYPES || path < 0) {
 		pr_err("ACDB=> Bad path sent to %s, path: %d\n",
 			__func__, path);
+		result = -EINVAL;
 		goto done;
 	}
 
@@ -573,15 +630,19 @@
 	cal_block->cal_kvaddr =
 		atomic_read(&acdb_data.audvol_cal[path].cal_kvaddr);
 done:
-	return;
+	return result;
 }
 
-void store_voice_col_data(uint32_t vocproc_type, uint32_t cal_size,
+int store_voice_col_data(uint32_t vocproc_type, uint32_t cal_size,
 			  uint32_t *cal_block)
 {
+	int result = 0;
+	pr_debug("%s,\n", __func__);
+
 	if (cal_size > MAX_COL_SIZE) {
 		pr_err("%s: col size is to big %d\n", __func__,
 				cal_size);
+		result = -EINVAL;
 		goto done;
 	}
 	if (copy_from_user(acdb_data.col_data[vocproc_type],
@@ -589,19 +650,24 @@
 			cal_size)) {
 		pr_err("%s: fail to copy col size %d\n",
 			__func__, cal_size);
+		result = -EINVAL;
 		goto done;
 	}
 	atomic_set(&acdb_data.vocproc_col_cal[vocproc_type].cal_size,
 		cal_size);
 done:
-	return;
+	return result;
 }
 
-void get_voice_col_data(uint32_t vocproc_type,
+int get_voice_col_data(uint32_t vocproc_type,
 			struct acdb_cal_block *cal_block)
 {
+	int result = 0;
+	pr_debug("%s,\n", __func__);
+
 	if (cal_block == NULL) {
 		pr_err("ACDB=> NULL pointer sent to %s\n", __func__);
+		result = -EINVAL;
 		goto done;
 	}
 
@@ -612,12 +678,13 @@
 	cal_block->cal_kvaddr = atomic_read(&acdb_data.
 				vocproc_col_cal[vocproc_type].cal_kvaddr);
 done:
-	return;
+	return result;
 }
 
-void store_vocproc_dev_cfg_cal(struct cal_block *cal_block)
+int store_vocproc_dev_cfg_cal(struct cal_block *cal_block)
 {
-	pr_debug("%s\n", __func__);
+	int result = 0;
+	pr_debug("%s,\n", __func__);
 
 
 	if (cal_block->cal_offset >
@@ -626,6 +693,7 @@
 			__func__, cal_block->cal_offset,
 			(long)atomic64_read(&acdb_data.mem_len));
 		atomic_set(&acdb_data.vocproc_dev_cal.cal_size, 0);
+		result = -EINVAL;
 		goto done;
 	}
 
@@ -639,12 +707,19 @@
 			atomic64_read(&acdb_data.kvaddr));
 
 done:
-	return;
+	return result;
 }
 
-void get_vocproc_dev_cfg_cal(struct acdb_cal_block *cal_block)
+int get_vocproc_dev_cfg_cal(struct acdb_cal_block *cal_block)
 {
-	pr_debug("%s\n", __func__);
+	int result = 0;
+	pr_debug("%s,\n", __func__);
+
+	if (cal_block == NULL) {
+		pr_err("ACDB=> NULL pointer sent to %s\n", __func__);
+		result = -EINVAL;
+		goto done;
+	}
 
 	cal_block->cal_size =
 		atomic_read(&acdb_data.vocproc_dev_cal.cal_size);
@@ -652,13 +727,16 @@
 		atomic_read(&acdb_data.vocproc_dev_cal.cal_paddr);
 	cal_block->cal_kvaddr =
 		atomic_read(&acdb_data.vocproc_dev_cal.cal_kvaddr);
+done:
+	return result;
 }
 
 
 
-void store_vocproc_cal(struct cal_block *cal_block)
+int store_vocproc_cal(struct cal_block *cal_block)
 {
-	pr_debug("%s\n", __func__);
+	int result = 0;
+	pr_debug("%s,\n", __func__);
 
 	if (cal_block->cal_offset >
 				atomic64_read(&acdb_data.mem_len)) {
@@ -666,6 +744,7 @@
 			__func__, cal_block->cal_offset,
 			(long)atomic64_read(&acdb_data.mem_len));
 		atomic_set(&acdb_data.vocproc_cal.cal_size, 0);
+		result = -EINVAL;
 		goto done;
 	}
 
@@ -679,15 +758,17 @@
 		atomic64_read(&acdb_data.kvaddr));
 
 done:
-	return;
+	return result;
 }
 
-void get_vocproc_cal(struct acdb_cal_block *cal_block)
+int get_vocproc_cal(struct acdb_cal_block *cal_block)
 {
-	pr_debug("%s\n", __func__);
+	int result = 0;
+	pr_debug("%s,\n", __func__);
 
 	if (cal_block == NULL) {
 		pr_err("ACDB=> NULL pointer sent to %s\n", __func__);
+		result = -EINVAL;
 		goto done;
 	}
 
@@ -698,12 +779,13 @@
 	cal_block->cal_kvaddr =
 		atomic_read(&acdb_data.vocproc_cal.cal_kvaddr);
 done:
-	return;
+	return result;
 }
 
-void store_vocstrm_cal(struct cal_block *cal_block)
+int store_vocstrm_cal(struct cal_block *cal_block)
 {
-	pr_debug("%s\n", __func__);
+	int result = 0;
+	pr_debug("%s,\n", __func__);
 
 	if (cal_block->cal_offset >
 			atomic64_read(&acdb_data.mem_len)) {
@@ -711,6 +793,7 @@
 			__func__, cal_block->cal_offset,
 			(long)atomic64_read(&acdb_data.mem_len));
 		atomic_set(&acdb_data.vocstrm_cal.cal_size, 0);
+		result = -EINVAL;
 		goto done;
 	}
 
@@ -724,15 +807,17 @@
 		atomic64_read(&acdb_data.kvaddr));
 
 done:
-	return;
+	return result;
 }
 
-void get_vocstrm_cal(struct acdb_cal_block *cal_block)
+int get_vocstrm_cal(struct acdb_cal_block *cal_block)
 {
-	pr_debug("%s\n", __func__);
+	int result = 0;
+	pr_debug("%s,\n", __func__);
 
 	if (cal_block == NULL) {
 		pr_err("ACDB=> NULL pointer sent to %s\n", __func__);
+		result = -EINVAL;
 		goto done;
 	}
 
@@ -743,12 +828,13 @@
 	cal_block->cal_kvaddr =
 		atomic_read(&acdb_data.vocstrm_cal.cal_kvaddr);
 done:
-	return;
+	return result;
 }
 
-void store_vocvol_cal(struct cal_block *cal_block)
+int store_vocvol_cal(struct cal_block *cal_block)
 {
-	pr_debug("%s\n", __func__);
+	int result = 0;
+	pr_debug("%s,\n", __func__);
 
 	if (cal_block->cal_offset >
 			atomic64_read(&acdb_data.mem_len)) {
@@ -756,6 +842,7 @@
 			__func__, cal_block->cal_offset,
 			(long)atomic64_read(&acdb_data.mem_len));
 		atomic_set(&acdb_data.vocvol_cal.cal_size, 0);
+		result = -EINVAL;
 		goto done;
 	}
 
@@ -769,15 +856,17 @@
 		atomic64_read(&acdb_data.kvaddr));
 
 done:
-	return;
+	return result;
 }
 
-void get_vocvol_cal(struct acdb_cal_block *cal_block)
+int get_vocvol_cal(struct acdb_cal_block *cal_block)
 {
-	pr_debug("%s\n", __func__);
+	int result = 0;
+	pr_debug("%s,\n", __func__);
 
 	if (cal_block == NULL) {
 		pr_err("ACDB=> NULL pointer sent to %s\n", __func__);
+		result = -EINVAL;
 		goto done;
 	}
 
@@ -788,47 +877,60 @@
 	cal_block->cal_kvaddr =
 		atomic_read(&acdb_data.vocvol_cal.cal_kvaddr);
 done:
-	return;
+	return result;
 }
 
 void store_sidetone_cal(struct sidetone_cal *cal_data)
 {
-	pr_debug("%s\n", __func__);
+	pr_debug("%s,\n", __func__);
 
 	atomic_set(&acdb_data.sidetone_cal.enable, cal_data->enable);
 	atomic_set(&acdb_data.sidetone_cal.gain, cal_data->gain);
 }
 
-
-void get_sidetone_cal(struct sidetone_cal *cal_data)
+int get_sidetone_cal(struct sidetone_cal *cal_data)
 {
-	pr_debug("%s\n", __func__);
+	int result = 0;
+	pr_debug("%s,\n", __func__);
 
 	if (cal_data == NULL) {
 		pr_err("ACDB=> NULL pointer sent to %s\n", __func__);
+		result = -EINVAL;
 		goto done;
 	}
 
 	cal_data->enable = atomic_read(&acdb_data.sidetone_cal.enable);
 	cal_data->gain = atomic_read(&acdb_data.sidetone_cal.gain);
 done:
-	return;
+	return result;
 }
-void get_spk_protection_cfg(struct msm_spk_prot_cfg *prot_cfg)
+
+int get_spk_protection_cfg(struct msm_spk_prot_cfg *prot_cfg)
 {
+	int result = 0;
+	pr_debug("%s,\n", __func__);
+
 	mutex_lock(&acdb_data.acdb_mutex);
 	if (prot_cfg) {
 		prot_cfg->mode = acdb_data.spk_prot_cfg.mode;
 		prot_cfg->r0 = acdb_data.spk_prot_cfg.r0;
 		prot_cfg->t0 = acdb_data.spk_prot_cfg.t0;
-	} else
+	} else {
 		pr_err("%s prot_cfg is NULL\n", __func__);
+		result = -EINVAL;
+	}
 	mutex_unlock(&acdb_data.acdb_mutex);
+
+	return result;
 }
-static void get_spk_protection_status(struct msm_spk_prot_status *status)
+
+static int get_spk_protection_status(struct msm_spk_prot_status *status)
 {
+	int					result = 0;
+	struct afe_spkr_prot_get_vi_calib	calib_resp;
+	pr_debug("%s,\n", __func__);
+
 	/*Call AFE function here to query the status*/
-	struct afe_spkr_prot_get_vi_calib calib_resp;
 	if (status) {
 		status->status = -EINVAL;
 		if (!afe_spk_prot_get_calib_data(&calib_resp)) {
@@ -839,8 +941,12 @@
 				status->r0 = calib_resp.res_cfg.r0_cali_q24;
 			}
 		 }
-	} else
+	} else {
 		pr_err("%s invalid params\n", __func__);
+		result =  -EINVAL;
+	}
+
+	return result;
 }
 
 static int acdb_open(struct inode *inode, struct file *f)
@@ -1054,13 +1160,16 @@
 
 	switch (cmd) {
 	case AUDIO_SET_VOCPROC_COL_CAL:
-		store_voice_col_data(VOCPROC_CAL, size, (uint32_t *)arg);
+		result = store_voice_col_data(VOCPROC_CAL,
+						size, (uint32_t *)arg);
 		goto done;
 	case AUDIO_SET_VOCSTRM_COL_CAL:
-		store_voice_col_data(VOCSTRM_CAL, size, (uint32_t *)arg);
+		result = store_voice_col_data(VOCSTRM_CAL,
+						size, (uint32_t *)arg);
 		goto done;
 	case AUDIO_SET_VOCVOL_COL_CAL:
-		store_voice_col_data(VOCVOL_CAL, size, (uint32_t *)arg);
+		result = store_voice_col_data(VOCVOL_CAL,
+						size, (uint32_t *)arg);
 		goto done;
 	}
 
@@ -1083,61 +1192,63 @@
 
 	switch (cmd) {
 	case AUDIO_SET_AUDPROC_TX_CAL:
-		store_audproc_cal(TX_CAL, (struct cal_block *)data);
+		result = store_audproc_cal(TX_CAL, (struct cal_block *)data);
 		goto done;
 	case AUDIO_SET_AUDPROC_RX_CAL:
-		store_audproc_cal(RX_CAL, (struct cal_block *)data);
+		result = store_audproc_cal(RX_CAL, (struct cal_block *)data);
 		goto done;
 	case AUDIO_SET_AUDPROC_TX_STREAM_CAL:
-		store_audstrm_cal(TX_CAL, (struct cal_block *)data);
+		result = store_audstrm_cal(TX_CAL, (struct cal_block *)data);
 		goto done;
 	case AUDIO_SET_AUDPROC_RX_STREAM_CAL:
-		store_audstrm_cal(RX_CAL, (struct cal_block *)data);
+		result = store_audstrm_cal(RX_CAL, (struct cal_block *)data);
 		goto done;
 	case AUDIO_SET_AUDPROC_TX_VOL_CAL:
-		store_audvol_cal(TX_CAL, (struct cal_block *)data);
+		result = store_audvol_cal(TX_CAL, (struct cal_block *)data);
 		goto done;
 	case AUDIO_SET_AUDPROC_RX_VOL_CAL:
-		store_audvol_cal(RX_CAL, (struct cal_block *)data);
+		result = store_audvol_cal(RX_CAL, (struct cal_block *)data);
 		goto done;
 	case AUDIO_SET_AFE_TX_CAL:
-		store_afe_cal(TX_CAL, (struct cal_block *)data);
+		result = store_afe_cal(TX_CAL, (struct cal_block *)data);
 		goto done;
 	case AUDIO_SET_AFE_RX_CAL:
-		store_afe_cal(RX_CAL, (struct cal_block *)data);
+		result = store_afe_cal(RX_CAL, (struct cal_block *)data);
 		goto done;
 	case AUDIO_SET_VOCPROC_CAL:
-		store_vocproc_cal((struct cal_block *)data);
+		result = store_vocproc_cal((struct cal_block *)data);
 		goto done;
 	case AUDIO_SET_VOCPROC_STREAM_CAL:
-		store_vocstrm_cal((struct cal_block *)data);
+		result = store_vocstrm_cal((struct cal_block *)data);
 		goto done;
 	case AUDIO_SET_VOCPROC_VOL_CAL:
-		store_vocvol_cal((struct cal_block *)data);
+		result = store_vocvol_cal((struct cal_block *)data);
 		goto done;
 	case AUDIO_SET_VOCPROC_DEV_CFG_CAL:
-		store_vocproc_dev_cfg_cal((struct cal_block *)data);
+		result = store_vocproc_dev_cfg_cal((struct cal_block *)data);
 		goto done;
 	case AUDIO_SET_SIDETONE_CAL:
 		store_sidetone_cal((struct sidetone_cal *)data);
 		goto done;
 	case AUDIO_SET_ANC_CAL:
-		store_anc_cal((struct cal_block *)data);
+		result = store_anc_cal((struct cal_block *)data);
 		goto done;
 	case AUDIO_SET_LSM_CAL:
-		store_lsm_cal((struct cal_block *)data);
+		result = store_lsm_cal((struct cal_block *)data);
 		goto done;
 	case AUDIO_SET_ADM_CUSTOM_TOPOLOGY:
-		store_adm_custom_topology((struct cal_block *)data);
+		result = store_adm_custom_topology((struct cal_block *)data);
 		goto done;
 	case AUDIO_SET_ASM_CUSTOM_TOPOLOGY:
-		store_asm_custom_topology((struct cal_block *)data);
+		result = store_asm_custom_topology((struct cal_block *)data);
 		goto done;
 	case AUDIO_SET_AANC_CAL:
-		store_aanc_cal((struct cal_block *)data);
+		result = store_aanc_cal((struct cal_block *)data);
 		goto done;
 	default:
 		pr_err("ACDB=> ACDB ioctl not found!\n");
+		result = -EFAULT;
+		goto done;
 	}
 
 done:
diff --git a/sound/soc/msm/qdsp6v2/audio_acdb.h b/sound/soc/msm/qdsp6v2/audio_acdb.h
index 3c644ed..1685894 100644
--- a/sound/soc/msm/qdsp6v2/audio_acdb.h
+++ b/sound/soc/msm/qdsp6v2/audio_acdb.h
@@ -48,23 +48,23 @@
 uint32_t get_adm_tx_topology(void);
 uint32_t get_asm_topology(void);
 void reset_custom_topology_flags(void);
-void get_adm_custom_topology(struct acdb_cal_block *cal_block);
-void get_asm_custom_topology(struct acdb_cal_block *cal_block);
-void get_voice_cal_allocation(struct acdb_cal_block *cal_block);
-void get_lsm_cal(struct acdb_cal_block *cal_block);
-void get_anc_cal(struct acdb_cal_block *cal_block);
-void get_afe_cal(int32_t path, struct acdb_cal_block *cal_block);
-void get_audproc_cal(int32_t path, struct acdb_cal_block *cal_block);
-void get_audstrm_cal(int32_t path, struct acdb_cal_block *cal_block);
-void get_audvol_cal(int32_t path, struct acdb_cal_block *cal_block);
-void get_voice_col_data(uint32_t vocproc_type,
+int get_adm_custom_topology(struct acdb_cal_block *cal_block);
+int get_asm_custom_topology(struct acdb_cal_block *cal_block);
+int get_voice_cal_allocation(struct acdb_cal_block *cal_block);
+int get_lsm_cal(struct acdb_cal_block *cal_block);
+int get_anc_cal(struct acdb_cal_block *cal_block);
+int get_afe_cal(int32_t path, struct acdb_cal_block *cal_block);
+int get_audproc_cal(int32_t path, struct acdb_cal_block *cal_block);
+int get_audstrm_cal(int32_t path, struct acdb_cal_block *cal_block);
+int get_audvol_cal(int32_t path, struct acdb_cal_block *cal_block);
+int get_voice_col_data(uint32_t vocproc_type,
 	struct acdb_cal_block *cal_block);
-void get_vocproc_dev_cfg_cal(struct acdb_cal_block *cal_block);
-void get_vocproc_cal(struct acdb_cal_block *cal_block);
-void get_vocstrm_cal(struct acdb_cal_block *cal_block);
-void get_vocvol_cal(struct acdb_cal_block *cal_block);
-void get_sidetone_cal(struct sidetone_cal *cal_data);
-void get_spk_protection_cfg(struct msm_spk_prot_cfg *prot_cfg);
-void get_aanc_cal(struct acdb_cal_block *cal_block);
+int get_vocproc_dev_cfg_cal(struct acdb_cal_block *cal_block);
+int get_vocproc_cal(struct acdb_cal_block *cal_block);
+int get_vocstrm_cal(struct acdb_cal_block *cal_block);
+int get_vocvol_cal(struct acdb_cal_block *cal_block);
+int get_sidetone_cal(struct sidetone_cal *cal_data);
+int get_spk_protection_cfg(struct msm_spk_prot_cfg *prot_cfg);
+int get_aanc_cal(struct acdb_cal_block *cal_block);
 
 #endif
diff --git a/sound/soc/msm/qdsp6v2/msm-compr-q6-v2.c b/sound/soc/msm/qdsp6v2/msm-compr-q6-v2.c
index 687f10d..9f4e189 100644
--- a/sound/soc/msm/qdsp6v2/msm-compr-q6-v2.c
+++ b/sound/soc/msm/qdsp6v2/msm-compr-q6-v2.c
@@ -36,6 +36,7 @@
 #include "msm-compr-q6-v2.h"
 #include "msm-pcm-routing-v2.h"
 #include "audio_ocmem.h"
+#include <sound/tlv.h>
 
 #define COMPRE_CAPTURE_NUM_PERIODS	16
 /* Allocate the worst case frame size for compressed audio */
@@ -48,13 +49,14 @@
 					  COMPRE_CAPTURE_HEADER_SIZE) * \
 					  MAX_NUM_FRAMES_PER_BUFFER)
 #define COMPRE_OUTPUT_METADATA_SIZE	(sizeof(struct output_meta_data_st))
+#define COMPRESSED_LR_VOL_MAX_STEPS	0x20002000
 
+const DECLARE_TLV_DB_LINEAR(compr_rx_vol_gain, 0,
+			    COMPRESSED_LR_VOL_MAX_STEPS);
 struct snd_msm {
-	struct msm_audio *prtd;
-	unsigned volume;
 	atomic_t audio_ocmem_req;
 };
-static struct snd_msm compressed_audio = {NULL, 0x20002000} ;
+static struct snd_msm compressed_audio;
 
 static struct audio_locks the_locks;
 
@@ -609,7 +611,6 @@
 	populate_codec_list(compr, runtime);
 	runtime->private_data = compr;
 	atomic_set(&prtd->eos, 0);
-	compressed_audio.prtd =  &compr->prtd;
 	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
 		if (!atomic_cmpxchg(&compressed_audio.audio_ocmem_req, 0, 1))
 			audio_ocmem_process_req(AUDIO, true);
@@ -621,33 +622,29 @@
 	return 0;
 }
 
-int compressed_set_volume(unsigned volume)
+static int compressed_set_volume(struct msm_audio *prtd, uint32_t volume)
 {
 	int rc = 0;
 	int avg_vol = 0;
 	int lgain = (volume >> 16) & 0xFFFF;
 	int rgain = volume & 0xFFFF;
-	if (compressed_audio.prtd && compressed_audio.prtd->audio_client) {
+	if (prtd && prtd->audio_client) {
 		pr_debug("%s: channels %d volume 0x%x\n", __func__,
-			compressed_audio.prtd->channel_mode, volume);
-		if ((compressed_audio.prtd->channel_mode <= 2) &&
+			prtd->channel_mode, volume);
+		if ((prtd->channel_mode == 2) &&
 			(lgain != rgain)) {
 			pr_debug("%s: call q6asm_set_lrgain\n", __func__);
-			rc = q6asm_set_lrgain(
-				compressed_audio.prtd->audio_client,
-				lgain, rgain);
+			rc = q6asm_set_lrgain(prtd->audio_client, lgain, rgain);
 		} else {
 			avg_vol = (lgain + rgain)/2;
 			pr_debug("%s: call q6asm_set_volume\n", __func__);
-			rc = q6asm_set_volume(
-				compressed_audio.prtd->audio_client, avg_vol);
+			rc = q6asm_set_volume(prtd->audio_client, avg_vol);
 		}
 		if (rc < 0) {
 			pr_err("%s: Send Volume command failed rc=%d\n",
 				__func__, rc);
 		}
 	}
-	compressed_audio.volume = volume;
 	return rc;
 }
 
@@ -673,7 +670,6 @@
 		atomic_read(&compressed_audio.audio_ocmem_req));
 	prtd->pcm_irq_pos = 0;
 	q6asm_cmd(prtd->audio_client, CMD_CLOSE);
-	compressed_audio.prtd = NULL;
 	q6asm_audio_client_buf_free_contiguous(dir,
 				prtd->audio_client);
 		msm_pcm_routing_dereg_phy_stream(
@@ -815,17 +811,15 @@
 		    (params_periods(params) <= runtime->hw.channels_max))
 			prtd->channel_mode = params_channels(params);
 
-		ret = compressed_set_volume(0);
+		ret = compressed_set_volume(prtd, 0);
 		if (ret < 0)
 			pr_err("%s : Set Volume failed : %d", __func__, ret);
 
-		ret = q6asm_set_softpause(compressed_audio.prtd->audio_client,
-								&softpause);
+		ret = q6asm_set_softpause(prtd->audio_client, &softpause);
 		if (ret < 0)
 			pr_err("%s: Send SoftPause Param failed ret=%d\n",
 				__func__, ret);
-		ret = q6asm_set_softvolume(compressed_audio.prtd->audio_client,
-								&softvol);
+		ret = q6asm_set_softvolume(prtd->audio_client, &softvol);
 		if (ret < 0)
 			pr_err("%s: Send SoftVolume Param failed ret=%d\n",
 				__func__, ret);
@@ -1165,6 +1159,66 @@
 	return 0;
 }
 
+static int msm_compr_volume_ctl_put(struct snd_kcontrol *kcontrol,
+				    struct snd_ctl_elem_value *ucontrol)
+{
+	int rc = 0;
+	struct snd_pcm_volume *vol = snd_kcontrol_chip(kcontrol);
+	struct snd_pcm_substream *substream =
+			 vol->pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream;
+	struct msm_audio *prtd;
+	int volume = ucontrol->value.integer.value[0];
+
+	pr_debug("%s: volume : %x\n", __func__, volume);
+	if (!substream)
+		return -ENODEV;
+	if (!substream->runtime)
+		return 0;
+	prtd = substream->runtime->private_data;
+	if (prtd)
+		rc = compressed_set_volume(prtd, volume);
+
+	return rc;
+}
+
+static int msm_compr_volume_ctl_get(struct snd_kcontrol *kcontrol,
+				  struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_pcm_volume *vol = snd_kcontrol_chip(kcontrol);
+	struct snd_pcm_substream *substream =
+			 vol->pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream;
+	struct msm_audio *prtd;
+
+	pr_debug("%s\n", __func__);
+	if (!substream)
+		return -ENODEV;
+	if (!substream->runtime)
+		return 0;
+	prtd = substream->runtime->private_data;
+	if (prtd)
+		ucontrol->value.integer.value[0] = prtd->volume;
+	return 0;
+}
+
+static int msm_compr_add_controls(struct snd_soc_pcm_runtime *rtd)
+{
+	int ret = 0;
+	struct snd_pcm *pcm = rtd->pcm;
+	struct snd_pcm_volume *volume_info;
+	struct snd_kcontrol *kctl;
+
+	dev_dbg(rtd->dev, "%s, Volume cntrl add\n", __func__);
+	ret = snd_pcm_add_volume_ctls(pcm, SNDRV_PCM_STREAM_PLAYBACK,
+				      NULL, 1, rtd->dai_link->be_id,
+				      &volume_info);
+	if (ret < 0)
+		return ret;
+	kctl = volume_info->kctl;
+	kctl->put = msm_compr_volume_ctl_put;
+	kctl->get = msm_compr_volume_ctl_get;
+	kctl->tlv.p = compr_rx_vol_gain;
+	return 0;
+}
 
 static struct snd_pcm_ops msm_compr_ops = {
 	.open	   = msm_compr_open,
@@ -1185,6 +1239,10 @@
 
 	if (!card->dev->coherent_dma_mask)
 		card->dev->coherent_dma_mask = DMA_BIT_MASK(32);
+
+	ret = msm_compr_add_controls(rtd);
+	if (ret)
+		pr_err("%s, kctl add failed\n", __func__);
 	return ret;
 }
 
diff --git a/sound/soc/msm/qdsp6v2/msm-dai-q6-hdmi-v2.c b/sound/soc/msm/qdsp6v2/msm-dai-q6-hdmi-v2.c
index 16df886..0cf044c 100644
--- a/sound/soc/msm/qdsp6v2/msm-dai-q6-hdmi-v2.c
+++ b/sound/soc/msm/qdsp6v2/msm-dai-q6-hdmi-v2.c
@@ -264,11 +264,12 @@
 
 static struct snd_soc_dai_driver msm_dai_q6_hdmi_hdmi_rx_dai = {
 	.playback = {
-		.rates = SNDRV_PCM_RATE_48000,
+		.rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_96000 |
+		 SNDRV_PCM_RATE_192000,
 		.formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE,
 		.channels_min = 2,
 		.channels_max = 8,
-		.rate_max =     48000,
+		.rate_max =     192000,
 		.rate_min =	48000,
 	},
 	.ops = &msm_dai_q6_hdmi_ops,
diff --git a/sound/soc/msm/qdsp6v2/msm-dai-q6-v2.c b/sound/soc/msm/qdsp6v2/msm-dai-q6-v2.c
index 95239a4..1434970 100644
--- a/sound/soc/msm/qdsp6v2/msm-dai-q6-v2.c
+++ b/sound/soc/msm/qdsp6v2/msm-dai-q6-v2.c
@@ -42,6 +42,10 @@
 };
 enum {
 	STATUS_PORT_STARTED, /* track if AFE port has started */
+	/* track AFE Tx port status for bi-directional transfers */
+	STATUS_TX_PORT,
+	/* track AFE Rx port status for bi-directional transfers */
+	STATUS_RX_PORT,
 	STATUS_MAX
 };
 
@@ -70,8 +74,9 @@
 };
 
 struct msm_dai_q6_auxpcm_dai_data {
+	/* BITMAP to track Rx and Tx port usage count */
+	DECLARE_BITMAP(auxpcm_port_status, STATUS_MAX);
 	struct mutex rlock; /* auxpcm dev resource lock */
-	int rcnt; /* auxpcm dev resource usage count */
 	u16 rx_pid; /* AUXPCM RX AFE port ID */
 	u16 tx_pid; /* AUXPCM TX AFE port ID */
 	struct afe_clk_cfg clk_cfg; /* hold LPASS clock configuration */
@@ -116,7 +121,8 @@
 
 	mutex_lock(&aux_dai_data->rlock);
 
-	if (aux_dai_data->rcnt) {
+	if (test_bit(STATUS_TX_PORT, aux_dai_data->auxpcm_port_status) ||
+	    test_bit(STATUS_RX_PORT, aux_dai_data->auxpcm_port_status)) {
 		/* AUXPCM DAI in use */
 		if (dai_data->rate != params_rate(params)) {
 			dev_err(dai->dev, "%s: rate mismatch of running DAI\n",
@@ -184,36 +190,46 @@
 {
 	int rc = 0;
 	struct afe_clk_cfg *lpass_pcm_src_clk = NULL;
-	struct afe_clk_cfg lpass_pcm_oe_clk;
 	struct msm_dai_q6_auxpcm_dai_data *aux_dai_data =
 		dev_get_drvdata(dai->dev);
 
 	mutex_lock(&aux_dai_data->rlock);
 
-	if (aux_dai_data->rcnt == 0) {
-		dev_dbg(dai->dev, "%s(): dai->id %d aux_pcm_count is 0. Just return\n",
+	if (!(test_bit(STATUS_TX_PORT, aux_dai_data->auxpcm_port_status) ||
+	      test_bit(STATUS_RX_PORT, aux_dai_data->auxpcm_port_status))) {
+		dev_dbg(dai->dev, "%s(): dai->id %d PCM ports already closed\n",
 				__func__, dai->id);
-		mutex_unlock(&aux_dai_data->rlock);
-		return;
+		goto exit;
 	}
 
-	aux_dai_data->rcnt--;
-
-	if (aux_dai_data->rcnt > 0) {
-		dev_dbg(dai->dev, "%s(): dai->id %d aux_pcm_count = %d\n",
-			__func__, dai->id, aux_dai_data->rcnt);
-		mutex_unlock(&aux_dai_data->rlock);
-		return;
-	} else if (aux_dai_data->rcnt < 0) {
-		dev_err(dai->dev, "%s(): ERROR: dai->id %d aux_pcm_count = %d < 0\n",
-			__func__, dai->id, aux_dai_data->rcnt);
-		aux_dai_data->rcnt = 0;
-		mutex_unlock(&aux_dai_data->rlock);
-		return;
+	if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
+		if (test_bit(STATUS_TX_PORT, aux_dai_data->auxpcm_port_status))
+			clear_bit(STATUS_TX_PORT,
+				  aux_dai_data->auxpcm_port_status);
+		else {
+			dev_dbg(dai->dev, "%s(): PCM_TX port already closed\n",
+				__func__);
+			goto exit;
+		}
+	} else if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+		if (test_bit(STATUS_RX_PORT, aux_dai_data->auxpcm_port_status))
+			clear_bit(STATUS_RX_PORT,
+				  aux_dai_data->auxpcm_port_status);
+		else {
+			dev_dbg(dai->dev, "%s(): PCM_RX port already closed\n",
+				__func__);
+			goto exit;
+		}
+	}
+	if (test_bit(STATUS_TX_PORT, aux_dai_data->auxpcm_port_status) ||
+	    test_bit(STATUS_RX_PORT, aux_dai_data->auxpcm_port_status)) {
+		dev_dbg(dai->dev, "%s(): cannot shutdown PCM ports\n",
+			__func__);
+		goto exit;
 	}
 
-	dev_dbg(dai->dev, "%s: dai->id = %d aux_pcm_count = %d\n", __func__,
-		dai->id, aux_dai_data->rcnt);
+	dev_dbg(dai->dev, "%s: dai->id = %d closing PCM AFE ports\n",
+			__func__, dai->id);
 
 	lpass_pcm_src_clk = (struct afe_clk_cfg *) &aux_dai_data->clk_cfg;
 
@@ -229,12 +245,9 @@
 	afe_set_lpass_clock(aux_dai_data->rx_pid, lpass_pcm_src_clk);
 	afe_set_lpass_clock(aux_dai_data->tx_pid, lpass_pcm_src_clk);
 
-	memcpy(&lpass_pcm_oe_clk, &lpass_clk_cfg_default,
-			 sizeof(struct afe_clk_cfg));
-	lpass_pcm_oe_clk.clk_val1 = 0;
-	afe_set_lpass_clock(aux_dai_data->rx_pid, &lpass_pcm_oe_clk);
-
+exit:
 	mutex_unlock(&aux_dai_data->rlock);
+	return;
 }
 
 static int msm_dai_q6_auxpcm_prepare(struct snd_pcm_substream *substream,
@@ -246,7 +259,6 @@
 	struct msm_dai_auxpcm_pdata *auxpcm_pdata = NULL;
 	int rc = 0;
 	unsigned long pcm_clk_rate;
-	struct afe_clk_cfg lpass_pcm_oe_clk;
 	struct afe_clk_cfg *lpass_pcm_src_clk = NULL;
 
 	auxpcm_pdata = dai->dev->platform_data;
@@ -254,32 +266,39 @@
 
 	mutex_lock(&aux_dai_data->rlock);
 
-	if (aux_dai_data->rcnt == 2) { /* xrun case ? */
-		dev_dbg(dai->dev, "%s(): dai->id %d aux_pcm_count is 2. Just return.\n",
+	if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
+		if (test_bit(STATUS_TX_PORT,
+				aux_dai_data->auxpcm_port_status)) {
+			dev_dbg(dai->dev, "%s(): PCM_TX port already ON\n",
+				__func__);
+			goto exit;
+		} else
+			set_bit(STATUS_TX_PORT,
+				  aux_dai_data->auxpcm_port_status);
+	} else if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+		if (test_bit(STATUS_RX_PORT,
+				aux_dai_data->auxpcm_port_status)) {
+			dev_dbg(dai->dev, "%s(): PCM_RX port already ON\n",
+				__func__);
+			goto exit;
+		} else
+			set_bit(STATUS_RX_PORT,
+				  aux_dai_data->auxpcm_port_status);
+	}
+	if (test_bit(STATUS_TX_PORT, aux_dai_data->auxpcm_port_status) &&
+	    test_bit(STATUS_RX_PORT, aux_dai_data->auxpcm_port_status)) {
+		dev_dbg(dai->dev, "%s(): PCM ports already set\n", __func__);
+		goto exit;
+	}
+
+	dev_dbg(dai->dev, "%s: dai->id:%d  opening afe ports\n",
 			__func__, dai->id);
-		mutex_unlock(&aux_dai_data->rlock);
-		return 0;
-	} else if (aux_dai_data->rcnt > 2) {
-		dev_err(dai->dev, "%s(): ERROR: dai->id %d aux_pcm_count = %d > 2\n",
-			__func__, dai->id, aux_dai_data->rcnt);
-		mutex_unlock(&aux_dai_data->rlock);
-		return 0;
-	}
-
-	aux_dai_data->rcnt++;
-	if (aux_dai_data->rcnt == 2)  {
-		dev_dbg(dai->dev, "%s(): dai->id %d aux_pcm_count = %d after increment\n",
-				__func__, dai->id, aux_dai_data->rcnt);
-		mutex_unlock(&aux_dai_data->rlock);
-		return 0;
-	}
-
-	dev_dbg(dai->dev, "%s:dai->id:%d  aux_pcm_count = %d. opening afe\n",
-		__func__, dai->id, aux_dai_data->rcnt);
 
 	rc = afe_q6_interface_prepare();
-	if (IS_ERR_VALUE(rc))
+	if (IS_ERR_VALUE(rc)) {
 		dev_err(dai->dev, "fail to open AFE APR\n");
+		goto fail;
+	}
 
 	/*
 	 * For AUX PCM Interface the below sequence of clk
@@ -300,18 +319,14 @@
 	} else {
 		dev_err(dai->dev, "%s: Invalid AUX PCM rate %d\n", __func__,
 			dai_data->rate);
-		mutex_unlock(&aux_dai_data->rlock);
-		return -EINVAL;
+		rc = -EINVAL;
+		goto fail;
 	}
 
 	memcpy(lpass_pcm_src_clk, &lpass_clk_cfg_default,
 			sizeof(struct afe_clk_cfg));
 	lpass_pcm_src_clk->clk_val1 = pcm_clk_rate;
 
-	memcpy(&lpass_pcm_oe_clk, &lpass_clk_cfg_default,
-			sizeof(struct afe_clk_cfg));
-	lpass_pcm_oe_clk.clk_val1 = Q6AFE_LPASS_OSR_CLK_12_P288_MHZ;
-
 	rc = afe_set_lpass_clock(aux_dai_data->rx_pid, lpass_pcm_src_clk);
 	if (rc < 0) {
 		dev_err(dai->dev,
@@ -328,18 +343,17 @@
 		goto fail;
 	}
 
-	rc = afe_set_lpass_clock(aux_dai_data->rx_pid, &lpass_pcm_oe_clk);
-	if (rc < 0) {
-		dev_err(dai->dev,
-			"%s:afe_set_lpass_clock on pcm_oe_clk failed\n",
-			__func__);
-		goto fail;
-	}
-
 	afe_open(aux_dai_data->rx_pid, &dai_data->port_config, dai_data->rate);
 	afe_open(aux_dai_data->tx_pid, &dai_data->port_config, dai_data->rate);
+	goto exit;
 
 fail:
+	if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
+		clear_bit(STATUS_TX_PORT, aux_dai_data->auxpcm_port_status);
+	else if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+		clear_bit(STATUS_RX_PORT, aux_dai_data->auxpcm_port_status);
+
+exit:
 	mutex_unlock(&aux_dai_data->rlock);
 	return rc;
 }
@@ -377,40 +391,30 @@
 {
 	struct msm_dai_q6_auxpcm_dai_data *aux_dai_data;
 	struct afe_clk_cfg *lpass_pcm_src_clk = NULL;
-	struct afe_clk_cfg lpass_pcm_oe_clk;
 	int rc;
 
 	aux_dai_data = dev_get_drvdata(dai->dev);
 
-	if (aux_dai_data->rcnt == 0) {
-		dev_dbg(dai->dev, "%s(): dai->id %d aux_pcm_count is 0. clean up and return\n",
-			__func__, dai->id);
-		goto done;
-	}
-
 	dev_dbg(dai->dev, "%s(): dai->id %d closing afe\n",
 		__func__, dai->id);
 
-	rc = afe_close(aux_dai_data->rx_pid); /* can block */
-	if (IS_ERR_VALUE(rc))
-		dev_err(dai->dev, "fail to close AUX PCM RX AFE port\n");
-
-	rc = afe_close(aux_dai_data->tx_pid);
-	if (IS_ERR_VALUE(rc))
-		dev_err(dai->dev, "fail to close AUX PCM TX AFE port\n");
+	if (test_bit(STATUS_TX_PORT, aux_dai_data->auxpcm_port_status) ||
+	    test_bit(STATUS_RX_PORT, aux_dai_data->auxpcm_port_status)) {
+		rc = afe_close(aux_dai_data->rx_pid); /* can block */
+		if (IS_ERR_VALUE(rc))
+			dev_err(dai->dev, "fail to close AUXPCM RX AFE port\n");
+		rc = afe_close(aux_dai_data->tx_pid);
+		if (IS_ERR_VALUE(rc))
+			dev_err(dai->dev, "fail to close AUXPCM TX AFE port\n");
+		clear_bit(STATUS_TX_PORT, aux_dai_data->auxpcm_port_status);
+		clear_bit(STATUS_RX_PORT, aux_dai_data->auxpcm_port_status);
+	}
 
 	lpass_pcm_src_clk = (struct afe_clk_cfg *) &aux_dai_data->clk_cfg;
-
 	lpass_pcm_src_clk->clk_val1 = 0;
 	afe_set_lpass_clock(aux_dai_data->rx_pid, lpass_pcm_src_clk);
 	afe_set_lpass_clock(aux_dai_data->tx_pid, lpass_pcm_src_clk);
 
-	memcpy(&lpass_pcm_oe_clk, &lpass_clk_cfg_default,
-			 sizeof(struct afe_clk_cfg));
-	lpass_pcm_oe_clk.clk_val1 = 0;
-	afe_set_lpass_clock(aux_dai_data->rx_pid, &lpass_pcm_oe_clk);
-
-done:
 	return 0;
 }
 
@@ -715,6 +719,7 @@
 		rc = msm_dai_q6_afe_rtproxy_hw_params(params, dai);
 		break;
 	case VOICE_PLAYBACK_TX:
+	case VOICE2_PLAYBACK_TX:
 	case VOICE_RECORD_RX:
 	case VOICE_RECORD_TX:
 		rc = msm_dai_q6_psuedo_port_hw_params(params,
@@ -1579,8 +1584,21 @@
 		goto error_invalid_data;
 	}
 	dai_data->rate = params_rate(params);
-	dai_data->port_config.i2s.bit_width = 16;
-	dai_data->bitwidth = 16;
+
+	switch (params_format(params)) {
+	case SNDRV_PCM_FORMAT_S16_LE:
+	case SNDRV_PCM_FORMAT_SPECIAL:
+		dai_data->port_config.i2s.bit_width = 16;
+		dai_data->bitwidth = 16;
+		break;
+	case SNDRV_PCM_FORMAT_S24_LE:
+		dai_data->port_config.i2s.bit_width = 24;
+		dai_data->bitwidth = 24;
+		break;
+	default:
+		return -EINVAL;
+	}
+
 	dai_data->port_config.i2s.i2s_cfg_minor_version =
 			AFE_API_VERSION_I2S_CONFIG;
 	dai_data->port_config.i2s.sample_rate = dai_data->rate;
@@ -1700,7 +1718,7 @@
 	.capture = {
 		.rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_8000 |
 		SNDRV_PCM_RATE_16000,
-		.formats = SNDRV_PCM_FMTBIT_S16_LE,
+		.formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE,
 		.rate_min =     8000,
 		.rate_max =     48000,
 	},
@@ -2021,6 +2039,7 @@
 		rc = snd_soc_register_dai(&pdev->dev, &msm_dai_q6_afe_tx_dai);
 		break;
 	case VOICE_PLAYBACK_TX:
+	case VOICE2_PLAYBACK_TX:
 		rc = snd_soc_register_dai(&pdev->dev,
 					&msm_dai_q6_voice_playback_tx_dai);
 		break;
diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-lpa-v2.c b/sound/soc/msm/qdsp6v2/msm-pcm-lpa-v2.c
index eeb1745..caf77ee 100644
--- a/sound/soc/msm/qdsp6v2/msm-pcm-lpa-v2.c
+++ b/sound/soc/msm/qdsp6v2/msm-pcm-lpa-v2.c
@@ -41,12 +41,15 @@
 #include "msm-pcm-routing-v2.h"
 #include "audio_ocmem.h"
 #include <sound/pcm.h>
+#include <sound/tlv.h>
 
+#define LPA_LR_VOL_MAX_STEPS	0x20002000
+
+const DECLARE_TLV_DB_LINEAR(lpa_rx_vol_gain, 0,
+			    LPA_LR_VOL_MAX_STEPS);
 static struct audio_locks the_locks;
 
 struct snd_msm {
-	struct msm_audio *prtd;
-	unsigned volume;
 	atomic_t audio_ocmem_req;
 };
 static struct snd_msm lpa_audio;
@@ -414,7 +417,6 @@
 	atomic_set(&prtd->stop, 1);
 	atomic_set(&lpa_audio.audio_ocmem_req, 0);
 	runtime->private_data = prtd;
-	lpa_audio.prtd = prtd;
 	if (!atomic_cmpxchg(&lpa_audio.audio_ocmem_req, 0, 1))
 		audio_ocmem_process_req(AUDIO, true);
 	else
@@ -424,19 +426,19 @@
 	return 0;
 }
 
-int lpa_set_volume(unsigned volume)
+static int lpa_set_volume(struct msm_audio *prtd, uint32_t volume)
 {
 	int rc = 0;
-	if (lpa_audio.prtd && lpa_audio.prtd->audio_client) {
-		rc = q6asm_set_lrgain(lpa_audio.prtd->audio_client,
-						(volume >> 16) & 0xFFFF,
-						volume & 0xFFFF);
+	if (prtd && prtd->audio_client) {
+		rc = q6asm_set_lrgain(prtd->audio_client,
+				      (volume >> 16) & 0xFFFF, volume & 0xFFFF);
 		if (rc < 0) {
 			pr_err("%s: Send Volume command failed rc=%d\n",
-					__func__, rc);
+						__func__, rc);
+		} else {
+			prtd->volume = volume;
 		}
 	}
-	lpa_audio.volume = volume;
 	return rc;
 }
 
@@ -476,10 +478,8 @@
 			atomic_dec(&lpa_audio.audio_ocmem_req);
 		else if (atomic_cmpxchg(&lpa_audio.audio_ocmem_req, 1, 0))
 			audio_ocmem_process_req(AUDIO, false);
-
 		pr_debug("%s: req: %d\n", __func__,
 			atomic_read(&lpa_audio.audio_ocmem_req));
-		lpa_audio.prtd = NULL;
 		q6asm_cmd(prtd->audio_client, CMD_CLOSE);
 		q6asm_audio_client_buf_free_contiguous(dir,
 				prtd->audio_client);
@@ -594,12 +594,12 @@
 		prtd->audio_client->perf_mode,
 		prtd->session_id, substream->stream);
 
-	lpa_set_volume(0);
-	ret = q6asm_set_softpause(lpa_audio.prtd->audio_client, &softpause);
+	lpa_set_volume(prtd, 0);
+	ret = q6asm_set_softpause(prtd->audio_client, &softpause);
 	if (ret < 0)
 		pr_err("%s: Send SoftPause Param failed ret=%d\n",
 			__func__, ret);
-	ret = q6asm_set_softvolume(lpa_audio.prtd->audio_client, &softvol);
+	ret = q6asm_set_softvolume(prtd->audio_client, &softvol);
 	if (ret < 0)
 		pr_err("%s: Send SoftVolume Param failed ret=%d\n",
 			__func__, ret);
@@ -695,6 +695,67 @@
 	return snd_pcm_lib_ioctl(substream, cmd, arg);
 }
 
+static int msm_lpa_volume_ctl_put(struct snd_kcontrol *kcontrol,
+				  struct snd_ctl_elem_value *ucontrol)
+{
+	int rc = 0;
+	struct snd_pcm_volume *vol = snd_kcontrol_chip(kcontrol);
+	struct snd_pcm_substream *substream =
+			 vol->pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream;
+	struct msm_audio *prtd;
+	int volume = ucontrol->value.integer.value[0];
+
+	pr_debug("%s: volume : %x\n", __func__, volume);
+	if (!substream)
+		return -ENODEV;
+	if (!substream->runtime)
+		return 0;
+	prtd = substream->runtime->private_data;
+	if (prtd)
+		rc = lpa_set_volume(prtd, volume);
+
+	return rc;
+}
+
+static int msm_lpa_volume_ctl_get(struct snd_kcontrol *kcontrol,
+				  struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_pcm_volume *vol = snd_kcontrol_chip(kcontrol);
+	struct snd_pcm_substream *substream =
+			 vol->pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream;
+	struct msm_audio *prtd;
+
+	pr_debug("%s\n", __func__);
+	if (!substream)
+		return -ENODEV;
+	if (!substream->runtime)
+		return 0;
+	prtd = substream->runtime->private_data;
+	if (prtd)
+		ucontrol->value.integer.value[0] = prtd->volume;
+	return 0;
+}
+
+static int msm_lpa_add_controls(struct snd_soc_pcm_runtime *rtd)
+{
+	int ret = 0;
+	struct snd_pcm *pcm = rtd->pcm->streams[0].pcm;
+	struct snd_pcm_volume *volume_info;
+	struct snd_kcontrol *kctl;
+
+	dev_dbg(rtd->dev, "%s, Volume cntrl add\n", __func__);
+	ret = snd_pcm_add_volume_ctls(pcm, SNDRV_PCM_STREAM_PLAYBACK,
+				      NULL, 1, rtd->dai_link->be_id,
+				      &volume_info);
+	if (ret < 0)
+		return ret;
+	kctl = volume_info->kctl;
+	kctl->put = msm_lpa_volume_ctl_put;
+	kctl->get = msm_lpa_volume_ctl_get;
+	kctl->tlv.p = lpa_rx_vol_gain;
+	return 0;
+}
+
 static struct snd_pcm_ops msm_pcm_ops = {
 	.open           = msm_pcm_open,
 	.hw_params	= msm_pcm_hw_params,
@@ -714,6 +775,10 @@
 
 	if (!card->dev->coherent_dma_mask)
 		card->dev->coherent_dma_mask = DMA_BIT_MASK(32);
+
+	ret = msm_lpa_add_controls(rtd);
+	if (ret)
+		pr_err("%s, kctl add failed\n", __func__);
 	return ret;
 }
 
diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.c b/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.c
index 11f9e72..49bc488 100644
--- a/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.c
+++ b/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.c
@@ -57,7 +57,8 @@
 				SNDRV_PCM_INFO_MMAP_VALID |
 				SNDRV_PCM_INFO_INTERLEAVED |
 				SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME),
-	.formats =              SNDRV_PCM_FMTBIT_S16_LE,
+	.formats =              (SNDRV_PCM_FMTBIT_S16_LE |
+				SNDRV_PCM_FMTBIT_S24_LE),
 	.rates =                SNDRV_PCM_RATE_8000_48000,
 	.rate_min =             8000,
 	.rate_max =             48000,
@@ -254,6 +255,8 @@
 	struct msm_audio *prtd = runtime->private_data;
 	int ret = 0;
 	int i = 0;
+	uint16_t bits_per_sample = 16;
+
 	pr_debug("%s\n", __func__);
 	prtd->pcm_size = snd_pcm_lib_buffer_bytes(substream);
 	prtd->pcm_count = snd_pcm_lib_period_bytes(substream);
@@ -266,10 +269,19 @@
 	if (prtd->enabled)
 		return 0;
 
+	switch (runtime->format) {
+	case SNDRV_PCM_FORMAT_S16_LE:
+		bits_per_sample = 16;
+		break;
+	case SNDRV_PCM_FORMAT_S24_LE:
+		bits_per_sample = 24;
+		break;
+	}
 	pr_debug("Samp_rate = %d\n", prtd->samp_rate);
 	pr_debug("Channel = %d\n", prtd->channel_mode);
-	ret = q6asm_enc_cfg_blk_pcm(prtd->audio_client, prtd->samp_rate,
-					prtd->channel_mode);
+	ret = q6asm_enc_cfg_blk_pcm_format_support(prtd->audio_client,
+					prtd->samp_rate, prtd->channel_mode,
+					bits_per_sample);
 	if (ret < 0)
 		pr_debug("%s: cmd cfg pcm was block failed", __func__);
 
@@ -694,10 +706,13 @@
 
 	/* Capture Path */
 	if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
+		if (params_format(params) == SNDRV_PCM_FORMAT_S24_LE)
+			bits_per_sample = 24;
 
 		pr_debug("%s Opening %d-ch PCM read stream\n",
 			__func__, params_channels(params));
-		ret = q6asm_open_read(prtd->audio_client, FORMAT_LINEAR_PCM);
+		ret = q6asm_open_read_v2(prtd->audio_client, FORMAT_LINEAR_PCM,
+				bits_per_sample);
 		if (ret < 0) {
 			pr_err("%s: q6asm_open_read failed\n", __func__);
 			q6asm_audio_client_free(prtd->audio_client);
diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.h b/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.h
index 6ded0d9..f7719ed 100644
--- a/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.h
+++ b/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.h
@@ -86,6 +86,7 @@
 	char channel_map[8];
 	int cmd_interrupt;
 	bool meta_data_mode;
+	uint32_t volume;
 };
 
 struct output_meta_data_st {
diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c b/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c
index 97803b3..76a525d 100644
--- a/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c
+++ b/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c
@@ -40,7 +40,10 @@
 	u16 port_id; /* AFE port ID */
 	u8 active; /* track if this backend is enabled */
 	unsigned long fe_sessions; /* Front-end sessions */
-	unsigned long port_sessions; /* track Tx BE ports -> Rx BE */
+	u64 port_sessions; /* track Tx BE ports -> Rx BE
+			    * number of BE should not exceed
+			    * the size of this field
+			    */
 	unsigned int  sample_rate;
 	unsigned int  channel;
 	unsigned int  format;
@@ -82,23 +85,14 @@
 
 #define INT_RX_VOL_MAX_STEPS 0x2000
 #define INT_RX_VOL_GAIN 0x2000
-#define INT_RX_LR_VOL_MAX_STEPS 0x20002000
 static int msm_route_fm_vol_control;
 static const DECLARE_TLV_DB_LINEAR(fm_rx_vol_gain, 0,
 			INT_RX_VOL_MAX_STEPS);
 
-static int msm_route_lpa_vol_control;
-static const DECLARE_TLV_DB_LINEAR(lpa_rx_vol_gain, 0,
-			INT_RX_LR_VOL_MAX_STEPS);
-
 static int msm_route_multimedia2_vol_control;
 static const DECLARE_TLV_DB_LINEAR(multimedia2_rx_vol_gain, 0,
 			INT_RX_VOL_MAX_STEPS);
 
-static int msm_route_compressed_vol_control;
-static const DECLARE_TLV_DB_LINEAR(compressed_rx_vol_gain, 0,
-			INT_RX_LR_VOL_MAX_STEPS);
-
 static int msm_route_multimedia5_vol_control;
 static const DECLARE_TLV_DB_LINEAR(multimedia5_rx_vol_gain, 0,
 			INT_RX_VOL_MAX_STEPS);
@@ -217,6 +211,7 @@
 	{ AFE_PORT_ID_PRIMARY_PCM_RX, 0, 0, 0, 0, 0},
 	{ AFE_PORT_ID_PRIMARY_PCM_TX, 0, 0, 0, 0, 0},
 	{ VOICE_PLAYBACK_TX, 0, 0, 0, 0, 0},
+	{ VOICE2_PLAYBACK_TX, 0, 0, 0, 0, 0},
 	{ VOICE_RECORD_RX, 0, 0, 0, 0, 0},
 	{ VOICE_RECORD_TX, 0, 0, 0, 0, 0},
 	{ MI2S_RX, 0, 0, 0, 0, 0},
@@ -264,6 +259,8 @@
 	{INVALID_SESSION, INVALID_SESSION},
 	/* MULTIMEDIA8 */
 	{INVALID_SESSION, INVALID_SESSION},
+	/* MULTIMEDIA9 */
+	{INVALID_SESSION, INVALID_SESSION},
 };
 
 static uint8_t is_be_dai_extproc(int be_dai)
@@ -511,8 +508,9 @@
 	topology = get_topology(path_type);
 	if (set) {
 		if (!test_bit(val, &msm_bedais[reg].fe_sessions) &&
-			(msm_bedais[reg].port_id == VOICE_PLAYBACK_TX))
-			voc_start_playback(set);
+			((msm_bedais[reg].port_id == VOICE_PLAYBACK_TX) ||
+			(msm_bedais[reg].port_id == VOICE2_PLAYBACK_TX)))
+			voc_start_playback(set, msm_bedais[reg].port_id);
 		set_bit(val, &msm_bedais[reg].fe_sessions);
 		if (msm_bedais[reg].active && fe_dai_map[val][session_type] !=
 			INVALID_SESSION) {
@@ -555,8 +553,9 @@
 		}
 	} else {
 		if (test_bit(val, &msm_bedais[reg].fe_sessions) &&
-			(msm_bedais[reg].port_id == VOICE_PLAYBACK_TX))
-			voc_start_playback(set);
+			((msm_bedais[reg].port_id == VOICE_PLAYBACK_TX) ||
+			(msm_bedais[reg].port_id == VOICE2_PLAYBACK_TX)))
+			voc_start_playback(set, msm_bedais[reg].port_id);
 		clear_bit(val, &msm_bedais[reg].fe_sessions);
 		if (msm_bedais[reg].active && fe_dai_map[val][session_type] !=
 			INVALID_SESSION) {
@@ -970,7 +969,8 @@
 	struct soc_mixer_control *mc =
 	(struct soc_mixer_control *)kcontrol->private_value;
 
-	if (test_bit(mc->shift, &msm_bedais[mc->reg].port_sessions))
+	if (test_bit(mc->shift,
+		(unsigned long *)&msm_bedais[mc->reg].port_sessions))
 		ucontrol->value.integer.value[0] = 1;
 	else
 		ucontrol->value.integer.value[0] = 0;
@@ -987,19 +987,19 @@
 	struct soc_mixer_control *mc =
 		(struct soc_mixer_control *)kcontrol->private_value;
 
-	pr_debug("%s: reg %x shift %x val %ld\n", __func__, mc->reg,
+	pr_debug("%s: reg 0x%x shift 0x%x val %ld\n", __func__, mc->reg,
 		mc->shift, ucontrol->value.integer.value[0]);
 
 	if (ucontrol->value.integer.value[0]) {
 		afe_loopback(1, msm_bedais[mc->reg].port_id,
 			    msm_bedais[mc->shift].port_id);
 		set_bit(mc->shift,
-		&msm_bedais[mc->reg].port_sessions);
+		(unsigned long *)&msm_bedais[mc->reg].port_sessions);
 	} else {
 		afe_loopback(0, msm_bedais[mc->reg].port_id,
 			    msm_bedais[mc->shift].port_id);
 		clear_bit(mc->shift,
-		&msm_bedais[mc->reg].port_sessions);
+		(unsigned long *)&msm_bedais[mc->reg].port_sessions);
 	}
 
 	return 1;
@@ -1022,23 +1022,6 @@
 	return 0;
 }
 
-static int msm_routing_get_lpa_vol_mixer(struct snd_kcontrol *kcontrol,
-				struct snd_ctl_elem_value *ucontrol)
-{
-	ucontrol->value.integer.value[0] = msm_route_lpa_vol_control;
-	return 0;
-}
-
-static int msm_routing_set_lpa_vol_mixer(struct snd_kcontrol *kcontrol,
-				struct snd_ctl_elem_value *ucontrol)
-{
-	if (!lpa_set_volume(ucontrol->value.integer.value[0]))
-		msm_route_lpa_vol_control =
-			ucontrol->value.integer.value[0];
-
-	return 0;
-}
-
 static int msm_routing_get_multimedia2_vol_mixer(struct snd_kcontrol *kcontrol,
 				struct snd_ctl_elem_value *ucontrol)
 {
@@ -1077,24 +1060,6 @@
 	return 0;
 }
 
-static int msm_routing_get_compressed_vol_mixer(struct snd_kcontrol *kcontrol,
-				struct snd_ctl_elem_value *ucontrol)
-{
-
-	ucontrol->value.integer.value[0] = msm_route_compressed_vol_control;
-	return 0;
-}
-
-static int msm_routing_set_compressed_vol_mixer(struct snd_kcontrol *kcontrol,
-				struct snd_ctl_elem_value *ucontrol)
-{
-	if (!compressed_set_volume(ucontrol->value.integer.value[0]))
-		msm_route_compressed_vol_control =
-			ucontrol->value.integer.value[0];
-
-	return 0;
-}
-
 static int msm_routing_get_channel_map_mixer(struct snd_kcontrol *kcontrol,
 					struct snd_ctl_elem_value *ucontrol)
 {
@@ -1418,6 +1383,9 @@
 	SOC_SINGLE_EXT("MultiMedia8", MSM_BACKEND_DAI_PRI_I2S_RX,
 	MSM_FRONTEND_DAI_MULTIMEDIA8, 1, 0, msm_routing_get_audio_mixer,
 	msm_routing_put_audio_mixer),
+	SOC_SINGLE_EXT("MultiMedia9", MSM_BACKEND_DAI_PRI_I2S_RX,
+	MSM_FRONTEND_DAI_MULTIMEDIA9, 1, 0, msm_routing_get_audio_mixer,
+	msm_routing_put_audio_mixer),
 };
 
 static const struct snd_kcontrol_new sec_i2s_rx_mixer_controls[] = {
@@ -1445,6 +1413,9 @@
 	SOC_SINGLE_EXT("MultiMedia8", MSM_BACKEND_DAI_SEC_I2S_RX,
 	MSM_FRONTEND_DAI_MULTIMEDIA8, 1, 0, msm_routing_get_audio_mixer,
 	msm_routing_put_audio_mixer),
+	SOC_SINGLE_EXT("MultiMedia9", MSM_BACKEND_DAI_SEC_I2S_RX,
+	MSM_FRONTEND_DAI_MULTIMEDIA9, 1, 0, msm_routing_get_audio_mixer,
+	msm_routing_put_audio_mixer),
 };
 
 static const struct snd_kcontrol_new slimbus_rx_mixer_controls[] = {
@@ -1472,6 +1443,9 @@
 	SOC_SINGLE_EXT("MultiMedia8", MSM_BACKEND_DAI_SLIMBUS_0_RX,
 	MSM_FRONTEND_DAI_MULTIMEDIA8, 1, 0, msm_routing_get_audio_mixer,
 	msm_routing_put_audio_mixer),
+	SOC_SINGLE_EXT("MultiMedia9", MSM_BACKEND_DAI_SLIMBUS_0_RX,
+	MSM_FRONTEND_DAI_MULTIMEDIA9, 1, 0, msm_routing_get_audio_mixer,
+	msm_routing_put_audio_mixer),
 };
 
 static const struct snd_kcontrol_new mi2s_rx_mixer_controls[] = {
@@ -1499,6 +1473,9 @@
 	SOC_SINGLE_EXT("MultiMedia8", MSM_BACKEND_DAI_MI2S_RX,
 	MSM_FRONTEND_DAI_MULTIMEDIA8, 1, 0, msm_routing_get_audio_mixer,
 	msm_routing_put_audio_mixer),
+	SOC_SINGLE_EXT("MultiMedia9", MSM_BACKEND_DAI_MI2S_RX,
+	MSM_FRONTEND_DAI_MULTIMEDIA9, 1, 0, msm_routing_get_audio_mixer,
+	msm_routing_put_audio_mixer),
 };
 
 static const struct snd_kcontrol_new quaternary_mi2s_rx_mixer_controls[] = {
@@ -1526,6 +1503,9 @@
 	SOC_SINGLE_EXT("MultiMedia8", MSM_BACKEND_DAI_QUATERNARY_MI2S_RX,
 	MSM_FRONTEND_DAI_MULTIMEDIA8, 1, 0, msm_routing_get_audio_mixer,
 	msm_routing_put_audio_mixer),
+	SOC_SINGLE_EXT("MultiMedia9", MSM_BACKEND_DAI_QUATERNARY_MI2S_RX,
+	MSM_FRONTEND_DAI_MULTIMEDIA9, 1, 0, msm_routing_get_audio_mixer,
+	msm_routing_put_audio_mixer),
 };
 
 static const struct snd_kcontrol_new tertiary_mi2s_rx_mixer_controls[] = {
@@ -1568,6 +1548,9 @@
 	SOC_SINGLE_EXT("MultiMedia8", MSM_BACKEND_DAI_SECONDARY_MI2S_RX,
 	MSM_FRONTEND_DAI_MULTIMEDIA8, 1, 0, msm_routing_get_audio_mixer,
 	msm_routing_put_audio_mixer),
+	SOC_SINGLE_EXT("MultiMedia9", MSM_BACKEND_DAI_SECONDARY_MI2S_RX,
+	MSM_FRONTEND_DAI_MULTIMEDIA9, 1, 0, msm_routing_get_audio_mixer,
+	msm_routing_put_audio_mixer),
 };
 
 static const struct snd_kcontrol_new mi2s_hl_mixer_controls[] = {
@@ -1604,6 +1587,9 @@
 	SOC_SINGLE_EXT("MultiMedia8", MSM_BACKEND_DAI_PRI_MI2S_RX,
 	MSM_FRONTEND_DAI_MULTIMEDIA8, 1, 0, msm_routing_get_audio_mixer,
 	msm_routing_put_audio_mixer),
+	SOC_SINGLE_EXT("MultiMedia9", MSM_BACKEND_DAI_PRI_MI2S_RX,
+	MSM_FRONTEND_DAI_MULTIMEDIA9, 1, 0, msm_routing_get_audio_mixer,
+	msm_routing_put_audio_mixer),
 };
 
 static const struct snd_kcontrol_new hdmi_mixer_controls[] = {
@@ -1631,6 +1617,9 @@
 	SOC_SINGLE_EXT("MultiMedia8", MSM_BACKEND_DAI_HDMI_RX,
 	MSM_FRONTEND_DAI_MULTIMEDIA8, 1, 0, msm_routing_get_audio_mixer,
 	msm_routing_put_audio_mixer),
+	SOC_SINGLE_EXT("MultiMedia9", MSM_BACKEND_DAI_HDMI_RX,
+	MSM_FRONTEND_DAI_MULTIMEDIA9, 1, 0, msm_routing_get_audio_mixer,
+	msm_routing_put_audio_mixer),
 };
 	/* incall music delivery mixer */
 static const struct snd_kcontrol_new incall_music_delivery_mixer_controls[] = {
@@ -1640,6 +1629,21 @@
 	SOC_SINGLE_EXT("MultiMedia2", MSM_BACKEND_DAI_VOICE_PLAYBACK_TX,
 	MSM_FRONTEND_DAI_MULTIMEDIA2, 1, 0, msm_routing_get_audio_mixer,
 	msm_routing_put_audio_mixer),
+	SOC_SINGLE_EXT("MultiMedia9", MSM_BACKEND_DAI_VOICE_PLAYBACK_TX,
+	MSM_FRONTEND_DAI_MULTIMEDIA9, 1, 0, msm_routing_get_audio_mixer,
+	msm_routing_put_audio_mixer),
+};
+
+static const struct snd_kcontrol_new incall_music2_delivery_mixer_controls[] = {
+	SOC_SINGLE_EXT("MultiMedia1", MSM_BACKEND_DAI_VOICE2_PLAYBACK_TX,
+	MSM_FRONTEND_DAI_MULTIMEDIA1, 1, 0, msm_routing_get_audio_mixer,
+	msm_routing_put_audio_mixer),
+	SOC_SINGLE_EXT("MultiMedia2", MSM_BACKEND_DAI_VOICE2_PLAYBACK_TX,
+	MSM_FRONTEND_DAI_MULTIMEDIA2, 1, 0, msm_routing_get_audio_mixer,
+	msm_routing_put_audio_mixer),
+	SOC_SINGLE_EXT("MultiMedia9", MSM_BACKEND_DAI_VOICE2_PLAYBACK_TX,
+	MSM_FRONTEND_DAI_MULTIMEDIA9, 1, 0, msm_routing_get_audio_mixer,
+	msm_routing_put_audio_mixer),
 };
 
 static const struct snd_kcontrol_new slimbus_4_rx_mixer_controls[] = {
@@ -1676,6 +1680,9 @@
 	SOC_SINGLE_EXT("MultiMedia8", MSM_BACKEND_DAI_INT_BT_SCO_RX,
 	MSM_FRONTEND_DAI_MULTIMEDIA8, 1, 0, msm_routing_get_audio_mixer,
 	msm_routing_put_audio_mixer),
+	SOC_SINGLE_EXT("MultiMedia9", MSM_BACKEND_DAI_INT_BT_SCO_RX,
+	MSM_FRONTEND_DAI_MULTIMEDIA9, 1, 0, msm_routing_get_audio_mixer,
+	msm_routing_put_audio_mixer),
 };
 
 static const struct snd_kcontrol_new int_fm_rx_mixer_controls[] = {
@@ -1703,6 +1710,9 @@
 	SOC_SINGLE_EXT("MultiMedia8", MSM_BACKEND_DAI_INT_FM_RX,
 	MSM_FRONTEND_DAI_MULTIMEDIA8, 1, 0, msm_routing_get_audio_mixer,
 	msm_routing_put_audio_mixer),
+	SOC_SINGLE_EXT("MultiMedia9", MSM_BACKEND_DAI_INT_FM_RX,
+	MSM_FRONTEND_DAI_MULTIMEDIA9, 1, 0, msm_routing_get_audio_mixer,
+	msm_routing_put_audio_mixer),
 };
 
 static const struct snd_kcontrol_new afe_pcm_rx_mixer_controls[] = {
@@ -1730,6 +1740,9 @@
 	SOC_SINGLE_EXT("MultiMedia8", MSM_BACKEND_DAI_AFE_PCM_RX,
 	MSM_FRONTEND_DAI_MULTIMEDIA8, 1, 0, msm_routing_get_audio_mixer,
 	msm_routing_put_audio_mixer),
+	SOC_SINGLE_EXT("MultiMedia9", MSM_BACKEND_DAI_AFE_PCM_RX,
+	MSM_FRONTEND_DAI_MULTIMEDIA9, 1, 0, msm_routing_get_audio_mixer,
+	msm_routing_put_audio_mixer),
 };
 
 static const struct snd_kcontrol_new auxpcm_rx_mixer_controls[] = {
@@ -1757,6 +1770,9 @@
 	SOC_SINGLE_EXT("MultiMedia8", MSM_BACKEND_DAI_AUXPCM_RX,
 	MSM_FRONTEND_DAI_MULTIMEDIA8, 1, 0, msm_routing_get_audio_mixer,
 	msm_routing_put_audio_mixer),
+	SOC_SINGLE_EXT("MultiMedia9", MSM_BACKEND_DAI_AUXPCM_RX,
+	MSM_FRONTEND_DAI_MULTIMEDIA9, 1, 0, msm_routing_get_audio_mixer,
+	msm_routing_put_audio_mixer),
 };
 
 static const struct snd_kcontrol_new sec_auxpcm_rx_mixer_controls[] = {
@@ -1784,6 +1800,9 @@
 	SOC_SINGLE_EXT("MultiMedia8", MSM_BACKEND_DAI_SEC_AUXPCM_RX,
 	MSM_FRONTEND_DAI_MULTIMEDIA8, 1, 0, msm_routing_get_audio_mixer,
 	msm_routing_put_audio_mixer),
+	SOC_SINGLE_EXT("MultiMedia9", MSM_BACKEND_DAI_SEC_AUXPCM_RX,
+	MSM_FRONTEND_DAI_MULTIMEDIA9, 1, 0, msm_routing_get_audio_mixer,
+	msm_routing_put_audio_mixer),
 };
 
 static const struct snd_kcontrol_new mmul1_mixer_controls[] = {
@@ -2141,6 +2160,9 @@
 	SOC_SINGLE_EXT("AUX_PCM_TX_Voice2", MSM_BACKEND_DAI_AUXPCM_TX,
 	MSM_FRONTEND_DAI_VOICE2, 1, 0, msm_routing_get_voice_mixer,
 	msm_routing_put_voice_mixer),
+	SOC_SINGLE_EXT("PRI_MI2S_TX_Voice2", MSM_BACKEND_DAI_PRI_MI2S_TX,
+	MSM_FRONTEND_DAI_VOICE2, 1, 0, msm_routing_get_voice_mixer,
+	msm_routing_put_voice_mixer),
 };
 
 static const struct snd_kcontrol_new tx_volte_mixer_controls[] = {
@@ -2381,12 +2403,6 @@
 	msm_routing_set_fm_vol_mixer, fm_rx_vol_gain),
 };
 
-static const struct snd_kcontrol_new lpa_vol_mixer_controls[] = {
-	SOC_SINGLE_EXT_TLV("LPA RX Volume", SND_SOC_NOPM, 0,
-	INT_RX_VOL_GAIN, 0, msm_routing_get_lpa_vol_mixer,
-	msm_routing_set_lpa_vol_mixer, lpa_rx_vol_gain),
-};
-
 static const struct snd_kcontrol_new multimedia2_vol_mixer_controls[] = {
 	SOC_SINGLE_EXT_TLV("HIFI2 RX Volume", SND_SOC_NOPM, 0,
 	INT_RX_VOL_GAIN, 0, msm_routing_get_multimedia2_vol_mixer,
@@ -2399,12 +2415,6 @@
 	msm_routing_set_multimedia5_vol_mixer, multimedia5_rx_vol_gain),
 };
 
-static const struct snd_kcontrol_new compressed_vol_mixer_controls[] = {
-	SOC_SINGLE_EXT_TLV("COMPRESSED RX Volume", SND_SOC_NOPM, 0,
-	INT_RX_VOL_GAIN, 0, msm_routing_get_compressed_vol_mixer,
-	msm_routing_set_compressed_vol_mixer, compressed_rx_vol_gain),
-};
-
 static const struct snd_kcontrol_new multi_ch_channel_map_mixer_controls[] = {
 	SOC_SINGLE_MULTI_EXT("Playback Channel Map", SND_SOC_NOPM, 0, 16,
 	0, 8, msm_routing_get_channel_map_mixer,
@@ -2763,11 +2773,13 @@
 	SND_SOC_DAPM_AIF_IN("MM_DL6", "MultiMedia6 Playback", 0, 0, 0, 0),
 	SND_SOC_DAPM_AIF_IN("MM_DL7", "MultiMedia7 Playback", 0, 0, 0, 0),
 	SND_SOC_DAPM_AIF_IN("MM_DL8", "MultiMedia8 Playback", 0, 0, 0, 0),
+	SND_SOC_DAPM_AIF_IN("MM_DL9", "MultiMedia9 Playback", 0, 0, 0, 0),
 	SND_SOC_DAPM_AIF_IN("VOIP_DL", "VoIP Playback", 0, 0, 0, 0),
 	SND_SOC_DAPM_AIF_OUT("MM_UL1", "MultiMedia1 Capture", 0, 0, 0, 0),
 	SND_SOC_DAPM_AIF_OUT("MM_UL2", "MultiMedia2 Capture", 0, 0, 0, 0),
 	SND_SOC_DAPM_AIF_OUT("MM_UL4", "MultiMedia4 Capture", 0, 0, 0, 0),
 	SND_SOC_DAPM_AIF_OUT("MM_UL5", "MultiMedia5 Capture", 0, 0, 0, 0),
+	SND_SOC_DAPM_AIF_OUT("MM_UL9", "MultiMedia9 Capture", 0, 0, 0, 0),
 	SND_SOC_DAPM_AIF_IN("CS-VOICE_DL1", "CS-VOICE Playback", 0, 0, 0, 0),
 	SND_SOC_DAPM_AIF_OUT("CS-VOICE_UL1", "CS-VOICE Capture", 0, 0, 0, 0),
 	SND_SOC_DAPM_AIF_IN("VOICE2_DL", "Voice2 Playback", 0, 0, 0, 0),
@@ -2862,6 +2874,8 @@
 	/* incall */
 	SND_SOC_DAPM_AIF_OUT("VOICE_PLAYBACK_TX", "Voice Farend Playback",
 				0, 0, 0 , 0),
+	SND_SOC_DAPM_AIF_OUT("VOICE2_PLAYBACK_TX", "Voice2 Farend Playback",
+				0, 0, 0 , 0),
 	SND_SOC_DAPM_AIF_OUT("SLIMBUS_4_RX", "Slimbus4 Playback",
 				0, 0, 0 , 0),
 	SND_SOC_DAPM_AIF_IN("INCALL_RECORD_TX", "Voice Uplink Capture",
@@ -2945,11 +2959,14 @@
 	sec_auxpcm_rx_mixer_controls, ARRAY_SIZE(sec_auxpcm_rx_mixer_controls)),
 	/* incall */
 	SND_SOC_DAPM_MIXER("Incall_Music Audio Mixer", SND_SOC_NOPM, 0, 0,
-			incall_music_delivery_mixer_controls,
-			ARRAY_SIZE(incall_music_delivery_mixer_controls)),
+	incall_music_delivery_mixer_controls,
+	ARRAY_SIZE(incall_music_delivery_mixer_controls)),
+	SND_SOC_DAPM_MIXER("Incall_Music_2 Audio Mixer", SND_SOC_NOPM, 0, 0,
+	incall_music2_delivery_mixer_controls,
+	ARRAY_SIZE(incall_music2_delivery_mixer_controls)),
 	SND_SOC_DAPM_MIXER("SLIMBUS_4_RX Audio Mixer", SND_SOC_NOPM, 0, 0,
-			slimbus_4_rx_mixer_controls,
-			ARRAY_SIZE(slimbus_4_rx_mixer_controls)),
+	slimbus_4_rx_mixer_controls,
+	ARRAY_SIZE(slimbus_4_rx_mixer_controls)),
 	/* Voice Mixer */
 	SND_SOC_DAPM_MIXER("PRI_RX_Voice Mixer",
 				SND_SOC_NOPM, 0, 0, pri_rx_voice_mixer_controls,
@@ -3066,6 +3083,7 @@
 	{"PRI_RX Audio Mixer", "MultiMedia6", "MM_DL6"},
 	{"PRI_RX Audio Mixer", "MultiMedia7", "MM_DL7"},
 	{"PRI_RX Audio Mixer", "MultiMedia8", "MM_DL8"},
+	{"PRI_RX Audio Mixer", "MultiMedia9", "MM_DL9"},
 	{"PRI_I2S_RX", NULL, "PRI_RX Audio Mixer"},
 
 	{"SEC_RX Audio Mixer", "MultiMedia1", "MM_DL1"},
@@ -3076,6 +3094,7 @@
 	{"SEC_RX Audio Mixer", "MultiMedia6", "MM_DL6"},
 	{"SEC_RX Audio Mixer", "MultiMedia7", "MM_DL7"},
 	{"SEC_RX Audio Mixer", "MultiMedia8", "MM_DL8"},
+	{"SEC_RX Audio Mixer", "MultiMedia9", "MM_DL9"},
 	{"SEC_I2S_RX", NULL, "SEC_RX Audio Mixer"},
 
 	{"SLIMBUS_0_RX Audio Mixer", "MultiMedia1", "MM_DL1"},
@@ -3086,6 +3105,7 @@
 	{"SLIMBUS_0_RX Audio Mixer", "MultiMedia6", "MM_DL6"},
 	{"SLIMBUS_0_RX Audio Mixer", "MultiMedia7", "MM_DL7"},
 	{"SLIMBUS_0_RX Audio Mixer", "MultiMedia8", "MM_DL8"},
+	{"SLIMBUS_0_RX Audio Mixer", "MultiMedia9", "MM_DL9"},
 	{"SLIMBUS_0_RX", NULL, "SLIMBUS_0_RX Audio Mixer"},
 
 	{"HDMI Mixer", "MultiMedia1", "MM_DL1"},
@@ -3096,12 +3116,18 @@
 	{"HDMI Mixer", "MultiMedia6", "MM_DL6"},
 	{"HDMI Mixer", "MultiMedia7", "MM_DL7"},
 	{"HDMI Mixer", "MultiMedia8", "MM_DL8"},
+	{"HDMI Mixer", "MultiMedia9", "MM_DL9"},
 	{"HDMI", NULL, "HDMI Mixer"},
 
 		/* incall */
 	{"Incall_Music Audio Mixer", "MultiMedia1", "MM_DL1"},
 	{"Incall_Music Audio Mixer", "MultiMedia2", "MM_DL2"},
+	{"Incall_Music Audio Mixer", "MultiMedia9", "MM_DL9"},
 	{"VOICE_PLAYBACK_TX", NULL, "Incall_Music Audio Mixer"},
+	{"Incall_Music_2 Audio Mixer", "MultiMedia1", "MM_DL1"},
+	{"Incall_Music_2 Audio Mixer", "MultiMedia2", "MM_DL2"},
+	{"Incall_Music_2 Audio Mixer", "MultiMedia9", "MM_DL9"},
+	{"VOICE2_PLAYBACK_TX", NULL, "Incall_Music_2 Audio Mixer"},
 	{"SLIMBUS_4_RX Audio Mixer", "MultiMedia1", "MM_DL1"},
 	{"SLIMBUS_4_RX Audio Mixer", "MultiMedia2", "MM_DL2"},
 	{"SLIMBUS_4_RX", NULL, "SLIMBUS_4_RX Audio Mixer"},
@@ -3119,6 +3145,7 @@
 	{"MI2S_RX Audio Mixer", "MultiMedia6", "MM_DL6"},
 	{"MI2S_RX Audio Mixer", "MultiMedia7", "MM_DL7"},
 	{"MI2S_RX Audio Mixer", "MultiMedia8", "MM_DL8"},
+	{"MI2S_RX Audio Mixer", "MultiMedia9", "MM_DL9"},
 	{"MI2S_RX", NULL, "MI2S_RX Audio Mixer"},
 
 	{"QUAT_MI2S_RX Audio Mixer", "MultiMedia1", "MM_DL1"},
@@ -3174,6 +3201,7 @@
 	{"INTERNAL_BT_SCO_RX Audio Mixer", "MultiMedia6", "MM_DL6"},
 	{"INTERNAL_BT_SCO_RX Audio Mixer", "MultiMedia7", "MM_DL7"},
 	{"INTERNAL_BT_SCO_RX Audio Mixer", "MultiMedia8", "MM_DL8"},
+	{"INTERNAL_BT_SCO_RX Audio Mixer", "MultiMedia9", "MM_DL9"},
 	{"INT_BT_SCO_RX", NULL, "INTERNAL_BT_SCO_RX Audio Mixer"},
 
 	{"INTERNAL_FM_RX Audio Mixer", "MultiMedia1", "MM_DL1"},
@@ -3184,6 +3212,7 @@
 	{"INTERNAL_FM_RX Audio Mixer", "MultiMedia6", "MM_DL6"},
 	{"INTERNAL_FM_RX Audio Mixer", "MultiMedia7", "MM_DL7"},
 	{"INTERNAL_FM_RX Audio Mixer", "MultiMedia8", "MM_DL8"},
+	{"INTERNAL_FM_RX Audio Mixer", "MultiMedia9", "MM_DL9"},
 	{"INT_FM_RX", NULL, "INTERNAL_FM_RX Audio Mixer"},
 
 	{"AFE_PCM_RX Audio Mixer", "MultiMedia1", "MM_DL1"},
@@ -3194,6 +3223,7 @@
 	{"AFE_PCM_RX Audio Mixer", "MultiMedia6", "MM_DL6"},
 	{"AFE_PCM_RX Audio Mixer", "MultiMedia7", "MM_DL7"},
 	{"AFE_PCM_RX Audio Mixer", "MultiMedia8", "MM_DL8"},
+	{"AFE_PCM_RX Audio Mixer", "MultiMedia9", "MM_DL9"},
 	{"PCM_RX", NULL, "AFE_PCM_RX Audio Mixer"},
 
 	{"MultiMedia1 Mixer", "INTERNAL_BT_SCO_TX", "INT_BT_SCO_TX"},
@@ -3217,6 +3247,7 @@
 	{"AUX_PCM_RX Audio Mixer", "MultiMedia6", "MM_DL6"},
 	{"AUX_PCM_RX Audio Mixer", "MultiMedia7", "MM_DL7"},
 	{"AUX_PCM_RX Audio Mixer", "MultiMedia8", "MM_DL8"},
+	{"AUX_PCM_RX Audio Mixer", "MultiMedia9", "MM_DL9"},
 	{"AUX_PCM_RX", NULL, "AUX_PCM_RX Audio Mixer"},
 
 	{"SEC_AUX_PCM_RX Audio Mixer", "MultiMedia1", "MM_DL1"},
@@ -3227,6 +3258,7 @@
 	{"SEC_AUX_PCM_RX Audio Mixer", "MultiMedia6", "MM_DL6"},
 	{"SEC_AUX_PCM_RX Audio Mixer", "MultiMedia7", "MM_DL7"},
 	{"SEC_AUX_PCM_RX Audio Mixer", "MultiMedia8", "MM_DL8"},
+	{"SEC_AUX_PCM_RX Audio Mixer", "MultiMedia9", "MM_DL9"},
 	{"SEC_AUX_PCM_RX", NULL, "SEC_AUX_PCM_RX Audio Mixer"},
 
 	{"MI2S_RX_Voice Mixer", "CSVoice", "CS-VOICE_DL1"},
@@ -3320,6 +3352,7 @@
 	{"CS-VOICE_UL1", NULL, "Voice_Tx Mixer"},
 
 	{"Voice2_Tx Mixer", "PRI_TX_Voice2", "PRI_I2S_TX"},
+	{"Voice2_Tx Mixer", "PRI_MI2S_TX_Voice2", "PRI_MI2S_TX"},
 	{"Voice2_Tx Mixer", "MI2S_TX_Voice2", "MI2S_TX"},
 	{"Voice2_Tx Mixer", "SLIM_0_TX_Voice2", "SLIMBUS_0_TX"},
 	{"Voice2_Tx Mixer", "INTERNAL_BT_SCO_TX_Voice2", "INT_BT_SCO_TX"},
@@ -3466,6 +3499,7 @@
 	{"BE_OUT", NULL, "AUX_PCM_RX"},
 	{"BE_OUT", NULL, "SEC_AUX_PCM_RX"},
 	{"BE_OUT", NULL, "VOICE_PLAYBACK_TX"},
+	{"BE_OUT", NULL, "VOICE2_PLAYBACK_TX"},
 
 	{"PRI_I2S_TX", NULL, "BE_IN"},
 	{"MI2S_TX", NULL, "BE_IN"},
@@ -3674,10 +3708,6 @@
 			ARRAY_SIZE(int_fm_vol_mixer_controls));
 
 	snd_soc_add_platform_controls(platform,
-				lpa_vol_mixer_controls,
-			ARRAY_SIZE(lpa_vol_mixer_controls));
-
-	snd_soc_add_platform_controls(platform,
 				eq_enable_mixer_controls,
 			ARRAY_SIZE(eq_enable_mixer_controls));
 
@@ -3698,10 +3728,6 @@
 			ARRAY_SIZE(multimedia5_vol_mixer_controls));
 
 	snd_soc_add_platform_controls(platform,
-				compressed_vol_mixer_controls,
-			ARRAY_SIZE(compressed_vol_mixer_controls));
-
-	snd_soc_add_platform_controls(platform,
 				lpa_SRS_trumedia_controls,
 			ARRAY_SIZE(lpa_SRS_trumedia_controls));
 
diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.h b/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.h
index 9750756..4ce0db5 100644
--- a/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.h
+++ b/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.h
@@ -29,6 +29,7 @@
 #define LPASS_BE_SEC_AUXPCM_RX "SEC_AUX_PCM_RX"
 #define LPASS_BE_SEC_AUXPCM_TX "SEC_AUX_PCM_TX"
 #define LPASS_BE_VOICE_PLAYBACK_TX "VOICE_PLAYBACK_TX"
+#define LPASS_BE_VOICE2_PLAYBACK_TX "VOICE2_PLAYBACK_TX"
 #define LPASS_BE_INCALL_RECORD_RX "INCALL_RECORD_TX"
 #define LPASS_BE_INCALL_RECORD_TX "INCALL_RECORD_RX"
 #define LPASS_BE_SEC_I2S_RX "SECONDARY_I2S_RX"
@@ -70,6 +71,7 @@
 	MSM_FRONTEND_DAI_MULTIMEDIA6,
 	MSM_FRONTEND_DAI_MULTIMEDIA7,
 	MSM_FRONTEND_DAI_MULTIMEDIA8,
+	MSM_FRONTEND_DAI_MULTIMEDIA9,
 	MSM_FRONTEND_DAI_CS_VOICE,
 	MSM_FRONTEND_DAI_VOIP,
 	MSM_FRONTEND_DAI_AFE_RX,
@@ -82,8 +84,8 @@
 	MSM_FRONTEND_DAI_MAX,
 };
 
-#define MSM_FRONTEND_DAI_MM_SIZE (MSM_FRONTEND_DAI_MULTIMEDIA8 + 1)
-#define MSM_FRONTEND_DAI_MM_MAX_ID MSM_FRONTEND_DAI_MULTIMEDIA8
+#define MSM_FRONTEND_DAI_MM_SIZE (MSM_FRONTEND_DAI_MULTIMEDIA9 + 1)
+#define MSM_FRONTEND_DAI_MM_MAX_ID MSM_FRONTEND_DAI_MULTIMEDIA9
 
 enum {
 	MSM_BACKEND_DAI_PRI_I2S_RX = 0,
@@ -100,6 +102,7 @@
 	MSM_BACKEND_DAI_AUXPCM_RX,
 	MSM_BACKEND_DAI_AUXPCM_TX,
 	MSM_BACKEND_DAI_VOICE_PLAYBACK_TX,
+	MSM_BACKEND_DAI_VOICE2_PLAYBACK_TX,
 	MSM_BACKEND_DAI_INCALL_RECORD_RX,
 	MSM_BACKEND_DAI_INCALL_RECORD_TX,
 	MSM_BACKEND_DAI_MI2S_RX,
@@ -140,14 +143,10 @@
 
 void msm_pcm_routing_dereg_phy_stream(int fedai_id, int stream_type);
 
-int lpa_set_volume(unsigned volume);
-
 int msm_routing_check_backend_enabled(int fedai_id);
 
 int multi_ch_pcm_set_volume(unsigned volume);
 
-int compressed_set_volume(unsigned volume);
-
 uint32_t get_adm_rx_topology(void);
 
 uint32_t get_adm_tx_topology(void);
diff --git a/sound/soc/msm/qdsp6v2/q6afe.c b/sound/soc/msm/qdsp6v2/q6afe.c
index 9882ec7..0eb13d4 100644
--- a/sound/soc/msm/qdsp6v2/q6afe.c
+++ b/sound/soc/msm/qdsp6v2/q6afe.c
@@ -234,6 +234,7 @@
 	case INT_BT_A2DP_RX:
 	case INT_FM_RX:
 	case VOICE_PLAYBACK_TX:
+	case VOICE2_PLAYBACK_TX:
 	case RT_PROXY_PORT_001_RX:
 	case AUDIO_PORT_ID_I2S_RX:
 	case AFE_PORT_ID_PRIMARY_MI2S_RX:
@@ -303,6 +304,7 @@
 		ret_size = SIZEOF_CFG_CMD(afe_param_id_slimbus_cfg);
 		break;
 	case VOICE_PLAYBACK_TX:
+	case VOICE2_PLAYBACK_TX:
 	case VOICE_RECORD_RX:
 	case VOICE_RECORD_TX:
 		ret_size = SIZEOF_CFG_CMD(afe_param_id_pseudo_port_cfg);
@@ -1263,6 +1265,7 @@
 		cfg_type = AFE_PARAM_ID_HDMI_CONFIG;
 		break;
 	case VOICE_PLAYBACK_TX:
+	case VOICE2_PLAYBACK_TX:
 	case VOICE_RECORD_RX:
 	case VOICE_RECORD_TX:
 		cfg_type = AFE_PARAM_ID_PSEUDO_PORT_CONFIG;
@@ -1356,6 +1359,7 @@
 	case VOICE_RECORD_RX: return IDX_VOICE_RECORD_RX;
 	case VOICE_RECORD_TX: return IDX_VOICE_RECORD_TX;
 	case VOICE_PLAYBACK_TX: return IDX_VOICE_PLAYBACK_TX;
+	case VOICE2_PLAYBACK_TX: return IDX_VOICE2_PLAYBACK_TX;
 	case SLIMBUS_0_RX: return IDX_SLIMBUS_0_RX;
 	case SLIMBUS_0_TX: return IDX_SLIMBUS_0_TX;
 	case SLIMBUS_1_RX: return IDX_SLIMBUS_1_RX;
@@ -2663,6 +2667,7 @@
 	case VOICE_RECORD_RX:
 	case VOICE_RECORD_TX:
 	case VOICE_PLAYBACK_TX:
+	case VOICE2_PLAYBACK_TX:
 	case SLIMBUS_0_RX:
 	case SLIMBUS_0_TX:
 	case SLIMBUS_1_RX:
diff --git a/sound/soc/msm/qdsp6v2/q6asm.c b/sound/soc/msm/qdsp6v2/q6asm.c
index c65222b..869d642 100644
--- a/sound/soc/msm/qdsp6v2/q6asm.c
+++ b/sound/soc/msm/qdsp6v2/q6asm.c
@@ -1383,15 +1383,12 @@
 	hdr->pkt_size  = pkt_size;
 	return;
 }
-int q6asm_open_read(struct audio_client *ac,
-		uint32_t format)
+static int __q6asm_open_read(struct audio_client *ac,
+		uint32_t format, uint16_t bits_per_sample)
 {
 	int rc = 0x00;
 	struct asm_stream_cmd_open_read_v3 open;
 
-	uint16_t bits_per_sample = 16;
-
-
 	config_debug_fs_reset_index();
 
 	if ((ac == NULL) || (ac->apr == NULL)) {
@@ -1466,6 +1463,18 @@
 	return -EINVAL;
 }
 
+int q6asm_open_read(struct audio_client *ac,
+		uint32_t format)
+{
+	return __q6asm_open_read(ac, format, 16);
+}
+
+int q6asm_open_read_v2(struct audio_client *ac, uint32_t format,
+			uint16_t bits_per_sample)
+{
+	return __q6asm_open_read(ac, format, bits_per_sample);
+}
+
 static int __q6asm_open_write(struct audio_client *ac, uint32_t format,
 		uint16_t bits_per_sample)
 {
@@ -1820,8 +1829,8 @@
 		return rc;
 }
 
-int q6asm_enc_cfg_blk_pcm(struct audio_client *ac,
-			uint32_t rate, uint32_t channels)
+static int __q6asm_enc_cfg_blk_pcm(struct audio_client *ac,
+		uint32_t rate, uint32_t channels, uint16_t bits_per_sample)
 {
 	struct asm_multi_channel_pcm_enc_cfg_v2  enc_cfg;
 	u8 *channel_mapping;
@@ -1842,7 +1851,7 @@
 					sizeof(struct asm_enc_cfg_blk_param_v2);
 
 	enc_cfg.num_channels = channels;
-	enc_cfg.bits_per_sample = 16;
+	enc_cfg.bits_per_sample = bits_per_sample;
 	enc_cfg.sample_rate = rate;
 	enc_cfg.is_signed = 1;
 	channel_mapping = enc_cfg.channel_mapping;
@@ -1869,6 +1878,18 @@
 	return -EINVAL;
 }
 
+int q6asm_enc_cfg_blk_pcm(struct audio_client *ac,
+			uint32_t rate, uint32_t channels)
+{
+	return __q6asm_enc_cfg_blk_pcm(ac, rate, channels, 16);
+}
+
+int q6asm_enc_cfg_blk_pcm_format_support(struct audio_client *ac,
+		uint32_t rate, uint32_t channels, uint16_t bits_per_sample)
+{
+	 return __q6asm_enc_cfg_blk_pcm(ac, rate, channels, bits_per_sample);
+}
+
 int q6asm_enc_cfg_blk_pcm_native(struct audio_client *ac,
 			uint32_t rate, uint32_t channels)
 {
diff --git a/sound/soc/msm/qdsp6v2/q6audio-v2.c b/sound/soc/msm/qdsp6v2/q6audio-v2.c
index bc7ad4d..57ea2a7 100644
--- a/sound/soc/msm/qdsp6v2/q6audio-v2.c
+++ b/sound/soc/msm/qdsp6v2/q6audio-v2.c
@@ -43,6 +43,7 @@
 	case VOICE_RECORD_RX: return IDX_VOICE_RECORD_RX;
 	case VOICE_RECORD_TX: return IDX_VOICE_RECORD_TX;
 	case VOICE_PLAYBACK_TX: return IDX_VOICE_PLAYBACK_TX;
+	case VOICE2_PLAYBACK_TX: return IDX_VOICE2_PLAYBACK_TX;
 	case SLIMBUS_0_RX: return IDX_SLIMBUS_0_RX;
 	case SLIMBUS_0_TX: return IDX_SLIMBUS_0_TX;
 	case SLIMBUS_1_RX: return IDX_SLIMBUS_1_RX;
@@ -103,6 +104,7 @@
 	case VOICE_RECORD_RX: return AFE_PORT_ID_VOICE_RECORD_RX;
 	case VOICE_RECORD_TX: return AFE_PORT_ID_VOICE_RECORD_TX;
 	case VOICE_PLAYBACK_TX: return AFE_PORT_ID_VOICE_PLAYBACK_TX;
+	case VOICE2_PLAYBACK_TX: return AFE_PORT_ID_VOICE2_PLAYBACK_TX;
 	case SLIMBUS_0_RX: return AFE_PORT_ID_SLIMBUS_MULTI_CHAN_0_RX;
 	case SLIMBUS_0_TX: return AFE_PORT_ID_SLIMBUS_MULTI_CHAN_0_TX;
 	case SLIMBUS_1_RX: return AFE_PORT_ID_SLIMBUS_MULTI_CHAN_1_RX;
@@ -213,6 +215,7 @@
 	case VOICE_RECORD_RX:
 	case VOICE_RECORD_TX:
 	case VOICE_PLAYBACK_TX:
+	case VOICE2_PLAYBACK_TX:
 	case SLIMBUS_0_RX:
 	case SLIMBUS_0_TX:
 	case SLIMBUS_1_RX:
diff --git a/sound/soc/msm/qdsp6v2/q6voice.c b/sound/soc/msm/qdsp6v2/q6voice.c
index 8339b64..f268171 100644
--- a/sound/soc/msm/qdsp6v2/q6voice.c
+++ b/sound/soc/msm/qdsp6v2/q6voice.c
@@ -3576,7 +3576,8 @@
 		cvs_start_playback.hdr.token = 0;
 		cvs_start_playback.hdr.opcode = VSS_IPLAYBACK_CMD_START;
 		cvs_start_playback.playback_mode.port_id =
-						VSS_IPLAYBACK_PORT_ID_DEFAULT;
+						v->music_info.port_id;
+
 		v->cvs_state = CMD_STATUS_FAIL;
 
 		ret = apr_send_pkt(apr_cvs, (uint32_t *) &cvs_start_playback);
@@ -3674,17 +3675,21 @@
 	return ret;
 }
 
-int voc_start_playback(uint32_t set)
+int voc_start_playback(uint32_t set, uint16_t port_id)
 {
 	int ret = 0;
 	u16 cvs_handle;
-	int i;
 
+	struct voice_data *v = NULL;
 
-	for (i = 0; i < MAX_VOC_SESSIONS; i++) {
-		struct voice_data *v = &common.voice[i];
+	if (port_id == VOICE_PLAYBACK_TX)
+		v = voice_get_session(voc_get_session_id(VOICE_SESSION_NAME));
+	else if (port_id == VOICE2_PLAYBACK_TX)
+		v = voice_get_session(voc_get_session_id(VOICE2_SESSION_NAME));
 
+	if (v != NULL) {
 		mutex_lock(&v->lock);
+		v->music_info.port_id = port_id;
 		v->music_info.play_enable = set;
 		if (set)
 			v->music_info.count++;
@@ -3702,6 +3707,8 @@
 		}
 
 		mutex_unlock(&v->lock);
+	} else {
+		pr_err("%s: Invalid port_id 0x%x", __func__, port_id);
 	}
 
 	return ret;
@@ -4406,9 +4413,14 @@
 			apr_reset(c->apr_q6_mvm);
 			c->apr_q6_mvm = NULL;
 
+			/* clean up memory handle */
+			c->cal_mem_handle = 0;
+
 			/* Sub-system restart is applicable to all sessions. */
-			for (i = 0; i < MAX_VOC_SESSIONS; i++)
+			for (i = 0; i < MAX_VOC_SESSIONS; i++) {
 				c->voice[i].mvm_handle = 0;
+				c->voice[i].shmem_info.mem_handle = 0;
+			}
 		}
 		return 0;
 	}
diff --git a/sound/soc/msm/qdsp6v2/q6voice.h b/sound/soc/msm/qdsp6v2/q6voice.h
index 8d6e151..b8f7008 100644
--- a/sound/soc/msm/qdsp6v2/q6voice.h
+++ b/sound/soc/msm/qdsp6v2/q6voice.h
@@ -486,6 +486,12 @@
 #define VSS_IPLAYBACK_PORT_ID_DEFAULT			0x0000FFFF
 /* Default AFE port ID. */
 
+#define VSS_IPLAYBACK_PORT_ID_VOICE			0x00008005
+/* AFE port ID for VOICE 1. */
+
+#define VSS_IPLAYBACK_PORT_ID_VOICE2			0x00008002
+/* AFE port ID for VOICE 2. */
+
 #define VSS_IRECORD_CMD_START				0x000112BE
 /* Start in-call conversation recording. */
 #define VSS_IRECORD_CMD_STOP				0x00011237
@@ -1209,6 +1215,7 @@
 	uint32_t playing;
 	int count;
 	int force;
+	uint16_t port_id;
 };
 
 struct share_memory_info {
@@ -1373,6 +1380,6 @@
 
 uint32_t voc_get_session_id(char *name);
 
-int voc_start_playback(uint32_t set);
+int voc_start_playback(uint32_t set, uint16_t port_id);
 int voc_start_record(uint32_t port_id, uint32_t set);
 #endif