Merge "block: add runtime pm helpers"
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/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/msm8226.dtsi b/arch/arm/boot/dts/msm8226.dtsi
index 6dfe15d..527a582 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 {
diff --git a/arch/arm/boot/dts/msm8610.dtsi b/arch/arm/boot/dts/msm8610.dtsi
index ad0980c..b99e6f8 100644
--- a/arch/arm/boot/dts/msm8610.dtsi
+++ b/arch/arm/boot/dts/msm8610.dtsi
@@ -772,6 +772,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-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..89cbc4c 100644
--- a/arch/arm/boot/dts/msm8974.dtsi
+++ b/arch/arm/boot/dts/msm8974.dtsi
@@ -1369,6 +1369,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/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/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/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..cdee5b7 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
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-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/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/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/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/gpu/msm/adreno.c b/drivers/gpu/msm/adreno.c
index da453a5..c76ab5b 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)
diff --git a/drivers/gpu/msm/adreno_a3xx.c b/drivers/gpu/msm/adreno_a3xx.c
index 0ae8db6..e4cb4ae 100644
--- a/drivers/gpu/msm/adreno_a3xx.c
+++ b/drivers/gpu/msm/adreno_a3xx.c
@@ -3136,8 +3136,134 @@
 	{ adreno_is_a305b, a305b_vbif },
 };
 
+/*
+ * Define the available perfcounter groups - these get used by
+ * adreno_perfcounter_get and adreno_perfcounter_put
+ */
+
+static struct adreno_perfcount_register a3xx_perfcounters_cp[] = {
+	{ KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_CP_0_LO, 0 },
+};
+
+static struct adreno_perfcount_register a3xx_perfcounters_rbbm[] = {
+	{ KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_RBBM_0_LO, 0 },
+	{ KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_RBBM_1_LO, 0 },
+};
+
+static struct adreno_perfcount_register a3xx_perfcounters_pc[] = {
+	{ KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_PC_0_LO, 0 },
+	{ KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_PC_1_LO, 0 },
+	{ KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_PC_2_LO, 0 },
+	{ KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_PC_3_LO, 0 },
+};
+
+static struct adreno_perfcount_register a3xx_perfcounters_vfd[] = {
+	{ KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_VFD_0_LO, 0 },
+	{ KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_VFD_1_LO, 0 },
+};
+
+static struct adreno_perfcount_register a3xx_perfcounters_hlsq[] = {
+	{ KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_HLSQ_0_LO, 0 },
+	{ KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_HLSQ_1_LO, 0 },
+	{ KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_HLSQ_2_LO, 0 },
+	{ KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_HLSQ_3_LO, 0 },
+	{ KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_HLSQ_4_LO, 0 },
+	{ KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_HLSQ_5_LO, 0 },
+};
+
+static struct adreno_perfcount_register a3xx_perfcounters_vpc[] = {
+	{ KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_VPC_0_LO, 0 },
+	{ KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_VPC_1_LO, 0 },
+};
+
+static struct adreno_perfcount_register a3xx_perfcounters_tse[] = {
+	{ KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_TSE_0_LO, 0 },
+	{ KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_TSE_1_LO, 0 },
+};
+
+static struct adreno_perfcount_register a3xx_perfcounters_ras[] = {
+	{ KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_RAS_0_LO, 0 },
+	{ KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_RAS_1_LO, 0 },
+};
+
+static struct adreno_perfcount_register a3xx_perfcounters_uche[] = {
+	{ KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_UCHE_0_LO, 0 },
+	{ KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_UCHE_1_LO, 0 },
+	{ KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_UCHE_2_LO, 0 },
+	{ KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_UCHE_3_LO, 0 },
+	{ KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_UCHE_4_LO, 0 },
+	{ KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_UCHE_5_LO, 0 },
+};
+
+static struct adreno_perfcount_register a3xx_perfcounters_tp[] = {
+	{ KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_TP_0_LO, 0 },
+	{ KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_TP_1_LO, 0 },
+	{ KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_TP_2_LO, 0 },
+	{ KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_TP_3_LO, 0 },
+	{ KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_TP_4_LO, 0 },
+	{ KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_TP_5_LO, 0 },
+};
+
+static struct adreno_perfcount_register a3xx_perfcounters_sp[] = {
+	{ KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_SP_0_LO, 0 },
+	{ KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_SP_1_LO, 0 },
+	{ KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_SP_2_LO, 0 },
+	{ KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_SP_3_LO, 0 },
+	{ KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_SP_4_LO, 0 },
+	{ KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_SP_5_LO, 0 },
+	{ KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_SP_6_LO, 0 },
+	{ KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_SP_7_LO, 0 },
+};
+
+static struct adreno_perfcount_register a3xx_perfcounters_rb[] = {
+	{ KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_RB_0_LO, 0 },
+	{ KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_RB_1_LO, 0 },
+};
+
+static struct adreno_perfcount_register a3xx_perfcounters_pwr[] = {
+	{ KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_PWR_0_LO, 0 },
+	{ KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_PWR_1_LO, 0 },
+};
+
+static struct adreno_perfcount_register a3xx_perfcounters_vbif[] = {
+	{ KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_VBIF_PERF_CNT0_LO },
+	{ KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_VBIF_PERF_CNT1_LO },
+};
+static struct adreno_perfcount_register a3xx_perfcounters_vbif_pwr[] = {
+	{ KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_VBIF_PERF_PWR_CNT0_LO },
+	{ KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_VBIF_PERF_PWR_CNT1_LO },
+	{ KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_VBIF_PERF_PWR_CNT2_LO },
+};
+
+static struct adreno_perfcount_group a3xx_perfcounter_groups[] = {
+	{ a3xx_perfcounters_cp, ARRAY_SIZE(a3xx_perfcounters_cp) },
+	{ a3xx_perfcounters_rbbm, ARRAY_SIZE(a3xx_perfcounters_rbbm) },
+	{ a3xx_perfcounters_pc, ARRAY_SIZE(a3xx_perfcounters_pc) },
+	{ a3xx_perfcounters_vfd, ARRAY_SIZE(a3xx_perfcounters_vfd) },
+	{ a3xx_perfcounters_hlsq, ARRAY_SIZE(a3xx_perfcounters_hlsq) },
+	{ a3xx_perfcounters_vpc, ARRAY_SIZE(a3xx_perfcounters_vpc) },
+	{ a3xx_perfcounters_tse, ARRAY_SIZE(a3xx_perfcounters_tse) },
+	{ a3xx_perfcounters_ras, ARRAY_SIZE(a3xx_perfcounters_ras) },
+	{ a3xx_perfcounters_uche, ARRAY_SIZE(a3xx_perfcounters_uche) },
+	{ a3xx_perfcounters_tp, ARRAY_SIZE(a3xx_perfcounters_tp) },
+	{ a3xx_perfcounters_sp, ARRAY_SIZE(a3xx_perfcounters_sp) },
+	{ a3xx_perfcounters_rb, ARRAY_SIZE(a3xx_perfcounters_rb) },
+	{ a3xx_perfcounters_pwr, ARRAY_SIZE(a3xx_perfcounters_pwr) },
+	{ a3xx_perfcounters_vbif, ARRAY_SIZE(a3xx_perfcounters_vbif) },
+	{ a3xx_perfcounters_vbif_pwr, ARRAY_SIZE(a3xx_perfcounters_vbif_pwr) },
+};
+
+static struct adreno_perfcounters a3xx_perfcounters = {
+	a3xx_perfcounter_groups,
+	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.
@@ -3346,128 +3472,6 @@
 }
 
 /*
- * Define the available perfcounter groups - these get used by
- * adreno_perfcounter_get and adreno_perfcounter_put
- */
-
-static struct adreno_perfcount_register a3xx_perfcounters_cp[] = {
-	{ KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_CP_0_LO, 0 },
-};
-
-static struct adreno_perfcount_register a3xx_perfcounters_rbbm[] = {
-	{ KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_RBBM_0_LO, 0 },
-	{ KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_RBBM_1_LO, 0 },
-};
-
-static struct adreno_perfcount_register a3xx_perfcounters_pc[] = {
-	{ KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_PC_0_LO, 0 },
-	{ KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_PC_1_LO, 0 },
-	{ KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_PC_2_LO, 0 },
-	{ KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_PC_3_LO, 0 },
-};
-
-static struct adreno_perfcount_register a3xx_perfcounters_vfd[] = {
-	{ KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_VFD_0_LO, 0 },
-	{ KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_VFD_1_LO, 0 },
-};
-
-static struct adreno_perfcount_register a3xx_perfcounters_hlsq[] = {
-	{ KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_HLSQ_0_LO, 0 },
-	{ KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_HLSQ_1_LO, 0 },
-	{ KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_HLSQ_2_LO, 0 },
-	{ KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_HLSQ_3_LO, 0 },
-	{ KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_HLSQ_4_LO, 0 },
-	{ KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_HLSQ_5_LO, 0 },
-};
-
-static struct adreno_perfcount_register a3xx_perfcounters_vpc[] = {
-	{ KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_VPC_0_LO, 0 },
-	{ KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_VPC_1_LO, 0 },
-};
-
-static struct adreno_perfcount_register a3xx_perfcounters_tse[] = {
-	{ KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_TSE_0_LO, 0 },
-	{ KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_TSE_1_LO, 0 },
-};
-
-static struct adreno_perfcount_register a3xx_perfcounters_ras[] = {
-	{ KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_RAS_0_LO, 0 },
-	{ KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_RAS_1_LO, 0 },
-};
-
-static struct adreno_perfcount_register a3xx_perfcounters_uche[] = {
-	{ KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_UCHE_0_LO, 0 },
-	{ KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_UCHE_1_LO, 0 },
-	{ KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_UCHE_2_LO, 0 },
-	{ KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_UCHE_3_LO, 0 },
-	{ KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_UCHE_4_LO, 0 },
-	{ KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_UCHE_5_LO, 0 },
-};
-
-static struct adreno_perfcount_register a3xx_perfcounters_tp[] = {
-	{ KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_TP_0_LO, 0 },
-	{ KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_TP_1_LO, 0 },
-	{ KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_TP_2_LO, 0 },
-	{ KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_TP_3_LO, 0 },
-	{ KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_TP_4_LO, 0 },
-	{ KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_TP_5_LO, 0 },
-};
-
-static struct adreno_perfcount_register a3xx_perfcounters_sp[] = {
-	{ KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_SP_0_LO, 0 },
-	{ KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_SP_1_LO, 0 },
-	{ KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_SP_2_LO, 0 },
-	{ KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_SP_3_LO, 0 },
-	{ KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_SP_4_LO, 0 },
-	{ KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_SP_5_LO, 0 },
-	{ KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_SP_6_LO, 0 },
-	{ KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_SP_7_LO, 0 },
-};
-
-static struct adreno_perfcount_register a3xx_perfcounters_rb[] = {
-	{ KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_RB_0_LO, 0 },
-	{ KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_RB_1_LO, 0 },
-};
-
-static struct adreno_perfcount_register a3xx_perfcounters_pwr[] = {
-	{ KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_PWR_0_LO, 0 },
-	{ KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_PWR_1_LO, 0 },
-};
-
-static struct adreno_perfcount_register a3xx_perfcounters_vbif[] = {
-	{ KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_VBIF_PERF_CNT0_LO },
-	{ KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_VBIF_PERF_CNT1_LO },
-};
-static struct adreno_perfcount_register a3xx_perfcounters_vbif_pwr[] = {
-	{ KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_VBIF_PERF_PWR_CNT0_LO },
-	{ KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_VBIF_PERF_PWR_CNT1_LO },
-	{ KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_VBIF_PERF_PWR_CNT2_LO },
-};
-
-static struct adreno_perfcount_group a3xx_perfcounter_groups[] = {
-	{ a3xx_perfcounters_cp, ARRAY_SIZE(a3xx_perfcounters_cp) },
-	{ a3xx_perfcounters_rbbm, ARRAY_SIZE(a3xx_perfcounters_rbbm) },
-	{ a3xx_perfcounters_pc, ARRAY_SIZE(a3xx_perfcounters_pc) },
-	{ a3xx_perfcounters_vfd, ARRAY_SIZE(a3xx_perfcounters_vfd) },
-	{ a3xx_perfcounters_hlsq, ARRAY_SIZE(a3xx_perfcounters_hlsq) },
-	{ a3xx_perfcounters_vpc, ARRAY_SIZE(a3xx_perfcounters_vpc) },
-	{ a3xx_perfcounters_tse, ARRAY_SIZE(a3xx_perfcounters_tse) },
-	{ a3xx_perfcounters_ras, ARRAY_SIZE(a3xx_perfcounters_ras) },
-	{ a3xx_perfcounters_uche, ARRAY_SIZE(a3xx_perfcounters_uche) },
-	{ a3xx_perfcounters_tp, ARRAY_SIZE(a3xx_perfcounters_tp) },
-	{ a3xx_perfcounters_sp, ARRAY_SIZE(a3xx_perfcounters_sp) },
-	{ a3xx_perfcounters_rb, ARRAY_SIZE(a3xx_perfcounters_rb) },
-	{ a3xx_perfcounters_pwr, ARRAY_SIZE(a3xx_perfcounters_pwr) },
-	{ a3xx_perfcounters_vbif, ARRAY_SIZE(a3xx_perfcounters_vbif) },
-	{ a3xx_perfcounters_vbif_pwr, ARRAY_SIZE(a3xx_perfcounters_vbif_pwr) },
-};
-
-static struct adreno_perfcounters a3xx_perfcounters = {
-	a3xx_perfcounter_groups,
-	ARRAY_SIZE(a3xx_perfcounter_groups),
-};
-
-/*
  * a3xx_soft_reset() - Soft reset GPU
  * @adreno_dev: Pointer to adreno device
  *
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/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..983a901 100644
--- a/drivers/power/qpnp-charger.c
+++ b/drivers/power/qpnp-charger.c
@@ -1066,6 +1066,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 +1246,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 +1397,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;
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/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..39952c9 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 {
@@ -562,6 +569,9 @@
 int mdss_mdp_calib_config(struct mdp_calib_config_data *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..953cbff 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;
 }
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_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/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/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/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/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/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-dai-q6-v2.c b/sound/soc/msm/qdsp6v2/msm-dai-q6-v2.c
index 95239a4..d31e2c5 100644
--- a/sound/soc/msm/qdsp6v2/msm-dai-q6-v2.c
+++ b/sound/soc/msm/qdsp6v2/msm-dai-q6-v2.c
@@ -715,6 +715,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 +1580,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 +1714,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 +2035,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-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-routing-v2.c b/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c
index 97803b3..e1b9243 100644
--- a/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c
+++ b/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c
@@ -217,6 +217,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 +265,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 +514,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 +559,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) {
@@ -1418,6 +1423,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 +1453,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 +1483,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 +1513,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 +1543,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 +1588,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 +1627,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 +1657,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 +1669,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 +1720,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 +1750,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 +1780,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 +1810,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 +1840,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 +2200,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[] = {
@@ -2763,11 +2825,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 +2926,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 +3011,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 +3135,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 +3146,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 +3157,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 +3168,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 +3197,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 +3253,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 +3264,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 +3275,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 +3299,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 +3310,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 +3404,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 +3551,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"},
diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.h b/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.h
index 9750756..0d87735 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,
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 87bee75..9fb4eae 100644
--- a/sound/soc/msm/qdsp6v2/q6voice.c
+++ b/sound/soc/msm/qdsp6v2/q6voice.c
@@ -3457,7 +3457,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);
@@ -3555,17 +3556,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++;
@@ -3583,6 +3588,8 @@
 		}
 
 		mutex_unlock(&v->lock);
+	} else {
+		pr_err("%s: Invalid port_id 0x%x", __func__, port_id);
 	}
 
 	return ret;
diff --git a/sound/soc/msm/qdsp6v2/q6voice.h b/sound/soc/msm/qdsp6v2/q6voice.h
index 5a16115..52cf940 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 {
@@ -1370,6 +1377,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