Merge "arm/dt: msm8974: Use no_force_update for config update"
diff --git a/Documentation/devicetree/bindings/arm/msm/bam_dmux.txt b/Documentation/devicetree/bindings/arm/msm/bam_dmux.txt
index d82284d..53a67a4 100644
--- a/Documentation/devicetree/bindings/arm/msm/bam_dmux.txt
+++ b/Documentation/devicetree/bindings/arm/msm/bam_dmux.txt
@@ -5,10 +5,14 @@
 - reg : the location and size of the BAM hardware
 - interrupts : the BAM hardware to apps processor interrupt line
 
+Optional properties:
+-qcom,satellite-mode: the hardware needs to be configured in satellite mode
+
 Example:
 
 	qcom,bam_dmux@fc834000 {
 		compatible = "qcom,bam_dmux";
 		reg = <0xfc834000 0x7000>;
 		interrupts = <0 29 1>;
+		qcom,satellite-mode;
 	};
diff --git a/Documentation/devicetree/bindings/arm/msm/memory-reserve.txt b/Documentation/devicetree/bindings/arm/msm/memory-reserve.txt
index 5f18893..c1b79ae 100644
--- a/Documentation/devicetree/bindings/arm/msm/memory-reserve.txt
+++ b/Documentation/devicetree/bindings/arm/msm/memory-reserve.txt
@@ -41,6 +41,17 @@
 The EXPORT_COMPAT is to ensure that memory is only carved out if the
 driver is actually enabled, otherwise the memory will not be used.
 
+If a reservation is needed that isn't associated directly with any one
+driver, the compatible string "qcom,msm-contig-mem" can be used. For
+example:
+
+	qcom,msm-contig-mem {
+		compatible = "qcom,msm-contig-mem";
+		qcom,memory-reservation-type = "EBI1";
+		qcom,memory-reservation-size = <0x280000>; /* 2.5M EBI1 buffer */
+	};
+
+
 In order to specify the size and address of the fixed memory which has
 previously been removed the memory-fixed binding can be used. This assumes
 that the region has been removed by a separate memblock-remove property
diff --git a/Documentation/devicetree/bindings/gpio/qpnp-pin.txt b/Documentation/devicetree/bindings/gpio/qpnp-pin.txt
index 31c3bc2..36ac336 100644
--- a/Documentation/devicetree/bindings/gpio/qpnp-pin.txt
+++ b/Documentation/devicetree/bindings/gpio/qpnp-pin.txt
@@ -94,7 +94,7 @@
 			QPNP_PIN_OUT_STRENGTH_MED  = 2, (GPIO)
 			QPNP_PIN_OUT_STRENGTH_HIGH = 3, (GPIO)
 
-  - qcom,src-select:	select a function for the pin. Certain pins
+  - qcom,src-sel:	select a function for the pin. Certain pins
 			can be paired (shorted) with each other. Some gpio pins
 			can act as alternate functions.
 			In the context of gpio, this acts as a source select.
diff --git a/Documentation/devicetree/bindings/pil/pil-mba.txt b/Documentation/devicetree/bindings/pil/pil-mba.txt
deleted file mode 100644
index ce6bb8f..0000000
--- a/Documentation/devicetree/bindings/pil/pil-mba.txt
+++ /dev/null
@@ -1,32 +0,0 @@
-Qualcomm Modem Boot Authenticator Peripheral Image Loader
-
-pil-mba is a peripheral image loader (PIL) driver. It is used for loading
-modem images using the self-authenticating hardware and software features
-of the Modem Boot Authenticator.
-
-Required properties:
-- compatible:	      Must be "qcom,pil-mba"
-- reg:		      Two pairs of physical base addresses and sizes. The
-		      first corresponds to the Relay Message Buffer (RMB)
-		      register base. The second specifies the address at which
-		      the primary modem image metadata should be stored.
-- reg-names:	      Names for the above base addresses. "rmb_base" and
-	              "metadata_base" are expected.
-- interrupts:         The modem watchdog interrupt
-- qcom,firmware-name: Base name of the firmware image. Ex. "modem"
-
-Optional properties:
-- qcom,depends-on:    firmware-name of a prerequisite image that must already
-		      be running.
-
-Example:
-	qcom,mba@fc820000 {
-		compatible = "qcom,pil-mba";
-		reg = <0xfc820000 0x0020>,
-		      <0x0d1f0000 0x4000>;
-		reg-names = "rmb_base", "metadata_base";
-		interrupts = <0 56 1>;
-
-		qcom,firmware-name = "modem";
-		qcom,depends-on    = "mba";
-	};
diff --git a/Documentation/devicetree/bindings/pil/pil-q6v5-mss.txt b/Documentation/devicetree/bindings/pil/pil-q6v5-mss.txt
index dd59ae8..f83de7e 100644
--- a/Documentation/devicetree/bindings/pil/pil-q6v5-mss.txt
+++ b/Documentation/devicetree/bindings/pil/pil-q6v5-mss.txt
@@ -10,7 +10,9 @@
 - reg:		      Pairs of physical base addresses and region sizes of
 		      memory mapped registers.
 - reg-names:	      Names of the bases for the above registers. "qdsp6_base",
-		      "halt_base", "rmb_base", and "restart_reg" are expected.
+		      "halt_base", "rmb_base", "restart_reg", and
+		      "metadata_base" are expected.
+- interrupts:         The modem watchdog interrupt
 - vdd_mss-supply:     Reference to the regulator that supplies the processor.
 - qcom,firmware-name: Base name of the firmware image. Ex. "mdsp"
 - qcom,pil-self-auth: <0> if the hardware does not require self-authenticating
@@ -23,9 +25,11 @@
 		reg = <0xfc880000 0x100>,
 		      <0xfd485000 0x400>,
 		      <0xfc820000 0x020>,
-		      <0xfc401680 0x004>;
+		      <0xfc401680 0x004>,
+		      <0x0d1f0000 0x4000>;
 		reg-names = "qdsp6_base", "halt_base", "rmb_base",
-			    "restart_reg";
+			    "restart_reg", metadata_base";
+		interrupts = <0 24 1>;
 		vdd_mss-supply = <&pm8841_s3>;
 
 		qcom,firmware-name = "mba";
diff --git a/arch/arm/boot/dts/msm-pm8941.dtsi b/arch/arm/boot/dts/msm-pm8941.dtsi
index de30884..341b49b 100644
--- a/arch/arm/boot/dts/msm-pm8941.dtsi
+++ b/arch/arm/boot/dts/msm-pm8941.dtsi
@@ -993,6 +993,36 @@
 			status = "disabled";
 		};
 
+		qcom,leds@d300 {
+			compatible = "qcom,leds-qpnp";
+			reg = <0xd300 0x100>;
+			label = "flash";
+		};
+
+		qcom,leds@d400 {
+			compatible = "qcom,leds-qpnp";
+			reg = <0xd400 0x100>;
+			label = "flash";
+		};
+
+		qcom,leds@d500 {
+			compatible = "qcom,leds-qpnp";
+			reg = <0xd500 0x100>;
+			label = "flash";
+		};
+
+		qcom,leds@d600 {
+			compatible = "qcom,leds-qpnp";
+			reg = <0xd600 0x100>;
+			label = "flash";
+		};
+
+		qcom,leds@d700 {
+			compatible = "qcom,leds-qpnp";
+			reg = <0xd700 0x100>;
+			label = "flash";
+		};
+
 		qcom,leds@d800 {
 			compatible = "qcom,leds-qpnp";
 			reg = <0xd800 0x100>;
diff --git a/arch/arm/boot/dts/msm8974-cdp.dtsi b/arch/arm/boot/dts/msm8974-cdp.dtsi
index c1f6071..6004d15 100644
--- a/arch/arm/boot/dts/msm8974-cdp.dtsi
+++ b/arch/arm/boot/dts/msm8974-cdp.dtsi
@@ -179,21 +179,21 @@
 		qcom,mode = <0>;
 		qcom,pull = <0>;
 		qcom,vin-sel = <2>;
-		qcom,select = <0>;
+		qcom,src-sel = <0>;
 	};
 
 	gpio@c300 { /* GPIO 4 */
 		qcom,mode = <0>;
 		qcom,pull = <0>;
 		qcom,vin-sel = <2>;
-		qcom,select = <0>;
+		qcom,src-sel = <0>;
 	};
 
 	gpio@c400 { /* GPIO 5 */
 		qcom,mode = <0>;
 		qcom,pull = <0>;
 		qcom,vin-sel = <2>;
-		qcom,select = <0>;
+		qcom,src-sel = <0>;
 	};
 
 	gpio@c500 { /* GPIO 6 */
@@ -229,7 +229,7 @@
 		qcom,pull = <5>;
 		qcom,vin-sel = <2>;
 		qcom,out-strength = <3>;
-		qcom,src-select = <2>;
+		qcom,src-sel = <2>;
 		qcom,master-en = <1>;
 	};
 
@@ -248,7 +248,7 @@
 		qcom,pull = <5>;		/* QPNP_PIN_PULL_NO */
 		qcom,vin-sel = <2>;		/* QPNP_PIN_VIN2 */
 		qcom,out-strength = <2>;	/* QPNP_PIN_OUT_STRENGTH_MED */
-		qcom,src-select = <0>;		/* QPNP_PIN_SEL_FUNC_CONSTANT */
+		qcom,src-sel = <0>;		/* QPNP_PIN_SEL_FUNC_CONSTANT */
 		qcom,master-en = <1>;
 	};
 
@@ -326,7 +326,7 @@
 		qcom,mode = <1>; /* DIG_OUT */
 		qcom,output-type = <0>; /* CMOS */
 		qcom,vin-sel = <2>; /* PM8941_S3 1.8V > 1.6V */
-		qcom,src-select = <0>; /* CONSTANT */
+		qcom,src-sel = <0>; /* CONSTANT */
 		qcom,master-en = <1>; /* ENABLE MPP */
 	};
 
@@ -335,7 +335,7 @@
 		qcom,mode = <1>; /* DIG_OUT */
 		qcom,output-type = <0>; /* CMOS */
 		qcom,vin-sel = <2>; /* PM8941_S3 1.8V > 1.6V */
-		qcom,src-select = <0>; /* CONSTANT */
+		qcom,src-sel = <0>; /* CONSTANT */
 		qcom,master-en = <1>; /* ENABLE MPP */
 	};
 
diff --git a/arch/arm/boot/dts/msm8974-fluid.dtsi b/arch/arm/boot/dts/msm8974-fluid.dtsi
index d333877..93f92c7 100644
--- a/arch/arm/boot/dts/msm8974-fluid.dtsi
+++ b/arch/arm/boot/dts/msm8974-fluid.dtsi
@@ -182,21 +182,21 @@
 		qcom,mode = <0>;
 		qcom,pull = <0>;
 		qcom,vin-sel = <2>;
-		qcom,select = <0>;
+		qcom,src-sel = <0>;
 	};
 
 	gpio@c300 { /* GPIO 4 */
 		qcom,mode = <0>;
 		qcom,pull = <0>;
 		qcom,vin-sel = <2>;
-		qcom,select = <0>;
+		qcom,src-sel = <0>;
 	};
 
 	gpio@c400 { /* GPIO 5 */
 		qcom,mode = <0>;
 		qcom,pull = <0>;
 		qcom,vin-sel = <2>;
-		qcom,select = <0>;
+		qcom,src-sel = <0>;
 	};
 
 	gpio@c500 { /* GPIO 6 */
@@ -232,7 +232,7 @@
 		qcom,pull = <5>;
 		qcom,vin-sel = <2>;
 		qcom,out-strength = <3>;
-		qcom,src-select = <2>;
+		qcom,src-sel = <2>;
 		qcom,master-en = <1>;
 	};
 
@@ -251,7 +251,7 @@
 		qcom,pull = <5>;		/* QPNP_PIN_PULL_NO */
 		qcom,vin-sel = <2>;		/* QPNP_PIN_VIN2 */
 		qcom,out-strength = <2>;	/* QPNP_PIN_OUT_STRENGTH_MED */
-		qcom,src-select = <0>;		/* QPNP_PIN_SEL_FUNC_CONSTANT */
+		qcom,src-sel = <0>;		/* QPNP_PIN_SEL_FUNC_CONSTANT */
 		qcom,master-en = <1>;
 	};
 
@@ -329,7 +329,7 @@
 		qcom,mode = <1>; /* DIG_OUT */
 		qcom,output-type = <0>; /* CMOS */
 		qcom,vin-sel = <2>; /* PM8941_S3 1.8V > 1.6V */
-		qcom,src-select = <0>; /* CONSTANT */
+		qcom,src-sel = <0>; /* CONSTANT */
 		qcom,master-en = <1>; /* ENABLE MPP */
 	};
 
@@ -338,7 +338,7 @@
 		qcom,mode = <1>; /* DIG_OUT */
 		qcom,output-type = <0>; /* CMOS */
 		qcom,vin-sel = <2>; /* PM8941_S3 1.8V > 1.6V */
-		qcom,src-select = <0>; /* CONSTANT */
+		qcom,src-sel = <0>; /* CONSTANT */
 		qcom,master-en = <1>; /* ENABLE MPP */
 	};
 
diff --git a/arch/arm/boot/dts/msm8974-ion.dtsi b/arch/arm/boot/dts/msm8974-ion.dtsi
index 9b5aaac..634ac43 100644
--- a/arch/arm/boot/dts/msm8974-ion.dtsi
+++ b/arch/arm/boot/dts/msm8974-ion.dtsi
@@ -45,6 +45,13 @@
 			qcom,memory-reservation-size = <0x2000>;
 		};
 
+		qcom,ion-heap@23 { /* PIL1 HEAP */
+			compatible = "qcom,msm-ion-reserve";
+			reg = <23>;
+			qcom,heap-align = <0x10000>;
+			qcom,memory-fixed = <0xd200000 0x2800000>;
+		};
+
 		qcom,ion-heap@24 { /* SF HEAP */
 			compatible = "qcom,msm-ion-reserve";
 			reg = <24>;
@@ -57,6 +64,13 @@
 			reg = <25>;
 		};
 
+		qcom,ion-heap@26 { /* PIL2 HEAP */
+			compatible = "qcom,msm-ion-reserve";
+			reg = <26>;
+			qcom,heap-align = <0x10000>;
+			qcom,memory-fixed = <0x8400000 0x4e00000>;
+		};
+
 		qcom,ion-heap@27 { /* QSECOM HEAP */
 			compatible = "qcom,msm-ion-reserve";
 			reg = <27>;
diff --git a/arch/arm/boot/dts/msm8974-liquid.dtsi b/arch/arm/boot/dts/msm8974-liquid.dtsi
index b61348e..e882c17 100644
--- a/arch/arm/boot/dts/msm8974-liquid.dtsi
+++ b/arch/arm/boot/dts/msm8974-liquid.dtsi
@@ -183,14 +183,14 @@
 		qcom,mode = <0>;
 		qcom,pull = <0>;
 		qcom,vin-sel = <2>;
-		qcom,select = <0>;
+		qcom,src-sel = <0>;
 	};
 
 	gpio@c100 { /* GPIO 2 */
 		qcom,mode = <0>;
 		qcom,pull = <0>;
 		qcom,vin-sel = <2>;
-		qcom,select = <0>;
+		qcom,src-sel = <0>;
 	};
 
 	gpio@c200 { /* GPIO 3 */
@@ -203,7 +203,7 @@
 		qcom,mode = <0>;
 		qcom,pull = <0>;
 		qcom,vin-sel = <2>;
-		qcom,select = <0>;
+		qcom,src-sel = <0>;
 	};
 
 	gpio@c500 { /* GPIO 6 */
@@ -239,7 +239,7 @@
 		qcom,pull = <5>;
 		qcom,vin-sel = <2>;
 		qcom,out-strength = <3>;
-		qcom,src-select = <2>;
+		qcom,src-sel = <2>;
 		qcom,master-en = <1>;
 	};
 
@@ -258,7 +258,7 @@
 		qcom,pull = <5>;		/* QPNP_PIN_PULL_NO */
 		qcom,vin-sel = <2>;		/* QPNP_PIN_VIN2 */
 		qcom,out-strength = <2>;	/* QPNP_PIN_OUT_STRENGTH_MED */
-		qcom,src-select = <0>;		/* QPNP_PIN_SEL_FUNC_CONSTANT */
+		qcom,src-sel = <0>;		/* QPNP_PIN_SEL_FUNC_CONSTANT */
 		qcom,master-en = <1>;
 	};
 
@@ -319,7 +319,7 @@
 		qcom,pull = <5>; /* QPNP_PIN_PULL_NO */
 		qcom,vin-sel = <2>; /* QPNP_PIN_VIN2 */
 		qcom,out-strength = <3>; /* QPNP_PIN_OUT_STRENGTH_HIGH */
-		qcom,src-select = <3>; /* QPNP_PIN_SEL_FUNC_2 */
+		qcom,src-sel = <3>; /* QPNP_PIN_SEL_FUNC_2 */
 		qcom,master-en = <1>;
 	};
 };
@@ -334,7 +334,7 @@
 		qcom,mode = <1>; /* Digital output */
 		qcom,invert = <0>; /* Output low initially */
 		qcom,vin-sel = <2>; /* PM8941 S3 = 1.8 V */
-		qcom,src-select = <0>; /* Constant */
+		qcom,src-sel = <0>; /* Constant */
 		qcom,master-en = <1>; /* Enable MPP */
 	};
 
@@ -349,7 +349,7 @@
 		qcom,mode = <1>; /* DIG_OUT */
 		qcom,output-type = <0>; /* CMOS */
 		qcom,vin-sel = <2>; /* PM8941_S3 1.8V > 1.6V */
-		qcom,src-select = <0>; /* CONSTANT */
+		qcom,src-sel = <0>; /* CONSTANT */
 		qcom,master-en = <1>; /* ENABLE MPP */
 	};
 
@@ -358,7 +358,7 @@
 		qcom,mode = <1>; /* DIG_OUT */
 		qcom,output-type = <0>; /* CMOS */
 		qcom,vin-sel = <2>; /* PM8941_S3 1.8V > 1.6V */
-		qcom,src-select = <0>; /* CONSTANT */
+		qcom,src-sel = <0>; /* CONSTANT */
 		qcom,master-en = <1>; /* ENABLE MPP */
 	};
 
@@ -382,7 +382,7 @@
 		qcom,mode = <1>; /* DIG_OUT */
 		qcom,output-type = <0>; /* CMOS */
 		qcom,vin-sel = <2>; /* PM8841_S3A 1.8V */
-		qcom,src-select = <0>; /* CONSTANT */
+		qcom,src-sel = <0>; /* CONSTANT */
 		qcom,master-en = <1>; /* ENABLE MPP */
 	};
 
@@ -391,7 +391,7 @@
 		qcom,mode = <1>; /* DIG_OUT */
 		qcom,output-type = <0>; /* CMOS */
 		qcom,vin-sel = <0>; /* PM8841_VPH 3.4V */
-		qcom,src-select = <0>; /* CONSTANT */
+		qcom,src-sel = <0>; /* CONSTANT */
 		qcom,master-en = <1>; /* ENABLE MPP */
 	};
 };
diff --git a/arch/arm/boot/dts/msm8974-mtp.dtsi b/arch/arm/boot/dts/msm8974-mtp.dtsi
index e332bbd..f4be0dc 100644
--- a/arch/arm/boot/dts/msm8974-mtp.dtsi
+++ b/arch/arm/boot/dts/msm8974-mtp.dtsi
@@ -220,21 +220,21 @@
 		qcom,mode = <0>;
 		qcom,pull = <0>;
 		qcom,vin-sel = <2>;
-		qcom,select = <0>;
+		qcom,src-sel = <0>;
 	};
 
 	gpio@c300 { /* GPIO 4 */
 		qcom,mode = <0>;
 		qcom,pull = <0>;
 		qcom,vin-sel = <2>;
-		qcom,select = <0>;
+		qcom,src-sel = <0>;
 	};
 
 	gpio@c400 { /* GPIO 5 */
 		qcom,mode = <0>;
 		qcom,pull = <0>;
 		qcom,vin-sel = <2>;
-		qcom,select = <0>;
+		qcom,src-sel = <0>;
 	};
 
 	gpio@c500 { /* GPIO 6 */
@@ -270,7 +270,7 @@
 		qcom,pull = <5>;
 		qcom,vin-sel = <2>;
 		qcom,out-strength = <3>;
-		qcom,src-select = <2>;
+		qcom,src-sel = <2>;
 		qcom,master-en = <1>;
 	};
 
@@ -289,7 +289,7 @@
 		qcom,pull = <5>;		/* QPNP_PIN_PULL_NO */
 		qcom,vin-sel = <2>;		/* QPNP_PIN_VIN2 */
 		qcom,out-strength = <2>;	/* QPNP_PIN_OUT_STRENGTH_MED */
-		qcom,src-select = <0>;		/* QPNP_PIN_SEL_FUNC_CONSTANT */
+		qcom,src-sel = <0>;		/* QPNP_PIN_SEL_FUNC_CONSTANT */
 		qcom,master-en = <1>;
 	};
 
@@ -367,7 +367,7 @@
 		qcom,mode = <1>; /* DIG_OUT */
 		qcom,output-type = <0>; /* CMOS */
 		qcom,vin-sel = <2>; /* PM8941_S3 1.8V > 1.6V */
-		qcom,src-select = <0>; /* CONSTANT */
+		qcom,src-sel = <0>; /* CONSTANT */
 		qcom,master-en = <1>; /* ENABLE MPP */
 	};
 
@@ -376,7 +376,7 @@
 		qcom,mode = <1>; /* DIG_OUT */
 		qcom,output-type = <0>; /* CMOS */
 		qcom,vin-sel = <2>; /* PM8941_S3 1.8V > 1.6V */
-		qcom,src-select = <0>; /* CONSTANT */
+		qcom,src-sel = <0>; /* CONSTANT */
 		qcom,master-en = <1>; /* ENABLE MPP */
 	};
 
diff --git a/arch/arm/boot/dts/msm8974-pm.dtsi b/arch/arm/boot/dts/msm8974-pm.dtsi
index c6cbca3..8da4ae6 100644
--- a/arch/arm/boot/dts/msm8974-pm.dtsi
+++ b/arch/arm/boot/dts/msm8974-pm.dtsi
@@ -422,4 +422,10 @@
 		compatible = "qcom,pc-cntr";
 		reg = <0xfe805664 0x40>;
 	};
+
+	qcom,pm-8x60 {
+		compatible = "qcom,pm-8x60";
+		qcom,pc-mode = <0>; /*MSM_PC_TZ_L2_INT */
+		qcom,use-sync-timer;
+	};
 };
diff --git a/arch/arm/boot/dts/msm8974.dtsi b/arch/arm/boot/dts/msm8974.dtsi
index 6b65837..467c7ac 100644
--- a/arch/arm/boot/dts/msm8974.dtsi
+++ b/arch/arm/boot/dts/msm8974.dtsi
@@ -527,6 +527,57 @@
 					 <0x1e70008c>; /* LPG_CHAN12 */
 
 		qcom,pm8941@1 {
+			qcom,leds@d300 {
+				status = "okay";
+				qcom,flash_0 {
+					qcom,max-current = <1000>;
+					qcom,default-state = "off";
+					qcom,headroom = <0>;
+					qcom,duration = <1280>;
+					qcom,clamp-curr = <200>;
+					qcom,startup-dly = <1>;
+					qcom,safety-timer;
+					label = "flash";
+					linux,default-trigger =
+						"flash0_trigger";
+					qcom,id = <1>;
+					linux,name = "led:flash_0";
+					qcom,current = <625>;
+				};
+
+				qcom,flash_1 {
+					qcom,max-current = <1000>;
+					qcom,default-state = "off";
+					qcom,headroom = <0>;
+					qcom,duration = <1280>;
+					qcom,clamp-curr = <200>;
+					qcom,startup-dly = <1>;
+					qcom,safety-timer;
+					linux,default-trigger =
+						"flash1_trigger";
+					label = "flash";
+					qcom,id = <2>;
+					linux,name = "led:flash_1";
+					qcom,current = <625>;
+				};
+			};
+
+			qcom,leds@d400 {
+				status = "disabled";
+			};
+
+			qcom,leds@d500 {
+				status = "disabled";
+			};
+
+			qcom,leds@d600 {
+				status = "disabled";
+			};
+
+			qcom,leds@d700 {
+				status = "disabled";
+			};
+
 			qcom,leds@d800 {
 				status = "okay";
 				qcom,wled_0 {
@@ -535,7 +586,7 @@
 					linux,default-trigger = "bkl-trigger";
 					qcom,cs-out-en;
 					qcom,op-fdbck;
-					qcom,default-state = "on";
+					qcom,default-state = "off";
 					qcom,max-current = <25>;
 					qcom,ctrl-delay-us = <0>;
 					qcom,boost-curr-lim = <3>;
@@ -582,6 +633,7 @@
 			qcom,leds@e100 {
 				status = "disabled";
 			};
+
 		};
 	};
 
@@ -828,27 +880,18 @@
 		reg = <0xfc880000 0x100>,
 		      <0xfd485000 0x400>,
 		      <0xfc820000 0x020>,
-		      <0xfc401680 0x004>;
+		      <0xfc401680 0x004>,
+		      <0x0d1fc000 0x4000>;
 		reg-names = "qdsp6_base", "halt_base", "rmb_base",
-			    "restart_reg";
+			    "restart_reg", "metadata_base";
 
+		interrupts = <0 24 1>;
 		vdd_mss-supply = <&pm8841_s3>;
 
 		qcom,firmware-name = "mba";
 		qcom,pil-self-auth = <1>;
 	};
 
-	qcom,mba@fc820000 {
-		compatible = "qcom,pil-mba";
-		reg = <0xfc820000 0x0020>,
-		      <0x0d1fc000 0x4000>;
-		reg-names = "rmb_base", "metadata_base";
-		interrupts = <0 24 1>;
-
-		qcom,firmware-name = "modem";
-		qcom,depends-on    = "mba";
-	};
-
 	qcom,pronto@fb21b000 {
 		compatible = "qcom,pil-pronto";
 		reg = <0xfb21b000 0x3000>,
@@ -1009,6 +1052,12 @@
 		qcom,memory-reservation-size = <0x100000>; /* 1M EBI1 buffer */
 	};
 
+	qcom,msm-contig-mem {
+		compatible = "qcom,msm-contig-mem";
+		qcom,memory-reservation-type = "EBI1";
+		qcom,memory-reservation-size = <0x280000>; /* 2.5M EBI1 buffer */
+	};
+
         qcom,qcedev@fd440000 {
 		compatible = "qcom,qcedev";
 		reg = <0xfd440000 0x20000>,
@@ -1117,7 +1166,10 @@
                compatible = "qcom,msm-wdog-debug";
                reg = <0xfc401000 0x1000>;
         };
-
+        qcom,msm-mem-hole {
+                compatible = "qcom,msm-mem-hole";
+                qcom,memblock-remove = <0x8400000 0x7b00000>; /* Address and Size of Hole */
+        };
 };
 
 /include/ "msm-pm8x41-rpm-regulator.dtsi"
diff --git a/arch/arm/boot/dts/msm9625-cdp.dts b/arch/arm/boot/dts/msm9625-cdp.dts
index 89c269e..e48572c 100644
--- a/arch/arm/boot/dts/msm9625-cdp.dts
+++ b/arch/arm/boot/dts/msm9625-cdp.dts
@@ -38,7 +38,7 @@
 		qcom,invert = <0>; /* Output low */
 		qcom,out-strength = <1>; /* Low */
 		qcom,vin-sel = <2>; /* PM8019 L11 - 1.8V */
-		qcom,src-select = <0>; /* Constant */
+		qcom,src-sel = <0>; /* Constant */
 		qcom,master-en = <1>; /* Enable GPIO */
 	};
 
diff --git a/arch/arm/boot/dts/msm9625-mtp.dts b/arch/arm/boot/dts/msm9625-mtp.dts
index a5673e5..606a4bc 100644
--- a/arch/arm/boot/dts/msm9625-mtp.dts
+++ b/arch/arm/boot/dts/msm9625-mtp.dts
@@ -38,7 +38,7 @@
 		qcom,invert = <0>; /* Output low */
 		qcom,out-strength = <1>; /* Low */
 		qcom,vin-sel = <2>; /* PM8019 L11 - 1.8V */
-		qcom,src-select = <0>; /* Constant */
+		qcom,src-sel = <0>; /* Constant */
 		qcom,master-en = <1>; /* Enable GPIO */
 	};
 
diff --git a/arch/arm/configs/msm8974-perf_defconfig b/arch/arm/configs/msm8974-perf_defconfig
index 98c1ede..23b4527 100644
--- a/arch/arm/configs/msm8974-perf_defconfig
+++ b/arch/arm/configs/msm8974-perf_defconfig
@@ -275,6 +275,7 @@
 CONFIG_QPNP_BMS=y
 CONFIG_SENSORS_QPNP_ADC_VOLTAGE=y
 CONFIG_SENSORS_QPNP_ADC_CURRENT=y
+CONFIG_SENSORS_EPM_ADC=y
 CONFIG_THERMAL=y
 CONFIG_THERMAL_TSENS8974=y
 CONFIG_THERMAL_QPNP=y
diff --git a/arch/arm/configs/msm8974_defconfig b/arch/arm/configs/msm8974_defconfig
index 328a4dc..1a03b5b 100644
--- a/arch/arm/configs/msm8974_defconfig
+++ b/arch/arm/configs/msm8974_defconfig
@@ -276,6 +276,7 @@
 CONFIG_QPNP_BMS=y
 CONFIG_SENSORS_QPNP_ADC_VOLTAGE=y
 CONFIG_SENSORS_QPNP_ADC_CURRENT=y
+CONFIG_SENSORS_EPM_ADC=y
 CONFIG_THERMAL=y
 CONFIG_THERMAL_TSENS8974=y
 CONFIG_THERMAL_QPNP=y
diff --git a/arch/arm/include/asm/io.h b/arch/arm/include/asm/io.h
index 42fef7c..938be62 100644
--- a/arch/arm/include/asm/io.h
+++ b/arch/arm/include/asm/io.h
@@ -268,12 +268,17 @@
 					__raw_readw(c)); __r; })
 #define readl_relaxed(c) ({ u32 __r = le32_to_cpu((__force __le32) \
 					__raw_readl(c)); __r; })
+#define readl_relaxed_no_log(c) ({ u32 __r = le32_to_cpu((__force __le32) \
+					__raw_readl_no_log(c)); __r; })
+
 
 #define writeb_relaxed(v,c)	((void)__raw_writeb(v,c))
 #define writew_relaxed(v,c)	((void)__raw_writew((__force u16) \
 					cpu_to_le16(v),c))
 #define writel_relaxed(v,c)	((void)__raw_writel((__force u32) \
 					cpu_to_le32(v),c))
+#define writel_relaxed_no_log(v, c)  ((void)__raw_writel_no_log((__force u32) \
+					cpu_to_le32(v), c))
 
 #define readb(c)		({ u8  __v = readb_relaxed(c); __iormb(); __v; })
 #define readw(c)		({ u16 __v = readw_relaxed(c); __iormb(); __v; })
diff --git a/arch/arm/mach-msm/Kconfig b/arch/arm/mach-msm/Kconfig
index 73e1ad2..6bd87de 100644
--- a/arch/arm/mach-msm/Kconfig
+++ b/arch/arm/mach-msm/Kconfig
@@ -963,7 +963,7 @@
 	default "0x00000000" if ARCH_MSM8974
 	default "0x00000000" if ARCH_MPQ8092
 	default "0x00000000" if ARCH_MSM8226
-	default "0x80200000" if ARCH_MSM8910
+	default "0x00000000" if ARCH_MSM8910
 	default "0x10000000" if ARCH_FSM9XXX
 	default "0x00200000" if ARCH_MSM9625
 	default "0x00200000" if !MSM_STACKED_MEMORY
@@ -1982,18 +1982,14 @@
 	  ADSP if the processor encounters a fatal error.
 
 config MSM_PIL_MSS_QDSP6V5
-       tristate "MSS QDSP6v5 (Hexagon) Boot Support"
-       depends on MSM_PIL
-       help
-         Support for booting and shutting down QDSP6v5 (Hexagon) processors
-	 in modem subsystems.
-
-config MSM_PIL_MBA
-	tristate "Support for modem self-authentication"
-	depends on MSM_PIL_MSS_QDSP6V5 && MSM_SUBSYSTEM_RESTART
+	tristate "MSS QDSP6v5 (Hexagon) Boot Support"
+	depends on MSM_PIL && MSM_SUBSYSTEM_RESTART
 	help
-	  Support for booting self-authenticating modems using the Modem Boot
-	  Authenticator.
+	  Support for booting and shutting down QDSP6v5 (Hexagon) processors
+	  in modem subsystems. If you would like to make or receive phone
+	  calls then say Y here.
+
+	  If unsure, say N.
 
 config MSM_PIL_RIVA
 	tristate "RIVA (WCNSS) Boot Support"
diff --git a/arch/arm/mach-msm/Makefile b/arch/arm/mach-msm/Makefile
index fe5fe8c..b9a16fa 100644
--- a/arch/arm/mach-msm/Makefile
+++ b/arch/arm/mach-msm/Makefile
@@ -84,7 +84,6 @@
 obj-$(CONFIG_MSM_PIL_MODEM_QDSP6V4) += pil-q6v4.o pil-q6v4-mss.o
 obj-$(CONFIG_MSM_PIL_LPASS_QDSP6V5) += pil-q6v5.o pil-q6v5-lpass.o
 obj-$(CONFIG_MSM_PIL_MSS_QDSP6V5) += pil-q6v5.o pil-q6v5-mss.o
-obj-$(CONFIG_MSM_PIL_MBA) += pil-mba.o
 obj-$(CONFIG_MSM_PIL_RIVA) += pil-riva.o
 obj-$(CONFIG_MSM_PIL_TZAPPS) += pil-tzapps.o
 obj-$(CONFIG_MSM_PIL_VIDC) += pil-vidc.o
diff --git a/arch/arm/mach-msm/Makefile.boot b/arch/arm/mach-msm/Makefile.boot
index fa9ee54..cf1f401 100644
--- a/arch/arm/mach-msm/Makefile.boot
+++ b/arch/arm/mach-msm/Makefile.boot
@@ -66,4 +66,4 @@
    zreladdr-$(CONFIG_ARCH_MPQ8092)	:= 0x00008000
 
 # MSM8910
-   zreladdr-$(CONFIG_ARCH_MSM8910)	:= 0x80208000
+   zreladdr-$(CONFIG_ARCH_MSM8910)	:= 0x00008000
diff --git a/arch/arm/mach-msm/bam_dmux.c b/arch/arm/mach-msm/bam_dmux.c
index 7ba22f4..c475e2d 100644
--- a/arch/arm/mach-msm/bam_dmux.c
+++ b/arch/arm/mach-msm/bam_dmux.c
@@ -193,6 +193,7 @@
 static struct sps_mem_buffer rx_desc_mem_buf;
 static struct sps_register_event tx_register_event;
 static struct sps_register_event rx_register_event;
+static bool satellite_mode;
 
 static struct bam_ch_info bam_ch[BAM_DMUX_NUM_CHANNELS];
 static int bam_mux_initialized;
@@ -2074,7 +2075,7 @@
 	a2_props.options = SPS_BAM_OPT_IRQ_WAKEUP;
 	a2_props.num_pipes = A2_NUM_PIPES;
 	a2_props.summing_threshold = A2_SUMMING_THRESHOLD;
-	if (cpu_is_msm9615())
+	if (cpu_is_msm9615() || satellite_mode)
 		a2_props.manage = SPS_BAM_MGR_DEVICE_REMOTE;
 	/* need to free on tear down */
 	ret = sps_register_bam_device(&a2_props, &h);
@@ -2246,7 +2247,7 @@
 	a2_props.options = SPS_BAM_OPT_IRQ_WAKEUP;
 	a2_props.num_pipes = A2_NUM_PIPES;
 	a2_props.summing_threshold = A2_SUMMING_THRESHOLD;
-	if (cpu_is_msm9615())
+	if (cpu_is_msm9615() || satellite_mode)
 		a2_props.manage = SPS_BAM_MGR_DEVICE_REMOTE;
 	ret = sps_register_bam_device(&a2_props, &h);
 	if (ret < 0) {
@@ -2374,10 +2375,14 @@
 			pr_err("%s: irq field missing\n", __func__);
 			return -ENODEV;
 		}
-		DBG("%s: base:%p size:%x irq:%d\n", __func__,
+		satellite_mode = of_property_read_bool(pdev->dev.of_node,
+						"qcom,satellite-mode");
+
+		DBG("%s: base:%p size:%x irq:%d satellite:%d\n", __func__,
 							a2_phys_base,
 							a2_phys_size,
-							a2_bam_irq);
+							a2_bam_irq,
+							satellite_mode);
 	} else { /* fallback to default init data */
 		a2_phys_base = (void *)(A2_PHYS_BASE);
 		a2_phys_size = A2_PHYS_SIZE;
diff --git a/arch/arm/mach-msm/board-8064-gpu.c b/arch/arm/mach-msm/board-8064-gpu.c
index f35ae6b..5ebb010 100644
--- a/arch/arm/mach-msm/board-8064-gpu.c
+++ b/arch/arm/mach-msm/board-8064-gpu.c
@@ -226,7 +226,7 @@
 			.io_fraction = 0,
 		},
 		{
-			.gpu_freq = 325000000,
+			.gpu_freq = 320000000,
 			.bus_freq = 3,
 			.io_fraction = 33,
 		},
diff --git a/arch/arm/mach-msm/board-8960.c b/arch/arm/mach-msm/board-8960.c
index ce2531b..167923f 100644
--- a/arch/arm/mach-msm/board-8960.c
+++ b/arch/arm/mach-msm/board-8960.c
@@ -2875,8 +2875,8 @@
 	/* Fixup data that needs to change based on GPU ID */
 	if (cpu_is_msm8960ab()) {
 		kgsl_3d0_pdata->chipid = ADRENO_CHIPID(3, 2, 1, 0);
-		/* 8960PRO nominal clock rate is 325Mhz instead of 320Mhz */
-		kgsl_3d0_pdata->pwrlevel[1].gpu_freq = 325000000;
+		/* 8960PRO nominal clock rate is 320Mhz */
+		kgsl_3d0_pdata->pwrlevel[1].gpu_freq = 320000000;
 	} else {
 		kgsl_3d0_pdata->iommu_count = 1;
 		if (SOCINFO_VERSION_MAJOR(soc_platform_version) == 1) {
diff --git a/arch/arm/mach-msm/board-8974.c b/arch/arm/mach-msm/board-8974.c
index 19fb222..98a82b1 100644
--- a/arch/arm/mach-msm/board-8974.c
+++ b/arch/arm/mach-msm/board-8974.c
@@ -49,17 +49,6 @@
 #include "modem_notifier.h"
 #include "lpm_resources.h"
 
-#define MSM_KERNEL_EBI1_MEM_SIZE	0x280000
-
-#ifdef CONFIG_KERNEL_PMEM_EBI_REGION
-static unsigned kernel_ebi1_mem_size = MSM_KERNEL_EBI1_MEM_SIZE;
-static int __init kernel_ebi1_mem_size_setup(char *p)
-{
-	kernel_ebi1_mem_size = memparse(p, NULL);
-	return 0;
-}
-early_param("kernel_ebi1_mem_size", kernel_ebi1_mem_size_setup);
-#endif
 
 static struct memtype_reserve msm8974_reserve_table[] __initdata = {
 	[MEMTYPE_SMI] = {
@@ -77,13 +66,6 @@
 	return MEMTYPE_EBI1;
 }
 
-static void __init reserve_ebi_memory(void)
-{
-#ifdef CONFIG_KERNEL_PMEM_EBI_REGION
-	msm8974_reserve_table[MEMTYPE_EBI1].size += kernel_ebi1_mem_size;
-#endif
-}
-
 static struct resource smd_resource[] = {
 	{
 		.name	= "modem_smd_in",
@@ -246,14 +228,8 @@
 	}
 };
 
-static void __init msm8974_calculate_reserve_sizes(void)
-{
-	reserve_ebi_memory();
-}
-
 static struct reserve_info msm8974_reserve_info __initdata = {
 	.memtype_reserve_table = msm8974_reserve_table,
-	.calculate_reserve_sizes = msm8974_calculate_reserve_sizes,
 	.paddr_to_memtype = msm8974_paddr_to_memtype,
 };
 
@@ -501,7 +477,6 @@
 	OF_DEV_AUXDATA("qcom,pil-q6v5-lpass",   0xFE200000, \
 			"pil-q6v5-lpass", NULL),
 	OF_DEV_AUXDATA("qcom,pil-q6v5-mss", 0xFC880000, "pil-q6v5-mss", NULL),
-	OF_DEV_AUXDATA("qcom,pil-mba",     0xFC820000, "pil-mba", NULL),
 	OF_DEV_AUXDATA("qcom,pil-pronto", 0xFB21B000, \
 			"pil_pronto", NULL),
 	OF_DEV_AUXDATA("arm,coresight-tmc", 0xFC322000, \
diff --git a/arch/arm/mach-msm/board-msm7627a-bt.c b/arch/arm/mach-msm/board-msm7627a-bt.c
index bcc9645..1c2d8a2 100644
--- a/arch/arm/mach-msm/board-msm7627a-bt.c
+++ b/arch/arm/mach-msm/board-msm7627a-bt.c
@@ -103,11 +103,12 @@
 	if (machine_is_msm7627a_qrd1())
 		gpio_bt_sys_rest_en = 114;
 	if (machine_is_msm7627a_evb() || machine_is_msm8625_evb()
-				|| machine_is_msm8625_evt()
-				|| machine_is_qrd_skud_prime())
+				|| machine_is_msm8625_evt())
 		gpio_bt_sys_rest_en = 16;
 	if (machine_is_msm8625_qrd7())
 		gpio_bt_sys_rest_en = 88;
+	if (machine_is_qrd_skud_prime())
+		gpio_bt_sys_rest_en = 35;
 	if (machine_is_msm7627a_qrd3()) {
 		if (socinfo == 0x70002)
 			gpio_bt_sys_rest_en = 88;
@@ -976,9 +977,6 @@
 	int i, rc = 0;
 	struct device *dev;
 
-	if (machine_is_qrd_skud_prime())
-		return;
-
 	gpio_bt_config();
 
 	rc = i2c_register_board_info(MSM_GSBI1_QUP_I2C_BUS_ID,
diff --git a/arch/arm/mach-msm/board-msm7x27a.c b/arch/arm/mach-msm/board-msm7x27a.c
index 13c4be2..4e14ff3 100644
--- a/arch/arm/mach-msm/board-msm7x27a.c
+++ b/arch/arm/mach-msm/board-msm7x27a.c
@@ -375,7 +375,8 @@
 };
 
 /* 8625 PM platform data */
-static struct msm_pm_platform_data msm8625_pm_data[MSM_PM_SLEEP_MODE_NR * 2] = {
+static struct msm_pm_platform_data
+		msm8625_pm_data[MSM_PM_SLEEP_MODE_NR * CONFIG_NR_CPUS] = {
 	/* CORE0 entries */
 	[MSM_PM_MODE(0, MSM_PM_SLEEP_MODE_POWER_COLLAPSE)] = {
 					.idle_supported = 1,
@@ -433,6 +434,44 @@
 					.residency = 10,
 	},
 
+	/* picked latency & redisdency values from 7x30 */
+	[MSM_PM_MODE(2, MSM_PM_SLEEP_MODE_POWER_COLLAPSE_STANDALONE)] = {
+					.idle_supported = 1,
+					.suspend_supported = 1,
+					.idle_enabled = 0,
+					.suspend_enabled = 0,
+					.latency = 500,
+					.residency = 6000,
+	},
+
+	[MSM_PM_MODE(2, MSM_PM_SLEEP_MODE_WAIT_FOR_INTERRUPT)] = {
+					.idle_supported = 1,
+					.suspend_supported = 1,
+					.idle_enabled = 1,
+					.suspend_enabled = 1,
+					.latency = 2,
+					.residency = 10,
+	},
+
+	/* picked latency & redisdency values from 7x30 */
+	[MSM_PM_MODE(3, MSM_PM_SLEEP_MODE_POWER_COLLAPSE_STANDALONE)] = {
+					.idle_supported = 1,
+					.suspend_supported = 1,
+					.idle_enabled = 0,
+					.suspend_enabled = 0,
+					.latency = 500,
+					.residency = 6000,
+	},
+
+	[MSM_PM_MODE(3, MSM_PM_SLEEP_MODE_WAIT_FOR_INTERRUPT)] = {
+					.idle_supported = 1,
+					.suspend_supported = 1,
+					.idle_enabled = 1,
+					.suspend_enabled = 1,
+					.latency = 2,
+					.residency = 10,
+	},
+
 };
 
 static struct msm_pm_boot_platform_data msm_pm_8625_boot_pdata __initdata = {
diff --git a/arch/arm/mach-msm/board-qrd7627a.c b/arch/arm/mach-msm/board-qrd7627a.c
index fd322e9..023ce86 100644
--- a/arch/arm/mach-msm/board-qrd7627a.c
+++ b/arch/arm/mach-msm/board-qrd7627a.c
@@ -349,7 +349,8 @@
 };
 
 /* 8625 PM platform data */
-static struct msm_pm_platform_data msm8625_pm_data[MSM_PM_SLEEP_MODE_NR * 2] = {
+static struct msm_pm_platform_data
+		msm8625_pm_data[MSM_PM_SLEEP_MODE_NR * CONFIG_NR_CPUS] = {
 	/* CORE0 entries */
 	[MSM_PM_MODE(0, MSM_PM_SLEEP_MODE_POWER_COLLAPSE)] = {
 					.idle_supported = 1,
@@ -407,6 +408,44 @@
 					.residency = 10,
 	},
 
+	/* picked latency & redisdency values from 7x30 */
+	[MSM_PM_MODE(2, MSM_PM_SLEEP_MODE_POWER_COLLAPSE_STANDALONE)] = {
+					.idle_supported = 1,
+					.suspend_supported = 1,
+					.idle_enabled = 0,
+					.suspend_enabled = 0,
+					.latency = 500,
+					.residency = 6000,
+	},
+
+	[MSM_PM_MODE(2, MSM_PM_SLEEP_MODE_WAIT_FOR_INTERRUPT)] = {
+					.idle_supported = 1,
+					.suspend_supported = 1,
+					.idle_enabled = 1,
+					.suspend_enabled = 1,
+					.latency = 2,
+					.residency = 10,
+	},
+
+	/* picked latency & redisdency values from 7x30 */
+	[MSM_PM_MODE(3, MSM_PM_SLEEP_MODE_POWER_COLLAPSE_STANDALONE)] = {
+					.idle_supported = 1,
+					.suspend_supported = 1,
+					.idle_enabled = 0,
+					.suspend_enabled = 0,
+					.latency = 500,
+					.residency = 6000,
+	},
+
+	[MSM_PM_MODE(3, MSM_PM_SLEEP_MODE_WAIT_FOR_INTERRUPT)] = {
+					.idle_supported = 1,
+					.suspend_supported = 1,
+					.idle_enabled = 1,
+					.suspend_enabled = 1,
+					.latency = 2,
+					.residency = 10,
+	},
+
 };
 
 static struct msm_pm_boot_platform_data msm_pm_8625_boot_pdata __initdata = {
diff --git a/arch/arm/mach-msm/clock-8974.c b/arch/arm/mach-msm/clock-8974.c
index 76b8abf..d080a379 100644
--- a/arch/arm/mach-msm/clock-8974.c
+++ b/arch/arm/mach-msm/clock-8974.c
@@ -5022,7 +5022,6 @@
 	CLK_LOOKUP("xo",	cxo_clk_src.c,	"msm_otg"),
 	CLK_LOOKUP("xo",	cxo_clk_src.c,	"pil-q6v5-lpass"),
 	CLK_LOOKUP("xo",	cxo_clk_src.c,	"pil-q6v5-mss"),
-	CLK_LOOKUP("xo",	cxo_clk_src.c,	"pil-mba"),
 	CLK_LOOKUP("xo",	cxo_clk_src.c,	"fb000000.qcom,wcnss-wlan"),
 	CLK_LOOKUP("xo",	cxo_clk_src.c,	"pil_pronto"),
 	CLK_LOOKUP("measure",	measure_clk.c,	"debug"),
diff --git a/arch/arm/mach-msm/clock-8x60.c b/arch/arm/mach-msm/clock-8x60.c
index 3816b54..5c5b51e 100644
--- a/arch/arm/mach-msm/clock-8x60.c
+++ b/arch/arm/mach-msm/clock-8x60.c
@@ -3101,7 +3101,7 @@
 	.c = {
 		.dbg_name = "pcm_clk",
 		.ops = &clk_ops_rcg,
-		VDD_DIG_FMAX_MAP1(LOW, 24580000),
+		VDD_DIG_FMAX_MAP1(LOW, 27000000),
 		CLK_INIT(pcm_clk.c),
 		.rate = ULONG_MAX,
 	},
diff --git a/arch/arm/mach-msm/include/mach/bam_dmux.h b/arch/arm/mach-msm/include/mach/bam_dmux.h
index f02a882..f11b72c 100644
--- a/arch/arm/mach-msm/include/mach/bam_dmux.h
+++ b/arch/arm/mach-msm/include/mach/bam_dmux.h
@@ -28,6 +28,18 @@
 	BAM_DMUX_DATA_RMNET_6,
 	BAM_DMUX_DATA_RMNET_7,
 	BAM_DMUX_USB_RMNET_0,
+	BAM_DMUX_RESERVED_0, /* 9..11 are reserved*/
+	BAM_DMUX_RESERVED_1,
+	BAM_DMUX_RESERVED_2,
+	BAM_DMUX_DATA_REV_RMNET_0,
+	BAM_DMUX_DATA_REV_RMNET_1,
+	BAM_DMUX_DATA_REV_RMNET_2,
+	BAM_DMUX_DATA_REV_RMNET_3,
+	BAM_DMUX_DATA_REV_RMNET_4,
+	BAM_DMUX_DATA_REV_RMNET_5,
+	BAM_DMUX_DATA_REV_RMNET_6,
+	BAM_DMUX_DATA_REV_RMNET_7,
+	BAM_DMUX_DATA_REV_RMNET_8,
 	BAM_DMUX_NUM_CHANNELS
 };
 
diff --git a/arch/arm/mach-msm/include/mach/msm_hdmi_audio.h b/arch/arm/mach-msm/include/mach/msm_hdmi_audio.h
index 2455e93..9b04141 100644
--- a/arch/arm/mach-msm/include/mach/msm_hdmi_audio.h
+++ b/arch/arm/mach-msm/include/mach/msm_hdmi_audio.h
@@ -29,7 +29,8 @@
 	HDMI_SAMPLE_RATE_88_2KHZ,
 	HDMI_SAMPLE_RATE_96KHZ,
 	HDMI_SAMPLE_RATE_176_4KHZ,
-	HDMI_SAMPLE_RATE_192KHZ
+	HDMI_SAMPLE_RATE_192KHZ,
+	HDMI_SAMPLE_RATE_MAX
 };
 
 int hdmi_audio_enable(bool on , u32 fifo_water_mark);
diff --git a/arch/arm/mach-msm/include/mach/subsystem_restart.h b/arch/arm/mach-msm/include/mach/subsystem_restart.h
index a95e943..64190d2 100644
--- a/arch/arm/mach-msm/include/mach/subsystem_restart.h
+++ b/arch/arm/mach-msm/include/mach/subsystem_restart.h
@@ -70,6 +70,8 @@
 extern struct subsys_device *subsys_register(struct subsys_desc *desc);
 extern void subsys_unregister(struct subsys_device *dev);
 
+extern void subsys_default_online(struct subsys_device *dev);
+
 #else
 
 static inline int get_restart_level(void)
@@ -102,6 +104,8 @@
 
 static inline void subsys_unregister(struct subsys_device *dev) { }
 
+static inline void subsys_default_online(struct subsys_device *dev) { }
+
 #endif /* CONFIG_MSM_SUBSYSTEM_RESTART */
 
 #endif
diff --git a/arch/arm/mach-msm/mdm.c b/arch/arm/mach-msm/mdm.c
index 02978cf..8dd4bac 100644
--- a/arch/arm/mach-msm/mdm.c
+++ b/arch/arm/mach-msm/mdm.c
@@ -354,6 +354,7 @@
 		ret = PTR_ERR(charm_subsys);
 		goto fatal_err;
 	}
+	subsys_default_online(charm_subsys);
 
 	irq = platform_get_irq(pdev, 0);
 	if (irq < 0) {
diff --git a/arch/arm/mach-msm/mdm_common.c b/arch/arm/mach-msm/mdm_common.c
index 58b26f2..b81832e 100644
--- a/arch/arm/mach-msm/mdm_common.c
+++ b/arch/arm/mach-msm/mdm_common.c
@@ -681,6 +681,7 @@
 		ret = PTR_ERR(mdm_subsys_dev);
 		goto fatal_err;
 	}
+	subsys_default_online(mdm_subsys_dev);
 
 	/* ERR_FATAL irq. */
 	irq = MSM_GPIO_TO_INT(mdm_drv->mdm2ap_errfatal_gpio);
diff --git a/arch/arm/mach-msm/memory.c b/arch/arm/mach-msm/memory.c
index 7d7380b..3fe65b8 100644
--- a/arch/arm/mach-msm/memory.c
+++ b/arch/arm/mach-msm/memory.c
@@ -464,3 +464,8 @@
 
 	return ret;
 }
+
+/* Provide a string that anonymous device tree allocations (those not
+ * directly associated with any driver) can use for their "compatible"
+ * field */
+EXPORT_COMPAT("qcom,msm-contig-mem");
diff --git a/arch/arm/mach-msm/pil-mba.c b/arch/arm/mach-msm/pil-mba.c
deleted file mode 100644
index daafd1d..0000000
--- a/arch/arm/mach-msm/pil-mba.c
+++ /dev/null
@@ -1,470 +0,0 @@
-/*
- * Copyright (c) 2012, Code Aurora Forum. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- */
-
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/platform_device.h>
-#include <linux/io.h>
-#include <linux/iopoll.h>
-#include <linux/ioport.h>
-#include <linux/elf.h>
-#include <linux/delay.h>
-#include <linux/sched.h>
-#include <linux/clk.h>
-#include <linux/err.h>
-#include <linux/of.h>
-#include <linux/interrupt.h>
-
-#include <mach/subsystem_restart.h>
-#include <mach/msm_smsm.h>
-#include <mach/peripheral-loader.h>
-
-#include "peripheral-loader.h"
-#include "ramdump.h"
-
-#define RMB_MBA_COMMAND			0x08
-#define RMB_MBA_STATUS			0x0C
-#define RMB_PMI_META_DATA		0x10
-#define RMB_PMI_CODE_START		0x14
-#define RMB_PMI_CODE_LENGTH		0x18
-
-#define CMD_META_DATA_READY		0x1
-#define CMD_LOAD_READY			0x2
-
-#define STATUS_META_DATA_AUTH_SUCCESS	0x3
-#define STATUS_AUTH_COMPLETE		0x4
-
-#define PROXY_TIMEOUT_MS		10000
-#define POLL_INTERVAL_US		50
-
-#define MAX_SSR_REASON_LEN 81U
-
-static int modem_auth_timeout_ms = 10000;
-module_param(modem_auth_timeout_ms, int, S_IRUGO | S_IWUSR);
-
-struct mba_data {
-	void __iomem *reg_base;
-	void __iomem *metadata_base;
-	unsigned long metadata_phys;
-	struct pil_device *pil;
-	struct pil_desc desc;
-	struct subsys_device *subsys;
-	struct subsys_desc subsys_desc;
-	struct clk *xo;
-	void *ramdump_dev;
-	void *smem_ramdump_dev;
-	bool crash_shutdown;
-	bool ignore_errors;
-	u32 img_length;
-};
-
-static int pil_mba_make_proxy_votes(struct pil_desc *pil)
-{
-	int ret;
-	struct mba_data *drv = dev_get_drvdata(pil->dev);
-
-	ret = clk_prepare_enable(drv->xo);
-	if (ret) {
-		dev_err(pil->dev, "Failed to enable XO\n");
-		return ret;
-	}
-	return 0;
-}
-
-static void pil_mba_remove_proxy_votes(struct pil_desc *pil)
-{
-	struct mba_data *drv = dev_get_drvdata(pil->dev);
-	clk_disable_unprepare(drv->xo);
-}
-
-static int pil_mba_init_image(struct pil_desc *pil,
-			      const u8 *metadata, size_t size)
-{
-	struct mba_data *drv = dev_get_drvdata(pil->dev);
-	s32 status;
-	int ret;
-
-	/* Copy metadata to assigned shared buffer location */
-	memcpy(drv->metadata_base, metadata, size);
-
-	/* Initialize length counter to 0 */
-	writel_relaxed(0, drv->reg_base + RMB_PMI_CODE_LENGTH);
-	drv->img_length = 0;
-
-	/* Pass address of meta-data to the MBA and perform authentication */
-	writel_relaxed(drv->metadata_phys, drv->reg_base + RMB_PMI_META_DATA);
-	writel_relaxed(CMD_META_DATA_READY, drv->reg_base + RMB_MBA_COMMAND);
-	ret = readl_poll_timeout(drv->reg_base + RMB_MBA_STATUS, status,
-		status == STATUS_META_DATA_AUTH_SUCCESS || status < 0,
-		POLL_INTERVAL_US, modem_auth_timeout_ms * 1000);
-	if (ret) {
-		dev_err(pil->dev, "MBA authentication timed out\n");
-	} else if (status < 0) {
-		dev_err(pil->dev, "MBA returned error %d\n", status);
-		ret = -EINVAL;
-	}
-
-	return ret;
-}
-
-static int pil_mba_verify_blob(struct pil_desc *pil, u32 phy_addr,
-			       size_t size)
-{
-	struct mba_data *drv = dev_get_drvdata(pil->dev);
-	s32 status;
-
-	/* Begin image authentication */
-	if (drv->img_length == 0) {
-		writel_relaxed(phy_addr, drv->reg_base + RMB_PMI_CODE_START);
-		writel_relaxed(CMD_LOAD_READY, drv->reg_base + RMB_MBA_COMMAND);
-	}
-	/* Increment length counter */
-	drv->img_length += size;
-	writel_relaxed(drv->img_length, drv->reg_base + RMB_PMI_CODE_LENGTH);
-
-	status = readl_relaxed(drv->reg_base + RMB_MBA_STATUS);
-	if (status < 0) {
-		dev_err(pil->dev, "MBA returned error %d\n", status);
-		return -EINVAL;
-	}
-
-	return 0;
-}
-
-static int pil_mba_auth(struct pil_desc *pil)
-{
-	struct mba_data *drv = dev_get_drvdata(pil->dev);
-	int ret;
-	s32 status;
-
-	/* Wait for all segments to be authenticated or an error to occur */
-	ret = readl_poll_timeout(drv->reg_base + RMB_MBA_STATUS, status,
-			status == STATUS_AUTH_COMPLETE || status < 0,
-			50, modem_auth_timeout_ms * 1000);
-	if (ret) {
-		dev_err(pil->dev, "MBA authentication timed out\n");
-	} else if (status < 0) {
-		dev_err(pil->dev, "MBA returned error %d\n", status);
-		ret = -EINVAL;
-	}
-
-	return ret;
-}
-
-static int pil_mba_shutdown(struct pil_desc *pil)
-{
-	return 0;
-}
-
-static struct pil_reset_ops pil_mba_ops = {
-	.init_image = pil_mba_init_image,
-	.proxy_vote = pil_mba_make_proxy_votes,
-	.proxy_unvote = pil_mba_remove_proxy_votes,
-	.verify_blob = pil_mba_verify_blob,
-	.auth_and_reset = pil_mba_auth,
-	.shutdown = pil_mba_shutdown,
-};
-
-#define subsys_to_drv(d) container_of(d, struct mba_data, subsys_desc)
-
-static void log_modem_sfr(void)
-{
-	u32 size;
-	char *smem_reason, reason[MAX_SSR_REASON_LEN];
-
-	smem_reason = smem_get_entry(SMEM_SSR_REASON_MSS0, &size);
-	if (!smem_reason || !size) {
-		pr_err("modem subsystem failure reason: (unknown, smem_get_entry failed).\n");
-		return;
-	}
-	if (!smem_reason[0]) {
-		pr_err("modem subsystem failure reason: (unknown, empty string found).\n");
-		return;
-	}
-
-	strlcpy(reason, smem_reason, min(size, sizeof(reason)));
-	pr_err("modem subsystem failure reason: %s.\n", reason);
-
-	smem_reason[0] = '\0';
-	wmb();
-}
-
-static void restart_modem(struct mba_data *drv)
-{
-	log_modem_sfr();
-	drv->ignore_errors = true;
-	subsystem_restart_dev(drv->subsys);
-}
-
-static void smsm_state_cb(void *data, uint32_t old_state, uint32_t new_state)
-{
-	struct mba_data *drv = data;
-
-	/* Ignore if we're the one that set SMSM_RESET */
-	if (drv->crash_shutdown)
-		return;
-
-	if (new_state & SMSM_RESET) {
-		pr_err("Probable fatal error on the modem.\n");
-		restart_modem(drv);
-	}
-}
-
-static int modem_shutdown(const struct subsys_desc *subsys)
-{
-	pil_force_shutdown("modem");
-	pil_force_shutdown("mba");
-	return 0;
-}
-
-static int modem_powerup(const struct subsys_desc *subsys)
-{
-	struct mba_data *drv = subsys_to_drv(subsys);
-	/*
-	 * At this time, the modem is shutdown. Therefore this function cannot
-	 * run concurrently with either the watchdog bite error handler or the
-	 * SMSM callback, making it safe to unset the flag below.
-	 */
-	drv->ignore_errors = 0;
-	pil_force_boot("mba");
-	pil_force_boot("modem");
-	return 0;
-}
-
-static void modem_crash_shutdown(const struct subsys_desc *subsys)
-{
-	struct mba_data *drv = subsys_to_drv(subsys);
-	drv->crash_shutdown = true;
-	smsm_reset_modem(SMSM_RESET);
-}
-
-static struct ramdump_segment modem_segments[] = {
-	{0x08400000, 0x0D100000 - 0x08400000},
-};
-
-static struct ramdump_segment smem_segments[] = {
-	{0x0FA00000, 0x0FC00000 - 0x0FA00000},
-};
-
-static int modem_ramdump(int enable, const struct subsys_desc *subsys)
-{
-	struct mba_data *drv = subsys_to_drv(subsys);
-	int ret;
-
-	if (!enable)
-		return 0;
-
-	pil_force_boot("mba");
-
-	ret = do_ramdump(drv->ramdump_dev, modem_segments,
-				ARRAY_SIZE(modem_segments));
-	if (ret < 0) {
-		pr_err("Unable to dump modem fw memory (rc = %d).\n", ret);
-		goto out;
-	}
-
-	ret = do_ramdump(drv->smem_ramdump_dev, smem_segments,
-		ARRAY_SIZE(smem_segments));
-	if (ret < 0) {
-		pr_err("Unable to dump smem memory (rc = %d).\n", ret);
-		goto out;
-	}
-
-out:
-	pil_force_shutdown("mba");
-	return ret;
-}
-
-static irqreturn_t modem_wdog_bite_irq(int irq, void *dev_id)
-{
-	struct mba_data *drv = dev_id;
-	if (drv->ignore_errors)
-		return IRQ_HANDLED;
-	pr_err("Watchdog bite received from modem software!\n");
-	restart_modem(drv);
-	return IRQ_HANDLED;
-}
-
-static int mss_start(const struct subsys_desc *desc)
-{
-	void *ret;
-	struct mba_data *drv = subsys_to_drv(desc);
-
-	ret = pil_get(drv->desc.name);
-	if (IS_ERR(ret))
-		return PTR_ERR(ret);
-	return 0;
-}
-
-static void mss_stop(const struct subsys_desc *desc)
-{
-	struct mba_data *drv = subsys_to_drv(desc);
-	pil_put(drv->pil);
-}
-
-static int __devinit pil_mba_driver_probe(struct platform_device *pdev)
-{
-	struct mba_data *drv;
-	struct resource *res;
-	struct pil_desc *desc;
-	int ret, irq;
-
-	drv = devm_kzalloc(&pdev->dev, sizeof(*drv), GFP_KERNEL);
-	if (!drv)
-		return -ENOMEM;
-	platform_set_drvdata(pdev, drv);
-
-	irq = platform_get_irq(pdev, 0);
-	if (irq < 0)
-		return irq;
-
-	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "rmb_base");
-	if (!res)
-		return -EINVAL;
-	drv->reg_base = devm_ioremap(&pdev->dev, res->start,
-				     resource_size(res));
-	if (!drv->reg_base)
-		return -ENOMEM;
-
-	res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
-					    "metadata_base");
-	if (res) {
-		drv->metadata_base = devm_ioremap(&pdev->dev, res->start,
-						  resource_size(res));
-		if (!drv->metadata_base)
-			return -ENOMEM;
-		drv->metadata_phys = res->start;
-	}
-
-	desc = &drv->desc;
-	ret = of_property_read_string(pdev->dev.of_node, "qcom,firmware-name",
-				      &desc->name);
-	if (ret)
-		return ret;
-
-	of_property_read_string(pdev->dev.of_node, "qcom,depends-on",
-				      &desc->depends_on);
-
-	drv->xo = devm_clk_get(&pdev->dev, "xo");
-	if (IS_ERR(drv->xo))
-		return PTR_ERR(drv->xo);
-
-	desc->dev = &pdev->dev;
-	desc->ops = &pil_mba_ops;
-	desc->owner = THIS_MODULE;
-	desc->proxy_timeout = PROXY_TIMEOUT_MS;
-
-	drv->pil = msm_pil_register(desc);
-	if (IS_ERR(drv->pil))
-		return PTR_ERR(drv->pil);
-
-	drv->subsys_desc.name = desc->name;
-	drv->subsys_desc.dev = &pdev->dev;
-	drv->subsys_desc.owner = THIS_MODULE;
-	drv->subsys_desc.shutdown = modem_shutdown;
-	drv->subsys_desc.powerup = modem_powerup;
-	drv->subsys_desc.ramdump = modem_ramdump;
-	drv->subsys_desc.crash_shutdown = modem_crash_shutdown;
-	drv->subsys_desc.start = mss_start;
-	drv->subsys_desc.stop = mss_stop;
-
-	drv->ramdump_dev = create_ramdump_device("modem");
-	if (!drv->ramdump_dev) {
-		pr_err("%s: Unable to create a modem ramdump device.\n",
-			__func__);
-		ret = -ENOMEM;
-		goto err_ramdump;
-	}
-
-	drv->smem_ramdump_dev = create_ramdump_device("smem-modem");
-	if (!drv->smem_ramdump_dev) {
-		pr_err("%s: Unable to create an smem ramdump device.\n",
-			__func__);
-		ret = -ENOMEM;
-		goto err_ramdump_smem;
-	}
-
-	drv->subsys = subsys_register(&drv->subsys_desc);
-	if (IS_ERR(drv->subsys)) {
-		goto err_subsys;
-		ret = PTR_ERR(drv->subsys);
-	}
-
-	ret = devm_request_irq(&pdev->dev, irq, modem_wdog_bite_irq,
-				IRQF_TRIGGER_RISING, "modem_wdog", drv);
-	if (ret < 0) {
-		dev_err(&pdev->dev, "Unable to request watchdog IRQ.\n");
-		goto err_irq;
-	}
-
-	ret = smsm_state_cb_register(SMSM_MODEM_STATE, SMSM_RESET,
-		smsm_state_cb, drv);
-	if (ret < 0) {
-		dev_err(&pdev->dev, "Unable to register SMSM callback!\n");
-		goto err_irq;
-	}
-
-	return 0;
-
-err_irq:
-	subsys_unregister(drv->subsys);
-err_subsys:
-	destroy_ramdump_device(drv->smem_ramdump_dev);
-err_ramdump_smem:
-	destroy_ramdump_device(drv->ramdump_dev);
-err_ramdump:
-	msm_pil_unregister(drv->pil);
-	return ret;
-}
-
-static int __devexit pil_mba_driver_exit(struct platform_device *pdev)
-{
-	struct mba_data *drv = platform_get_drvdata(pdev);
-	smsm_state_cb_deregister(SMSM_MODEM_STATE, SMSM_RESET,
-			smsm_state_cb, drv);
-	subsys_unregister(drv->subsys);
-	destroy_ramdump_device(drv->smem_ramdump_dev);
-	destroy_ramdump_device(drv->ramdump_dev);
-	msm_pil_unregister(drv->pil);
-	return 0;
-}
-
-static struct of_device_id mba_match_table[] = {
-	{ .compatible = "qcom,pil-mba" },
-	{}
-};
-
-struct platform_driver pil_mba_driver = {
-	.probe = pil_mba_driver_probe,
-	.remove = __devexit_p(pil_mba_driver_exit),
-	.driver = {
-		.name = "pil-mba",
-		.of_match_table = mba_match_table,
-		.owner = THIS_MODULE,
-	},
-};
-
-static int __init pil_mba_init(void)
-{
-	return platform_driver_register(&pil_mba_driver);
-}
-module_init(pil_mba_init);
-
-static void __exit pil_mba_exit(void)
-{
-	platform_driver_unregister(&pil_mba_driver);
-}
-module_exit(pil_mba_exit);
-
-MODULE_DESCRIPTION("Support for modem boot using the Modem Boot Authenticator");
-MODULE_LICENSE("GPL v2");
diff --git a/arch/arm/mach-msm/pil-q6v4-lpass.c b/arch/arm/mach-msm/pil-q6v4-lpass.c
index 8164d64..c32cf5c 100644
--- a/arch/arm/mach-msm/pil-q6v4-lpass.c
+++ b/arch/arm/mach-msm/pil-q6v4-lpass.c
@@ -348,6 +348,8 @@
 		ret = PTR_ERR(drv->subsys);
 		goto err_subsys;
 	}
+	if (!drv->loadable)
+		subsys_default_online(drv->subsys);
 
 	ret = devm_request_irq(&pdev->dev, q6->wdog_irq, lpass_wdog_bite_irq,
 			IRQF_TRIGGER_RISING, dev_name(&pdev->dev), drv);
diff --git a/arch/arm/mach-msm/pil-q6v4-mss.c b/arch/arm/mach-msm/pil-q6v4-mss.c
index fe8c3b1..aa59bbd 100644
--- a/arch/arm/mach-msm/pil-q6v4-mss.c
+++ b/arch/arm/mach-msm/pil-q6v4-mss.c
@@ -449,6 +449,8 @@
 		ret = PTR_ERR(drv->subsys);
 		goto err_subsys;
 	}
+	if (!drv->loadable)
+		subsys_default_online(drv->subsys);
 
 	ret = devm_request_irq(&pdev->dev, drv_fw->wdog_irq,
 			modem_wdog_bite_irq, IRQF_TRIGGER_RISING,
diff --git a/arch/arm/mach-msm/pil-q6v5-mss.c b/arch/arm/mach-msm/pil-q6v5-mss.c
index b856d05..8a02251 100644
--- a/arch/arm/mach-msm/pil-q6v5-mss.c
+++ b/arch/arm/mach-msm/pil-q6v5-mss.c
@@ -24,11 +24,16 @@
 #include <linux/err.h>
 #include <linux/of.h>
 #include <linux/regulator/consumer.h>
+#include <linux/interrupt.h>
 
+#include <mach/peripheral-loader.h>
+#include <mach/subsystem_restart.h>
 #include <mach/clk.h>
+#include <mach/msm_smsm.h>
 
 #include "peripheral-loader.h"
 #include "pil-q6v5.h"
+#include "ramdump.h"
 
 /* Q6 Register Offsets */
 #define QDSP6SS_RST_EVB			0x010
@@ -46,14 +51,47 @@
 /* PBL/MBA interface registers */
 #define RMB_MBA_IMAGE			0x00
 #define RMB_PBL_STATUS			0x04
+#define RMB_MBA_COMMAND			0x08
 #define RMB_MBA_STATUS			0x0C
+#define RMB_PMI_META_DATA		0x10
+#define RMB_PMI_CODE_START		0x14
+#define RMB_PMI_CODE_LENGTH		0x18
 
 #define PROXY_TIMEOUT_MS		10000
 #define POLL_INTERVAL_US		50
 
+#define CMD_META_DATA_READY		0x1
+#define CMD_LOAD_READY			0x2
+
+#define STATUS_META_DATA_AUTH_SUCCESS	0x3
+#define STATUS_AUTH_COMPLETE		0x4
+
+#define MAX_SSR_REASON_LEN 81U
+
+struct mba_data {
+	void __iomem *metadata_base;
+	void __iomem *rmb_base;
+	void __iomem *io_clamp_reg;
+	unsigned long metadata_phys;
+	struct pil_device *pil;
+	struct pil_desc desc;
+	struct subsys_device *subsys;
+	struct subsys_desc subsys_desc;
+	u32 img_length;
+	struct q6v5_data *q6;
+	int self_auth;
+	void *ramdump_dev;
+	void *smem_ramdump_dev;
+	bool crash_shutdown;
+	bool ignore_errors;
+};
+
 static int pbl_mba_boot_timeout_ms = 100;
 module_param(pbl_mba_boot_timeout_ms, int, S_IRUGO | S_IWUSR);
 
+static int modem_auth_timeout_ms = 10000;
+module_param(modem_auth_timeout_ms, int, S_IRUGO | S_IWUSR);
+
 static int pil_mss_power_up(struct q6v5_data *drv)
 {
 	int ret;
@@ -105,11 +143,12 @@
 static int wait_for_mba_ready(struct q6v5_data *drv)
 {
 	struct device *dev = drv->desc.dev;
+	struct mba_data *mba = platform_get_drvdata(to_platform_device(dev));
 	int ret;
 	u32 status;
 
 	/* Wait for PBL completion. */
-	ret = readl_poll_timeout(drv->rmb_base + RMB_PBL_STATUS, status,
+	ret = readl_poll_timeout(mba->rmb_base + RMB_PBL_STATUS, status,
 		status != 0, POLL_INTERVAL_US, pbl_mba_boot_timeout_ms * 1000);
 	if (ret) {
 		dev_err(dev, "PBL boot timed out\n");
@@ -121,7 +160,7 @@
 	}
 
 	/* Wait for MBA completion. */
-	ret = readl_poll_timeout(drv->rmb_base + RMB_MBA_STATUS, status,
+	ret = readl_poll_timeout(mba->rmb_base + RMB_MBA_STATUS, status,
 		status != 0, POLL_INTERVAL_US, pbl_mba_boot_timeout_ms * 1000);
 	if (ret) {
 		dev_err(dev, "MBA boot timed out\n");
@@ -168,6 +207,8 @@
 static int pil_mss_reset(struct pil_desc *pil)
 {
 	struct q6v5_data *drv = container_of(pil, struct q6v5_data, desc);
+	struct platform_device *pdev = to_platform_device(pil->dev);
+	struct mba_data *mba = platform_get_drvdata(pdev);
 	int ret;
 
 	/* Deassert reset to subsystem and wait for propagation */
@@ -188,8 +229,8 @@
 		goto err_clks;
 
 	/* Program Image Address */
-	if (drv->self_auth) {
-		writel_relaxed(drv->start_addr, drv->rmb_base + RMB_MBA_IMAGE);
+	if (mba->self_auth) {
+		writel_relaxed(drv->start_addr, mba->rmb_base + RMB_MBA_IMAGE);
 		/* Ensure write to RMB base occurs before reset is released. */
 		mb();
 	} else {
@@ -202,7 +243,7 @@
 		goto err_q6v5_reset;
 
 	/* Wait for MBA to start. Check for PBL and MBA errors while waiting. */
-	if (drv->self_auth) {
+	if (mba->self_auth) {
 		ret = wait_for_mba_ready(drv);
 		if (ret)
 			goto err_auth;
@@ -230,22 +271,277 @@
 	.shutdown = pil_mss_shutdown,
 };
 
-static int __devinit pil_mss_driver_probe(struct platform_device *pdev)
+static int pil_mba_make_proxy_votes(struct pil_desc *pil)
 {
-	struct q6v5_data *drv;
-	struct pil_desc *desc;
-	struct resource *res;
+	int ret;
+	struct mba_data *drv = dev_get_drvdata(pil->dev);
+
+	ret = clk_prepare_enable(drv->q6->xo);
+	if (ret) {
+		dev_err(pil->dev, "Failed to enable XO\n");
+		return ret;
+	}
+	return 0;
+}
+
+static void pil_mba_remove_proxy_votes(struct pil_desc *pil)
+{
+	struct mba_data *drv = dev_get_drvdata(pil->dev);
+	clk_disable_unprepare(drv->q6->xo);
+}
+
+static int pil_mba_init_image(struct pil_desc *pil,
+			      const u8 *metadata, size_t size)
+{
+	struct mba_data *drv = dev_get_drvdata(pil->dev);
+	s32 status;
 	int ret;
 
-	drv = pil_q6v5_init(pdev);
-	if (IS_ERR(drv))
-		return PTR_ERR(drv);
+	/* Copy metadata to assigned shared buffer location */
+	memcpy(drv->metadata_base, metadata, size);
+
+	/* Initialize length counter to 0 */
+	writel_relaxed(0, drv->rmb_base + RMB_PMI_CODE_LENGTH);
+	drv->img_length = 0;
+
+	/* Pass address of meta-data to the MBA and perform authentication */
+	writel_relaxed(drv->metadata_phys, drv->rmb_base + RMB_PMI_META_DATA);
+	writel_relaxed(CMD_META_DATA_READY, drv->rmb_base + RMB_MBA_COMMAND);
+	ret = readl_poll_timeout(drv->rmb_base + RMB_MBA_STATUS, status,
+		status == STATUS_META_DATA_AUTH_SUCCESS || status < 0,
+		POLL_INTERVAL_US, modem_auth_timeout_ms * 1000);
+	if (ret) {
+		dev_err(pil->dev, "MBA authentication of headers timed out\n");
+	} else if (status < 0) {
+		dev_err(pil->dev, "MBA returned error %d for headers\n",
+				status);
+		ret = -EINVAL;
+	}
+
+	return ret;
+}
+
+static int pil_mba_verify_blob(struct pil_desc *pil, u32 phy_addr,
+			       size_t size)
+{
+	struct mba_data *drv = dev_get_drvdata(pil->dev);
+	s32 status;
+
+	/* Begin image authentication */
+	if (drv->img_length == 0) {
+		writel_relaxed(phy_addr, drv->rmb_base + RMB_PMI_CODE_START);
+		writel_relaxed(CMD_LOAD_READY, drv->rmb_base + RMB_MBA_COMMAND);
+	}
+	/* Increment length counter */
+	drv->img_length += size;
+	writel_relaxed(drv->img_length, drv->rmb_base + RMB_PMI_CODE_LENGTH);
+
+	status = readl_relaxed(drv->rmb_base + RMB_MBA_STATUS);
+	if (status < 0) {
+		dev_err(pil->dev, "MBA returned error %d\n", status);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int pil_mba_auth(struct pil_desc *pil)
+{
+	struct mba_data *drv = dev_get_drvdata(pil->dev);
+	int ret;
+	s32 status;
+
+	/* Wait for all segments to be authenticated or an error to occur */
+	ret = readl_poll_timeout(drv->rmb_base + RMB_MBA_STATUS, status,
+			status == STATUS_AUTH_COMPLETE || status < 0,
+			50, modem_auth_timeout_ms * 1000);
+	if (ret) {
+		dev_err(pil->dev, "MBA authentication of image timed out\n");
+	} else if (status < 0) {
+		dev_err(pil->dev, "MBA returned error %d for image\n", status);
+		ret = -EINVAL;
+	}
+
+	return ret;
+}
+
+static int pil_mba_shutdown(struct pil_desc *pil)
+{
+	return 0;
+}
+
+static struct pil_reset_ops pil_mba_ops = {
+	.init_image = pil_mba_init_image,
+	.proxy_vote = pil_mba_make_proxy_votes,
+	.proxy_unvote = pil_mba_remove_proxy_votes,
+	.verify_blob = pil_mba_verify_blob,
+	.auth_and_reset = pil_mba_auth,
+	.shutdown = pil_mba_shutdown,
+};
+
+#define subsys_to_drv(d) container_of(d, struct mba_data, subsys_desc)
+
+static void log_modem_sfr(void)
+{
+	u32 size;
+	char *smem_reason, reason[MAX_SSR_REASON_LEN];
+
+	smem_reason = smem_get_entry(SMEM_SSR_REASON_MSS0, &size);
+	if (!smem_reason || !size) {
+		pr_err("modem subsystem failure reason: (unknown, smem_get_entry failed).\n");
+		return;
+	}
+	if (!smem_reason[0]) {
+		pr_err("modem subsystem failure reason: (unknown, empty string found).\n");
+		return;
+	}
+
+	strlcpy(reason, smem_reason, min(size, sizeof(reason)));
+	pr_err("modem subsystem failure reason: %s.\n", reason);
+
+	smem_reason[0] = '\0';
+	wmb();
+}
+
+static void restart_modem(struct mba_data *drv)
+{
+	log_modem_sfr();
+	drv->ignore_errors = true;
+	subsystem_restart_dev(drv->subsys);
+}
+
+static void smsm_state_cb(void *data, uint32_t old_state, uint32_t new_state)
+{
+	struct mba_data *drv = data;
+
+	/* Ignore if we're the one that set SMSM_RESET */
+	if (drv->crash_shutdown)
+		return;
+
+	if (new_state & SMSM_RESET) {
+		pr_err("Probable fatal error on the modem.\n");
+		restart_modem(drv);
+	}
+}
+
+static int modem_shutdown(const struct subsys_desc *subsys)
+{
+	pil_force_shutdown("modem");
+	pil_force_shutdown("mba");
+	return 0;
+}
+
+static int modem_powerup(const struct subsys_desc *subsys)
+{
+	struct mba_data *drv = subsys_to_drv(subsys);
+	/*
+	 * At this time, the modem is shutdown. Therefore this function cannot
+	 * run concurrently with either the watchdog bite error handler or the
+	 * SMSM callback, making it safe to unset the flag below.
+	 */
+	drv->ignore_errors = false;
+	pil_force_boot("mba");
+	pil_force_boot("modem");
+	return 0;
+}
+
+static void modem_crash_shutdown(const struct subsys_desc *subsys)
+{
+	struct mba_data *drv = subsys_to_drv(subsys);
+	drv->crash_shutdown = true;
+	smsm_reset_modem(SMSM_RESET);
+}
+
+static struct ramdump_segment modem_segments[] = {
+	{0x08400000, 0x0D100000 - 0x08400000},
+};
+
+static struct ramdump_segment smem_segments[] = {
+	{0x0FA00000, 0x0FC00000 - 0x0FA00000},
+};
+
+static int modem_ramdump(int enable, const struct subsys_desc *subsys)
+{
+	struct mba_data *drv = subsys_to_drv(subsys);
+	int ret;
+
+	if (!enable)
+		return 0;
+
+	pil_force_boot("mba");
+
+	ret = do_ramdump(drv->ramdump_dev, modem_segments,
+				ARRAY_SIZE(modem_segments));
+	if (ret < 0) {
+		pr_err("Unable to dump modem fw memory (rc = %d).\n", ret);
+		goto out;
+	}
+
+	ret = do_ramdump(drv->smem_ramdump_dev, smem_segments,
+		ARRAY_SIZE(smem_segments));
+	if (ret < 0) {
+		pr_err("Unable to dump smem memory (rc = %d).\n", ret);
+		goto out;
+	}
+
+out:
+	pil_force_shutdown("mba");
+	return ret;
+}
+
+static irqreturn_t modem_wdog_bite_irq(int irq, void *dev_id)
+{
+	struct mba_data *drv = dev_id;
+	if (drv->ignore_errors)
+		return IRQ_HANDLED;
+	pr_err("Watchdog bite received from modem software!\n");
+	restart_modem(drv);
+	return IRQ_HANDLED;
+}
+
+static int mss_start(const struct subsys_desc *desc)
+{
+	void *ret;
+	struct mba_data *drv = subsys_to_drv(desc);
+
+	ret = pil_get(drv->desc.name);
+	if (IS_ERR(ret))
+		return PTR_ERR(ret);
+	return 0;
+}
+
+static void mss_stop(const struct subsys_desc *desc)
+{
+	struct mba_data *drv = subsys_to_drv(desc);
+	pil_put(drv->pil);
+}
+
+static int __devinit pil_mss_driver_probe(struct platform_device *pdev)
+{
+	struct mba_data *drv;
+	struct q6v5_data *q6;
+	struct pil_desc *q6_desc, *mba_desc;
+	struct resource *res;
+	int ret, irq;
+
+	drv = devm_kzalloc(&pdev->dev, sizeof(*drv), GFP_KERNEL);
+	if (!drv)
+		return -ENOMEM;
 	platform_set_drvdata(pdev, drv);
 
-	desc = &drv->desc;
-	desc->ops = &pil_mss_ops;
-	desc->owner = THIS_MODULE;
-	desc->proxy_timeout = PROXY_TIMEOUT_MS;
+	irq = platform_get_irq(pdev, 0);
+	if (irq < 0)
+		return irq;
+
+	q6 = pil_q6v5_init(pdev);
+	if (IS_ERR(q6))
+		return PTR_ERR(q6);
+	drv->q6 = q6;
+
+	q6_desc = &q6->desc;
+	q6_desc->ops = &pil_mss_ops;
+	q6_desc->owner = THIS_MODULE;
+	q6_desc->proxy_timeout = PROXY_TIMEOUT_MS;
 
 	of_property_read_u32(pdev->dev.of_node, "qcom,pil-self-auth",
 			     &drv->self_auth);
@@ -256,51 +552,138 @@
 					     resource_size(res));
 		if (!drv->rmb_base)
 			return -ENOMEM;
+		res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
+					    "metadata_base");
+		if (res) {
+			drv->metadata_base = devm_ioremap(&pdev->dev,
+						res->start, resource_size(res));
+			if (!drv->metadata_base)
+				return -ENOMEM;
+			drv->metadata_phys = res->start;
+		}
 	}
 
 	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "restart_reg");
-	drv->restart_reg = devm_ioremap(&pdev->dev, res->start,
+	q6->restart_reg = devm_ioremap(&pdev->dev, res->start,
 					resource_size(res));
-	if (!drv->restart_reg)
+	if (!q6->restart_reg)
 		return -ENOMEM;
 
-	drv->vreg = devm_regulator_get(&pdev->dev, "vdd_mss");
-	if (IS_ERR(drv->vreg))
-		return PTR_ERR(drv->vreg);
+	q6->vreg = devm_regulator_get(&pdev->dev, "vdd_mss");
+	if (IS_ERR(q6->vreg))
+		return PTR_ERR(q6->vreg);
 
-	ret = regulator_set_voltage(drv->vreg, 1050000, 1050000);
+	ret = regulator_set_voltage(q6->vreg, 1050000, 1050000);
 	if (ret)
 		dev_err(&pdev->dev, "Failed to set regulator's voltage.\n");
 
-	ret = regulator_set_optimum_mode(drv->vreg, 100000);
+	ret = regulator_set_optimum_mode(q6->vreg, 100000);
 	if (ret < 0) {
 		dev_err(&pdev->dev, "Failed to set regulator's mode.\n");
 		return ret;
 	}
 
-	drv->ahb_clk = devm_clk_get(&pdev->dev, "iface_clk");
-	if (IS_ERR(drv->ahb_clk))
-		return PTR_ERR(drv->ahb_clk);
+	q6->ahb_clk = devm_clk_get(&pdev->dev, "iface_clk");
+	if (IS_ERR(q6->ahb_clk))
+		return PTR_ERR(q6->ahb_clk);
 
-	drv->axi_clk = devm_clk_get(&pdev->dev, "bus_clk");
-	if (IS_ERR(drv->axi_clk))
-		return PTR_ERR(drv->axi_clk);
+	q6->axi_clk = devm_clk_get(&pdev->dev, "bus_clk");
+	if (IS_ERR(q6->axi_clk))
+		return PTR_ERR(q6->axi_clk);
 
-	drv->rom_clk = devm_clk_get(&pdev->dev, "mem_clk");
-	if (IS_ERR(drv->rom_clk))
-		return PTR_ERR(drv->rom_clk);
+	q6->rom_clk = devm_clk_get(&pdev->dev, "mem_clk");
+	if (IS_ERR(q6->rom_clk))
+		return PTR_ERR(q6->rom_clk);
 
-	drv->pil = msm_pil_register(desc);
-	if (IS_ERR(drv->pil))
-		return PTR_ERR(drv->pil);
+	q6->pil = msm_pil_register(q6_desc);
+	if (IS_ERR(q6->pil))
+		return PTR_ERR(q6->pil);
+
+	mba_desc = &drv->desc;
+	mba_desc->name = "modem";
+	mba_desc->depends_on = "mba";
+	mba_desc->dev = &pdev->dev;
+	mba_desc->ops = &pil_mba_ops;
+	mba_desc->owner = THIS_MODULE;
+	mba_desc->proxy_timeout = PROXY_TIMEOUT_MS;
+
+	drv->pil = msm_pil_register(mba_desc);
+	if (IS_ERR(drv->pil)) {
+		ret = PTR_ERR(drv->pil);
+		goto err_mba_desc;
+	}
+
+	drv->subsys_desc.name = "modem";
+	drv->subsys_desc.dev = &pdev->dev;
+	drv->subsys_desc.owner = THIS_MODULE;
+	drv->subsys_desc.shutdown = modem_shutdown;
+	drv->subsys_desc.powerup = modem_powerup;
+	drv->subsys_desc.ramdump = modem_ramdump;
+	drv->subsys_desc.crash_shutdown = modem_crash_shutdown;
+	drv->subsys_desc.start = mss_start;
+	drv->subsys_desc.stop = mss_stop;
+
+	drv->ramdump_dev = create_ramdump_device("modem");
+	if (!drv->ramdump_dev) {
+		pr_err("%s: Unable to create a modem ramdump device.\n",
+			__func__);
+		ret = -ENOMEM;
+		goto err_ramdump;
+	}
+
+	drv->smem_ramdump_dev = create_ramdump_device("smem-modem");
+	if (!drv->smem_ramdump_dev) {
+		pr_err("%s: Unable to create an smem ramdump device.\n",
+			__func__);
+		ret = -ENOMEM;
+		goto err_ramdump_smem;
+	}
+
+	drv->subsys = subsys_register(&drv->subsys_desc);
+	if (IS_ERR(drv->subsys)) {
+		ret = PTR_ERR(drv->subsys);
+		goto err_subsys;
+	}
+
+	ret = devm_request_irq(&pdev->dev, irq, modem_wdog_bite_irq,
+				IRQF_TRIGGER_RISING, "modem_wdog", drv);
+	if (ret < 0) {
+		dev_err(&pdev->dev, "Unable to request watchdog IRQ.\n");
+		goto err_irq;
+	}
+
+	ret = smsm_state_cb_register(SMSM_MODEM_STATE, SMSM_RESET,
+		smsm_state_cb, drv);
+	if (ret < 0) {
+		dev_err(&pdev->dev, "Unable to register SMSM callback!\n");
+		goto err_irq;
+	}
 
 	return 0;
+
+err_irq:
+	subsys_unregister(drv->subsys);
+err_subsys:
+	destroy_ramdump_device(drv->smem_ramdump_dev);
+err_ramdump_smem:
+	destroy_ramdump_device(drv->ramdump_dev);
+err_ramdump:
+	msm_pil_unregister(drv->pil);
+err_mba_desc:
+	msm_pil_unregister(q6->pil);
+	return ret;
 }
 
 static int __devexit pil_mss_driver_exit(struct platform_device *pdev)
 {
-	struct q6v5_data *drv = platform_get_drvdata(pdev);
+	struct mba_data *drv = platform_get_drvdata(pdev);
+	smsm_state_cb_deregister(SMSM_MODEM_STATE, SMSM_RESET,
+			smsm_state_cb, drv);
+	subsys_unregister(drv->subsys);
+	destroy_ramdump_device(drv->smem_ramdump_dev);
+	destroy_ramdump_device(drv->ramdump_dev);
 	msm_pil_unregister(drv->pil);
+	msm_pil_unregister(drv->q6->pil);
 	return 0;
 }
 
diff --git a/arch/arm/mach-msm/pil-q6v5.h b/arch/arm/mach-msm/pil-q6v5.h
index 7304757..340b5e3 100644
--- a/arch/arm/mach-msm/pil-q6v5.h
+++ b/arch/arm/mach-msm/pil-q6v5.h
@@ -29,12 +29,10 @@
 	struct clk *reg_clk;	/* CPU access registers */
 	struct clk *rom_clk;	/* Boot ROM */
 	void __iomem *axi_halt_base;
-	void __iomem *rmb_base;
 	void __iomem *restart_reg;
 	unsigned long start_addr;
 	struct regulator *vreg;
 	bool is_booted;
-	int self_auth;
 	struct pil_device *pil;
 	struct pil_desc desc;
 };
diff --git a/arch/arm/mach-msm/qdsp6v2/Makefile b/arch/arm/mach-msm/qdsp6v2/Makefile
index 0f17a0b..66d6bda 100644
--- a/arch/arm/mach-msm/qdsp6v2/Makefile
+++ b/arch/arm/mach-msm/qdsp6v2/Makefile
@@ -27,4 +27,3 @@
 obj-$(CONFIG_MSM_QDSP6V2_CODECS) += audio_mp3.o audio_amrnb.o audio_amrwb.o audio_evrc.o audio_qcelp.o amrwb_in.o
 obj-$(CONFIG_MSM_ADSP_LOADER) += adsp-loader.o
 obj-$(CONFIG_MSM_ULTRASOUND_A) += ultrasound/version_a/
-obj-m += adsprpc.o
diff --git a/arch/arm/mach-msm/subsystem_restart.c b/arch/arm/mach-msm/subsystem_restart.c
index e5cc4ec..8951cfe 100644
--- a/arch/arm/mach-msm/subsystem_restart.c
+++ b/arch/arm/mach-msm/subsystem_restart.c
@@ -178,6 +178,20 @@
 	spin_unlock_irqrestore(&subsys->track.s_lock, flags);
 }
 
+/**
+ * subsytem_default_online() - Mark a subsystem as online by default
+ * @dev: subsystem to mark as online
+ *
+ * Marks a subsystem as "online" without increasing the reference count
+ * on the subsystem. This is typically used by subsystems that are already
+ * online when the kernel boots up.
+ */
+void subsys_default_online(struct subsys_device *dev)
+{
+	subsys_set_state(dev, SUBSYS_ONLINE);
+}
+EXPORT_SYMBOL(subsys_default_online);
+
 static struct device_attribute subsys_attrs[] = {
 	__ATTR_RO(name),
 	__ATTR_RO(state),
@@ -671,6 +685,18 @@
 	}
 
 	name = dev->desc->name;
+
+	/*
+	 * If a system reboot/shutdown is underway, ignore subsystem errors.
+	 * However, print a message so that we know that a subsystem behaved
+	 * unexpectedly here.
+	 */
+	if (system_state == SYSTEM_RESTART
+		|| system_state == SYSTEM_POWER_OFF) {
+		pr_err("%s crashed during a system poweroff/shutdown.\n", name);
+		return -EBUSY;
+	}
+
 	pr_info("Restart sequence requested for %s, restart_level = %d.\n",
 		name, restart_level);
 
diff --git a/arch/arm/mach-msm/sysmon.c b/arch/arm/mach-msm/sysmon.c
index 02ba5ea..112daca 100644
--- a/arch/arm/mach-msm/sysmon.c
+++ b/arch/arm/mach-msm/sysmon.c
@@ -43,6 +43,7 @@
 	struct completion	resp_ready;
 	char			rx_buf[RX_BUF_SIZE];
 	enum transports		transport;
+	struct device		*dev;
 };
 
 static struct sysmon_subsys subsys[SYSMON_NUM_SS] = {
@@ -138,6 +139,9 @@
 	char tx_buf[TX_BUF_SIZE];
 	int ret;
 
+	if (ss->dev == NULL)
+		return -ENODEV;
+
 	if (dest_ss < 0 || dest_ss >= SYSMON_NUM_SS ||
 	    notif < 0 || notif >= SUBSYS_NOTIF_TYPE_COUNT ||
 	    event_ss == NULL)
@@ -178,6 +182,9 @@
 	size_t prefix_len = ARRAY_SIZE(expect) - 1;
 	int ret;
 
+	if (ss->dev == NULL)
+		return -ENODEV;
+
 	if (dest_ss < 0 || dest_ss >= SYSMON_NUM_SS)
 		return -EINVAL;
 
@@ -214,6 +221,9 @@
 	size_t prefix_len = ARRAY_SIZE(expect) - 1;
 	int ret;
 
+	if (ss->dev == NULL)
+		return -ENODEV;
+
 	if (dest_ss < 0 || dest_ss >= SYSMON_NUM_SS ||
 	    buf == NULL || len == 0)
 		return -EINVAL;
@@ -293,6 +303,7 @@
 	default:
 		return -EINVAL;
 	}
+	ss->dev = &pdev->dev;
 
 	return 0;
 }
@@ -301,6 +312,9 @@
 {
 	struct sysmon_subsys *ss = &subsys[pdev->id];
 
+	ss->dev = NULL;
+
+	mutex_lock(&ss->lock);
 	switch (ss->transport) {
 	case TRANSPORT_SMD:
 		smd_close(ss->chan);
@@ -309,6 +323,7 @@
 		hsic_sysmon_close(HSIC_SYSMON_DEV_EXT_MODEM);
 		break;
 	}
+	mutex_unlock(&ss->lock);
 
 	return 0;
 }
diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig
index 00a07a0..0b3ffef 100644
--- a/drivers/char/Kconfig
+++ b/drivers/char/Kconfig
@@ -649,6 +649,16 @@
           block.  Or some systems may want the iMem to be dedicated to a
           different function.
 
+config MSM_ADSPRPC
+        tristate "Qualcomm ADSP RPC driver"
+        depends on MSM_AUDIO_QDSP6 || MSM_AUDIO_QDSP6V2
+        default m
+        help
+          Provides a communication mechanism that allows for clients to
+          make remote method invocations across processor boundary to
+          applications DSP processor. Say M if you want to enable this
+          module.
+
 config MMC_GENERIC_CSDIO
 	tristate "Generic sdio driver"
 	default n
diff --git a/drivers/char/Makefile b/drivers/char/Makefile
index c38c26c..8032f0b 100644
--- a/drivers/char/Makefile
+++ b/drivers/char/Makefile
@@ -66,4 +66,5 @@
 obj-$(CONFIG_TILE_SROM)		+= tile-srom.o
 obj-$(CONFIG_MSM_ROTATOR)	+= msm_rotator.o
 obj-$(CONFIG_MMC_GENERIC_CSDIO)	+= csdio.o
-obj-$(CONFIG_DIAG_CHAR)		+= diag/
\ No newline at end of file
+obj-$(CONFIG_DIAG_CHAR)		+= diag/
+obj-$(CONFIG_MSM_ADSPRPC)       += adsprpc.o
diff --git a/arch/arm/mach-msm/qdsp6v2/adsprpc.c b/drivers/char/adsprpc.c
similarity index 100%
rename from arch/arm/mach-msm/qdsp6v2/adsprpc.c
rename to drivers/char/adsprpc.c
diff --git a/arch/arm/mach-msm/qdsp6v2/adsprpc.h b/drivers/char/adsprpc.h
similarity index 100%
rename from arch/arm/mach-msm/qdsp6v2/adsprpc.h
rename to drivers/char/adsprpc.h
diff --git a/arch/arm/mach-msm/qdsp6v2/adsprpc_shared.h b/drivers/char/adsprpc_shared.h
similarity index 100%
rename from arch/arm/mach-msm/qdsp6v2/adsprpc_shared.h
rename to drivers/char/adsprpc_shared.h
diff --git a/drivers/coresight/coresight-csr.c b/drivers/coresight/coresight-csr.c
index e9ac904..1f6bd1d 100644
--- a/drivers/coresight/coresight-csr.c
+++ b/drivers/coresight/coresight-csr.c
@@ -86,7 +86,7 @@
 	CSR_UNLOCK(drvdata);
 
 	usbbamctrl = csr_readl(drvdata, CSR_USBBAMCTRL);
-	usbbamctrl = (usbbamctrl & ~0x3) | BLKSIZE_256;
+	usbbamctrl = (usbbamctrl & ~0x3) | BLKSIZE_2048;
 	csr_writel(drvdata, usbbamctrl, CSR_USBBAMCTRL);
 
 	usbflshctrl = csr_readl(drvdata, CSR_USBFLSHCTRL);
diff --git a/drivers/gpio/qpnp-pin.c b/drivers/gpio/qpnp-pin.c
index 67a2e6b..527fd1b 100644
--- a/drivers/gpio/qpnp-pin.c
+++ b/drivers/gpio/qpnp-pin.c
@@ -128,7 +128,7 @@
 	Q_PIN_CFG_PULL,
 	Q_PIN_CFG_VIN_SEL,
 	Q_PIN_CFG_OUT_STRENGTH,
-	Q_PIN_CFG_SELECT,
+	Q_PIN_CFG_SRC_SEL,
 	Q_PIN_CFG_MASTER_EN,
 	Q_PIN_CFG_AOUT_REF,
 	Q_PIN_CFG_AIN_ROUTE,
@@ -289,7 +289,7 @@
 		    val == 0)
 			return -EINVAL;
 		break;
-	case Q_PIN_CFG_SELECT:
+	case Q_PIN_CFG_SRC_SEL:
 		if (q_spec->type == Q_MPP_TYPE &&
 		    (val == QPNP_PIN_SEL_FUNC_1 ||
 		     val == QPNP_PIN_SEL_FUNC_2))
@@ -348,9 +348,9 @@
 	else if (Q_CHK_INVALID(Q_PIN_CFG_INVERT, q_spec, param->invert))
 		pr_err("invalid invert polarity value %d for %s %d\n",
 						param->invert,  name, pin);
-	else if (Q_CHK_INVALID(Q_PIN_CFG_SELECT, q_spec, param->select))
+	else if (Q_CHK_INVALID(Q_PIN_CFG_SRC_SEL, q_spec, param->src_sel))
 		pr_err("invalid source select value %d for %s %d\n",
-						param->select, name, pin);
+						param->src_sel, name, pin);
 	else if (Q_CHK_INVALID(Q_PIN_CFG_OUT_STRENGTH,
 						q_spec, param->out_strength))
 		pr_err("invalid out strength value %d for %s %d\n",
@@ -506,10 +506,10 @@
 		q_reg_clr_set(&q_spec->regs[Q_REG_I_MODE_CTL],
 			  Q_REG_OUT_INVERT_SHIFT, Q_REG_OUT_INVERT_MASK,
 			  param->invert);
-	if (Q_HAVE_HW_SP(Q_PIN_CFG_SELECT, q_spec, param->select))
+	if (Q_HAVE_HW_SP(Q_PIN_CFG_SRC_SEL, q_spec, param->src_sel))
 		q_reg_clr_set(&q_spec->regs[Q_REG_I_MODE_CTL],
 			  Q_REG_SRC_SEL_SHIFT, Q_REG_SRC_SEL_MASK,
-			  param->select);
+			  param->src_sel);
 	if (Q_HAVE_HW_SP(Q_PIN_CFG_OUT_STRENGTH, q_spec, param->out_strength))
 		q_reg_clr_set(&q_spec->regs[Q_REG_I_DIG_OUT_CTL],
 			  Q_REG_OUT_STRENGTH_SHIFT, Q_REG_OUT_STRENGTH_MASK,
@@ -828,7 +828,7 @@
 	param.out_strength = q_reg_get(&q_spec->regs[Q_REG_I_DIG_OUT_CTL],
 				       Q_REG_OUT_STRENGTH_SHIFT,
 				       Q_REG_OUT_STRENGTH_MASK);
-	param.select   = q_reg_get(&q_spec->regs[Q_REG_I_MODE_CTL],
+	param.src_sel   = q_reg_get(&q_spec->regs[Q_REG_I_MODE_CTL],
 				       Q_REG_SRC_SEL_SHIFT, Q_REG_SRC_SEL_MASK);
 	param.master_en    = q_reg_get(&q_spec->regs[Q_REG_I_EN_CTL],
 				       Q_REG_MASTER_EN_SHIFT,
@@ -855,8 +855,8 @@
 		&param.vin_sel);
 	of_property_read_u32(node, "qcom,out-strength",
 		&param.out_strength);
-	of_property_read_u32(node, "qcom,src-select",
-		&param.select);
+	of_property_read_u32(node, "qcom,src-sel",
+		&param.src_sel);
 	of_property_read_u32(node, "qcom,master-en",
 		&param.master_en);
 	of_property_read_u32(node, "qcom,aout-ref",
@@ -942,7 +942,7 @@
 		cfg->shift = Q_REG_OUT_STRENGTH_SHIFT;
 		cfg->mask = Q_REG_OUT_STRENGTH_MASK;
 		break;
-	case Q_PIN_CFG_SELECT:
+	case Q_PIN_CFG_SRC_SEL:
 		cfg->addr = Q_REG_MODE_CTL;
 		cfg->idx = Q_REG_I_MODE_CTL;
 		cfg->shift = Q_REG_SRC_SEL_SHIFT;
@@ -1036,7 +1036,7 @@
 	{ Q_PIN_CFG_PULL, "pull" },
 	{ Q_PIN_CFG_VIN_SEL, "vin_sel" },
 	{ Q_PIN_CFG_OUT_STRENGTH, "out_strength" },
-	{ Q_PIN_CFG_SELECT, "select" },
+	{ Q_PIN_CFG_SRC_SEL, "src_sel" },
 	{ Q_PIN_CFG_MASTER_EN, "master_en" },
 	{ Q_PIN_CFG_AOUT_REF, "aout_ref" },
 	{ Q_PIN_CFG_AIN_ROUTE, "ain_route" },
diff --git a/drivers/gpu/msm/adreno.h b/drivers/gpu/msm/adreno.h
index bec19e2..f9d0316 100644
--- a/drivers/gpu/msm/adreno.h
+++ b/drivers/gpu/msm/adreno.h
@@ -38,6 +38,7 @@
 /* Command identifiers */
 #define KGSL_CONTEXT_TO_MEM_IDENTIFIER	0x2EADBEEF
 #define KGSL_CMD_IDENTIFIER		0x2EEDFACE
+#define KGSL_CMD_INTERNAL_IDENTIFIER	0x2EEDD00D
 #define KGSL_START_OF_IB_IDENTIFIER	0x2EADEABE
 #define KGSL_END_OF_IB_IDENTIFIER	0x2ABEDEAD
 
diff --git a/drivers/gpu/msm/adreno_postmortem.c b/drivers/gpu/msm/adreno_postmortem.c
index daa78ed..e069fa5 100644
--- a/drivers/gpu/msm/adreno_postmortem.c
+++ b/drivers/gpu/msm/adreno_postmortem.c
@@ -70,6 +70,14 @@
 	{CP_WAIT_FOR_IDLE,		"WAIT4IDL"},
 };
 
+static const struct pm_id_name pm3_nop_values[] = {
+	{KGSL_CONTEXT_TO_MEM_IDENTIFIER,	"CTX_SWCH"},
+	{KGSL_CMD_IDENTIFIER,			"CMD__EXT"},
+	{KGSL_CMD_INTERNAL_IDENTIFIER,		"CMD__INT"},
+	{KGSL_START_OF_IB_IDENTIFIER,		"IB_START"},
+	{KGSL_END_OF_IB_IDENTIFIER,		"IB___END"},
+};
+
 static uint32_t adreno_is_pm4_len(uint32_t word)
 {
 	if (word == INVALID_RB_CMD)
@@ -129,6 +137,28 @@
 	return "????????";
 }
 
+static bool adreno_is_pm3_nop_value(uint32_t word)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(pm3_nop_values); ++i) {
+		if (word == pm3_nop_values[i].id)
+			return 1;
+	}
+	return 0;
+}
+
+static const char *adreno_pm3_nop_name(uint32_t word)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(pm3_nop_values); ++i) {
+		if (word == pm3_nop_values[i].id)
+			return pm3_nop_values[i].name;
+	}
+	return "????????";
+}
+
 static void adreno_dump_regs(struct kgsl_device *device,
 			   const int *registers, int size)
 {
@@ -245,8 +275,13 @@
 				"%s", adreno_pm4_name(ptr4[j]));
 			*argp = -(adreno_is_pm4_len(ptr4[j])+1);
 		} else {
-			lx += scnprintf(linebuf + lx, linebuflen - lx,
-				"%8.8X", ptr4[j]);
+			if (adreno_is_pm3_nop_value(ptr4[j]))
+				lx += scnprintf(linebuf + lx, linebuflen - lx,
+					"%s", adreno_pm3_nop_name(ptr4[j]));
+			else
+				lx += scnprintf(linebuf + lx, linebuflen - lx,
+					"%8.8X", ptr4[j]);
+
 			if (*argp > 1)
 				--*argp;
 			else if (*argp == 1) {
diff --git a/drivers/gpu/msm/adreno_ringbuffer.c b/drivers/gpu/msm/adreno_ringbuffer.c
index da9daf7..e5a790f 100644
--- a/drivers/gpu/msm/adreno_ringbuffer.c
+++ b/drivers/gpu/msm/adreno_ringbuffer.c
@@ -524,6 +524,9 @@
 	total_sizedwords += flags & KGSL_CMD_FLAGS_PMODE ? 4 : 0;
 	/* 2 dwords to store the start of command sequence */
 	total_sizedwords += 2;
+	/* internal ib command identifier for the ringbuffer */
+	total_sizedwords += (flags & KGSL_CMD_FLAGS_INTERNAL_ISSUE) ? 2 : 0;
+
 	/*
 	 * Add CP_COND_EXEC commands to generate CP_INTERRUPT only
 	 * for submissions from userspace.
@@ -560,6 +563,11 @@
 	GSL_RB_WRITE(ringcmds, rcmd_gpu, cp_nop_packet(1));
 	GSL_RB_WRITE(ringcmds, rcmd_gpu, KGSL_CMD_IDENTIFIER);
 
+	if (flags & KGSL_CMD_FLAGS_INTERNAL_ISSUE) {
+		GSL_RB_WRITE(ringcmds, rcmd_gpu, cp_nop_packet(1));
+		GSL_RB_WRITE(ringcmds, rcmd_gpu, KGSL_CMD_INTERNAL_IDENTIFIER);
+	}
+
 	if (flags & KGSL_CMD_FLAGS_PMODE) {
 		/* disable protected mode error checking */
 		GSL_RB_WRITE(ringcmds, rcmd_gpu,
diff --git a/drivers/hwmon/qpnp-adc-current.c b/drivers/hwmon/qpnp-adc-current.c
index 0a85b93..10c5a17 100644
--- a/drivers/hwmon/qpnp-adc-current.c
+++ b/drivers/hwmon/qpnp-adc-current.c
@@ -672,9 +672,9 @@
 		qpnp_adc_attr.index = iadc->adc->adc_channels[i].channel_num;
 		qpnp_adc_attr.dev_attr.attr.name =
 						iadc->adc->adc_channels[i].name;
-		sysfs_attr_init(&iadc->sens_attr[i].dev_attr.attr);
 		memcpy(&iadc->sens_attr[i], &qpnp_adc_attr,
 						sizeof(qpnp_adc_attr));
+		sysfs_attr_init(&iadc->sens_attr[i].dev_attr.attr);
 		rc = device_create_file(&spmi->dev,
 				&iadc->sens_attr[i].dev_attr);
 		if (rc) {
diff --git a/drivers/hwmon/qpnp-adc-voltage.c b/drivers/hwmon/qpnp-adc-voltage.c
index 5690c88..5eef34f 100644
--- a/drivers/hwmon/qpnp-adc-voltage.c
+++ b/drivers/hwmon/qpnp-adc-voltage.c
@@ -714,9 +714,9 @@
 		qpnp_adc_attr.index = vadc->adc->adc_channels[i].channel_num;
 		qpnp_adc_attr.dev_attr.attr.name =
 						vadc->adc->adc_channels[i].name;
-		sysfs_attr_init(&vadc->sens_attr[i].dev_attr.attr);
 		memcpy(&vadc->sens_attr[i], &qpnp_adc_attr,
 						sizeof(qpnp_adc_attr));
+		sysfs_attr_init(&vadc->sens_attr[i].dev_attr.attr);
 		rc = device_create_file(&spmi->dev,
 				&vadc->sens_attr[i].dev_attr);
 		if (rc) {
diff --git a/drivers/media/radio/radio-iris.c b/drivers/media/radio/radio-iris.c
index ac143b1..fde7cb7 100644
--- a/drivers/media/radio/radio-iris.c
+++ b/drivers/media/radio/radio-iris.c
@@ -39,6 +39,17 @@
 #include <asm/unaligned.h>
 
 static unsigned int rds_buf = 100;
+static int oda_agt;
+static int grp_mask;
+static int rt_plus_carrier = -1;
+static int ert_carrier = -1;
+static unsigned char ert_buf[256];
+static unsigned char ert_len;
+static unsigned char c_byt_pair_index;
+static char utf_8_flag;
+static char rt_ert_flag;
+static char formatting_dir;
+
 module_param(rds_buf, uint, 0);
 MODULE_PARM_DESC(rds_buf, "RDS buffer entries: *100*");
 
@@ -108,7 +119,11 @@
 
 static struct video_device *priv_videodev;
 static int iris_do_calibration(struct iris_device *radio);
-
+static void hci_buff_ert(struct iris_device *radio,
+		struct rds_grp_data *rds_buf);
+static void hci_ev_rt_plus(struct iris_device *radio,
+		struct rds_grp_data rds_buf);
+static void hci_ev_ert(struct iris_device *radio);
 static int update_spur_table(struct iris_device *radio);
 static struct v4l2_queryctrl iris_v4l2_queryctrl[] = {
 	{
@@ -921,6 +936,20 @@
 	return radio_hci_send_cmd(hdev, opcode, 0, NULL);
 }
 
+static int hci_fm_rds_grp_mask_req(struct radio_hci_dev *hdev,
+		unsigned long param)
+{
+	 __u16 opcode = 0;
+
+	struct hci_fm_rds_grp_req *fm_grp_mask =
+		(struct hci_fm_rds_grp_req *)param;
+
+	opcode = hci_opcode_pack(HCI_OGF_FM_RECV_CTRL_CMD_REQ,
+		HCI_OCF_FM_RDS_GRP);
+	return radio_hci_send_cmd(hdev, opcode, sizeof(*fm_grp_mask),
+		fm_grp_mask);
+}
+
 static int hci_fm_rds_grp_process_req(struct radio_hci_dev *hdev,
 		unsigned long param)
 {
@@ -1313,7 +1342,13 @@
 static int hci_fm_rds_grp(struct hci_fm_rds_grp_req *arg,
 	struct radio_hci_dev *hdev)
 {
-	return 0;
+	int ret = 0;
+	struct hci_fm_rds_grp_req *fm_grp_mask = arg;
+
+	ret = radio_hci_request(hdev, hci_fm_rds_grp_mask_req, (unsigned
+		long)fm_grp_mask, RADIO_HCI_TIMEOUT);
+
+	return ret;
 }
 
 static int hci_fm_rds_grps_process(__u32 *arg, struct radio_hci_dev *hdev)
@@ -2078,6 +2113,234 @@
 		iris_q_event(radio, IRIS_EVT_MONO);
 }
 
+static void hci_ev_raw_rds_group_data(struct radio_hci_dev *hdev,
+		struct sk_buff *skb)
+{
+	struct iris_device *radio;
+	unsigned char blocknum, index;
+	struct rds_grp_data temp;
+	unsigned int mask_bit;
+	unsigned short int aid, agt, gtc;
+	unsigned short int carrier;
+
+	radio = video_get_drvdata(video_get_dev());
+	index = RDSGRP_DATA_OFFSET;
+
+	for (blocknum = 0; blocknum < RDS_BLOCKS_NUM; blocknum++) {
+		temp.rdsBlk[blocknum].rdsLsb =
+			(skb->data[index]);
+		temp.rdsBlk[blocknum].rdsMsb =
+			(skb->data[index+1]);
+		index = index + 2;
+	}
+
+	aid = AID(temp.rdsBlk[3].rdsLsb, temp.rdsBlk[3].rdsMsb);
+	gtc = GTC(temp.rdsBlk[1].rdsMsb);
+	agt = AGT(temp.rdsBlk[1].rdsLsb);
+
+	if (gtc == GRP_3A) {
+		switch (aid) {
+		case ERT_AID:
+			/* calculate the grp mask for RDS grp
+			 * which will contain actual eRT text
+			 *
+			 * Bit Pos  0  1  2  3  4   5  6   7
+			 * Grp Type 0A 0B 1A 1B 2A  2B 3A  3B
+			 *
+			 * similary for rest grps
+			 */
+			mask_bit = (((agt >> 1) << 1) + (agt & 1));
+			oda_agt = (1 << mask_bit);
+			utf_8_flag = (temp.rdsBlk[2].rdsLsb & 1);
+			formatting_dir = EXTRACT_BIT(temp.rdsBlk[2].rdsLsb,
+							ERT_FORMAT_DIR_BIT);
+			if (ert_carrier != agt)
+				iris_q_event(radio, IRIS_EVT_NEW_ODA);
+			ert_carrier = agt;
+			break;
+		case RT_PLUS_AID:
+			/* calculate the grp mask for RDS grp
+			 * which will contain actual eRT text
+			 *
+			 * Bit Pos  0  1  2  3  4   5  6   7
+			 * Grp Type 0A 0B 1A 1B 2A  2B 3A  3B
+			 *
+			 * similary for rest grps
+			 */
+			mask_bit = (((agt >> 1) << 1) + (agt & 1));
+			oda_agt =  (1 << mask_bit);
+			/*Extract 5th bit of MSB (b7b6b5b4b3b2b1b0)*/
+			rt_ert_flag = EXTRACT_BIT(temp.rdsBlk[2].rdsMsb,
+					 RT_ERT_FLAG_BIT);
+			if (rt_plus_carrier != agt)
+				iris_q_event(radio, IRIS_EVT_NEW_ODA);
+			rt_plus_carrier = agt;
+			break;
+		default:
+			oda_agt = 0;
+			break;
+		}
+	} else {
+		carrier = gtc;
+		if ((carrier == rt_plus_carrier))
+			hci_ev_rt_plus(radio, temp);
+		else if (carrier == ert_carrier)
+			hci_buff_ert(radio, &temp);
+	}
+}
+
+static void hci_buff_ert(struct iris_device *radio,
+	struct rds_grp_data *rds_buf)
+{
+	int i;
+	unsigned short int info_byte = 0;
+	unsigned short int byte_pair_index;
+
+	byte_pair_index = AGT(rds_buf->rdsBlk[1].rdsLsb);
+	if (byte_pair_index == 0) {
+		c_byt_pair_index = 0;
+		ert_len = 0;
+	}
+	if (c_byt_pair_index == byte_pair_index) {
+		c_byt_pair_index++;
+		for (i = 2; i <= 3; i++) {
+			info_byte = rds_buf->rdsBlk[i].rdsLsb;
+			info_byte |= (rds_buf->rdsBlk[i].rdsMsb << 8);
+			ert_buf[ert_len++] = rds_buf->rdsBlk[i].rdsMsb;
+			ert_buf[ert_len++] = rds_buf->rdsBlk[i].rdsLsb;
+			if ((utf_8_flag == 0)
+				 && (info_byte == CARRIAGE_RETURN)) {
+				ert_len -= 2;
+				break;
+			} else if ((utf_8_flag == 1)
+					&&
+					(rds_buf->rdsBlk[i].rdsMsb
+						 == CARRIAGE_RETURN)) {
+				info_byte = CARRIAGE_RETURN;
+				ert_len -= 2;
+				break;
+			} else if ((utf_8_flag == 1)
+					&&
+					(rds_buf->rdsBlk[i].rdsLsb
+						 == CARRIAGE_RETURN)) {
+				info_byte = CARRIAGE_RETURN;
+				ert_len--;
+				break;
+			}
+		}
+		if ((byte_pair_index == MAX_ERT_SEGMENT) ||
+			(info_byte == CARRIAGE_RETURN)) {
+			hci_ev_ert(radio);
+			c_byt_pair_index = 0;
+			ert_len = 0;
+		}
+	} else {
+		ert_len = 0;
+		c_byt_pair_index = 0;
+	}
+}
+static void hci_ev_ert(struct iris_device *radio)
+
+{
+	char *data = NULL;
+
+	if (ert_len <= 0)
+		return;
+	data = kmalloc((ert_len + 3), GFP_ATOMIC);
+	if (data != NULL) {
+		data[0] = ert_len;
+		data[1] = utf_8_flag;
+		data[2] = formatting_dir;
+		memcpy((data + 3), ert_buf, ert_len);
+		iris_q_evt_data(radio, data, (ert_len + 3), IRIS_BUF_ERT);
+		iris_q_event(radio, IRIS_EVT_NEW_ERT);
+		kfree(data);
+	}
+}
+
+static void hci_ev_rt_plus(struct iris_device *radio,
+		 struct rds_grp_data rds_buf)
+{
+	char tag_type1, tag_type2;
+	char *data = NULL;
+	int len = 0;
+	unsigned short int agt;
+
+	agt = AGT(rds_buf.rdsBlk[1].rdsLsb);
+	/*right most 3 bits of Lsb of block 2
+	 * and left most 3 bits of Msb of block 3
+	 */
+	tag_type1 = (((agt & TAG1_MSB_MASK) << TAG1_MSB_OFFSET) |
+			 (rds_buf.rdsBlk[2].rdsMsb >> TAG1_LSB_OFFSET));
+
+	/*right most 1 bit of lsb of 3rd block
+	 * and left most 5 bits of Msb of 4th block
+	*/
+	tag_type2 = (((rds_buf.rdsBlk[2].rdsLsb & TAG2_MSB_MASK)
+			 << TAG2_MSB_OFFSET) |
+			 (rds_buf.rdsBlk[3].rdsMsb >> TAG2_LSB_OFFSET));
+
+	if (tag_type1 != DUMMY_CLASS)
+		len += RT_PLUS_LEN_1_TAG;
+	if (tag_type2 != DUMMY_CLASS)
+		len += RT_PLUS_LEN_1_TAG;
+
+	if (len != 0) {
+		len += 2;
+		data = kmalloc(len, GFP_ATOMIC);
+	} else {
+		FMDERR("Len is zero\n");
+		return ;
+	}
+	if (data != NULL) {
+		data[0] = len;
+		len = 1;
+		data[len++] = rt_ert_flag;
+		if (tag_type1 != DUMMY_CLASS) {
+			data[len++] = tag_type1;
+			/*start position of tag1
+			 *right most 5 bits of msb of 3rd block
+			 *and left most bit of lsb of 3rd block
+			 */
+			data[len++] = (((rds_buf.rdsBlk[2].rdsMsb &
+						 TAG1_POS_MSB_MASK)
+						<< TAG1_POS_MSB_OFFSET)
+						|
+					(rds_buf.rdsBlk[2].rdsLsb >>
+						TAG1_POS_LSB_OFFSET));
+			/*length of tag1
+			 *left most 6 bits of lsb of 3rd block
+			 */
+			data[len++] = ((rds_buf.rdsBlk[2].rdsLsb
+						>> TAG1_LEN_OFFSET)
+							 &
+						TAG1_LEN_MASK) + 1;
+		}
+		if (tag_type2 != DUMMY_CLASS) {
+			data[len++] = tag_type2;
+			/*start position of tag2
+			 *right most 3 bit of msb of 4th block
+			 *and left most 3 bits of lsb of 4th block
+			 */
+			data[len++] = (((rds_buf.rdsBlk[3].rdsMsb
+						& TAG2_POS_MSB_MASK)
+						<< TAG2_POS_MSB_OFFSET)
+						|
+					(rds_buf.rdsBlk[3].rdsLsb
+						>> TAG2_POS_LSB_OFFSET));
+			/*length of tag2
+			 *right most 5 bits of lsb of 4th block
+			 */
+			data[len++] = (rds_buf.rdsBlk[3].rdsLsb
+						& TAG2_LEN_MASK) + 1;
+		}
+		iris_q_evt_data(radio, data, len, IRIS_BUF_RT_PLUS);
+		iris_q_event(radio,  IRIS_EVT_NEW_RT_PLUS);
+		kfree(data);
+	} else {
+		FMDERR("memory allocation failed\n");
+	}
+}
 
 static inline void hci_ev_program_service(struct radio_hci_dev *hdev,
 		struct sk_buff *skb)
@@ -2217,6 +2480,7 @@
 		hci_ev_service_available(hdev, skb);
 		break;
 	case HCI_EV_RDS_RX_DATA:
+		hci_ev_raw_rds_group_data(hdev, skb);
 		break;
 	case HCI_EV_PROGRAM_SERVICE:
 		hci_ev_program_service(hdev, skb);
@@ -2984,8 +3248,13 @@
 		}
 		break;
 	case V4L2_CID_PRIVATE_IRIS_RDSGROUP_MASK:
-		radio->rds_grp.rds_grp_enable_mask = ctrl->value;
+		grp_mask = (grp_mask | oda_agt | ctrl->value);
+		radio->rds_grp.rds_grp_enable_mask = grp_mask;
+		radio->rds_grp.rds_buf_size = 1;
+		radio->rds_grp.en_rds_change_filter = 0;
 		retval = hci_fm_rds_grp(&radio->rds_grp, radio->fm_hdev);
+		if (retval < 0)
+			FMDERR("error in setting group mask\n");
 		break;
 	case V4L2_CID_PRIVATE_IRIS_RDSGROUP_PROC:
 		rds_grps_proc = radio->g_rds_grp_proc_ps | ctrl->value;
diff --git a/drivers/mfd/marimba-core.c b/drivers/mfd/marimba-core.c
index d84bb7b..26f3ece 100644
--- a/drivers/mfd/marimba-core.c
+++ b/drivers/mfd/marimba-core.c
@@ -857,8 +857,7 @@
 			ssbi_adap = NULL;
 
 		if (!marimba->client) {
-			dev_err(&marimba->client->dev,
-				"can't attach client %d\n", i);
+			pr_err("can't attach client %d\n", i);
 			status = -ENOMEM;
 			goto fail;
 		}
diff --git a/drivers/misc/qseecom.c b/drivers/misc/qseecom.c
index 12f896e..8cb903a 100644
--- a/drivers/misc/qseecom.c
+++ b/drivers/misc/qseecom.c
@@ -1,6 +1,6 @@
 
 
-/* Qualcomm Secure Execution Environment Communicator (QSEECOM) driver
+/*Qualcomm Secure Execution Environment Communicator (QSEECOM) driver
  *
  * Copyright (c) 2012, Code Aurora Forum. All rights reserved.
  *
@@ -32,6 +32,8 @@
 #include <linux/types.h>
 #include <linux/clk.h>
 #include <linux/qseecom.h>
+#include <linux/elf.h>
+#include <linux/firmware.h>
 #include <linux/freezer.h>
 #include <mach/board.h>
 #include <mach/msm_bus.h>
@@ -40,6 +42,7 @@
 #include <mach/peripheral-loader.h>
 #include <mach/socinfo.h>
 #include "qseecom_legacy.h"
+#include "qseecom_kernel.h"
 
 #define QSEECOM_DEV			"qseecom"
 #define QSEOS_VERSION_13		0x13
@@ -168,6 +171,11 @@
 	u32  ref_cnt;
 };
 
+struct qseecom_registered_kclient_list {
+	struct list_head list;
+	struct qseecom_handle *handle;
+};
+
 struct qseecom_control {
 	struct ion_client *ion_clnt;		/* Ion client */
 	struct list_head  registered_listener_list_head;
@@ -176,6 +184,9 @@
 	struct list_head  registered_app_list_head;
 	spinlock_t        registered_app_list_lock;
 
+	struct list_head   registered_kclient_list_head;
+	spinlock_t        registered_kclient_list_lock;
+
 	wait_queue_head_t send_resp_wq;
 	int               send_resp_flag;
 
@@ -642,7 +653,6 @@
 	ion_phys_addr_t pa = 0;
 	uint32_t len;
 	struct qseecom_command_scm_resp resp;
-	struct qseecom_check_app_ireq req;
 	struct qseecom_load_app_ireq load_req;
 
 	/* Copy the relevant information needed for loading the image */
@@ -657,11 +667,8 @@
 	if (ret)
 		pr_warning("Unable to vote for SFPB clock");
 
-	req.qsee_cmd_id = QSEOS_APP_LOOKUP_COMMAND;
-	memcpy(req.app_name, load_img_req.img_name, MAX_APP_NAME_SIZE);
-
 	pr_warn("App (%s) does not exist, loading apps for first time\n",
-			(char *)(req.app_name));
+			(char *)(load_img_req.img_name));
 	/* Get the handle of the shared fd */
 	ihandle = ion_import_dma_buf(qseecom.ion_clnt,
 					load_img_req.ifd_data_fd);
@@ -675,6 +682,7 @@
 	ret = ion_phys(qseecom.ion_clnt, ihandle, &pa, &len);
 
 	/* Populate the structure for sending scm call to load image */
+	memcpy(load_req.app_name, load_img_req.img_name, MAX_APP_NAME_SIZE);
 	load_req.qsee_cmd_id = QSEOS_APP_START_COMMAND;
 	load_req.mdt_len = load_img_req.mdt_len;
 	load_req.img_len = load_img_req.img_len;
@@ -738,7 +746,7 @@
 	spin_unlock_irqrestore(&qseecom.registered_app_list_lock, flags);
 
 	pr_warn("App with id %d (%s) now loaded\n", app_id,
-		(char *)(req.app_name));
+		(char *)(load_img_req.img_name));
 
 	data->client.app_id = app_id;
 	load_img_req.app_id = app_id;
@@ -1171,6 +1179,394 @@
 	return ret;
 }
 
+static bool __qseecom_is_fw_image_valid(const struct firmware *fw_entry)
+{
+	struct elf32_hdr *ehdr;
+
+	if (fw_entry->size < sizeof(*ehdr)) {
+		pr_err("%s: Not big enough to be an elf header\n",
+				 qseecom.pdev->init_name);
+		return false;
+	}
+	ehdr = (struct elf32_hdr *)fw_entry->data;
+	if (memcmp(ehdr->e_ident, ELFMAG, SELFMAG)) {
+		pr_err("%s: Not an elf header\n",
+				 qseecom.pdev->init_name);
+		return false;
+	}
+
+	if (ehdr->e_phnum == 0) {
+		pr_err("%s: No loadable segments\n",
+				 qseecom.pdev->init_name);
+		return false;
+	}
+	if (sizeof(struct elf32_phdr) * ehdr->e_phnum +
+	    sizeof(struct elf32_hdr) > fw_entry->size) {
+		pr_err("%s: Program headers not within mdt\n",
+				 qseecom.pdev->init_name);
+		return false;
+	}
+	return true;
+}
+
+static int __qseecom_get_fw_size(char *appname, uint32_t *fw_size)
+{
+	int ret = -1;
+	int i = 0, rc = 0;
+	const struct firmware *fw_entry = NULL;
+	struct elf32_phdr *phdr;
+	char fw_name[MAX_APP_NAME_SIZE];
+	struct elf32_hdr *ehdr;
+	int num_images = 0;
+
+	snprintf(fw_name, sizeof(fw_name), "%s.mdt", appname);
+	rc = request_firmware(&fw_entry, fw_name,  qseecom.pdev);
+	if (rc) {
+		pr_err("error with request_firmware\n");
+		ret = -EIO;
+		goto err;
+	}
+	if (!__qseecom_is_fw_image_valid(fw_entry)) {
+		ret = -EIO;
+		goto err;
+	}
+	*fw_size = fw_entry->size;
+	phdr = (struct elf32_phdr *)(fw_entry->data + sizeof(struct elf32_hdr));
+	ehdr = (struct elf32_hdr *)fw_entry->data;
+	num_images = ehdr->e_phnum;
+	release_firmware(fw_entry);
+	for (i = 0; i < num_images; i++, phdr++) {
+		memset(fw_name, 0, sizeof(fw_name));
+		snprintf(fw_name, ARRAY_SIZE(fw_name), "%s.b%02d", appname, i);
+		ret = request_firmware(&fw_entry, fw_name, qseecom.pdev);
+		if (ret)
+			goto err;
+		*fw_size += fw_entry->size;
+		release_firmware(fw_entry);
+	}
+	return ret;
+err:
+	if (fw_entry)
+		release_firmware(fw_entry);
+	*fw_size = 0;
+	return ret;
+}
+
+static int __qseecom_get_fw_data(char *appname, u8 *img_data,
+					struct qseecom_load_app_ireq *load_req)
+{
+	int ret = -1;
+	int i = 0, rc = 0;
+	const struct firmware *fw_entry = NULL;
+	char fw_name[MAX_APP_NAME_SIZE];
+	u8 *img_data_ptr = img_data;
+	struct elf32_hdr *ehdr;
+	int num_images = 0;
+
+	snprintf(fw_name, sizeof(fw_name), "%s.mdt", appname);
+	rc = request_firmware(&fw_entry, fw_name,  qseecom.pdev);
+	if (rc) {
+		ret = -EIO;
+		goto err;
+	}
+	load_req->img_len = fw_entry->size;
+	memcpy(img_data_ptr, fw_entry->data, fw_entry->size);
+	img_data_ptr = img_data_ptr + fw_entry->size;
+	load_req->mdt_len = fw_entry->size; /*Get MDT LEN*/
+	ehdr = (struct elf32_hdr *)fw_entry->data;
+	num_images = ehdr->e_phnum;
+	release_firmware(fw_entry);
+	for (i = 0; i < num_images; i++) {
+		snprintf(fw_name, ARRAY_SIZE(fw_name), "%s.b%02d", appname, i);
+		ret = request_firmware(&fw_entry, fw_name,  qseecom.pdev);
+		if (ret) {
+			pr_err("Failed to locate blob %s\n", fw_name);
+			goto err;
+		}
+		memcpy(img_data_ptr, fw_entry->data, fw_entry->size);
+		img_data_ptr = img_data_ptr + fw_entry->size;
+		load_req->img_len += fw_entry->size;
+		release_firmware(fw_entry);
+	}
+	load_req->phy_addr = virt_to_phys(img_data);
+	return ret;
+err:
+	release_firmware(fw_entry);
+	return ret;
+}
+
+static int __qseecom_load_fw(struct qseecom_dev_handle *data, char *appname)
+{
+	int ret = -1;
+	uint32_t fw_size = 0;
+	struct qseecom_load_app_ireq load_req = {0, 0, 0, 0};
+	struct qseecom_command_scm_resp resp;
+	u8 *img_data = NULL;
+
+	if (__qseecom_get_fw_size(appname, &fw_size))
+		return -EIO;
+
+	img_data = kzalloc(fw_size, GFP_KERNEL);
+	if (!img_data) {
+		pr_err("Failied to allocate memory for copying image data\n");
+		return -ENOMEM;
+	}
+	ret = __qseecom_get_fw_data(appname, img_data, &load_req);
+	if (ret) {
+		kzfree(img_data);
+		return -EIO;
+	}
+
+	/* Populate the remaining parameters */
+	load_req.qsee_cmd_id = QSEOS_APP_START_COMMAND;
+	memcpy(load_req.app_name, appname, MAX_APP_NAME_SIZE);
+	/* SCM_CALL to load the image */
+	ret = scm_call(SCM_SVC_TZSCHEDULER, 1,	&load_req,
+			sizeof(struct qseecom_load_app_ireq),
+			&resp, sizeof(resp));
+	kzfree(img_data);
+	if (ret) {
+		pr_err("scm_call to load failed : ret %d\n", ret);
+		return -EIO;
+	}
+
+	switch (resp.result) {
+	case QSEOS_RESULT_SUCCESS:
+		ret = resp.data;
+		break;
+	case QSEOS_RESULT_INCOMPLETE:
+		ret = __qseecom_process_incomplete_cmd(data, &resp);
+		if (ret)
+			pr_err("process_incomplete_cmd FAILED\n");
+		else
+			ret = resp.data;
+		break;
+	case QSEOS_RESULT_FAILURE:
+		pr_err("scm call failed with response QSEOS_RESULT FAILURE\n");
+		break;
+	default:
+		pr_err("scm call return unknown response %d\n", resp.result);
+		ret = -EINVAL;
+		break;
+	}
+	return ret;
+}
+
+int qseecom_start_app(struct qseecom_handle **handle,
+						char *app_name, uint32_t size)
+{
+	int32_t ret;
+	unsigned long flags = 0;
+	struct qseecom_dev_handle *data = NULL;
+	struct qseecom_check_app_ireq app_ireq;
+	struct qseecom_registered_app_list *entry = NULL;
+	struct qseecom_registered_kclient_list *kclient_entry = NULL;
+	bool found_app = false;
+	uint32_t len;
+	ion_phys_addr_t pa;
+
+	if (qseecom.qseos_version == QSEOS_VERSION_13) {
+		pr_err("This functionality is UNSUPPORTED in version 1.3\n");
+		return -EINVAL;
+	}
+
+	*handle = kzalloc(sizeof(struct qseecom_handle), GFP_KERNEL);
+	if (!(*handle)) {
+		pr_err("failed to allocate memory for kernel client handle\n");
+		return -ENOMEM;
+	}
+
+	app_ireq.qsee_cmd_id = QSEOS_APP_LOOKUP_COMMAND;
+	memcpy(app_ireq.app_name, app_name, MAX_APP_NAME_SIZE);
+	ret = __qseecom_check_app_exists(app_ireq);
+	if (ret < 0)
+		return -EINVAL;
+
+	data = kzalloc(sizeof(*data), GFP_KERNEL);
+	if (!data) {
+		pr_err("kmalloc failed\n");
+		if (ret == 0) {
+			kfree(*handle);
+			*handle = NULL;
+		}
+		return -ENOMEM;
+	}
+	data->abort = 0;
+	data->service = false;
+	data->released = false;
+	data->client.app_id = ret;
+	data->client.sb_length = size;
+	data->client.user_virt_sb_base = 0;
+	data->client.ihandle = NULL;
+
+	init_waitqueue_head(&data->abort_wq);
+	atomic_set(&data->ioctl_count, 0);
+
+	data->client.ihandle = ion_alloc(qseecom.ion_clnt, size, 4096,
+				ION_HEAP(ION_QSECOM_HEAP_ID), 0);
+	if (IS_ERR_OR_NULL(data->client.ihandle)) {
+		pr_err("Ion client could not retrieve the handle\n");
+		kfree(data);
+		kfree(*handle);
+		*handle = NULL;
+		return -EINVAL;
+	}
+
+	if (ret > 0) {
+		pr_warn("App id %d for [%s] app exists\n", ret,
+			(char *)app_ireq.app_name);
+		spin_lock_irqsave(&qseecom.registered_app_list_lock, flags);
+		list_for_each_entry(entry,
+				&qseecom.registered_app_list_head, list){
+			if (entry->app_id == ret) {
+				entry->ref_cnt++;
+				found_app = true;
+				break;
+			}
+		}
+		spin_unlock_irqrestore(
+				&qseecom.registered_app_list_lock, flags);
+		if (!found_app)
+			pr_warn("App_id %d [%s] was loaded but not registered\n",
+					ret, (char *)app_ireq.app_name);
+	} else {
+		/* load the app and get the app_id  */
+		pr_debug("%s: Loading app for the first time'\n",
+				qseecom.pdev->init_name);
+		mutex_lock(&app_access_lock);
+		ret = __qseecom_load_fw(data, app_name);
+		mutex_unlock(&app_access_lock);
+
+		if (ret < 0) {
+			kfree(*handle);
+			*handle = NULL;
+			return ret;
+		}
+		data->client.app_id = ret;
+	}
+	if (!found_app) {
+		entry = kmalloc(sizeof(*entry), GFP_KERNEL);
+		if (!entry) {
+			pr_err("kmalloc failed\n");
+			return -ENOMEM;
+		}
+		entry->app_id = ret;
+		entry->ref_cnt = 1;
+
+		spin_lock_irqsave(&qseecom.registered_app_list_lock, flags);
+		list_add_tail(&entry->list, &qseecom.registered_app_list_head);
+		spin_unlock_irqrestore(&qseecom.registered_app_list_lock,
+									flags);
+	}
+
+	/* Get the physical address of the ION BUF */
+	ret = ion_phys(qseecom.ion_clnt, data->client.ihandle, &pa, &len);
+	/* Populate the structure for sending scm call to load image */
+	data->client.sb_virt = (char *) ion_map_kernel(qseecom.ion_clnt,
+							data->client.ihandle);
+	data->client.sb_phys = pa;
+	(*handle)->dev = (void *)data;
+	(*handle)->sbuf = (unsigned char *)data->client.sb_virt;
+	(*handle)->sbuf_len = data->client.sb_length;
+
+	kclient_entry = kzalloc(sizeof(*kclient_entry), GFP_KERNEL);
+	if (!kclient_entry) {
+		pr_err("kmalloc failed\n");
+		return -ENOMEM;
+	}
+	kclient_entry->handle = *handle;
+
+	spin_lock_irqsave(&qseecom.registered_kclient_list_lock, flags);
+	list_add_tail(&kclient_entry->list,
+			&qseecom.registered_kclient_list_head);
+	spin_unlock_irqrestore(&qseecom.registered_kclient_list_lock, flags);
+
+	return 0;
+}
+EXPORT_SYMBOL(qseecom_start_app);
+
+int qseecom_shutdown_app(struct qseecom_handle **handle)
+{
+	int ret = -EINVAL;
+	struct qseecom_dev_handle *data =
+			(struct qseecom_dev_handle *) ((*handle)->dev);
+	struct qseecom_registered_kclient_list *kclient = NULL;
+	unsigned long flags = 0;
+	bool found_handle = false;
+
+	if (qseecom.qseos_version == QSEOS_VERSION_13) {
+		pr_err("This functionality is UNSUPPORTED in version 1.3\n");
+		return -EINVAL;
+	}
+	if (*handle == NULL) {
+		pr_err("Handle is not initialized\n");
+		return -EINVAL;
+	}
+
+	spin_lock_irqsave(&qseecom.registered_kclient_list_lock, flags);
+	list_for_each_entry(kclient, &qseecom.registered_kclient_list_head,
+				list) {
+		if (kclient->handle == (*handle)) {
+			list_del(&kclient->list);
+			found_handle = true;
+			break;
+		}
+	}
+	spin_unlock_irqrestore(&qseecom.registered_kclient_list_lock, flags);
+	if (!found_handle)
+		pr_err("Unable to find the handle, exiting\n");
+	else
+		ret = qseecom_unload_app(data);
+	if (ret == 0) {
+		kzfree(data);
+		kzfree(*handle);
+		kzfree(kclient);
+		*handle = NULL;
+	}
+	return ret;
+}
+EXPORT_SYMBOL(qseecom_shutdown_app);
+
+int qseecom_send_command(struct qseecom_handle *handle, void *send_buf,
+			uint32_t sbuf_len, void *resp_buf, uint32_t rbuf_len)
+{
+	int ret = 0;
+	struct qseecom_send_cmd_req req = {0, 0, 0, 0};
+	struct qseecom_dev_handle *data;
+
+	if (qseecom.qseos_version == QSEOS_VERSION_13) {
+		pr_err("This functionality is UNSUPPORTED in version 1.3\n");
+		return -EINVAL;
+	}
+
+	if (handle == NULL) {
+		pr_err("Handle is not initialized\n");
+		return -EINVAL;
+	}
+	data = handle->dev;
+
+	req.cmd_req_len = sbuf_len;
+	req.resp_len = rbuf_len;
+	req.cmd_req_buf = send_buf;
+	req.resp_buf = resp_buf;
+
+	mutex_lock(&app_access_lock);
+	atomic_inc(&data->ioctl_count);
+
+	ret = __qseecom_send_cmd(data, &req);
+
+	atomic_dec(&data->ioctl_count);
+	mutex_unlock(&app_access_lock);
+
+	if (ret)
+		return ret;
+
+	pr_debug("sending cmd_req->rsp size: %u, ptr: 0x%p\n",
+			req.resp_len, req.resp_buf);
+	return ret;
+}
+EXPORT_SYMBOL(qseecom_send_command);
+
 static int qseecom_send_resp(void)
 {
 	qseecom.send_resp_flag = 1;
@@ -1871,7 +2267,7 @@
 	int ret;
 	struct device *class_dev;
 	char qsee_not_legacy = 0;
-	struct msm_bus_scale_pdata *qseecom_platform_support;
+	struct msm_bus_scale_pdata *qseecom_platform_support = NULL;
 	uint32_t system_call_id = QSEOS_CHECK_VERSION_CMD;
 
 	qsee_bw_count = 0;
@@ -1911,6 +2307,8 @@
 	spin_lock_init(&qseecom.registered_listener_list_lock);
 	INIT_LIST_HEAD(&qseecom.registered_app_list_head);
 	spin_lock_init(&qseecom.registered_app_list_lock);
+	INIT_LIST_HEAD(&qseecom.registered_kclient_list_head);
+	spin_lock_init(&qseecom.registered_kclient_list_lock);
 	init_waitqueue_head(&qseecom.send_resp_wq);
 	qseecom.send_resp_flag = 0;
 
@@ -1930,7 +2328,7 @@
 
 	qseecom.pdev = class_dev;
 	/* Create ION msm client */
-	qseecom.ion_clnt = msm_ion_client_create(0x03, "qseecom-kernel");
+	qseecom.ion_clnt = msm_ion_client_create(-1, "qseecom-kernel");
 	if (qseecom.ion_clnt == NULL) {
 		pr_err("Ion client cannot be created\n");
 		rc = -ENOMEM;
@@ -1966,9 +2364,60 @@
 
 static int __devinit qseecom_remove(struct platform_device *pdev)
 {
+	struct qseecom_registered_kclient_list *kclient = NULL;
+	unsigned long flags = 0;
+	int ret = 0;
+
 	if (pdev->dev.platform_data != NULL)
 		msm_bus_scale_unregister_client(qsee_perf_client);
-	return 0;
+
+	spin_lock_irqsave(&qseecom.registered_kclient_list_lock, flags);
+	kclient = list_entry((&qseecom.registered_kclient_list_head)->next,
+		struct qseecom_registered_kclient_list, list);
+	if (list_empty(&kclient->list)) {
+		spin_unlock_irqrestore(&qseecom.registered_kclient_list_lock,
+			flags);
+		return 0;
+	}
+	list_for_each_entry(kclient, &qseecom.registered_kclient_list_head,
+				list) {
+			if (kclient)
+				list_del(&kclient->list);
+			break;
+	}
+	spin_unlock_irqrestore(&qseecom.registered_kclient_list_lock, flags);
+
+
+	while (kclient->handle != NULL) {
+		ret = qseecom_unload_app(kclient->handle->dev);
+		if (ret == 0) {
+			kzfree(kclient->handle->dev);
+			kzfree(kclient->handle);
+			kzfree(kclient);
+		}
+		spin_lock_irqsave(&qseecom.registered_kclient_list_lock, flags);
+		kclient = list_entry(
+				(&qseecom.registered_kclient_list_head)->next,
+				struct qseecom_registered_kclient_list, list);
+		if (list_empty(&kclient->list)) {
+			spin_unlock_irqrestore(
+				&qseecom.registered_kclient_list_lock, flags);
+			return 0;
+		}
+		list_for_each_entry(kclient,
+				&qseecom.registered_kclient_list_head, list) {
+			if (kclient)
+				list_del(&kclient->list);
+			break;
+		}
+		spin_unlock_irqrestore(&qseecom.registered_kclient_list_lock,
+				flags);
+		if (!kclient) {
+			ret = 0;
+			break;
+		}
+	}
+	return ret;
 };
 
 static struct of_device_id qseecom_match[] = {
diff --git a/drivers/misc/qseecom_kernel.h b/drivers/misc/qseecom_kernel.h
new file mode 100644
index 0000000..bfa5709
--- /dev/null
+++ b/drivers/misc/qseecom_kernel.h
@@ -0,0 +1,36 @@
+/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __QSEECOM_KERNEL_H_
+#define __QSEECOM_KERNEL_H_
+
+#include <linux/types.h>
+/*
+ * struct qseecom_handle -
+ *      Handle to the qseecom device for kernel clients
+ * @sbuf - shared buffer pointer
+ * @sbbuf_len - shared buffer size
+ */
+struct qseecom_handle {
+	void *dev; /* in/out */
+	unsigned char *sbuf; /* in/out */
+	uint32_t sbuf_len; /* in/out */
+};
+
+int qseecom_start_app(struct qseecom_handle **handle,
+						char *app_name, uint32_t size);
+int qseecom_shutdown_app(struct qseecom_handle **handle);
+int qseecom_send_command(struct qseecom_handle *handle, void *send_buf,
+			uint32_t sbuf_len, void *resp_buf, uint32_t rbuf_len);
+
+
+#endif /* __QSEECOM_KERNEL_H_ */
diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c
index 91253ff..fe41cdd 100644
--- a/drivers/mmc/card/block.c
+++ b/drivers/mmc/card/block.c
@@ -2361,7 +2361,7 @@
 	ret = device_create_file(disk_to_dev(md->disk),
 				 &md->num_wr_reqs_to_start_packing);
 	if (ret)
-		goto power_ro_lock_fail;
+		goto num_wr_reqs_to_start_packing_fail;
 
 	md->min_sectors_to_check_bkops_status.show =
 		min_sectors_to_check_bkops_status_show;
@@ -2374,14 +2374,19 @@
 	ret = device_create_file(disk_to_dev(md->disk),
 				 &md->min_sectors_to_check_bkops_status);
 	if (ret)
-		goto power_ro_lock_fail;
+		goto min_sectors_to_check_bkops_status_fails;
 
 	return ret;
 
+min_sectors_to_check_bkops_status_fails:
+	device_remove_file(disk_to_dev(md->disk),
+			   &md->num_wr_reqs_to_start_packing);
+num_wr_reqs_to_start_packing_fail:
+	device_remove_file(disk_to_dev(md->disk), &md->power_ro_lock);
 power_ro_lock_fail:
-		device_remove_file(disk_to_dev(md->disk), &md->force_ro);
+	device_remove_file(disk_to_dev(md->disk), &md->force_ro);
 force_ro_fail:
-		del_gendisk(md->disk);
+	del_gendisk(md->disk);
 
 	return ret;
 }
diff --git a/drivers/power/bq28400_battery.c b/drivers/power/bq28400_battery.c
index 39d52cb..47fced1 100644
--- a/drivers/power/bq28400_battery.c
+++ b/drivers/power/bq28400_battery.c
@@ -818,6 +818,11 @@
 		return -EIO;
 	}
 
+	if (bq28400_read_reg(client, SBS_BATTERY_STATUS) < 0) {
+		pr_err("Device doesn't exist.\n");
+		return -ENODEV;
+	}
+
 	bq28400_dev = kzalloc(sizeof(*bq28400_dev), GFP_KERNEL);
 	if (!bq28400_dev) {
 		pr_err(" alloc fail.\n");
diff --git a/drivers/power/pm8921-bms.c b/drivers/power/pm8921-bms.c
index 23903df..60eee64 100644
--- a/drivers/power/pm8921-bms.c
+++ b/drivers/power/pm8921-bms.c
@@ -856,6 +856,22 @@
 	*val = cc_uah;
 }
 
+int pm8921_bms_cc_uah(int *cc_uah)
+{
+	int cc;
+
+	*cc_uah = 0;
+
+	if (!the_chip)
+		return -EINVAL;
+
+	read_cc(the_chip, &cc);
+	calculate_cc_uah(the_chip, cc, cc_uah);
+
+	return 0;
+}
+EXPORT_SYMBOL(pm8921_bms_cc_uah);
+
 static int calculate_termination_uuc(struct pm8921_bms_chip *chip,
 				 int batt_temp, int chargecycles,
 				int fcc_uah, int i_ma,
@@ -1398,7 +1414,7 @@
 						(s64)fcc_uah - uuc_uah);
 	soc_est = bound_soc(soc_est);
 
-	if (ibat_ua < 0) {
+	if (ibat_ua < 0 && pm8921_is_batfet_closed()) {
 		soc = charging_adjustments(chip, soc, vbat_uv, ibat_ua,
 				batt_temp, chargecycles,
 				fcc_uah, cc_uah, uuc_uah);
diff --git a/drivers/power/pm8921-charger.c b/drivers/power/pm8921-charger.c
index 8c561b9b..8a36d6c 100644
--- a/drivers/power/pm8921-charger.c
+++ b/drivers/power/pm8921-charger.c
@@ -1354,6 +1354,7 @@
 	POWER_SUPPLY_PROP_CURRENT_NOW,
 	POWER_SUPPLY_PROP_TEMP,
 	POWER_SUPPLY_PROP_ENERGY_FULL,
+	POWER_SUPPLY_PROP_CHARGE_NOW,
 };
 
 static int get_prop_battery_uvolts(struct pm8921_chg_chip *chip)
@@ -1489,6 +1490,20 @@
 	return rc;
 }
 
+static int get_prop_batt_charge_now(struct pm8921_chg_chip *chip)
+{
+	int rc;
+	int cc_uah;
+
+	rc = pm8921_bms_cc_uah(&cc_uah);
+
+	if (rc == 0)
+		return cc_uah;
+
+	pr_err("unable to get batt fcc rc = %d\n", rc);
+	return rc;
+}
+
 static int get_prop_batt_health(struct pm8921_chg_chip *chip)
 {
 	int temp;
@@ -1627,6 +1642,9 @@
 	case POWER_SUPPLY_PROP_ENERGY_FULL:
 		val->intval = get_prop_batt_fcc(chip) * 1000;
 		break;
+	case POWER_SUPPLY_PROP_CHARGE_NOW:
+		val->intval = get_prop_batt_charge_now(chip);
+		break;
 	default:
 		return -EINVAL;
 	}
@@ -4339,6 +4357,11 @@
 						vin_collapse_check_worker);
 	INIT_DELAYED_WORK(&chip->unplug_check_work, unplug_check_worker);
 
+	INIT_WORK(&chip->bms_notify.work, bms_notify);
+	INIT_WORK(&chip->battery_id_valid_work, battery_id_valid);
+
+	INIT_DELAYED_WORK(&chip->update_heartbeat_work, update_heartbeat);
+
 	rc = request_irqs(chip, pdev);
 	if (rc) {
 		pr_err("couldn't register interrupts rc=%d\n", rc);
@@ -4375,19 +4398,13 @@
 	}
 	create_debugfs_entries(chip);
 
-	INIT_WORK(&chip->bms_notify.work, bms_notify);
-	INIT_WORK(&chip->battery_id_valid_work, battery_id_valid);
-
 	/* determine what state the charger is in */
 	determine_initial_state(chip);
 
-	if (chip->update_time) {
-		INIT_DELAYED_WORK(&chip->update_heartbeat_work,
-							update_heartbeat);
+	if (chip->update_time)
 		schedule_delayed_work(&chip->update_heartbeat_work,
 				      round_jiffies_relative(msecs_to_jiffies
 							(chip->update_time)));
-	}
 	return 0;
 
 free_irq:
diff --git a/drivers/usb/host/ehci-mem.c b/drivers/usb/host/ehci-mem.c
index 12f70c3..c61591a 100644
--- a/drivers/usb/host/ehci-mem.c
+++ b/drivers/usb/host/ehci-mem.c
@@ -178,12 +178,15 @@
 static int ehci_mem_init (struct ehci_hcd *ehci, gfp_t flags)
 {
 	int i;
+	size_t align;
+
+	align = ((ehci->pool_64_bit_align) ? 64 : 32);
 
 	/* QTDs for control/bulk/intr transfers */
 	ehci->qtd_pool = dma_pool_create ("ehci_qtd",
 			ehci_to_hcd(ehci)->self.controller,
 			sizeof (struct ehci_qtd),
-			32 /* byte alignment (for hw parts) */,
+			align /* byte alignment (for hw parts) */,
 			4096 /* can't cross 4K */);
 	if (!ehci->qtd_pool) {
 		goto fail;
@@ -193,7 +196,7 @@
 	ehci->qh_pool = dma_pool_create ("ehci_qh",
 			ehci_to_hcd(ehci)->self.controller,
 			sizeof(struct ehci_qh_hw),
-			32 /* byte alignment (for hw parts) */,
+			align /* byte alignment (for hw parts) */,
 			4096 /* can't cross 4K */);
 	if (!ehci->qh_pool) {
 		goto fail;
diff --git a/drivers/usb/host/ehci-platform.c b/drivers/usb/host/ehci-platform.c
index d238b4e2..07a232a 100644
--- a/drivers/usb/host/ehci-platform.c
+++ b/drivers/usb/host/ehci-platform.c
@@ -30,6 +30,7 @@
 
 	hcd->has_tt = pdata->has_tt;
 	ehci->has_synopsys_hc_bug = pdata->has_synopsys_hc_bug;
+	ehci->pool_64_bit_align = pdata->pool_64_bit_align;
 	ehci->big_endian_desc = pdata->big_endian_desc;
 	ehci->big_endian_mmio = pdata->big_endian_mmio;
 
diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h
index f8b884a..cd17421 100644
--- a/drivers/usb/host/ehci.h
+++ b/drivers/usb/host/ehci.h
@@ -166,6 +166,7 @@
 	unsigned		has_hostpc:1;
 	unsigned		has_lpm:1;  /* support link power management */
 	unsigned		has_ppcd:1; /* support per-port change bits */
+	unsigned		pool_64_bit_align:1; /* for 64 bit alignment */
 	u8			sbrn;		/* packed release number */
 
 	/* irq statistics */
diff --git a/drivers/video/msm/mdp4_overlay.c b/drivers/video/msm/mdp4_overlay.c
index 1bd697e..04da6f5 100644
--- a/drivers/video/msm/mdp4_overlay.c
+++ b/drivers/video/msm/mdp4_overlay.c
@@ -1777,6 +1777,7 @@
 	struct mdp4_overlay_pipe *bspipe;
 	int ptype, pnum, pndx, mixer;
 	int format, alpha_enable, alpha;
+	struct mdp4_iommu_pipe_info iom;
 
 	if (pipe->pipe_type != OVERLAY_TYPE_BF)
 		return;
@@ -1791,6 +1792,7 @@
 		return;
 	}
 
+	iom = bspipe->iommu;
 	ptype = bspipe->pipe_type;
 	pnum = bspipe->pipe_num;
 	pndx = bspipe->pipe_ndx;
@@ -1804,6 +1806,7 @@
 	bspipe->src_format = format;
 	bspipe->alpha_enable = alpha_enable;
 	bspipe->alpha = alpha;
+	bspipe->iommu = iom;
 
 	bspipe->pipe_used++;	/* mark base layer pipe used */
 
diff --git a/drivers/video/msm/mdss/mdss_hdmi_tx.c b/drivers/video/msm/mdss/mdss_hdmi_tx.c
index c2d5f28..d53240f 100644
--- a/drivers/video/msm/mdss/mdss_hdmi_tx.c
+++ b/drivers/video/msm/mdss/mdss_hdmi_tx.c
@@ -18,6 +18,7 @@
 #include <linux/of_address.h>
 #include <linux/of_gpio.h>
 #include <linux/types.h>
+#include <mach/msm_hdmi_audio.h>
 
 #define REG_DUMP 0
 
@@ -40,6 +41,17 @@
 	((d & 0xff) + ((d >> 8) & 0xff) +	\
 	((d >> 16) & 0xff) + ((d >> 24) & 0xff))
 
+/* parameters for clock regeneration */
+struct hdmi_tx_audio_acr {
+	u32 n;
+	u32 cts;
+};
+
+struct hdmi_tx_audio_acr_arry {
+	u32 pclk;
+	struct hdmi_tx_audio_acr lut[HDMI_SAMPLE_RATE_MAX];
+};
+
 static int hdmi_tx_sysfs_enable_hpd(struct hdmi_tx_ctrl *hdmi_ctrl, int on);
 static irqreturn_t hdmi_tx_isr(int irq, void *data);
 
@@ -90,6 +102,27 @@
 	 0x07,	0x07,	0x07,	0x07,	0x02, 0x02, 0x02}  /*12*/
 };
 
+/* Audio constants lookup table for hdmi_tx_audio_acr_setup */
+/* Valid Pixel-Clock rates: 25.2MHz, 27MHz, 27.03MHz, 74.25MHz, 148.5MHz */
+static const struct hdmi_tx_audio_acr_arry hdmi_tx_audio_acr_lut[] = {
+	/*  25.200MHz  */
+	{25200, {{4096, 25200}, {6272, 28000}, {6144, 25200}, {12544, 28000},
+		{12288, 25200}, {25088, 28000}, {24576, 25200} } },
+	/*  27.000MHz  */
+	{27000, {{4096, 27000}, {6272, 30000}, {6144, 27000}, {12544, 30000},
+		{12288, 27000}, {25088, 30000}, {24576, 27000} } },
+	/*  27.027MHz */
+	{27030, {{4096, 27027}, {6272, 30030}, {6144, 27027}, {12544, 30030},
+		{12288, 27027}, {25088, 30030}, {24576, 27027} } },
+	/*  74.250MHz */
+	{74250, {{4096, 74250}, {6272, 82500}, {6144, 74250}, {12544, 82500},
+		{12288, 74250}, {25088, 82500}, {24576, 74250} } },
+	/* 148.500MHz */
+	{148500, {{4096, 148500}, {6272, 165000}, {6144, 148500},
+		{12544, 165000}, {12288, 148500}, {25088, 165000},
+		{24576, 148500} } },
+};
+
 const char *hdmi_tx_pm_name(enum hdmi_tx_power_module_type module)
 {
 	switch (module) {
@@ -335,8 +368,8 @@
 
 static inline u32 hdmi_tx_is_dvi_mode(struct hdmi_tx_ctrl *hdmi_ctrl)
 {
-	struct dss_io_data *io = &hdmi_ctrl->pdata.io[HDMI_TX_CORE_IO];
-	return !(DSS_REG_R_ND(io, HDMI_CTRL) & BIT(1));
+	return hdmi_edid_get_sink_mode(
+		hdmi_ctrl->feature_data[HDMI_TX_FEAT_EDID]) ? 0 : 1;
 } /* hdmi_tx_is_dvi_mode */
 
 static int hdmi_tx_init_panel_info(uint32_t resolution,
@@ -1275,6 +1308,335 @@
 	DSS_REG_W_ND(io, HDMI_PHY_PD_CTRL0, 0x7F);
 } /* hdmi_tx_powerdown_phy */
 
+static int hdmi_tx_audio_acr_setup(struct hdmi_tx_ctrl *hdmi_ctrl,
+	bool enabled, int num_of_channels)
+{
+	/* Read first before writing */
+	u32 acr_pck_ctrl_reg;
+	struct dss_io_data *io = NULL;
+
+	if (!hdmi_ctrl) {
+		DEV_ERR("%s: Invalid input\n", __func__);
+		return -EINVAL;
+	}
+
+	io = &hdmi_ctrl->pdata.io[HDMI_TX_CORE_IO];
+	if (!io->base) {
+		DEV_ERR("%s: core io not inititalized\n", __func__);
+		return -EINVAL;
+	}
+
+	acr_pck_ctrl_reg = DSS_REG_R(io, HDMI_ACR_PKT_CTRL);
+
+	if (enabled) {
+		const struct hdmi_disp_mode_timing_type *timing =
+			hdmi_get_supported_mode(hdmi_ctrl->video_resolution);
+		const struct hdmi_tx_audio_acr_arry *audio_acr =
+			&hdmi_tx_audio_acr_lut[0];
+		const int lut_size = sizeof(hdmi_tx_audio_acr_lut)
+			/ sizeof(*hdmi_tx_audio_acr_lut);
+		u32 i, n, cts, layout, multiplier, aud_pck_ctrl_2_reg;
+
+		if (timing == NULL) {
+			DEV_WARN("%s: video format %d not supported\n",
+				__func__, hdmi_ctrl->video_resolution);
+			return -EPERM;
+		}
+
+		for (i = 0; i < lut_size;
+			audio_acr = &hdmi_tx_audio_acr_lut[++i]) {
+			if (audio_acr->pclk == timing->pixel_freq)
+				break;
+		}
+		if (i >= lut_size) {
+			DEV_WARN("%s: pixel clk %d not supported\n", __func__,
+				timing->pixel_freq);
+			return -EPERM;
+		}
+
+		n = audio_acr->lut[hdmi_ctrl->audio_sample_rate].n;
+		cts = audio_acr->lut[hdmi_ctrl->audio_sample_rate].cts;
+		layout = (MSM_HDMI_AUDIO_CHANNEL_2 == num_of_channels) ? 0 : 1;
+
+		if (
+		(HDMI_SAMPLE_RATE_192KHZ == hdmi_ctrl->audio_sample_rate) ||
+		(HDMI_SAMPLE_RATE_176_4KHZ == hdmi_ctrl->audio_sample_rate)) {
+			multiplier = 4;
+			n >>= 2; /* divide N by 4 and use multiplier */
+		} else if (
+		(HDMI_SAMPLE_RATE_96KHZ == hdmi_ctrl->audio_sample_rate) ||
+		(HDMI_SAMPLE_RATE_88_2KHZ == hdmi_ctrl->audio_sample_rate)) {
+			multiplier = 2;
+			n >>= 1; /* divide N by 2 and use multiplier */
+		} else {
+			multiplier = 1;
+		}
+		DEV_DBG("%s: n=%u, cts=%u, layout=%u\n", __func__, n, cts,
+			layout);
+
+		/* AUDIO_PRIORITY | SOURCE */
+		acr_pck_ctrl_reg |= 0x80000100;
+		/* N_MULTIPLE(multiplier) */
+		acr_pck_ctrl_reg |= (multiplier & 7) << 16;
+
+		if ((HDMI_SAMPLE_RATE_48KHZ == hdmi_ctrl->audio_sample_rate) ||
+		(HDMI_SAMPLE_RATE_96KHZ == hdmi_ctrl->audio_sample_rate) ||
+		(HDMI_SAMPLE_RATE_192KHZ == hdmi_ctrl->audio_sample_rate)) {
+			/* SELECT(3) */
+			acr_pck_ctrl_reg |= 3 << 4;
+			/* CTS_48 */
+			cts <<= 12;
+
+			/* CTS: need to determine how many fractional bits */
+			DSS_REG_W(io, HDMI_ACR_48_0, cts);
+			/* N */
+			DSS_REG_W(io, HDMI_ACR_48_1, n);
+		} else if (
+		(HDMI_SAMPLE_RATE_44_1KHZ == hdmi_ctrl->audio_sample_rate) ||
+		(HDMI_SAMPLE_RATE_88_2KHZ == hdmi_ctrl->audio_sample_rate) ||
+		(HDMI_SAMPLE_RATE_176_4KHZ == hdmi_ctrl->audio_sample_rate)) {
+			/* SELECT(2) */
+			acr_pck_ctrl_reg |= 2 << 4;
+			/* CTS_44 */
+			cts <<= 12;
+
+			/* CTS: need to determine how many fractional bits */
+			DSS_REG_W(io, HDMI_ACR_44_0, cts);
+			/* N */
+			DSS_REG_W(io, HDMI_ACR_44_1, n);
+		} else {	/* default to 32k */
+			/* SELECT(1) */
+			acr_pck_ctrl_reg |= 1 << 4;
+			/* CTS_32 */
+			cts <<= 12;
+
+			/* CTS: need to determine how many fractional bits */
+			DSS_REG_W(io, HDMI_ACR_32_0, cts);
+			/* N */
+			DSS_REG_W(io, HDMI_ACR_32_1, n);
+		}
+		/* Payload layout depends on number of audio channels */
+		/* LAYOUT_SEL(layout) */
+		aud_pck_ctrl_2_reg = 1 | (layout << 1);
+		/* override | layout */
+		DSS_REG_W(io, HDMI_AUDIO_PKT_CTRL2, aud_pck_ctrl_2_reg);
+
+		/* SEND | CONT */
+		acr_pck_ctrl_reg |= 0x00000003;
+	} else {
+		/* ~(SEND | CONT) */
+		acr_pck_ctrl_reg &= ~0x00000003;
+	}
+	DSS_REG_W(io, HDMI_ACR_PKT_CTRL, acr_pck_ctrl_reg);
+
+	return 0;
+} /* hdmi_tx_audio_acr_setup */
+
+static int hdmi_tx_audio_info_setup(void *priv_d, bool enabled,
+	u32 num_of_channels, u32 channel_allocation, u32 level_shift,
+	bool down_mix)
+{
+	struct hdmi_tx_ctrl *hdmi_ctrl = (struct hdmi_tx_ctrl *)priv_d;
+	struct dss_io_data *io = NULL;
+
+	u32 channel_count = 1; /* Def to 2 channels -> Table 17 in CEA-D */
+	u32 check_sum, audio_info_0_reg, audio_info_1_reg;
+	u32 audio_info_ctrl_reg;
+	u32 aud_pck_ctrl_2_reg;
+	u32 layout;
+
+	if (!hdmi_ctrl) {
+		DEV_ERR("%s: invalid input\n", __func__);
+		return -EINVAL;
+	}
+
+	io = &hdmi_ctrl->pdata.io[HDMI_TX_CORE_IO];
+	if (!io->base) {
+		DEV_ERR("%s: core io not inititalized\n", __func__);
+		return -EINVAL;
+	}
+
+	layout = (MSM_HDMI_AUDIO_CHANNEL_2 == num_of_channels) ? 0 : 1;
+	aud_pck_ctrl_2_reg = 1 | (layout << 1);
+	DSS_REG_W(io, HDMI_AUDIO_PKT_CTRL2, aud_pck_ctrl_2_reg);
+
+	/*
+	 * Please see table 20 Audio InfoFrame in HDMI spec
+	 * FL  = front left
+	 * FC  = front Center
+	 * FR  = front right
+	 * FLC = front left center
+	 * FRC = front right center
+	 * RL  = rear left
+	 * RC  = rear center
+	 * RR  = rear right
+	 * RLC = rear left center
+	 * RRC = rear right center
+	 * LFE = low frequency effect
+	 */
+
+	/* Read first then write because it is bundled with other controls */
+	audio_info_ctrl_reg = DSS_REG_R(io, HDMI_INFOFRAME_CTRL0);
+
+	if (enabled) {
+		switch (num_of_channels) {
+		case MSM_HDMI_AUDIO_CHANNEL_2:
+			channel_allocation = 0;	/* Default to FR, FL */
+			break;
+		case MSM_HDMI_AUDIO_CHANNEL_4:
+			channel_count = 3;
+			/* FC, LFE, FR, FL */
+			channel_allocation = 0x3;
+			break;
+		case MSM_HDMI_AUDIO_CHANNEL_6:
+			channel_count = 5;
+			/* RR, RL, FC, LFE, FR, FL */
+			channel_allocation = 0xB;
+			break;
+		case MSM_HDMI_AUDIO_CHANNEL_8:
+			channel_count = 7;
+			/* FRC, FLC, RR, RL, FC, LFE, FR, FL */
+			channel_allocation = 0x1f;
+			break;
+		default:
+			DEV_ERR("%s: Unsupported num_of_channels = %u\n",
+				__func__, num_of_channels);
+			return -EINVAL;
+		}
+
+		/* Program the Channel-Speaker allocation */
+		audio_info_1_reg = 0;
+		/* CA(channel_allocation) */
+		audio_info_1_reg |= channel_allocation & 0xff;
+		/* Program the Level shifter */
+		audio_info_1_reg |= (level_shift << 11) & 0x00007800;
+		/* Program the Down-mix Inhibit Flag */
+		audio_info_1_reg |= (down_mix << 15) & 0x00008000;
+
+		DSS_REG_W(io, HDMI_AUDIO_INFO1, audio_info_1_reg);
+
+		/*
+		 * Calculate CheckSum: Sum of all the bytes in the
+		 * Audio Info Packet (See table 8.4 in HDMI spec)
+		 */
+		check_sum = 0;
+		/* HDMI_AUDIO_INFO_FRAME_PACKET_HEADER_TYPE[0x84] */
+		check_sum += 0x84;
+		/* HDMI_AUDIO_INFO_FRAME_PACKET_HEADER_VERSION[0x01] */
+		check_sum += 1;
+		/* HDMI_AUDIO_INFO_FRAME_PACKET_LENGTH[0x0A] */
+		check_sum += 0x0A;
+		check_sum += channel_count;
+		check_sum += channel_allocation;
+		/* See Table 8.5 in HDMI spec */
+		check_sum += (level_shift & 0xF) << 3 | (down_mix & 0x1) << 7;
+		check_sum &= 0xFF;
+		check_sum = (u8) (256 - check_sum);
+
+		audio_info_0_reg = 0;
+		/* CHECKSUM(check_sum) */
+		audio_info_0_reg |= check_sum & 0xff;
+		/* CC(channel_count) */
+		audio_info_0_reg |= (channel_count << 8) & 0x00000700;
+
+		DSS_REG_W(io, HDMI_AUDIO_INFO0, audio_info_0_reg);
+
+		/*
+		 * Set these flags
+		 * AUDIO_INFO_UPDATE |
+		 * AUDIO_INFO_SOURCE |
+		 * AUDIO_INFO_CONT   |
+		 * AUDIO_INFO_SEND
+		 */
+		audio_info_ctrl_reg |= 0x000000F0;
+	} else {
+		/*Clear these flags
+		 * ~(AUDIO_INFO_UPDATE |
+		 *   AUDIO_INFO_SOURCE |
+		 *   AUDIO_INFO_CONT   |
+		 *   AUDIO_INFO_SEND)
+		 */
+		audio_info_ctrl_reg &= ~0x000000F0;
+	}
+	DSS_REG_W(io, HDMI_INFOFRAME_CTRL0, audio_info_ctrl_reg);
+
+	dss_reg_dump(io->base, io->len, "HDMI-AUDIO-ON: ", REG_DUMP);
+
+	return 0;
+} /* hdmi_tx_audio_info_setup */
+
+static int hdmi_tx_audio_setup(struct hdmi_tx_ctrl *hdmi_ctrl)
+{
+	int rc = 0;
+	const int channels = MSM_HDMI_AUDIO_CHANNEL_2;
+	struct dss_io_data *io = NULL;
+
+	if (!hdmi_ctrl) {
+		DEV_ERR("%s: invalid input\n", __func__);
+		return -EINVAL;
+	}
+
+	io = &hdmi_ctrl->pdata.io[HDMI_TX_CORE_IO];
+	if (!io->base) {
+		DEV_ERR("%s: core io not inititalized\n", __func__);
+		return -EINVAL;
+	}
+
+	rc = hdmi_tx_audio_acr_setup(hdmi_ctrl, true, channels);
+	if (rc) {
+		DEV_ERR("%s: hdmi_tx_audio_acr_setup failed. rc=%d\n",
+			__func__, rc);
+		return rc;
+	}
+
+	rc = hdmi_tx_audio_info_setup(hdmi_ctrl, true, channels, 0, 0, false);
+	if (rc) {
+		DEV_ERR("%s: hdmi_tx_audio_info_setup failed. rc=%d\n",
+			__func__, rc);
+		return rc;
+	}
+
+	DEV_INFO("HDMI Audio: Enabled\n");
+
+	return 0;
+} /* hdmi_tx_audio_setup */
+
+static void hdmi_tx_audio_off(struct hdmi_tx_ctrl *hdmi_ctrl)
+{
+	int i;
+	u32 audio_pkt_ctrl, audio_cfg;
+	struct dss_io_data *io = NULL;
+
+	if (!hdmi_ctrl) {
+		DEV_ERR("%s: invalid input\n", __func__);
+		return;
+	}
+
+	io = &hdmi_ctrl->pdata.io[HDMI_TX_CORE_IO];
+	if (!io->base) {
+		DEV_ERR("%s: core io not inititalized\n", __func__);
+		return;
+	}
+
+	/* Number of wait iterations */
+	i = 10;
+	do {
+		audio_pkt_ctrl = DSS_REG_R_ND(io, HDMI_AUDIO_PKT_CTRL);
+		audio_cfg = DSS_REG_R_ND(io, HDMI_AUDIO_CFG);
+		DEV_DBG("%s: i=%d, AUDIO PACKET=%08x, AUDIO CFG=%08x",
+			__func__, i, audio_pkt_ctrl, audio_cfg);
+		msleep(20);
+	} while (((audio_pkt_ctrl & BIT(0)) || (audio_cfg & BIT(0))) && i--);
+
+	if (hdmi_tx_audio_info_setup(hdmi_ctrl, false, 0, 0, 0, false))
+		DEV_ERR("%s: hdmi_tx_audio_info_setup failed.\n", __func__);
+
+	if (hdmi_tx_audio_acr_setup(hdmi_ctrl, false, 0))
+		DEV_ERR("%s: hdmi_tx_audio_acr_setup failed.\n", __func__);
+
+	DEV_INFO("HDMI Audio: Disabled\n");
+} /* hdmi_tx_audio_off */
+
 static int hdmi_tx_start(struct hdmi_tx_ctrl *hdmi_ctrl)
 {
 	int rc = 0;
@@ -1290,8 +1652,6 @@
 		return -EINVAL;
 	}
 
-	/* todo: Audio */
-
 	hdmi_tx_set_mode(hdmi_ctrl, false);
 	hdmi_tx_init_phy(hdmi_ctrl);
 	DSS_REG_W(io, HDMI_USEC_REFTIMER, 0x0001001B);
@@ -1299,7 +1659,21 @@
 	hdmi_tx_set_mode(hdmi_ctrl, true);
 
 	hdmi_tx_video_setup(hdmi_ctrl, hdmi_ctrl->video_resolution);
-	/* todo: Audio */
+
+	if (!hdmi_tx_is_dvi_mode(hdmi_ctrl)) {
+		rc = hdmi_tx_audio_setup(hdmi_ctrl);
+		if (rc) {
+			DEV_ERR("%s: hdmi_msm_audio_setup failed. rc=%d\n",
+				__func__, rc);
+			hdmi_tx_set_mode(hdmi_ctrl, false);
+			return rc;
+		}
+
+		switch_set_state(&hdmi_ctrl->audio_sdev, 1);
+		DEV_INFO("%s: hdmi_audio state switch to %d\n", __func__,
+			hdmi_ctrl->audio_sdev.state);
+	}
+
 	hdmi_tx_set_avi_infoframe(hdmi_ctrl);
 	/* todo: CONFIG_FB_MSM_HDMI_3D */
 	hdmi_tx_set_spd_infoframe(hdmi_ctrl);
@@ -1324,8 +1698,16 @@
 		return -EINVAL;
 	}
 
-	DEV_INFO("%s: power: OFF (audio off, Reset Core)\n", __func__);
-	/* todo: Audio */
+	DEV_INFO("%s: HDMI Core: OFF\n", __func__);
+
+	if (!hdmi_tx_is_dvi_mode(hdmi_ctrl)) {
+		switch_set_state(&hdmi_ctrl->audio_sdev, 0);
+		DEV_INFO("%s: hdmi_audio state switch to %d\n", __func__,
+			hdmi_ctrl->audio_sdev.state);
+
+		hdmi_tx_audio_off(hdmi_ctrl);
+	}
+
 	hdmi_tx_powerdown_phy(hdmi_ctrl);
 	hdmi_ctrl->panel_power_on = false;
 	hdmi_tx_core_off(hdmi_ctrl);
@@ -1546,6 +1928,7 @@
 	if (hdmi_ctrl->feature_data[HDMI_TX_FEAT_EDID])
 		hdmi_edid_deinit(hdmi_ctrl->feature_data[HDMI_TX_FEAT_EDID]);
 
+	switch_dev_unregister(&hdmi_ctrl->audio_sdev);
 	switch_dev_unregister(&hdmi_ctrl->sdev);
 	del_timer_sync(&hdmi_ctrl->hpd_state_timer);
 	if (hdmi_ctrl->workq)
@@ -1581,6 +1964,7 @@
 	hdmi_ctrl->workq = create_workqueue("hdmi_tx_workq");
 	if (!hdmi_ctrl->workq) {
 		DEV_ERR("%s: hdmi_tx_workq creation failed.\n", __func__);
+		rc = -EPERM;
 		goto fail_create_workq;
 	}
 
@@ -1594,14 +1978,27 @@
 	hdmi_ctrl->hpd_state_timer.data = (u32)hdmi_ctrl;
 	hdmi_ctrl->hpd_state_timer.expires = 0xffffffffL;
 
+	hdmi_ctrl->audio_sample_rate = HDMI_SAMPLE_RATE_48KHZ;
+
 	hdmi_ctrl->sdev.name = "hdmi";
 	if (switch_dev_register(&hdmi_ctrl->sdev) < 0) {
 		DEV_ERR("%s: Hdmi switch registration failed\n", __func__);
+		rc = -ENODEV;
 		goto fail_switch_dev;
 	}
 
+	hdmi_ctrl->audio_sdev.name = "hdmi_audio";
+	if (switch_dev_register(&hdmi_ctrl->audio_sdev) < 0) {
+		DEV_ERR("%s: hdmi_audio switch registration failed\n",
+			__func__);
+		rc = -ENODEV;
+		goto fail_audio_switch_dev;
+	}
+
 	return 0;
 
+fail_audio_switch_dev:
+	switch_dev_unregister(&hdmi_ctrl->sdev);
 fail_switch_dev:
 	del_timer_sync(&hdmi_ctrl->hpd_state_timer);
 fail_create_workq:
diff --git a/drivers/video/msm/mdss/mdss_hdmi_tx.h b/drivers/video/msm/mdss/mdss_hdmi_tx.h
index 94e0fda..437f681 100644
--- a/drivers/video/msm/mdss/mdss_hdmi_tx.h
+++ b/drivers/video/msm/mdss/mdss_hdmi_tx.h
@@ -41,9 +41,12 @@
 	struct hdmi_tx_platform_data pdata;
 	struct mdss_panel_data panel_data;
 
+	int audio_sample_rate;
+
 	struct mutex mutex;
 	struct kobject *kobj;
 	struct switch_dev sdev;
+	struct switch_dev audio_sdev;
 	struct workqueue_struct *workq;
 
 	uint32_t video_resolution;
diff --git a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_interrupt_handler.c b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_interrupt_handler.c
index 8cfa95b..2c41ab4 100644
--- a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_interrupt_handler.c
+++ b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_interrupt_handler.c
@@ -493,6 +493,7 @@
 				ddl_get_state_string(ddl->client_state));
 			ddl_calc_core_proc_time(__func__, DEC_OP_TIME, ddl);
 			ddl_reset_core_time_variables(DEC_OP_TIME);
+			ddl_vidc_decode_reset_avg_time(ddl);
 			ddl->client_state = DDL_CLIENT_WAIT_FOR_FRAME;
 			ddl_vidc_decode_frame_run(ddl);
 			ret_status = false;
diff --git a/drivers/video/msm/vidc/1080p/resource_tracker/vcd_res_tracker.c b/drivers/video/msm/vidc/1080p/resource_tracker/vcd_res_tracker.c
index 0bc2228..75856b2a 100644
--- a/drivers/video/msm/vidc/1080p/resource_tracker/vcd_res_tracker.c
+++ b/drivers/video/msm/vidc/1080p/resource_tracker/vcd_res_tracker.c
@@ -452,6 +452,10 @@
 static struct ion_client *res_trk_create_ion_client(void){
 	struct ion_client *video_client;
 	video_client = msm_ion_client_create(-1, "video_client");
+	if (IS_ERR_OR_NULL(video_client)) {
+		VCDRES_MSG_ERROR("%s: Unable to create ION client\n", __func__);
+		video_client = NULL;
+	}
 	return video_client;
 }
 
diff --git a/drivers/video/msm/vidc/720p/ddl/vcd_ddl_utils.c b/drivers/video/msm/vidc/720p/ddl/vcd_ddl_utils.c
index 3b40640..9fb8162 100644
--- a/drivers/video/msm/vidc/720p/ddl/vcd_ddl_utils.c
+++ b/drivers/video/msm/vidc/720p/ddl/vcd_ddl_utils.c
@@ -125,9 +125,8 @@
 					alloc_size,
 					SZ_4K,
 					buff_addr->mem_type, 0);
-		if (!buff_addr->alloc_handle) {
-			ERR("\n%s(): DDL ION alloc failed\n",
-					__func__);
+		if (IS_ERR_OR_NULL(buff_addr->alloc_handle)) {
+			ERR("\n%s(): DDL ION alloc failed\n", __func__);
 			goto bailout;
 		}
 		ret = ion_phys(ddl_context->video_ion_client,
diff --git a/drivers/video/msm/vidc/720p/resource_tracker/vcd_res_tracker.c b/drivers/video/msm/vidc/720p/resource_tracker/vcd_res_tracker.c
index aee9dfe..d8b8f18 100644
--- a/drivers/video/msm/vidc/720p/resource_tracker/vcd_res_tracker.c
+++ b/drivers/video/msm/vidc/720p/resource_tracker/vcd_res_tracker.c
@@ -681,6 +681,10 @@
 	struct ion_client *video_client;
 	VCDRES_MSG_LOW("%s", __func__);
 	video_client = msm_ion_client_create(-1, "video_client");
+	if (IS_ERR_OR_NULL(video_client)) {
+		VCDRES_MSG_ERROR("%s: Unable to create ION client\n", __func__);
+		video_client = NULL;
+	}
 	return video_client;
 }
 
diff --git a/drivers/video/msm/vidc/common/vcd/vcd_sub.c b/drivers/video/msm/vidc/common/vcd/vcd_sub.c
index 5fdee02..8d28fd5 100644
--- a/drivers/video/msm/vidc/common/vcd/vcd_sub.c
+++ b/drivers/video/msm/vidc/common/vcd/vcd_sub.c
@@ -93,7 +93,7 @@
 		map_buffer->alloc_handle = ion_alloc(
 			    cctxt->vcd_ion_client, sz, SZ_4K,
 			    memtype, 0);
-		if (!map_buffer->alloc_handle) {
+		if (IS_ERR_OR_NULL(map_buffer->alloc_handle)) {
 			pr_err("%s() ION alloc failed", __func__);
 			goto bailout;
 		}
diff --git a/include/linux/mfd/pm8xxx/pm8921-bms.h b/include/linux/mfd/pm8xxx/pm8921-bms.h
index 5f2fe9f..ba70c96 100644
--- a/include/linux/mfd/pm8xxx/pm8921-bms.h
+++ b/include/linux/mfd/pm8xxx/pm8921-bms.h
@@ -127,6 +127,15 @@
  *					soc stored in a coincell backed register
  */
 void pm8921_bms_invalidate_shutdown_soc(void);
+
+/**
+ * pm8921_bms_cc_uah -	function to get the coulomb counter based charge. Note
+ *			that the coulomb counter are reset when the current
+ *			consumption is low (below 8mA for more than 5 minutes),
+ *			This will lead in a very low coulomb counter charge
+ *			value upon wakeup from sleep.
+ */
+int pm8921_bms_cc_uah(int *cc_uah);
 #else
 static inline int pm8921_bms_get_vsense_avg(int *result)
 {
@@ -165,6 +174,10 @@
 static inline void pm8921_bms_invalidate_shutdown_soc(void)
 {
 }
+static inline int pm8921_bms_cc_uah(int *cc_uah)
+{
+	return -ENXIO;
+}
 #endif
 
 #endif
diff --git a/include/linux/qpnp/pin.h b/include/linux/qpnp/pin.h
index fa9c30f..fff29ab 100644
--- a/include/linux/qpnp/pin.h
+++ b/include/linux/qpnp/pin.h
@@ -131,7 +131,7 @@
  *			the input is interpreted as a logical 1.
  * @out_strength:	the amount of current supplied for an output gpio,
  *			should be of the type QPNP_PIN_STRENGTH_*.
- * @select:		select alternate function for the pin. Certain pins
+ * @src_sel:		select alternate function for the pin. Certain pins
  *			can be paired (shorted) with each other. Some pins
  *			can act as alternate functions. In the context of
  *			gpio, this acts as a source select. For mpps,
@@ -159,7 +159,7 @@
 	int pull;
 	int vin_sel;
 	int out_strength;
-	int select;
+	int src_sel;
 	int master_en;
 	int aout_ref;
 	int ain_route;
diff --git a/include/linux/usb/ehci_pdriver.h b/include/linux/usb/ehci_pdriver.h
index 1894f42..4c1b7a0 100644
--- a/include/linux/usb/ehci_pdriver.h
+++ b/include/linux/usb/ehci_pdriver.h
@@ -41,6 +41,7 @@
 	unsigned	big_endian_mmio:1;
 	unsigned	port_power_on:1;
 	unsigned	port_power_off:1;
+	unsigned	pool_64_bit_align:1;
 };
 
 #endif /* __USB_CORE_EHCI_PDRIVER_H */
diff --git a/include/media/radio-iris.h b/include/media/radio-iris.h
index db69518..0efeff4 100644
--- a/include/media/radio-iris.h
+++ b/include/media/radio-iris.h
@@ -363,6 +363,53 @@
 #define HCI_REQ_CANCELED  2
 #define HCI_REQ_STATUS    3
 
+#define MAX_RAW_RDS_GRPS	21
+
+#define RDSGRP_DATA_OFFSET	 0x1
+
+/*RT PLUS*/
+#define DUMMY_CLASS		0
+#define RT_PLUS_LEN_1_TAG	3
+#define RT_ERT_FLAG_BIT		5
+
+/*TAG1*/
+#define TAG1_MSB_OFFSET		3
+#define TAG1_MSB_MASK		7
+#define TAG1_LSB_OFFSET		5
+#define TAG1_POS_MSB_MASK	31
+#define TAG1_POS_MSB_OFFSET	1
+#define TAG1_POS_LSB_OFFSET	7
+#define TAG1_LEN_OFFSET		1
+#define TAG1_LEN_MASK		63
+
+/*TAG2*/
+#define TAG2_MSB_OFFSET		5
+#define TAG2_MSB_MASK		1
+#define TAG2_LSB_OFFSET		3
+#define TAG2_POS_MSB_MASK	7
+#define TAG2_POS_MSB_OFFSET	3
+#define TAG2_POS_LSB_OFFSET	5
+#define TAG2_LEN_MASK		31
+
+#define AGT_MASK		31
+/*Extract 5 left most bits of lsb of 2nd block*/
+#define AGT(x)			(x & AGT_MASK)
+/*16 bits of 4th block*/
+#define AID(lsb, msb)		((msb << 8) | (lsb))
+/*Extract 5 right most bits of msb of 2nd block*/
+#define GTC(blk2msb)		(blk2msb >> 3)
+
+#define GRP_3A			0x6
+#define RT_PLUS_AID		0x4bd7
+
+/*ERT*/
+#define ERT_AID			0x6552
+#define CARRIAGE_RETURN		0x000D
+#define MAX_ERT_SEGMENT		31
+#define ERT_FORMAT_DIR_BIT	1
+
+#define EXTRACT_BIT(data, bit_pos) ((data & (1 << bit_pos)) >> bit_pos)
+
 struct hci_ev_tune_status {
 	__u8    sub_event;
 	__le32  station_freq;
@@ -375,9 +422,19 @@
 	__u8	intf_det_th;
 } __packed;
 
+struct rds_blk_data {
+	__u8	rdsMsb;
+	__u8	rdsLsb;
+	__u8	blockStatus;
+} __packed;
+
+struct rds_grp_data {
+	struct rds_blk_data rdsBlk[4];
+} __packed;
+
 struct hci_ev_rds_rx_data {
 	__u8    num_rds_grps;
-	__u8    rds_grp_data[12];
+	struct  rds_grp_data rds_grp_data[MAX_RAW_RDS_GRPS];
 } __packed;
 
 struct hci_ev_prg_service {
@@ -628,7 +685,10 @@
 	IRIS_EVT_NEW_AF_LIST,
 	IRIS_EVT_TXRDSDAT,
 	IRIS_EVT_TXRDSDONE,
-	IRIS_EVT_RADIO_DISABLED
+	IRIS_EVT_RADIO_DISABLED,
+	IRIS_EVT_NEW_ODA,
+	IRIS_EVT_NEW_RT_PLUS,
+	IRIS_EVT_NEW_ERT,
 };
 enum emphasis_type {
 	FM_RX_EMP75 = 0x0,
@@ -660,7 +720,7 @@
 	IRIS_REGION_OTHER
 };
 
-#define STD_BUF_SIZE        (128)
+#define STD_BUF_SIZE        (256)
 
 enum iris_buf_t {
 	IRIS_BUF_SRCH_LIST,
@@ -674,7 +734,9 @@
 	IRIS_BUF_RDS_CNTRS,
 	IRIS_BUF_RD_DEFAULT,
 	IRIS_BUF_CAL_DATA,
-	IRIS_BUF_MAX
+	IRIS_BUF_RT_PLUS,
+	IRIS_BUF_ERT,
+	IRIS_BUF_MAX,
 };
 
 enum iris_xfr_t {
diff --git a/include/media/tavarua.h b/include/media/tavarua.h
index 1cccb2b..881b851 100644
--- a/include/media/tavarua.h
+++ b/include/media/tavarua.h
@@ -52,7 +52,7 @@
 #define SRCH_MASK                  (1 << SRCH200KHZ_OFFSET)
 
 /* Standard buffer size */
-#define STD_BUF_SIZE               (128)
+#define STD_BUF_SIZE               (256)
 /* Search direction */
 #define SRCH_DIR_UP                 (0)
 #define SRCH_DIR_DOWN               (1)
diff --git a/include/sound/apr_audio.h b/include/sound/apr_audio.h
index 8c35ada..23c1d51 100644
--- a/include/sound/apr_audio.h
+++ b/include/sound/apr_audio.h
@@ -61,7 +61,7 @@
 #define RT_PROXY_PORT_001_TX	0x2001    /* index = 31 */
 #define SECONDARY_PCM_RX 12			/* index = 32 */
 #define SECONDARY_PCM_TX 13			/* index = 33 */
-
+#define PSEUDOPORT_01           0x8001    /* index =34 */
 
 #define AFE_PORT_INVALID 0xFFFF
 #define SLIMBUS_EXTPROC_RX AFE_PORT_INVALID
@@ -299,6 +299,14 @@
 	int	num_ch;		/* 1 to 8 */
 } __packed;
 
+struct afe_port_pseudo_cfg {
+	u16 bit_width;
+	u16 num_channels;
+	u16 data_format;
+	u16 timing_mode;
+	u16 reserved;
+} __packed;
+
 #define AFE_PORT_AUDIO_IF_CONFIG 0x000100d3
 #define AFE_PORT_AUDIO_SLIM_SCH_CONFIG 0x000100e4
 #define AFE_PORT_MULTI_CHAN_HDMI_AUDIO_IF_CONFIG	0x000100D9
@@ -312,6 +320,7 @@
 	struct afe_port_slimbus_cfg	  slimbus;
 	struct afe_port_slimbus_sch_cfg	  slim_sch;
 	struct afe_port_rtproxy_cfg       rtproxy;
+	struct afe_port_pseudo_cfg        pseudo;
 } __attribute__((packed));
 
 struct afe_audioif_config_command {
@@ -574,6 +583,19 @@
 	u32 rate;
 	u8 dev_channel_mapping[8];
 } __packed;
+
+struct adm_multi_channel_copp_open_v3 {
+	struct apr_hdr hdr;
+	u16 flags;
+	u16 mode;
+	u16 endpoint_id1;
+	u16 endpoint_id2;
+	u32 topology_id;
+	u16 channel_config;
+	u16 bit_width;
+	u32 rate;
+	u8  dev_channel_mapping[8];
+};
 #define ADM_CMD_MEMORY_MAP				0x00010C30
 struct adm_cmd_memory_map{
 	struct apr_hdr	hdr;
@@ -914,7 +936,38 @@
 				 * An unused channel is set to zero.
 				 */
 };
+struct asm_dts_enc_cfg {
+	uint32_t	sample_rate;
+	/*
+	* Samples at which input is to be encoded.
+	* Supported values:
+	* 44100 -- encode at 44.1 Khz
+	* 48000 -- encode at 48 Khz
+	*/
 
+	uint32_t	num_channels;
+	/*
+	* Number of channels for multi-channel encoding.
+	* Supported values: 1 to 6
+	*/
+
+	uint8_t		channel_mapping[6];
+	/*
+	* Channel array of size 16. Channel[i] mapping describes channel I.
+	* Each element i of the array describes channel I inside the buffer
+	* where num_channels. An unused channel is set to zero. Only first
+	* num_channels elements are valid
+
+	* Supported values:
+	* - # PCM_CHANNEL_L
+	* - # PCM_CHANNEL_R
+	* - # PCM_CHANNEL_C
+	* - # PCM_CHANNEL_LS
+	* - # PCM_CHANNEL_RS
+	* - # PCM_CHANNEL_LFE
+	*/
+
+};
 struct asm_adpcm_cfg {
 	u16 ch_cfg;
 	u16 bits_per_sample;
@@ -1107,6 +1160,7 @@
 		struct asm_sbc_read_cfg     sbc;
 		struct asm_amrwb_read_cfg   amrwb;
 		struct asm_multi_channel_pcm_fmt_blk      mpcm;
+		struct asm_dts_enc_cfg      dts;
 	} __attribute__((packed)) cfg;
 };
 
@@ -1209,6 +1263,148 @@
 	u32	flags;
 	u32	format;
 } __packed;
+#define ASM_STREAM_CMD_OPEN_TRANSCODE_LOOPBACK     0x00010DBA
+struct asm_stream_cmd_open_transcode_loopback {
+	struct apr_hdr hdr;
+	uint32_t	mode_flags;
+	/*
+	* All bits are reserved. Clients must set them to zero.
+	*/
+
+	uint32_t	src_format_id;
+	/*
+	* Specifies the media format of the input audio stream.
+
+	* Supported values:
+	* - #ASM_MEDIA_FMT_LINEAR_PCM
+	* - #ASM_MEDIA_FMT_MULTI_CHANNEL_PCM
+	*/
+
+	uint32_t	sink_format_id;
+	/*
+	* Specifies the media format of the output stream.
+
+	* Supported values:
+	* - #ASM_MEDIA_FMT_LINEAR_PCM
+	* - #ASM_MEDIA_FMT_MULTI_CHANNEL_PCM
+	* - #ASM_MEDIA_FMT_DTS
+	*/
+
+	uint32_t	audproc_topo_id;
+	/*
+	* Postprocessing topology ID, which specifies the topology (order of
+	* processing) of postprocessing algorithms.
+
+	* Supported values:
+	* - #ASM_STREAM_POSTPROC_TOPO_ID_DEFAULT
+	* - #ASM_STREAM_POSTPROC_TOPO_ID_PEAKMETER
+	* - #ASM_STREAM_POSTPROC_TOPO_ID_NONE
+	* - #ASM_STREAM_POSTPROC_TOPO_ID_MCH_PEAK_VOL
+	*/
+
+	uint16_t	src_endpoint_type;
+	/*
+	* Specifies the source endpoint that provides the input samples.
+
+	* Supported values:
+	* - 0 -- Tx device matrix or stream router
+	* (gateway to the hardware ports)
+	* - All other values are reserved
+
+	* Clients must set this field to zero. Otherwise, an error is returned.
+	*/
+
+	uint16_t	sink_endpoint_type;
+	/*
+	* Specifies the sink endpoint type.
+
+	* Supported values:
+	* - 0 -- Rx device matrix or stream router
+	* (gateway to the hardware ports)
+	* - All other values are reserved
+
+	* Clients must set this field to zero. Otherwise, an error is returned.
+	*/
+
+	uint16_t	bits_per_sample;
+	/*
+	* Number of bits per sample processed by the ASM modules.
+	* Supported values: 16, 24
+	*/
+
+	uint16_t	reserved;
+	/*
+	* This field must be set to zero.
+	*/
+} __packed;
+
+/*
+* ID of the DTS mix LFE channel to front channels parameter in the
+* #ASM_STREAM_CMD_SET_ENCDEC_PARAM command.
+* asm_dts_generic_param_t
+* ASM_PARAM_ID_DTS_MIX_LFE_TO_FRONT
+*/
+#define ASM_PARAM_ID_DTS_MIX_LFE_TO_FRONT                          0x00010DB6
+
+/*
+* ID of the DTS DRC ratio parameter in the
+* #ASM_STREAM_CMD_SET_ENCDEC_PARAM command.
+* asm_dts_generic_param_t
+* ASM_PARAM_ID_DTS_DRC_RATIO
+*/
+#define ASM_PARAM_ID_DTS_DRC_RATIO                                   0x00010DB7
+
+/*
+* ID of the DTS enable dialog normalization parameter in the
+* #ASM_STREAM_CMD_SET_ENCDEC_PARAM command.
+
+* asm_dts_generic_param_t
+* ASM_PARAM_ID_DTS_ENABLE_DIALNORM
+*/
+#define ASM_PARAM_ID_DTS_ENABLE_DIALNORM                             0x00010DB8
+
+/*
+* ID of the DTS enable parse REV2AUX parameter in the
+* #ASM_STREAM_CMD_SET_ENCDEC_PARAM command.
+* asm_dts_generic_param_t
+* ASM_PARAM_ID_DTS_ENABLE_PARSE_REV2AUX
+*/
+#define ASM_PARAM_ID_DTS_ENABLE_PARSE_REV2AUX                         0x00010DB9
+
+struct asm_dts_generic_param {
+	int32_t		generic_parameter;
+	/*
+	* #ASM_PARAM_ID_DTS_MIX_LFE_TO_FRONT:
+	* - if enabled, mixes LFE channel to front
+	* while downmixing (if necessary)
+	* - Supported values: 1-> enable, 0-> disable
+	* - Default: disabled
+
+	* #ASM_PARAM_ID_DTS_DRC_RATIO:
+	* - percentage of DRC ratio.
+	* - Supported values: 0-100
+	* - Default: 0, DRC is disabled.
+
+	* #ASM_PARAM_ID_DTS_ENABLE_DIALNORM:
+	* - flag to enable dialog normalization post processing.
+	* - Supported values: 1-> enable, 0-> disable.
+	* - Default: enabled.
+
+	* #ASM_PARAM_ID_DTS_ENABLE_PARSE_REV2AUX:
+	* - flag to enable parsing of rev2aux chunk in the bitstream.
+	* This chunk contains broadcast metadata.
+	* - Supported values: 1-> enable, 0-> disable.
+	* - Default: disabled.
+	*/
+};
+
+struct asm_stream_cmd_dts_dec_param {
+	struct apr_hdr hdr;
+	u32            param_id;
+	u32            param_size;
+	struct asm_dts_generic_param generic_param;
+} __packed;
+
 
 #define ASM_STREAM_CMD_OPEN_READWRITE                    0x00010BCC
 
@@ -1238,7 +1434,7 @@
 	u8	session_id; /*ASM session ID*/
 	u16	afe_port_id;
 	u32	num_channels;
-	u32	sampleing_rate;
+	u32	sampling_rate;
 } __packed;
 
 #define ASM_STREAM_CMD_SET_ENCDEC_PARAM                  0x00010C10
diff --git a/include/sound/compress_params.h b/include/sound/compress_params.h
index f5c2d13..b95fa3c 100644
--- a/include/sound/compress_params.h
+++ b/include/sound/compress_params.h
@@ -418,6 +418,8 @@
 	__u32 ch_mode;
 	__u32 format;
 	__u32 align;
+	__u32 transcode_dts;
+	struct snd_dec_dts dts;
 	union snd_codec_options options;
 	__u32 reserved[3];
 };
diff --git a/include/sound/q6adm.h b/include/sound/q6adm.h
index 676c4cb..70c68a8 100644
--- a/include/sound/q6adm.h
+++ b/include/sound/q6adm.h
@@ -37,6 +37,8 @@
 
 int adm_close(int port);
 
+int adm_pseudo_close(int port);
+
 int adm_matrix_map(int session_id, int path, int num_copps,
 				unsigned int *port_id, int copp_id);
 
@@ -45,6 +47,12 @@
 
 void adm_ec_ref_rx_id(int  port_id);
 
+int adm_connect_afe_port_v2(int mode, int session_id, int port_id,
+					int sample_rate, int channels);
+
+int adm_multi_ch_copp_pseudo_open_v3(int port_id, int path, int rate,
+				int channel_mode, int topology);
+
 #ifdef CONFIG_RTAC
 int adm_get_copp_id(int port_id);
 #endif
diff --git a/include/sound/q6afe.h b/include/sound/q6afe.h
index a7264e8..8451ac6 100644
--- a/include/sound/q6afe.h
+++ b/include/sound/q6afe.h
@@ -70,6 +70,7 @@
 	IDX_RT_PROXY_PORT_001_TX = 31,
 	IDX_SECONDARY_PCM_RX = 32,
 	IDX_SECONDARY_PCM_TX = 33,
+	IDX_PSEUDOPORT_01 = 34,
 	AFE_MAX_PORTS
 };
 
diff --git a/include/sound/q6asm.h b/include/sound/q6asm.h
index b0d74ba..6b4c17b 100644
--- a/include/sound/q6asm.h
+++ b/include/sound/q6asm.h
@@ -55,6 +55,7 @@
 #define ENCDEC_SBCBITRATE   0x0001
 #define ENCDEC_IMMEDIATE_DECODE 0x0002
 #define ENCDEC_CFG_BLK          0x0003
+#define DTS_ENC_SAMPLE_RATE48k	48000
 
 #define CMD_PAUSE          0x0001
 #define CMD_FLUSH          0x0002
@@ -194,6 +195,11 @@
 
 int q6asm_open_write_compressed(struct audio_client *ac, uint32_t format);
 
+int q6asm_open_transcode_loopback(struct audio_client *ac, uint32_t channels);
+
+int q6asm_enc_cfg_blk_dts(struct audio_client *ac,
+				uint32_t sample_rate, uint32_t channels);
+
 int q6asm_open_read_write(struct audio_client *ac,
 			uint32_t rd_format,
 			uint32_t wr_format);
diff --git a/sound/soc/msm/mpq8064.c b/sound/soc/msm/mpq8064.c
index 016ef94..90c96b4 100644
--- a/sound/soc/msm/mpq8064.c
+++ b/sound/soc/msm/mpq8064.c
@@ -1486,6 +1486,20 @@
 		.ignore_pmdown_time = 1, /* dainlink has playback support */
 		.codec_dai_name = "snd-soc-dummy-dai",
 		.codec_name = "snd-soc-dummy",
+
+	},
+	{
+		.name = "MSM8960 Pseudo",
+		.stream_name = "Pseudo",
+		.cpu_dai_name   = "Pseudo",
+		.dynamic = 1,
+		.trigger = {SND_SOC_DPCM_TRIGGER_POST,
+				SND_SOC_DPCM_TRIGGER_POST},
+		.codec_dai_name = "snd-soc-dummy-dai",
+		.codec_name = "snd-soc-dummy",
+		.ignore_suspend = 1,
+		.ignore_pmdown_time = 1,
+		.be_id = MSM_FRONTEND_DAI_PSEUDO,
 	},
 	/* Backend DAI Links */
 	{
@@ -1624,6 +1638,18 @@
 		.be_id = MSM_BACKEND_DAI_AUXPCM_TX,
 		.be_hw_params_fixup = mpq8064_auxpcm_be_params_fixup,
 	},
+	{
+		.name = LPASS_BE_PSEUDO,
+		.stream_name = "PSEUDO Playback",
+		.cpu_dai_name = "msm-dai-q6.32769",
+		.platform_name = "msm-pcm-routing",
+		.codec_name     = "snd-soc-dummy",
+		.codec_dai_name = "snd-soc-dummy-dai",
+		.no_pcm = 1,
+		.be_id = MSM_BACKEND_DAI_PSEUDO_PORT,
+		.be_hw_params_fixup = msm_be_hw_params_fixup,
+		.ignore_pmdown_time = 1,
+	},
 };
 
 
diff --git a/sound/soc/msm/msm-compr-q6.c b/sound/soc/msm/msm-compr-q6.c
index eeabb78..5b0eb9c 100644
--- a/sound/soc/msm/msm-compr-q6.c
+++ b/sound/soc/msm/msm-compr-q6.c
@@ -474,7 +474,23 @@
 	default:
 		return -EINVAL;
 	}
-
+	if (compr->info.codec_param.codec.transcode_dts) {
+		msm_pcm_routing_reg_pseudo_stream(
+			MSM_FRONTEND_DAI_PSEUDO,
+			prtd->enc_audio_client->perf_mode,
+			prtd->enc_audio_client->session,
+			SNDRV_PCM_STREAM_CAPTURE,
+			48000, runtime->channels > 6 ?
+			6 : runtime->channels);
+		pr_debug("%s: cmd: DTS ENCDEC CFG BLK\n", __func__);
+		ret = q6asm_enc_cfg_blk_dts(prtd->enc_audio_client,
+				DTS_ENC_SAMPLE_RATE48k,
+				runtime->channels > 6 ?
+				6 : runtime->channels);
+		if (ret < 0)
+			pr_err("%s: CMD: DTS ENCDEC CFG BLK failed\n",
+				__func__);
+	}
 	prtd->enabled = 1;
 	prtd->cmd_ack = 0;
 
@@ -650,6 +666,8 @@
 	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
 		pr_debug("%s: Trigger start\n", __func__);
 		q6asm_run_nowait(prtd->audio_client, 0, 0, 0);
+		if (prtd->enc_audio_client)
+			q6asm_run_nowait(prtd->enc_audio_client, 0, 0, 0);
 		atomic_set(&prtd->start, 1);
 		break;
 	case SNDRV_PCM_TRIGGER_STOP:
@@ -660,6 +678,8 @@
 	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
 		pr_debug("SNDRV_PCM_TRIGGER_PAUSE\n");
 		q6asm_cmd_nowait(prtd->audio_client, CMD_PAUSE);
+		if (prtd->enc_audio_client)
+			q6asm_cmd_nowait(prtd->enc_audio_client, CMD_PAUSE);
 		atomic_set(&prtd->start, 0);
 		runtime->render_flag &= ~SNDRV_RENDER_STOPPED;
 		break;
@@ -811,6 +831,8 @@
 	atomic_set(&prtd->pending_buffer, 0);
 	prtd->pcm_irq_pos = 0;
 	q6asm_cmd(prtd->audio_client, CMD_CLOSE);
+	if (prtd->enc_audio_client)
+		q6asm_cmd(prtd->enc_audio_client, CMD_CLOSE);
 	compressed_audio.prtd = NULL;
 	q6asm_audio_client_buf_free_contiguous(dir,
 				prtd->audio_client);
@@ -827,6 +849,12 @@
 			soc_prtd->dai_link->be_id,
 			SNDRV_PCM_STREAM_PLAYBACK);
 	}
+	if (compr->info.codec_param.codec.transcode_dts) {
+		msm_pcm_routing_dereg_pseudo_stream(MSM_FRONTEND_DAI_PSEUDO,
+			prtd->enc_audio_client->session);
+	}
+	if (prtd->enc_audio_client)
+		q6asm_audio_client_free(prtd->enc_audio_client);
 	q6asm_audio_client_free(prtd->audio_client);
 	kfree(prtd);
 	return 0;
@@ -968,6 +996,29 @@
 				prtd->session_id,
 				substream->stream);
 
+			if (compr->info.codec_param.codec.transcode_dts) {
+				prtd->enc_audio_client =
+					q6asm_audio_client_alloc(
+					(app_cb)compr_event_handler, compr);
+				if (!prtd->enc_audio_client) {
+					pr_err("%s: Could not allocate " \
+							"memory\n", __func__);
+					return -ENOMEM;
+				}
+				prtd->enc_audio_client->perf_mode = false;
+				pr_debug("%s Setting up loopback path\n",
+						__func__);
+				ret = q6asm_open_transcode_loopback(
+					prtd->enc_audio_client,
+					params_channels(params));
+				if (ret < 0) {
+					pr_err("%s: Session transcode " \
+						"loopback open failed\n",
+						__func__);
+					return -ENODEV;
+				}
+			}
+
 			break;
 		}
 	} else if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
@@ -1117,6 +1168,22 @@
 			pr_err("%s: ERROR: copy from user\n", __func__);
 			return rc;
 		}
+		/*
+		* DTS Security needed for the transcode path
+		*/
+		if (compr->info.codec_param.codec.transcode_dts) {
+			char modelId[128];
+			struct snd_dec_dts opt_dts =
+				compr->info.codec_param.codec.dts;
+			int modelIdLength = opt_dts.modelIdLength;
+			if (copy_from_user(modelId, (void *)opt_dts.modelId,
+				modelIdLength))
+				pr_err("%s: ERROR: copy modelId\n", __func__);
+			modelId[modelIdLength] = '\0';
+			pr_debug("%s: Received modelId =%s,length=%d\n",
+				__func__, modelId, modelIdLength);
+			core_set_dts_model_id(modelIdLength, modelId);
+		}
 		switch (compr->info.codec_param.codec.id) {
 		case SND_AUDIOCODEC_MP3:
 			/* For MP3 we dont need any other parameter */
@@ -1150,7 +1217,7 @@
 		case SND_AUDIOCODEC_DTS: {
 			char modelId[128];
 			struct snd_dec_dts opt_dts =
-				compr->info.codec_param.codec.options.dts;
+				compr->info.codec_param.codec.dts;
 			int modelIdLength = opt_dts.modelIdLength;
 			pr_debug("SND_AUDIOCODEC_DTS\n");
 			if (copy_from_user(modelId, (void *)opt_dts.modelId,
@@ -1166,7 +1233,7 @@
 		case SND_AUDIOCODEC_DTS_LBR:{
 			char modelId[128];
 			struct snd_dec_dts opt_dts =
-				compr->info.codec_param.codec.options.dts;
+				compr->info.codec_param.codec.dts;
 			int modelIdLength = opt_dts.modelIdLength;
 			pr_debug("SND_AUDIOCODEC_DTS_LBR\n");
 			if (copy_from_user(modelId, (void *)opt_dts.modelId,
diff --git a/sound/soc/msm/msm-dai-fe.c b/sound/soc/msm/msm-dai-fe.c
index dc8d9e6..e91ed86 100644
--- a/sound/soc/msm/msm-dai-fe.c
+++ b/sound/soc/msm/msm-dai-fe.c
@@ -477,6 +477,32 @@
 		.ops = &msm_fe_dai_ops,
 		.name = "SGLTE",
 	},
+	{
+		.playback = {
+			.stream_name = "Pseudo Playback",
+			.aif_name = "MM_DL9",
+			.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,
+		},
+		.capture = {
+			.stream_name = "Pseudo 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 = "Pseudo",
+	},
 };
 
 static __devinit int msm_fe_dai_dev_probe(struct platform_device *pdev)
diff --git a/sound/soc/msm/msm-dai-q6.c b/sound/soc/msm/msm-dai-q6.c
index 18c2329..8cc0eaa 100644
--- a/sound/soc/msm/msm-dai-q6.c
+++ b/sound/soc/msm/msm-dai-q6.c
@@ -660,6 +660,24 @@
 	return 0;
 }
 
+static int msm_dai_q6_pseudo_hw_params(struct snd_pcm_hw_params *params,
+				struct snd_soc_dai *dai)
+{
+	struct msm_dai_q6_dai_data *dai_data = dev_get_drvdata(dai->dev);
+
+	dai_data->rate = params_rate(params);
+	dai_data->channels = params_channels(params) > 6 ?
+				params_channels(params) : 6;
+
+	dai_data->port_config.pseudo.bit_width = 16;
+	dai_data->port_config.pseudo.num_channels =
+			dai_data->channels;
+	dai_data->port_config.pseudo.data_format = 0;
+	dai_data->port_config.pseudo.timing_mode = 1;
+	dai_data->port_config.pseudo.reserved = 16;
+	return 0;
+}
+
 /* Current implementation assumes hw_param is called once
  * This may not be the case but what to do when ADM and AFE
  * port are already opened and parameter changes
@@ -703,6 +721,9 @@
 	case RT_PROXY_DAI_002_RX:
 		rc = msm_dai_q6_afe_rtproxy_hw_params(params, dai);
 		break;
+	case PSEUDOPORT_01:
+		rc = msm_dai_q6_pseudo_hw_params(params, dai);
+		break;
 	case VOICE_PLAYBACK_TX:
 	case VOICE_RECORD_RX:
 	case VOICE_RECORD_TX:
@@ -1819,6 +1840,20 @@
 	.probe = msm_dai_q6_dai_probe,
 	.remove = msm_dai_q6_dai_remove,
 };
+static struct snd_soc_dai_driver msm_dai_q6_pseudo_dai = {
+	.playback = {
+		.rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 |
+		SNDRV_PCM_RATE_48000,
+		.formats = SNDRV_PCM_FMTBIT_S16_LE,
+		.channels_min = 1,
+		.channels_max = 6,
+		.rate_min = 8000,
+		.rate_max = 48000,
+	},
+	.ops = &msm_dai_q6_ops,
+	.probe = msm_dai_q6_dai_probe,
+	.remove = msm_dai_q6_dai_remove,
+};
 
 /* To do: change to register DAIs as batch */
 static __devinit int msm_dai_q6_dev_probe(struct platform_device *pdev)
@@ -1915,6 +1950,10 @@
 		rc = snd_soc_register_dai(&pdev->dev,
 						&msm_dai_q6_incall_record_dai);
 		break;
+	case PSEUDOPORT_01:
+		rc = snd_soc_register_dai(&pdev->dev,
+					&msm_dai_q6_pseudo_dai);
+		break;
 	default:
 		rc = -ENODEV;
 		break;
diff --git a/sound/soc/msm/msm-pcm-q6.h b/sound/soc/msm/msm-pcm-q6.h
index 2678498..86e5c54 100644
--- a/sound/soc/msm/msm-pcm-q6.h
+++ b/sound/soc/msm/msm-pcm-q6.h
@@ -59,6 +59,7 @@
 	uint16_t source; /* Encoding source bit mask */
 
 	struct audio_client *audio_client;
+	struct audio_client *enc_audio_client;
 
 	uint16_t session_id;
 
diff --git a/sound/soc/msm/msm-pcm-routing.c b/sound/soc/msm/msm-pcm-routing.c
index 800bea8..378baf1 100644
--- a/sound/soc/msm/msm-pcm-routing.c
+++ b/sound/soc/msm/msm-pcm-routing.c
@@ -194,6 +194,7 @@
 	{ SLIMBUS_EXTPROC_RX, 0, 0, 0, 0, 0},
 	{ SECONDARY_PCM_RX, 0, 0, 0, 0, 0},
 	{ SECONDARY_PCM_TX, 0, 0, 0, 0, 0},
+	{ PSEUDOPORT_01, 0, 0, 0, 0, 0},
 };
 
 
@@ -215,7 +216,8 @@
 	{INVALID_SESSION, INVALID_SESSION},
 	/* MULTIMEDIA8 */
 	{INVALID_SESSION, INVALID_SESSION},
-
+	/* PSEUDO */
+	{INVALID_SESSION, INVALID_SESSION},
 };
 
 static uint8_t is_be_dai_extproc(int be_dai)
@@ -298,6 +300,59 @@
 	mutex_unlock(&routing_lock);
 }
 
+void msm_pcm_routing_reg_pseudo_stream(int fedai_id, bool perf_mode,
+					int dspst_id, int stream_type,
+					int sample_rate, int channels)
+{
+	int i, session_type, path_type, port_type, mode, ret;
+	struct route_payload payload;
+	pr_debug("%s:fedai_id = %d dspst_id = %d stream_type %d",
+				__func__, fedai_id, dspst_id, stream_type);
+
+	if (stream_type == SNDRV_PCM_STREAM_PLAYBACK) {
+		session_type = SESSION_TYPE_RX;
+		path_type = ADM_PATH_PLAYBACK;
+		port_type = MSM_AFE_PORT_TYPE_RX;
+	} else {
+		session_type = SESSION_TYPE_TX;
+		path_type = ADM_PATH_LIVE_REC;
+		port_type = MSM_AFE_PORT_TYPE_TX;
+	}
+
+	mutex_lock(&routing_lock);
+
+	payload.num_copps = 0;
+	adm_multi_ch_copp_pseudo_open_v3(PSEUDOPORT_01,
+					path_type, sample_rate, channels,
+					DEFAULT_COPP_TOPOLOGY);
+
+	payload.copp_ids[payload.num_copps++] = PSEUDOPORT_01;
+
+	for (i = 0; i < MSM_BACKEND_DAI_MAX; i++) {
+		if (test_bit(fedai_id, &msm_bedais[i].fe_sessions))
+			msm_bedais[i].perf_mode = perf_mode;
+		if (!is_be_dai_extproc(i) &&
+		   (msm_bedais[i].active) &&
+		   (test_bit(fedai_id, &msm_bedais[i].fe_sessions))) {
+
+			mode = afe_get_port_type(msm_bedais[i].port_id);
+			ret = adm_connect_afe_port_v2(mode, dspst_id,
+						msm_bedais[i].port_id,
+						msm_bedais[i].sample_rate,
+						msm_bedais[i].channel);
+
+			if (ret < 0)
+				pr_err("%s: adm_connect_afe_port_v2 failed\n",
+					__func__);
+		}
+	}
+	if (payload.num_copps)
+		adm_matrix_map(dspst_id, path_type,
+			payload.num_copps, payload.copp_ids, 0);
+
+	mutex_unlock(&routing_lock);
+}
+
 void msm_pcm_routing_reg_phy_stream(int fedai_id, bool perf_mode, int dspst_id,
 							int stream_type)
 {
@@ -375,6 +430,32 @@
 	mutex_unlock(&routing_lock);
 }
 
+void msm_pcm_routing_dereg_pseudo_stream(int fedai_id, int dspst_id)
+{
+	int i, mode, ret;
+	pr_debug("%s:fedai_id = %d dspst_id = %d",
+			__func__, fedai_id, dspst_id);
+
+	mutex_lock(&routing_lock);
+
+	adm_pseudo_close(PSEUDOPORT_01);
+	for (i = 0; i < MSM_BACKEND_DAI_MAX; i++) {
+		if (!is_be_dai_extproc(i) &&
+			(msm_bedais[i].active) &&
+			(test_bit(fedai_id, &msm_bedais[i].fe_sessions))) {
+
+			mode = afe_get_port_type(msm_bedais[i].port_id);
+			ret = adm_disconnect_afe_port(mode, dspst_id,
+					msm_bedais[i].port_id);
+			if (ret < 0)
+				pr_err("%s: adm_connect_afe_port_v2 failed\n",
+					__func__);
+		}
+	}
+
+	mutex_unlock(&routing_lock);
+
+}
 void msm_pcm_routing_dereg_phy_stream(int fedai_id, int stream_type)
 {
 	int i, port_type, session_type;
@@ -1210,6 +1291,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("Pseudo", MSM_BACKEND_DAI_SEC_I2S_RX,
+	MSM_FRONTEND_DAI_PSEUDO, 1, 0, msm_routing_get_audio_mixer,
+	msm_routing_put_audio_mixer),
 };
 
 static const struct snd_kcontrol_new slimbus_rx_mixer_controls[] = {
@@ -1291,6 +1375,17 @@
 	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("Pseudo", MSM_BACKEND_DAI_HDMI_RX,
+	MSM_FRONTEND_DAI_PSEUDO, 1, 0, msm_routing_get_audio_mixer,
+	msm_routing_put_audio_mixer),
+};
+static const struct snd_kcontrol_new pseudo_mixer_controls[] = {
+	SOC_SINGLE_EXT("MultiMedia4", MSM_BACKEND_DAI_PSEUDO_PORT,
+	MSM_FRONTEND_DAI_MULTIMEDIA4, 1, 0, msm_routing_get_audio_mixer,
+	msm_routing_put_audio_mixer),
+	SOC_SINGLE_EXT("MultiMedia2", MSM_BACKEND_DAI_PSEUDO_PORT,
+	MSM_FRONTEND_DAI_MULTIMEDIA2, 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[] = {
@@ -2163,6 +2258,7 @@
 	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", "Pseudo 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),
@@ -2201,6 +2297,7 @@
 				0, 0, 0 , 0),
 	SND_SOC_DAPM_AIF_OUT("SLIMBUS_0_RX", "Slimbus Playback", 0, 0, 0, 0),
 	SND_SOC_DAPM_AIF_OUT("HDMI", "HDMI Playback", 0, 0, 0 , 0),
+	SND_SOC_DAPM_AIF_OUT("PSEUDO", "PSEUDO Playback", 0, 0, 0 , 0),
 	SND_SOC_DAPM_AIF_OUT("MI2S_RX", "MI2S Playback", 0, 0, 0, 0),
 	SND_SOC_DAPM_AIF_IN("PRI_I2S_TX", "Primary I2S Capture", 0, 0, 0, 0),
 	SND_SOC_DAPM_AIF_IN("SEC_I2S_TX", "Secondary I2S Capture", 0, 0, 0, 0),
@@ -2260,6 +2357,8 @@
 	slimbus_rx_mixer_controls, ARRAY_SIZE(slimbus_rx_mixer_controls)),
 	SND_SOC_DAPM_MIXER("HDMI Mixer", SND_SOC_NOPM, 0, 0,
 	hdmi_mixer_controls, ARRAY_SIZE(hdmi_mixer_controls)),
+	SND_SOC_DAPM_MIXER("PSEUDO Mixer", SND_SOC_NOPM, 0, 0,
+	pseudo_mixer_controls, ARRAY_SIZE(pseudo_mixer_controls)),
 	SND_SOC_DAPM_MIXER("MI2S_RX Audio Mixer", SND_SOC_NOPM, 0, 0,
 	mi2s_rx_mixer_controls, ARRAY_SIZE(mi2s_rx_mixer_controls)),
 	SND_SOC_DAPM_MIXER("MultiMedia1 Mixer", SND_SOC_NOPM, 0, 0,
@@ -2398,6 +2497,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", "Pseudo", "MM_DL9"},
 	{"SEC_I2S_RX", NULL, "SEC_RX Audio Mixer"},
 
 	{"SLIMBUS_0_RX Audio Mixer", "MultiMedia1", "MM_DL1"},
@@ -2418,8 +2518,12 @@
 	{"HDMI Mixer", "MultiMedia6", "MM_DL6"},
 	{"HDMI Mixer", "MultiMedia7", "MM_DL7"},
 	{"HDMI Mixer", "MultiMedia8", "MM_DL8"},
+	{"HDMI Mixer", "Pseudo", "MM_DL9"},
 	{"HDMI", NULL, "HDMI Mixer"},
 
+	{"PSEUDO Mixer", "MultiMedia4", "MM_DL4"},
+	{"PSEUDO", NULL, "PSEUDO Mixer"},
+
 		/* incall */
 	{"Incall_Music Audio Mixer", "MultiMedia1", "MM_DL1"},
 	{"Incall_Music Audio Mixer", "MultiMedia2", "MM_DL2"},
@@ -2665,6 +2769,7 @@
 	{"BE_OUT", NULL, "SLIMBUS_3_RX"},
 	{"BE_OUT", NULL, "SLIMBUS_4_RX"},
 	{"BE_OUT", NULL, "HDMI"},
+	{"BE_OUT", NULL, "PSEUDO"},
 	{"BE_OUT", NULL, "MI2S_RX"},
 	{"PRI_I2S_TX", NULL, "BE_IN"},
 	{"SEC_I2S_TX", NULL, "BE_IN"},
@@ -2784,7 +2889,14 @@
 	for_each_set_bit(i, &bedai->fe_sessions, MSM_FRONTEND_DAI_MM_SIZE) {
 		if (fe_dai_map[i][session_type] != INVALID_SESSION) {
 			channels = bedai->channel;
-			if ((playback || capture)
+			if (bedai->port_id == PSEUDOPORT_01) {
+				adm_multi_ch_copp_pseudo_open_v3(bedai->port_id,
+							path_type,
+							bedai->sample_rate,
+							channels > 6 ? 6 :
+							channels,
+							DEFAULT_COPP_TOPOLOGY);
+			} else if ((playback || capture)
 				&& ((channels == 2) || (channels == 1)) &&
 				bedai->perf_mode) {
 				adm_multi_ch_copp_open(bedai->port_id,
diff --git a/sound/soc/msm/msm-pcm-routing.h b/sound/soc/msm/msm-pcm-routing.h
index e11133e..32ab063 100644
--- a/sound/soc/msm/msm-pcm-routing.h
+++ b/sound/soc/msm/msm-pcm-routing.h
@@ -18,6 +18,7 @@
 #define LPASS_BE_SLIMBUS_0_RX "SLIMBUS_0_RX"
 #define LPASS_BE_SLIMBUS_0_TX "SLIMBUS_0_TX"
 #define LPASS_BE_HDMI "HDMI"
+#define LPASS_BE_PSEUDO "PSEUDO"
 #define LPASS_BE_INT_BT_SCO_RX "INT_BT_SCO_RX"
 #define LPASS_BE_INT_BT_SCO_TX "INT_BT_SCO_TX"
 #define LPASS_BE_INT_FM_RX "INT_FM_RX"
@@ -61,6 +62,7 @@
 	MSM_FRONTEND_DAI_MULTIMEDIA6,
 	MSM_FRONTEND_DAI_MULTIMEDIA7,
 	MSM_FRONTEND_DAI_MULTIMEDIA8,
+	MSM_FRONTEND_DAI_PSEUDO,
 	MSM_FRONTEND_DAI_CS_VOICE,
 	MSM_FRONTEND_DAI_VOIP,
 	MSM_FRONTEND_DAI_AFE_RX,
@@ -71,8 +73,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_PSEUDO + 1)
+#define MSM_FRONTEND_DAI_MM_MAX_ID MSM_FRONTEND_DAI_PSEUDO
 
 enum {
 	MSM_BACKEND_DAI_PRI_I2S_RX = 0,
@@ -106,6 +108,7 @@
 	MSM_BACKEND_DAI_EXTPROC_EC_TX,
 	MSM_BACKEND_DAI_SEC_AUXPCM_RX,
 	MSM_BACKEND_DAI_SEC_AUXPCM_TX,
+	MSM_BACKEND_DAI_PSEUDO_PORT,
 	MSM_BACKEND_DAI_MAX,
 };
 
@@ -118,6 +121,12 @@
 void msm_pcm_routing_reg_psthr_stream(int fedai_id, int dspst_id,
 		int stream_type, int enable);
 
+void msm_pcm_routing_reg_pseudo_stream(int fedai_id, bool perf_mode,
+				int dspst_id, int stream_type, int sample_rate,
+				int channels);
+
+void msm_pcm_routing_dereg_pseudo_stream(int fedai_id, int dspst_id);
+
 void msm_pcm_routing_dereg_phy_stream(int fedai_id, int stream_type);
 
 int lpa_set_volume(unsigned volume);
diff --git a/sound/soc/msm/msm8930.c b/sound/soc/msm/msm8930.c
index b3db9e1..08cd06c 100644
--- a/sound/soc/msm/msm8930.c
+++ b/sound/soc/msm/msm8930.c
@@ -788,6 +788,18 @@
 	return 0;
 }
 
+static int msm8930_proxy_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
+			struct snd_pcm_hw_params *params)
+{
+	struct snd_interval *rate = hw_param_interval(params,
+	SNDRV_PCM_HW_PARAM_RATE);
+
+	pr_debug("%s()\n", __func__);
+	rate->min = rate->max = 48000;
+
+	return 0;
+}
+
 static int msm8930_aux_pcm_get_gpios(void)
 {
 	int ret = 0;
@@ -1195,6 +1207,7 @@
 		.codec_dai_name = "msm-stub-rx",
 		.no_pcm = 1,
 		.be_id = MSM_BACKEND_DAI_AFE_PCM_RX,
+		.be_hw_params_fixup = msm8930_proxy_be_hw_params_fixup,
 		.ignore_pmdown_time = 1, /* this dainlink has playback support */
 	},
 	{
@@ -1206,6 +1219,7 @@
 		.codec_dai_name = "msm-stub-tx",
 		.no_pcm = 1,
 		.be_id = MSM_BACKEND_DAI_AFE_PCM_TX,
+		.be_hw_params_fixup = msm8930_proxy_be_hw_params_fixup,
 	},
 	/* AUX PCM Backend DAI Links */
 	{
diff --git a/sound/soc/msm/qdsp6/q6adm.c b/sound/soc/msm/qdsp6/q6adm.c
index c6970f1..00394aa 100644
--- a/sound/soc/msm/qdsp6/q6adm.c
+++ b/sound/soc/msm/qdsp6/q6adm.c
@@ -45,7 +45,7 @@
 static struct acdb_cal_block mem_addr_audvol[MAX_AUDPROC_TYPES];
 
 static struct adm_ctl			this_adm;
-
+static int pseudo_copp[2];
 
 int srs_trumedia_open(int port_id, int srs_tech_id, void *srs_params)
 {
@@ -293,6 +293,8 @@
 			case ADM_CMD_MATRIX_MAP_ROUTINGS:
 			case ADM_CMD_CONNECT_AFE_PORT:
 			case ADM_CMD_DISCONNECT_AFE_PORT:
+			case ADM_CMD_CONNECT_AFE_PORT_V2:
+			case ADM_CMD_MULTI_CHANNEL_COPP_OPEN_V3:
 				atomic_set(&this_adm.copp_stat[index], 1);
 				wake_up(&this_adm.wait);
 				break;
@@ -305,9 +307,10 @@
 		}
 
 		switch (data->opcode) {
+
+		case ADM_CMDRSP_MULTI_CHANNEL_COPP_OPEN_V3:
 		case ADM_CMDRSP_COPP_OPEN:
-		case ADM_CMDRSP_MULTI_CHANNEL_COPP_OPEN:
-		case ADM_CMDRSP_MULTI_CHANNEL_COPP_OPEN_V3: {
+		case ADM_CMDRSP_MULTI_CHANNEL_COPP_OPEN: {
 			struct adm_copp_open_respond *open = data->payload;
 			if (open->copp_id == INVALID_COPP_ID) {
 				pr_err("%s: invalid coppid rxed %d\n",
@@ -316,6 +319,10 @@
 				wake_up(&this_adm.wait);
 				break;
 			}
+			if (index == IDX_PSEUDOPORT_01)
+				pseudo_copp[
+				atomic_read(&this_adm.copp_cnt[index])] =
+					open->copp_id;
 			atomic_set(&this_adm.copp_id[index], open->copp_id);
 			atomic_set(&this_adm.copp_stat[index], 1);
 			pr_debug("%s: coppid rxed=%d\n", __func__,
@@ -337,6 +344,79 @@
 	return 0;
 }
 
+int adm_connect_afe_port_v2(int mode, int session_id, int port_id,
+				int sample_rate, int channels)
+{
+	struct adm_cmd_connect_afe_port_v2 cmd;
+	int ret = 0;
+	int index;
+
+	pr_debug("%s: port %d session id:%d\n", __func__,
+				port_id, session_id);
+
+	port_id = afe_convert_virtual_to_portid(port_id);
+
+	if (afe_validate_port(port_id) < 0) {
+		pr_err("%s port idi[%d] is invalid\n", __func__, port_id);
+		return -ENODEV;
+	}
+	if (this_adm.apr == NULL) {
+		this_adm.apr = apr_register("ADSP", "ADM", adm_callback,
+						0xFFFFFFFF, &this_adm);
+		if (this_adm.apr == NULL) {
+			pr_err("%s: Unable to register ADM\n", __func__);
+			ret = -ENODEV;
+			return ret;
+		}
+		rtac_set_adm_handle(this_adm.apr);
+	}
+	index = afe_get_port_index(port_id);
+	pr_debug("%s: Port ID %d, index %d\n", __func__, port_id, index);
+
+	cmd.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
+			APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
+	cmd.hdr.pkt_size = sizeof(cmd);
+	cmd.hdr.src_svc = APR_SVC_ADM;
+	cmd.hdr.src_domain = APR_DOMAIN_APPS;
+	cmd.hdr.src_port = port_id;
+	cmd.hdr.dest_svc = APR_SVC_ADM;
+	cmd.hdr.dest_domain = APR_DOMAIN_ADSP;
+	cmd.hdr.dest_port = port_id;
+	cmd.hdr.token = port_id;
+	cmd.hdr.opcode = ADM_CMD_CONNECT_AFE_PORT_V2;
+
+	cmd.mode = mode;
+	cmd.session_id = session_id;
+	cmd.afe_port_id = port_id;
+	cmd.num_channels = channels;
+	cmd.sampling_rate = sample_rate;
+
+	atomic_set(&this_adm.copp_stat[index], 0);
+	ret = apr_send_pkt(this_adm.apr, (uint32_t *)&cmd);
+	if (ret < 0) {
+		pr_err("%s:ADM enable for port %d failed\n",
+					__func__, port_id);
+		ret = -EINVAL;
+		goto fail_cmd;
+	}
+	ret = wait_event_timeout(this_adm.wait,
+		atomic_read(&this_adm.copp_stat[index]),
+		msecs_to_jiffies(TIMEOUT_MS));
+	if (!ret) {
+		pr_err("%s ADM connect AFE failed for port %d\n", __func__,
+							port_id);
+		ret = -EINVAL;
+		goto fail_cmd;
+	}
+	atomic_inc(&this_adm.copp_cnt[index]);
+	return 0;
+
+fail_cmd:
+
+	return ret;
+
+}
+
 static int send_adm_cal_block(int port_id, struct acdb_cal_block *aud_cal)
 {
 	s32				result = 0;
@@ -718,6 +798,138 @@
 	return ret;
 }
 
+int adm_multi_ch_copp_pseudo_open_v3(int port_id, int path,
+				int rate, int channel_mode,
+				int topology)
+{
+	struct adm_multi_channel_copp_open_v3	open;
+	int ret = 0;
+	int index;
+
+	pr_debug("%s: port %d path:%d rate:%d mode:%d\n", __func__,
+				port_id, path, rate, channel_mode);
+
+	port_id = afe_convert_virtual_to_portid(port_id);
+
+	if (afe_validate_port(port_id) < 0) {
+		pr_err("%s port idi[%d] is invalid\n", __func__, port_id);
+		return -ENODEV;
+	}
+
+	index = afe_get_port_index(port_id);
+	pr_debug("%s: Port ID %d, index %d\n", __func__, port_id, index);
+
+	if (this_adm.apr == NULL) {
+		this_adm.apr = apr_register("ADSP", "ADM", adm_callback,
+						0xFFFFFFFF, &this_adm);
+		if (this_adm.apr == NULL) {
+			pr_err("%s: Unable to register ADM\n", __func__);
+			ret = -ENODEV;
+			return ret;
+		}
+		rtac_set_adm_handle(this_adm.apr);
+	}
+
+
+	{
+		open.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
+				APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
+		open.hdr.pkt_size = sizeof(open);
+		open.hdr.src_svc = APR_SVC_ADM;
+		open.hdr.src_domain = APR_DOMAIN_APPS;
+		open.hdr.src_port = port_id;
+		open.hdr.dest_svc = APR_SVC_ADM;
+		open.hdr.dest_domain = APR_DOMAIN_ADSP;
+		open.hdr.dest_port = port_id;
+		open.hdr.token = port_id;
+		open.hdr.opcode = ADM_CMD_MULTI_CHANNEL_COPP_OPEN_V3;
+		memset(open.dev_channel_mapping, 0, 8);
+
+		if (channel_mode == 1)	{
+			open.dev_channel_mapping[0] = PCM_CHANNEL_FC;
+		} else if (channel_mode == 2) {
+			open.dev_channel_mapping[0] = PCM_CHANNEL_FL;
+			open.dev_channel_mapping[1] = PCM_CHANNEL_FR;
+		} else if (channel_mode == 4) {
+			open.dev_channel_mapping[0] = PCM_CHANNEL_FL;
+			open.dev_channel_mapping[1] = PCM_CHANNEL_FR;
+			open.dev_channel_mapping[2] = PCM_CHANNEL_RB;
+			open.dev_channel_mapping[3] = PCM_CHANNEL_LB;
+		} else if (channel_mode == 6) {
+			open.dev_channel_mapping[0] = PCM_CHANNEL_FL;
+			open.dev_channel_mapping[1] = PCM_CHANNEL_FR;
+			open.dev_channel_mapping[2] = PCM_CHANNEL_LFE;
+			open.dev_channel_mapping[3] = PCM_CHANNEL_FC;
+			open.dev_channel_mapping[4] = PCM_CHANNEL_LB;
+			open.dev_channel_mapping[5] = PCM_CHANNEL_RB;
+		} else if (channel_mode == 8) {
+			open.dev_channel_mapping[0] = PCM_CHANNEL_FL;
+			open.dev_channel_mapping[1] = PCM_CHANNEL_FR;
+			open.dev_channel_mapping[2] = PCM_CHANNEL_LFE;
+			open.dev_channel_mapping[3] = PCM_CHANNEL_FC;
+			open.dev_channel_mapping[4] = PCM_CHANNEL_LB;
+			open.dev_channel_mapping[5] = PCM_CHANNEL_RB;
+			open.dev_channel_mapping[6] = PCM_CHANNEL_FLC;
+			open.dev_channel_mapping[7] = PCM_CHANNEL_FRC;
+		} else {
+			pr_err("%s invalid num_chan %d\n", __func__,
+					channel_mode);
+			return -EINVAL;
+		}
+
+		open.mode = path;
+		open.endpoint_id1 = port_id;
+		open.endpoint_id2 = 0xFFFF;
+		open.bit_width = 16;
+
+		if (path == ADM_PATH_PLAYBACK)
+			open.topology_id = get_adm_rx_topology();
+		else {
+			open.topology_id = get_adm_tx_topology();
+			if ((open.topology_id ==
+				VPM_TX_SM_ECNS_COPP_TOPOLOGY) ||
+				(open.topology_id ==
+				VPM_TX_DM_FLUENCE_COPP_TOPOLOGY))
+				rate = 16000;
+		}
+
+		if (open.topology_id  == 0)
+			open.topology_id = topology;
+
+		open.channel_config = channel_mode & 0x00FF;
+		open.rate  = rate;
+		open.flags = 0;
+
+		pr_debug("%s: channel_config=%d port_id=%d rate=%d" \
+			"topology_id=0x%X\n", __func__, open.channel_config,\
+			open.endpoint_id1, open.rate,\
+			open.topology_id);
+
+		atomic_set(&this_adm.copp_stat[index], 0);
+		ret = apr_send_pkt(this_adm.apr, (uint32_t *)&open);
+		if (ret < 0) {
+			pr_err("%s:ADM enable for port %d failed\n",
+						__func__, port_id);
+			ret = -EINVAL;
+			goto fail_cmd;
+		}
+		ret = wait_event_timeout(this_adm.wait,
+			atomic_read(&this_adm.copp_stat[index]),
+			msecs_to_jiffies(TIMEOUT_MS));
+		if (!ret) {
+			pr_err("%s ADM open failed for port %d\n", __func__,
+								port_id);
+			ret = -EINVAL;
+			goto fail_cmd;
+		}
+	}
+	atomic_inc(&this_adm.copp_cnt[index]);
+	return 0;
+
+fail_cmd:
+	return ret;
+
+}
 
 int adm_multi_ch_copp_open(int port_id, int path, int rate, int channel_mode,
 				int topology, int perfmode)
@@ -1127,6 +1339,56 @@
 	pr_debug("%s ec_ref_rx:%d", __func__, this_adm.ec_ref_rx);
 }
 
+int adm_pseudo_close(int port_id)
+{
+	struct apr_hdr close;
+
+	int ret = 0, i = 0;
+	int index = 0;
+	int pseudo_copp_cnt;
+	index = afe_get_port_index(port_id);
+	if (afe_validate_port(port_id) < 0)
+		return -EINVAL;
+
+	pseudo_copp_cnt = atomic_read(&this_adm.copp_cnt[index]);
+	pr_debug("%s port_id=%d index %d copp_cnt %d\n", __func__, port_id,
+				index, pseudo_copp_cnt);
+
+	for (i = 0; i < pseudo_copp_cnt; i++) {
+		close.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
+				APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
+		close.pkt_size = sizeof(close);
+		close.src_svc = APR_SVC_ADM;
+		close.src_domain = APR_DOMAIN_APPS;
+		close.src_port = port_id;
+		close.dest_svc = APR_SVC_ADM;
+		close.dest_domain = APR_DOMAIN_ADSP;
+		close.dest_port = pseudo_copp[i];
+		close.token = port_id;
+		close.opcode = ADM_CMD_COPP_CLOSE;
+
+		atomic_set(&this_adm.copp_id[index], RESET_COPP_ID);
+		atomic_set(&this_adm.copp_stat[index], 0);
+
+
+		pr_debug("%s:coppid %d portid=%d index=%d coppcnt=%d\n",
+				__func__,
+		atomic_read(&this_adm.copp_id[index]),
+			port_id, index,
+			atomic_read(&this_adm.copp_cnt[index]));
+
+		ret = apr_send_pkt(this_adm.apr, (uint32_t *)&close);
+
+		ret = wait_event_timeout(this_adm.wait,
+				atomic_read(&this_adm.copp_stat[index]),
+		msecs_to_jiffies(TIMEOUT_MS));
+	}
+
+	atomic_set(&this_adm.copp_cnt[index], 0);
+	return ret;
+
+}
+
 int adm_close(int port_id)
 {
 	struct apr_hdr close;
diff --git a/sound/soc/msm/qdsp6/q6afe.c b/sound/soc/msm/qdsp6/q6afe.c
index a4f4b60..9c62a2e 100644
--- a/sound/soc/msm/qdsp6/q6afe.c
+++ b/sound/soc/msm/qdsp6/q6afe.c
@@ -156,6 +156,7 @@
 	case VOICE_PLAYBACK_TX:
 	case RT_PROXY_PORT_001_RX:
 	case SLIMBUS_4_RX:
+	case PSEUDOPORT_01:
 		ret = MSM_AFE_PORT_TYPE_RX;
 		break;
 
@@ -225,6 +226,7 @@
 	case RT_PROXY_PORT_001_TX:
 	case SLIMBUS_4_RX:
 	case SLIMBUS_4_TX:
+	case PSEUDOPORT_01:
 	{
 		ret = 0;
 		break;
@@ -295,6 +297,7 @@
 	case RT_PROXY_PORT_001_TX: return IDX_RT_PROXY_PORT_001_TX;
 	case SLIMBUS_4_RX: return IDX_SLIMBUS_4_RX;
 	case SLIMBUS_4_TX: return IDX_SLIMBUS_4_TX;
+	case PSEUDOPORT_01: return IDX_PSEUDOPORT_01;
 
 	default: return -EINVAL;
 	}
@@ -331,6 +334,9 @@
 	case RT_PROXY_PORT_001_TX:
 		ret_size = SIZEOF_CFG_CMD(afe_port_rtproxy_cfg);
 		break;
+	case PSEUDOPORT_01:
+		ret_size = SIZEOF_CFG_CMD(afe_port_pseudo_cfg);
+		break;
 	case PCM_RX:
 	case PCM_TX:
 	case SECONDARY_PCM_RX:
@@ -506,6 +512,11 @@
 			else
 				config.hdr.opcode = AFE_PORT_CMD_I2S_CONFIG;
 		break;
+		case PSEUDOPORT_01:
+			config.hdr.opcode = AFE_PORT_AUDIO_IF_CONFIG;
+			pr_debug("%s, config, opcode=%x\n", __func__,
+					config.hdr.opcode);
+		break;
 		default:
 			config.hdr.opcode = AFE_PORT_AUDIO_IF_CONFIG;
 		break;
diff --git a/sound/soc/msm/qdsp6/q6asm.c b/sound/soc/msm/qdsp6/q6asm.c
index b7d5d33..26957b6 100644
--- a/sound/soc/msm/qdsp6/q6asm.c
+++ b/sound/soc/msm/qdsp6/q6asm.c
@@ -894,6 +894,7 @@
 		case ASM_STREAM_CMD_SET_ENCDEC_PARAM:
 		case ASM_STREAM_CMD_OPEN_WRITE_COMPRESSED:
 		case ASM_STREAM_CMD_OPEN_READ_COMPRESSED:
+		case ASM_STREAM_CMD_OPEN_TRANSCODE_LOOPBACK:
 			if (atomic_read(&ac->cmd_state) && wakeup_flag) {
 				atomic_set(&ac->cmd_state, 0);
 				pr_debug("response payload[1]:%d",
@@ -1066,6 +1067,114 @@
 	return 0;
 }
 
+int q6asm_open_transcode_loopback(struct audio_client *ac, uint32_t channels)
+{
+	int rc = 0x00;
+	struct asm_stream_cmd_open_transcode_loopback open;
+
+	if ((ac == NULL) || (ac->apr == NULL)) {
+		pr_err("%s: APR handle NULL\n", __func__);
+		return -EINVAL;
+	}
+	pr_debug("%s: session[%d] channels = %d", __func__, ac->session,
+		channels);
+
+	q6asm_add_hdr(ac, &open.hdr, sizeof(open), TRUE);
+
+	open.hdr.opcode = ASM_STREAM_CMD_OPEN_TRANSCODE_LOOPBACK;
+
+	open.mode_flags = 0;
+
+	if (channels > 2)
+		open.src_format_id = MULTI_CHANNEL_PCM;
+	else
+		open.src_format_id = LINEAR_PCM;
+
+
+	open.sink_format_id = DTS;
+	open.audproc_topo_id = DEFAULT_POPP_TOPOLOGY;
+	open.src_endpoint_type = 0;
+	open.sink_endpoint_type = 0;
+	open.bits_per_sample = 16;
+	open.reserved = 0;
+
+	rc = apr_send_pkt(ac->apr, (uint32_t *) &open);
+	if (rc < 0) {
+		pr_err("%s: open failed op[0x%x]rc[%d]\n", \
+					__func__, open.hdr.opcode, rc);
+		goto fail_cmd;
+	}
+	rc = wait_event_timeout(ac->cmd_wait,
+			(atomic_read(&ac->cmd_state) == 0), 5*HZ);
+	if (!rc) {
+		pr_err("%s: timeout. waited for OPEN_WRITE rc[%d]\n", __func__,
+			rc);
+		goto fail_cmd;
+	}
+	return 0;
+fail_cmd:
+	return -EINVAL;
+}
+
+int q6asm_enc_cfg_blk_dts(struct audio_client *ac,
+			uint32_t sample_rate,
+			uint32_t channels)
+{
+	struct asm_stream_cmd_encdec_cfg_blk enc_cfg;
+	int rc = 0;
+
+	pr_debug("%s: sample_rate=%d,channels=%d\n", __func__,
+				sample_rate, channels);
+
+	q6asm_add_hdr(ac, &enc_cfg.hdr, sizeof(enc_cfg), TRUE);
+
+	enc_cfg.hdr.opcode = ASM_STREAM_CMD_SET_ENCDEC_PARAM;
+	enc_cfg.param_id = ASM_ENCDEC_CFG_BLK_ID;
+	enc_cfg.param_size = sizeof(struct asm_encode_cfg_blk);
+	enc_cfg.enc_blk.frames_per_buf = 0;
+	enc_cfg.enc_blk.format_id = DTS;
+	enc_cfg.enc_blk.cfg_size  = sizeof(struct asm_dts_enc_cfg);
+	enc_cfg.enc_blk.cfg.dts.sample_rate = sample_rate;
+	enc_cfg.enc_blk.cfg.dts.num_channels = channels;
+	if (channels == 2) {
+		enc_cfg.enc_blk.cfg.dts.channel_mapping[0] = PCM_CHANNEL_FL;
+		enc_cfg.enc_blk.cfg.dts.channel_mapping[1] = PCM_CHANNEL_FR;
+		enc_cfg.enc_blk.cfg.dts.channel_mapping[2] = 0;
+		enc_cfg.enc_blk.cfg.dts.channel_mapping[3] = 0;
+		enc_cfg.enc_blk.cfg.dts.channel_mapping[4] = 0;
+		enc_cfg.enc_blk.cfg.dts.channel_mapping[5] = 0;
+	} else if (channels == 4) {
+		enc_cfg.enc_blk.cfg.dts.channel_mapping[0] = PCM_CHANNEL_FL;
+		enc_cfg.enc_blk.cfg.dts.channel_mapping[1] = PCM_CHANNEL_FR;
+		enc_cfg.enc_blk.cfg.dts.channel_mapping[2] = PCM_CHANNEL_LS;
+		enc_cfg.enc_blk.cfg.dts.channel_mapping[3] = PCM_CHANNEL_RS;
+		enc_cfg.enc_blk.cfg.dts.channel_mapping[4] = 0;
+		enc_cfg.enc_blk.cfg.dts.channel_mapping[5] = 0;
+	} else if (channels == 6) {
+		enc_cfg.enc_blk.cfg.dts.channel_mapping[0] = PCM_CHANNEL_FL;
+		enc_cfg.enc_blk.cfg.dts.channel_mapping[1] = PCM_CHANNEL_FR;
+		enc_cfg.enc_blk.cfg.dts.channel_mapping[2] = PCM_CHANNEL_LFE;
+		enc_cfg.enc_blk.cfg.dts.channel_mapping[3] = PCM_CHANNEL_LS;
+		enc_cfg.enc_blk.cfg.dts.channel_mapping[4] = PCM_CHANNEL_RS;
+		enc_cfg.enc_blk.cfg.dts.channel_mapping[5] = PCM_CHANNEL_FC;
+	}
+	rc = apr_send_pkt(ac->apr, (uint32_t *) &enc_cfg);
+	if (rc < 0) {
+		pr_err("Comamnd %d failed\n", ASM_STREAM_CMD_SET_ENCDEC_PARAM);
+		rc = -EINVAL;
+		goto fail_cmd;
+	}
+	rc = wait_event_timeout(ac->cmd_wait,
+			(atomic_read(&ac->cmd_state) == 0), 5*HZ);
+	if (!rc) {
+		pr_err("timeout. waited for FORMAT_UPDATE\n");
+		goto fail_cmd;
+	}
+	return 0;
+fail_cmd:
+	return -EINVAL;
+}
+
 void *q6asm_is_cpu_buf_avail(int dir, struct audio_client *ac, uint32_t *size,
 				uint32_t *index)
 {
diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.c b/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.c
index af1e19c..1e6fc04 100644
--- a/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.c
+++ b/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.c
@@ -297,6 +297,7 @@
 static int msm_pcm_open(struct snd_pcm_substream *substream)
 {
 	struct snd_pcm_runtime *runtime = substream->runtime;
+	struct snd_soc_pcm_runtime *soc_prtd = substream->private_data;
 	struct msm_audio *prtd;
 	int ret = 0;
 
@@ -314,8 +315,25 @@
 		kfree(prtd);
 		return -ENOMEM;
 	}
-	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
 		runtime->hw = msm_pcm_hardware_playback;
+		ret = q6asm_open_write(prtd->audio_client, FORMAT_LINEAR_PCM);
+		if (ret < 0) {
+			pr_err("%s: pcm out open failed\n", __func__);
+			q6asm_audio_client_free(prtd->audio_client);
+			kfree(prtd);
+			return -ENOMEM;
+		}
+
+		pr_debug("%s: session ID %d\n", __func__,
+			prtd->audio_client->session);
+		prtd->session_id = prtd->audio_client->session;
+		msm_pcm_routing_reg_phy_stream(soc_prtd->dai_link->be_id,
+			prtd->session_id, substream->stream);
+		prtd->cmd_ack = 1;
+
+	}
+	/* Capture path */
 	else if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
 		runtime->hw = msm_pcm_hardware_capture;
 	else {
@@ -601,25 +619,15 @@
 	struct audio_buffer *buf;
 	int dir, ret;
 
-	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
 		dir = IN;
-		pr_debug("%s Opening %d-ch PCM Write stream\n",
-			__func__, params_channels(params));
-
-		ret = q6asm_open_write(prtd->audio_client, FORMAT_LINEAR_PCM);
-		if (ret < 0) {
-			pr_err("%s: pcm out open failed\n", __func__);
-			q6asm_audio_client_free(prtd->audio_client);
-			kfree(prtd);
-			return -ENOMEM;
-		}
-	} else {
+	else {
 		dir = OUT;
 		pr_debug("%s Opening %d-ch PCM read stream\n",
 			__func__, params_channels(params));
 		ret = q6asm_open_read(prtd->audio_client, FORMAT_LINEAR_PCM);
 		if (ret < 0) {
-			pr_err("%s: pcm in open failed\n", __func__);
+			pr_err("%s: q6asm_open_read failed\n", __func__);
 			q6asm_audio_client_free(prtd->audio_client);
 			prtd->audio_client = NULL;
 			return -ENOMEM;
@@ -631,10 +639,7 @@
 	msm_pcm_routing_reg_phy_stream(soc_prtd->dai_link->be_id,
 			prtd->session_id, substream->stream);
 
-	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
-		prtd->cmd_ack = 1;
 
-	pr_debug("%s: before buf alloc\n", __func__);
 	ret = q6asm_audio_client_buf_alloc_contiguous(dir,
 			prtd->audio_client,
 			runtime->hw.period_bytes_min,
@@ -644,7 +649,6 @@
 							ret);
 		return -ENOMEM;
 	}
-	pr_debug("%s: after buf alloc\n", __func__);
 	buf = prtd->audio_client->port[dir].buf;
 	if (buf == NULL || buf[0].data == NULL)
 		return -ENOMEM;