Merge "ASoC: wcd9xxx: Fix MBHC irq handler deadlock scenario"
diff --git a/Documentation/devicetree/bindings/arm/msm/jtag-mm.txt b/Documentation/devicetree/bindings/arm/msm/jtag-mm.txt
new file mode 100644
index 0000000..21dead3
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/msm/jtag-mm.txt
@@ -0,0 +1,21 @@
+* JTAG-MM
+
+The jtag-mm entry specifies the memory mapped addresses for the debug and ETM
+registers. The jtag-mm driver uses these to save and restore the registers
+using memory mapped access during power collapse so as to retain their state
+accross power collapse. This is necessary in case cp14 access to the registers
+is not permitted.
+
+Required Properties:
+compatible: component name used for driver matching, should be "qcom,jtag-mm"
+reg: physical base address and length of the register set
+reg-names: should be "etm-base" for etm register set and "debug-base" for debug
+	register set.
+
+Example:
+jtag_mm: jtagmm@fc332000 {
+	compatible = "qcom,jtag-mm";
+	reg = <0xfc332000 0x1000>,
+		<0xfc333000 0x1000>;
+	reg-names = "etm-base","debug-base";
+	};
diff --git a/Documentation/devicetree/bindings/arm/msm/msm_bus.txt b/Documentation/devicetree/bindings/arm/msm/msm_bus.txt
index fb72525..5f534a2 100644
--- a/Documentation/devicetree/bindings/arm/msm/msm_bus.txt
+++ b/Documentation/devicetree/bindings/arm/msm/msm_bus.txt
@@ -1,6 +1,11 @@
 MSM Bus Scaling Driver
 
-The msm bus scaling driver provides the ability to configure
+The bus scaling driver builds the topology of chipsets by adding
+bus devices (fabrics/NoCs) to the kernel tree. The device-tree
+data for bus devices contains the register addresses for QoS
+related registers on each NoC/Fabric.
+
+The bus scaling driver also provides the ability to configure
 bus performance parameters across the entire chip-set.
 Various clients use MSM scaling APIs to request bandwidth
 between multiple master-slave pairs. The bus driver then finds
diff --git a/Documentation/devicetree/bindings/iommu/msm_iommu.txt b/Documentation/devicetree/bindings/iommu/msm_iommu.txt
index f093f51..313f0a3 100644
--- a/Documentation/devicetree/bindings/iommu/msm_iommu.txt
+++ b/Documentation/devicetree/bindings/iommu/msm_iommu.txt
@@ -3,12 +3,17 @@
 Required properties:
 - compatible : one of:
 	- "qcom,msm-smmu-v2"
-- reg : offset and length of the register set for the device.
+- reg : offset and length of the register set for the device. Optional
+	offset and length for clock register for additional clock that
+	needs to be turned on for access to this IOMMU.
+- reg-names: "iommu_base", "clk_base" (optional)
 
 Optional properties:
 - qcom,iommu-secure-id : Secure identifier for the IOMMU block
 - qcom,secure-context : boolean indicating that a context is secure and
   programmed by the secure environment.
+- qcom,alt-vdd-supply : Alternative regulator needed to access IOMMU
+  configuration registers.
 
 - List of sub nodes, one for each of the translation context banks supported.
   Each sub node has the following required properties:
@@ -39,23 +44,24 @@
 
 Example:
 
-        qcom,iommu@fda64000 {
-                compatible = "qcom,msm-smmu-v2";
-                reg = <0xfda64000 0x10000>;
+	qcom,iommu@fda64000 {
+		compatible = "qcom,msm-smmu-v2";
+		reg = <0xfda64000 0x10000>;
+		reg-names = "iommu_base";
 		vdd-supply = <&gdsc_iommu>;
 		qcom,iommu-bfb-regs = <0x204c 0x2050>;
 		qcom,iommu-bfb-data = <0xffff 0xffce>;
 
-                qcom,iommu-ctx@fda6c000 {
-                        reg = <0xfda6c000 0x1000>;
-                        interrupts = <0 70 0>;
-                        qcom,iommu-ctx-sids = <0 2>;
+		qcom,iommu-ctx@fda6c000 {
+			reg = <0xfda6c000 0x1000>;
+			interrupts = <0 70 0>;
+			qcom,iommu-ctx-sids = <0 2>;
 			label = "ctx_0";
-                };
-                qcom,iommu-ctx@fda6d000 {
-                        reg = <0xfda6d000 0x1000>;
-                        interrupts = <0 71 0>;
-                        qcom,iommu-ctx-sids = <1>;
+		};
+		qcom,iommu-ctx@fda6d000 {
+			reg = <0xfda6d000 0x1000>;
+			interrupts = <0 71 0>;
+			qcom,iommu-ctx-sids = <1>;
 			label = "ctx_1";
-                };
-        };
+		};
+	};
diff --git a/Documentation/devicetree/bindings/media/video/msm-vidc.txt b/Documentation/devicetree/bindings/media/video/msm-vidc.txt
index 79a3ab5..2f2ea22 100644
--- a/Documentation/devicetree/bindings/media/video/msm-vidc.txt
+++ b/Documentation/devicetree/bindings/media/video/msm-vidc.txt
@@ -13,6 +13,9 @@
   or non-secure.
 - load-freq-tbl : load (in macroblocks/sec) and corresponding vcodec clock
   required for optimal performance in descending order.
+- hfi : supported Host-Firmware Interface, one of:
+	- "venus"
+	- "q6"
 
 Example:
 
@@ -29,4 +32,5 @@
 				<243000 133330000>,
 				<108000 100000000>,
 				<36000 50000000>;
+		hfi = "venus";
 	};
diff --git a/Documentation/devicetree/bindings/sound/qcom-audio-dev.txt b/Documentation/devicetree/bindings/sound/qcom-audio-dev.txt
index 104d6a2..032c814 100644
--- a/Documentation/devicetree/bindings/sound/qcom-audio-dev.txt
+++ b/Documentation/devicetree/bindings/sound/qcom-audio-dev.txt
@@ -459,6 +459,11 @@
 - qcom,taiko-mclk-clk-freq : Master clock value given to codec. Some WCD9XXX
   codec can run at different mclk values. Mclk value can be 9.6MHz or 12.288MHz.
   This element represents the value for MCLK provided to codec.
+- prim-i2s-gpio-ws : Specifies gpio assigned for primary WS I2S pin.
+- prim-i2s-gpio-din : Specifies gpio assigned for primary DIN I2S pin.
+- prim-i2s-gpio-dout : Specifies gpio assigned for primary DOUT I2S pin.
+- prim-i2s-gpio-sclk : Specifies gpio assigned for primary SCLK I2S pin.
+- prim-i2s-gpio-mclk : Specifies gpio assigned for MCLK I2S pin.
 
 Example:
 
@@ -494,6 +499,11 @@
 			"DMIC6", "MIC BIAS4 External",
 			"MIC BIAS4 External", "Digital Mic6";
 			qcom,taiko-mclk-clk-freq = <12288000>;
+			prim-i2s-gpio-ws   =  <&msmgpio 12 0>;
+			prim-i2s-gpio-din  =  <&msmgpio 13 0>;
+			prim-i2s-gpio-dout =  <&msmgpio 14 0>;
+			prim-i2s-gpio-sclk =  <&msmgpio 15 0>;
+			prim-i2s-gpio-mclk =  <&msmgpio 71 0>;
 };
 
 * msm-adsp-loader
diff --git a/Documentation/devicetree/bindings/usb/msm-hsusb.txt b/Documentation/devicetree/bindings/usb/msm-hsusb.txt
index 015822f..8b7b31b 100644
--- a/Documentation/devicetree/bindings/usb/msm-hsusb.txt
+++ b/Documentation/devicetree/bindings/usb/msm-hsusb.txt
@@ -147,6 +147,10 @@
 - qcom,descriptor-fifo-offset: descriptor fifo offset address
 - qcom,descriptor-fifo-size: descriptor fifo size
 
+Optional Properties for Subnode:
+- qcom,reset-bam-on-connect: If present then BAM is RESET before connecting
+  pipe. This may be required if BAM peripheral is also reset before connect.
+
 Optional properties :
 - qcom,ignore-core-reset-ack: If present then BAM ignores ACK from USB core
 	    while performing PIPE RESET
@@ -193,6 +197,7 @@
 			qcom,data-fifo-size = <0x4000>;
 			qcom,descriptor-fifo-offset = <0xf4000>;
 			qcom,descriptor-fifo-size = <0x1400>;
+			qcom,reset-bam-on-connect;
 		};
 
 		qcom,pipe3 {
diff --git a/Documentation/devicetree/bindings/usb/msm-ssusb.txt b/Documentation/devicetree/bindings/usb/msm-ssusb.txt
index 5d10940..7add91f 100644
--- a/Documentation/devicetree/bindings/usb/msm-ssusb.txt
+++ b/Documentation/devicetree/bindings/usb/msm-ssusb.txt
@@ -41,7 +41,12 @@
 - qcom,charging-disabled: If present then battery charging using USB
   is disabled.
 - qcom,dwc-hsphy-init: This property if present represents phy init
-  value to be used for overriding HSPHY parameters.
+  value to be used for overriding HSPHY parameters into QSCRATCH register.
+  This 32 bit value represents parameters as follows:
+		bits 0-5   PARAMETER_OVERRIDE_A
+		bits 6-12  PARAMETER_OVERRIDE_B
+		bits 13-19 PARAMETER_OVERRIDE_C
+		bits 20-25 PARAMETER_OVERRIDE_D
 
 Example MSM USB3.0 controller device node :
 	usb@f9200000 {
diff --git a/Documentation/mmc/mmc-dev-attrs.txt b/Documentation/mmc/mmc-dev-attrs.txt
index 43453d0..d96b431 100644
--- a/Documentation/mmc/mmc-dev-attrs.txt
+++ b/Documentation/mmc/mmc-dev-attrs.txt
@@ -25,14 +25,14 @@
 	running parallel lmdd write and lmdd read operations and calculating
 	the max number of packed writes requests.
 
-	min_sectors_to_check_bkops_status	This attribute is used to
-	determine whether the status bit that indicates the need for BKOPS
-	should be checked. The value is stored in this attribute represents
-	the minimum number of sectors that needs to be changed in the device
-	(written or discarded) in order to require the status-bit of BKOPS
-	to be checked. The value can modified via sysfs by writing the
-	required value to:
-	/sys/block/<block_dev_name>/min_sectors_to_check_bkops_status
+	bkops_check_threshold	This attribute is used to determine whether
+	the status bit that indicates the need for BKOPS should be checked.
+	The value should be given in percentages of the card size.
+	This value is used to calculate the minimum number of sectors that
+	needs to be changed in the device (written or discarded) in order to
+	require the status-bit of BKOPS to be checked.
+	The value can modified via sysfs by writing the required value to:
+	/sys/block/<block_dev_name>/bkops_check_threshold
 
 SD and MMC Device Attributes
 ============================
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 23181d9..5a9cecf 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -782,6 +782,7 @@
 	select HAVE_CLK_PREPARE
 	select NEED_MACH_MEMORY_H
 	select NEED_MACH_IO_H
+	select SOC_BUS
 	help
 	  Support for Qualcomm MSM/QSD based systems.  This runs on the
 	  apps processor of the MSM/QSD and depends on a shared memory
diff --git a/arch/arm/boot/dts/msm-iommu.dtsi b/arch/arm/boot/dts/msm-iommu.dtsi
index 8343c7a..3c65491 100755
--- a/arch/arm/boot/dts/msm-iommu.dtsi
+++ b/arch/arm/boot/dts/msm-iommu.dtsi
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -17,7 +17,9 @@
 		#size-cells = <1>;
 		ranges;
 		reg = <0xfda64000 0x10000>;
+		reg-names = "iommu_base";
 		vdd-supply = <&gdsc_jpeg>;
+		qcom,needs-alt-core-clk;
 		status = "disabled";
 
 		qcom,iommu-bfb-regs =  <0x204c
@@ -80,6 +82,7 @@
 		#size-cells = <1>;
 		ranges;
 		reg = <0xfd928000 0x10000>;
+		reg-names = "iommu_base";
 		vdd-supply = <&gdsc_mdss>;
 		qcom,iommu-secure-id = <1>;
 		status = "disabled";
@@ -143,7 +146,9 @@
 		#address-cells = <1>;
 		#size-cells = <1>;
 		ranges;
-		reg = <0xfdc84000 0x10000>;
+		reg = <0xfdc84000 0x10000
+		       0xfdce0004 0x4>;
+		reg-names = "iommu_base", "clk_base";
 		vdd-supply = <&gdsc_venus>;
 		qcom,iommu-secure-id = <0>;
 		qcom,needs-alt-core-clk;
@@ -229,7 +234,9 @@
 		#size-cells = <1>;
 		ranges;
 		reg = <0xfdb10000 0x10000>;
+		reg-names = "iommu_base";
 		vdd-supply = <&gdsc_oxili_cx>;
+		qcom,alt-vdd-supply = <&gdsc_oxili_gx>;
 		qcom,needs-alt-core-clk;
 		status = "disabled";
 
@@ -280,7 +287,9 @@
 		#size-cells = <1>;
 		ranges;
 		reg = <0xfda44000 0x10000>;
+		reg-names = "iommu_base";
 		vdd-supply = <&gdsc_vfe>;
+		qcom,needs-alt-core-clk;
 		status = "disabled";
 
 		qcom,iommu-bfb-regs =  <0x204c
diff --git a/arch/arm/boot/dts/msm8226-iommu.dtsi b/arch/arm/boot/dts/msm8226-iommu.dtsi
new file mode 100644
index 0000000..66a7848
--- /dev/null
+++ b/arch/arm/boot/dts/msm8226-iommu.dtsi
@@ -0,0 +1,37 @@
+/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+/include/ "msm-iommu.dtsi"
+
+&jpeg_iommu {
+	status = "ok";
+};
+
+&mdp_iommu {
+	status = "ok";
+	/* HACK: set to -1 during pre-si due to lack of TZ */
+	qcom,iommu-secure-id = <0xFFFFFFFF>;
+};
+
+&venus_iommu {
+	status = "ok";
+	/* HACK: set to -1 during pre-si due to lack of TZ */
+	qcom,iommu-secure-id = <0xFFFFFFFF>;
+};
+
+&kgsl_iommu {
+	status = "ok";
+};
+
+&vfe_iommu {
+	status = "ok";
+};
diff --git a/arch/arm/boot/dts/msm8226.dtsi b/arch/arm/boot/dts/msm8226.dtsi
index 36bcdd7..854a708 100644
--- a/arch/arm/boot/dts/msm8226.dtsi
+++ b/arch/arm/boot/dts/msm8226.dtsi
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -13,6 +13,7 @@
 /include/ "skeleton.dtsi"
 /include/ "msm8226-ion.dtsi"
 /include/ "msm-gdsc.dtsi"
+/include/ "msm8226-iommu.dtsi"
 
 / {
 	model = "Qualcomm MSM 8226";
@@ -546,6 +547,17 @@
 					 <0x1d80002b>; /* WLED */
 	};
 
+	i2c@f9926000 { /* BLSP-1 QUP-4 */
+		cell-index = <0>;
+		compatible = "qcom,i2c-qup";
+		reg = <0xf9926000 0x1000>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		reg-names = "qup_phys_addr";
+		interrupts = <0 98 0>;
+		interrupt-names = "qup_err_intr";
+		qcom,i2c-bus-freq = <100000>;
+	};
 };
 
 &gdsc_venus {
diff --git a/arch/arm/boot/dts/msm8974-liquid.dtsi b/arch/arm/boot/dts/msm8974-liquid.dtsi
index 81f8c09..7368788 100644
--- a/arch/arm/boot/dts/msm8974-liquid.dtsi
+++ b/arch/arm/boot/dts/msm8974-liquid.dtsi
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -121,6 +121,7 @@
 			atmel,panel-coords = <0 0 1080 1920>;
 			atmel,display-coords = <0 0 1080 1920>;
 			atmel,i2c-pull-up;
+			atmel,no-force-update;
 			atmel,cfg_1 {
 				atmel,family-id = <0xa2>;
 				atmel,variant-id = <0x00>;
@@ -562,6 +563,12 @@
 	};
 };
 
+&slim_msm {
+	taiko_codec {
+		qcom,cdc-micbias2-ext-cap;
+	};
+};
+
 &spi_epm {
 	epm-adc@0 {
 		compatible = "cy,epm-adc-cy8c5568lti-114";
diff --git a/arch/arm/boot/dts/msm8974-pm.dtsi b/arch/arm/boot/dts/msm8974-pm.dtsi
index b8a977b..1302ccb 100644
--- a/arch/arm/boot/dts/msm8974-pm.dtsi
+++ b/arch/arm/boot/dts/msm8974-pm.dtsi
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -183,11 +183,11 @@
 			reg = <0x0>;
 			qcom,mode = <0>;        /* MSM_PM_SLEEP_MODE_WAIT_FOR_INTERRUPT */
 			qcom,xo = <1>;          /* ON */
-			qcom,l2 = <3>;          /* ACTIVE */
-			qcom,vdd-mem-upper-bound = <1150000>; /* MAX */
-			qcom,vdd-mem-lower-bound = <1050000>; /* ACTIVE */
-			qcom,vdd-dig-upper-bound = <5>; /* MAX */
-			qcom,vdd-dig-lower-bound = <3>;  /* ACTIVE */
+			qcom,l2 = <2>;          /* Retention */
+			qcom,vdd-mem-upper-bound = <1050000>; /* SUPER TURBO */
+			qcom,vdd-mem-lower-bound = <950000>; /* NORMAL */
+			qcom,vdd-dig-upper-bound = <6>; /* SUPER TURBO */
+			qcom,vdd-dig-lower-bound = <4>;  /* NORMAL */
 			qcom,latency-us = <1>;
 			qcom,ss-power = <784>;
 			qcom,energy-overhead = <190000>;
@@ -198,27 +198,26 @@
 			reg = <0x1>;
 			qcom,mode = <4>;        /* MSM_PM_SLEEP_MODE_RETENTION*/
 			qcom,xo = <1>;          /* ON */
-			qcom,l2 = <3>;          /* ACTIVE */
-			qcom,vdd-mem-upper-bound = <1150000>; /* MAX */
-			qcom,vdd-mem-lower-bound = <1050000>; /* ACTIVE */
-			qcom,vdd-dig-upper-bound = <5>; /* MAX */
-			qcom,vdd-dig-lower-bound = <3>;  /* ACTIVE */
+			qcom,l2 = <2>;          /* Retention */
+			qcom,vdd-mem-upper-bound = <1050000>; /* SUPER TURBO */
+			qcom,vdd-mem-lower-bound = <950000>; /* NORMAL */
+			qcom,vdd-dig-upper-bound = <6>; /* SUPER TURBO */
+			qcom,vdd-dig-lower-bound = <4>;  /* NORMAL */
 			qcom,latency-us = <75>;
 			qcom,ss-power = <735>;
 			qcom,energy-overhead = <77341>;
 			qcom,time-overhead = <105>;
 		};
 
-
 		qcom,lpm-level@2 {
 			reg = <0x2>;
 			qcom,mode = <2>;        /* MSM_PM_SLEEP_MODE_STANDALONE_POWER_COLLAPSE */
 			qcom,xo = <1>;          /* ON */
-			qcom,l2 = <3>;          /* ACTIVE */
-			qcom,vdd-mem-upper-bound = <1150000>; /* MAX */
-			qcom,vdd-mem-lower-bound = <1050000>; /* ACTIVE */
-			qcom,vdd-dig-upper-bound = <5>; /* MAX */
-			qcom,vdd-dig-lower-bound = <3>;  /* ACTIVE */
+			qcom,l2 = <2>;          /* Retention */
+			qcom,vdd-mem-upper-bound = <1050000>; /* SUPER TURBO */
+			qcom,vdd-mem-lower-bound = <950000>; /* NORMAL */
+			qcom,vdd-dig-upper-bound = <6>; /* SUPER TURBO */
+			qcom,vdd-dig-lower-bound = <4>;  /* NORMAL */
 			qcom,latency-us = <95>;
 			qcom,ss-power = <725>;
 			qcom,energy-overhead = <99500>;
@@ -230,10 +229,10 @@
 			qcom,mode = <3>;        /* MSM_PM_SLEEP_MODE_POWER_COLLAPSE */
 			qcom,xo = <1>;          /* ON */
 			qcom,l2 = <1>;          /* GDHS */
-			qcom,vdd-mem-upper-bound = <1150000>; /* MAX */
-			qcom,vdd-mem-lower-bound = <1050000>; /* ACTIVE */
-			qcom,vdd-dig-upper-bound = <5>; /* MAX */
-			qcom,vdd-dig-lower-bound = <3>;  /* ACTIVE */
+			qcom,vdd-mem-upper-bound = <1050000>; /* SUPER TURBO */
+			qcom,vdd-mem-lower-bound = <950000>; /* NORMAL */
+			qcom,vdd-dig-upper-bound = <6>; /* SUPER TURBO */
+			qcom,vdd-dig-lower-bound = <4>;  /* NORMAL */
 			qcom,latency-us = <2000>;
 			qcom,ss-power = <138>;
 			qcom,energy-overhead = <1208400>;
@@ -244,11 +243,11 @@
 			reg = <0x4>;
 			qcom,mode = <3>;        /* MSM_PM_SLEEP_MODE_POWER_COLLAPSE */
 			qcom,xo = <1>;          /* ON */
-			qcom,l2 = <0>;          /* OFF */
-			qcom,vdd-mem-upper-bound = <1050000>; /* ACTIVE */
-			qcom,vdd-mem-lower-bound = <750000>;  /* RETENTION HIGH */
-			qcom,vdd-dig-upper-bound = <3>;  /* ACTIVE */
-			qcom,vdd-dig-lower-bound = <2>;  /* RETENTION HIGH */
+			qcom,l2 = <1>;          /* GDHS */
+			qcom,vdd-mem-upper-bound = <1050000>; /* SUPER TURBO */
+			qcom,vdd-mem-lower-bound = <950000>; /* SVS SOC */
+			qcom,vdd-dig-upper-bound = <6>; /* SUPER TURBO  */
+			qcom,vdd-dig-lower-bound = <3>;  /* SVS SOC */
 			qcom,latency-us = <3000>;
 			qcom,ss-power = <110>;
 			qcom,energy-overhead = <1250300>;
@@ -260,10 +259,10 @@
 			qcom,mode = <3>;        /* MSM_PM_SLEEP_MODE_POWER_COLLAPSE */
 			qcom,xo = <0>;          /* OFF */
 			qcom,l2 = <1>;          /* GDHS */
-			qcom,vdd-mem-upper-bound = <1150000>; /* MAX */
-			qcom,vdd-mem-lower-bound = <1050000>; /* ACTIVE */
-			qcom,vdd-dig-upper-bound = <5>; /* MAX */
-			qcom,vdd-dig-lower-bound = <3>;  /* ACTIVE */
+			qcom,vdd-mem-upper-bound = <1050000>; /* SUPER TURBO */
+			qcom,vdd-mem-lower-bound = <950000>; /* NORMAL */
+			qcom,vdd-dig-upper-bound = <6>; /* SUPER TURBO */
+			qcom,vdd-dig-lower-bound = <4>;  /* NORMAL */
 			qcom,latency-us = <3000>;
 			qcom,ss-power = <68>;
 			qcom,energy-overhead = <1350200>;
@@ -272,17 +271,17 @@
 
 		qcom,lpm-level@6 {
 			reg = <0x6>;
-			qcom,mode = <3>;        /* MSM_PM_SLEEP_MODE_POWER_COLLAPSE */
+			qcom,mode= <3>;         /* MSM_PM_SLEEP_MODE_POWER_COLLAPSE */
 			qcom,xo = <0>;          /* OFF */
-			qcom,l2 = <0>;          /* OFF */
-			qcom,vdd-mem-upper-bound = <1150000>; /* MAX */
-			qcom,vdd-mem-lower-bound = <1050000>; /* ACTIVE */
-			qcom,vdd-dig-upper-bound = <5>; /* MAX */
-			qcom,vdd-dig-lower-bound = <3>;  /* ACTIVE */
-			qcom,latency-us = <10300>;
-			qcom,ss-power = <63>;
-			qcom,energy-overhead = <2128000>;
-			qcom,time-overhead = <18200>;
+			qcom,l2 = <1>;          /* GDHS */
+			qcom,vdd-mem-upper-bound = <950000>; /* NORMAL */
+			qcom,vdd-mem-lower-bound = <950000>;  /* SVS SOC */
+			qcom,vdd-dig-upper-bound = <4>;  /* NORMAL */
+			qcom,vdd-dig-lower-bound = <3>;  /* SVS SOC */
+			qcom,latency-us = <18000>;
+			qcom,ss-power = <10>;
+			qcom,energy-overhead = <3202600>;
+			qcom,time-overhead = <27000>;
 		};
 
 		qcom,lpm-level@7 {
@@ -290,25 +289,10 @@
 			qcom,mode= <3>;         /* MSM_PM_SLEEP_MODE_POWER_COLLAPSE */
 			qcom,xo = <0>;          /* OFF */
 			qcom,l2 = <0>;          /* OFF */
-			qcom,vdd-mem-upper-bound = <1050000>; /* ACTIVE */
-			qcom,vdd-mem-lower-bound = <750000>;  /* RETENTION HIGH */
-			qcom,vdd-dig-upper-bound = <3>;  /* ACTIVE */
-			qcom,vdd-dig-lower-bound = <2>;  /* RETIONTION HIGH */
-			qcom,latency-us = <18000>;
-			qcom,ss-power = <10>;
-			qcom,energy-overhead = <3202600>;
-			qcom,time-overhead = <27000>;
-		};
-
-		qcom,lpm-level@8 {
-			reg = <0x8>;
-			qcom,mode= <3>;         /* MSM_PM_SLEEP_MODE_POWER_COLLAPSE */
-			qcom,xo = <0>;          /* OFF */
-			qcom,l2 = <0>;          /* OFF */
-			qcom,vdd-mem-upper-bound = <750000>; /* RETENTION HIGH */
-			qcom,vdd-mem-lower-bound = <750000>; /* RETENTION LOW */
-			qcom,vdd-dig-upper-bound = <2>; /* RETENTION HIGH */
-			qcom,vdd-dig-lower-bound = <0>; /* RETENTION LOW */
+			qcom,vdd-mem-upper-bound = <950000>; /* SVS SOC */
+			qcom,vdd-mem-lower-bound = <675000>; /* RETENTION */
+			qcom,vdd-dig-upper-bound = <3>; /* SVS SOC */
+			qcom,vdd-dig-lower-bound = <1>; /* RETENTION */
 			qcom,latency-us = <20000>;
 			qcom,ss-power = <2>;
 			qcom,energy-overhead = <4252000>;
diff --git a/arch/arm/boot/dts/msm8974.dtsi b/arch/arm/boot/dts/msm8974.dtsi
index 6a9a071..b673526 100644
--- a/arch/arm/boot/dts/msm8974.dtsi
+++ b/arch/arm/boot/dts/msm8974.dtsi
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -70,6 +70,7 @@
 			<783360 410000000>,
 			<489600 266670000>,
 			<244800 133330000>;
+		hfi = "venus";
 	};
 
 	qcom,wfd {
@@ -99,6 +100,8 @@
 
 	usb_otg: usb@f9a55000 {
 		compatible = "qcom,hsusb-otg";
+		status = "disabled";
+
 		reg = <0xf9a55000 0x400>;
 		interrupts = <0 134 0 0 140 0>;
 		interrupt-names = "core_irq", "async_irq";
@@ -653,6 +656,7 @@
 		vbus_dwc3-supply = <&pm8941_mvs1>;
 		qcom,dwc-usb3-msm-dbm-eps = <4>;
 		qcom,vdd-voltage-level = <1 5 7>;
+		qcom,dwc-hsphy-init = <0x00D195A4>;
 
 		qcom,msm-bus,name = "usb3";
 		qcom,msm-bus,num-cases = <2>;
@@ -1114,6 +1118,7 @@
 			qcom,data-fifo-size = <0x1800>;
 			qcom,descriptor-fifo-offset = <0xf4000>;
 			qcom,descriptor-fifo-size = <0x1400>;
+			qcom,reset-bam-on-connect;
 		};
 
 		qcom,pipe3 {
diff --git a/arch/arm/boot/dts/msm9625-coresight.dtsi b/arch/arm/boot/dts/msm9625-coresight.dtsi
index f01fe63..9a49c32 100644
--- a/arch/arm/boot/dts/msm9625-coresight.dtsi
+++ b/arch/arm/boot/dts/msm9625-coresight.dtsi
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -107,11 +107,23 @@
 		coresight-child-ports = <7>;
 	};
 
+	etm: etm@fc332000 {
+		compatible = "arm,coresight-etm";
+		reg = <0xfc332000 0x1000>;
+
+		coresight-id = <8>;
+		coresight-name = "coresight-etm";
+		coresight-nr-inports = <0>;
+		coresight-outports = <0>;
+		coresight-child-list = <&funnel_in0>;
+		coresight-child-ports = <4>;
+	};
+
 	csr: csr@fc302000 {
 		compatible = "qcom,coresight-csr";
 		reg = <0xfc302000 0x1000>;
 
-		coresight-id = <8>;
+		coresight-id = <9>;
 		coresight-name = "coresight-csr";
 		coresight-nr-inports = <0>;
 	};
diff --git a/arch/arm/boot/dts/msm9625.dtsi b/arch/arm/boot/dts/msm9625.dtsi
index 75a0ae5..d374b59 100644
--- a/arch/arm/boot/dts/msm9625.dtsi
+++ b/arch/arm/boot/dts/msm9625.dtsi
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -81,7 +81,7 @@
 		vbus_otg-supply = <&usb_vbus>;
 
 		qcom,hsusb-otg-phy-type = <2>;
-		qcom,hsusb-otg-mode = <1>;
+		qcom,hsusb-otg-mode = <3>;
 		qcom,hsusb-otg-otg-control = <1>;
 		qcom,hsusb-otg-disable-reset;
 	};
@@ -470,6 +470,11 @@
 			"DMIC6", "MIC BIAS4 External",
 			"MIC BIAS4 External", "Digital Mic6";
 			qcom,taiko-mclk-clk-freq = <12288000>;
+			prim-i2s-gpio-ws   = <&msmgpio 12 0>;
+			prim-i2s-gpio-din  = <&msmgpio 13 0>;
+			prim-i2s-gpio-dout = <&msmgpio 14 0>;
+			prim-i2s-gpio-sclk = <&msmgpio 15 0>;
+			prim-i2s-gpio-mclk = <&msmgpio 71 0>;
 	};
 
 	qcom,msm-adsp-loader {
@@ -597,6 +602,12 @@
 		qcom,bam-pipe-pair = <2>;
 	};
 
+	jtag_mm: jtagmm@fc332000 {
+		compatible = "qcom,jtag-mm";
+		reg = <0xfc332000 0x1000>,
+			<0xfc330000 0x1000>;
+		reg-names = "etm-base","debug-base";
+	};
 };
 
 /include/ "msm-pm8019-rpm-regulator.dtsi"
diff --git a/arch/arm/configs/msm8974-perf_defconfig b/arch/arm/configs/msm8974-perf_defconfig
index 1fadd28..71b6990 100644
--- a/arch/arm/configs/msm8974-perf_defconfig
+++ b/arch/arm/configs/msm8974-perf_defconfig
@@ -1,7 +1,6 @@
 # CONFIG_ARM_PATCH_PHYS_VIRT is not set
 CONFIG_EXPERIMENTAL=y
 CONFIG_LOCALVERSION="-perf"
-# CONFIG_LOCALVERSION_AUTO is not set
 CONFIG_SYSVIPC=y
 CONFIG_RCU_FAST_NO_HZ=y
 CONFIG_IKCONFIG=y
@@ -46,6 +45,7 @@
 CONFIG_MSM_SMD=y
 CONFIG_MSM_SMD_PKG4=y
 CONFIG_MSM_BAM_DMUX=y
+CONFIG_MSM_IPC_LOGGING=y
 CONFIG_MSM_IPC_ROUTER=y
 CONFIG_MSM_IPC_ROUTER_SMD_XPRT=y
 CONFIG_MSM_IPC_ROUTER_SECURITY=y
@@ -217,7 +217,7 @@
 CONFIG_BT_HIDP=y
 CONFIG_BT_HCISMD=y
 CONFIG_MSM_BT_POWER=y
-CONFIG_CFG80211=m
+CONFIG_CFG80211=y
 CONFIG_RFKILL=y
 CONFIG_GENLOCK=y
 CONFIG_GENLOCK_MISCDEVICE=y
@@ -330,6 +330,7 @@
 CONFIG_FB_MSM_MDSS=y
 CONFIG_FB_MSM_MDSS_WRITEBACK=y
 CONFIG_FB_MSM_MDSS_HDMI_PANEL=y
+CONFIG_FB_MSM_MDSS_HDMI_MHL_SII8334=y
 CONFIG_BACKLIGHT_LCD_SUPPORT=y
 # CONFIG_LCD_CLASS_DEVICE is not set
 CONFIG_BACKLIGHT_CLASS_DEVICE=y
diff --git a/arch/arm/configs/msm8974_defconfig b/arch/arm/configs/msm8974_defconfig
index 87f72f6..1479954 100644
--- a/arch/arm/configs/msm8974_defconfig
+++ b/arch/arm/configs/msm8974_defconfig
@@ -1,6 +1,5 @@
 # CONFIG_ARM_PATCH_PHYS_VIRT is not set
 CONFIG_EXPERIMENTAL=y
-# CONFIG_LOCALVERSION_AUTO is not set
 CONFIG_SYSVIPC=y
 CONFIG_RCU_FAST_NO_HZ=y
 CONFIG_IKCONFIG=y
@@ -45,6 +44,7 @@
 CONFIG_MSM_SMD=y
 CONFIG_MSM_SMD_PKG4=y
 CONFIG_MSM_BAM_DMUX=y
+CONFIG_MSM_IPC_LOGGING=y
 CONFIG_MSM_IPC_ROUTER=y
 CONFIG_MSM_IPC_ROUTER_SMD_XPRT=y
 CONFIG_MSM_IPC_ROUTER_SECURITY=y
@@ -219,7 +219,7 @@
 CONFIG_BT_HIDP=y
 CONFIG_BT_HCISMD=y
 CONFIG_MSM_BT_POWER=y
-CONFIG_CFG80211=m
+CONFIG_CFG80211=y
 CONFIG_RFKILL=y
 CONFIG_GENLOCK=y
 CONFIG_GENLOCK_MISCDEVICE=y
@@ -331,6 +331,7 @@
 CONFIG_FB_MSM_MDSS=y
 CONFIG_FB_MSM_MDSS_WRITEBACK=y
 CONFIG_FB_MSM_MDSS_HDMI_PANEL=y
+CONFIG_FB_MSM_MDSS_HDMI_MHL_SII8334=y
 CONFIG_BACKLIGHT_LCD_SUPPORT=y
 # CONFIG_LCD_CLASS_DEVICE is not set
 CONFIG_BACKLIGHT_CLASS_DEVICE=y
diff --git a/arch/arm/configs/msm9625_defconfig b/arch/arm/configs/msm9625_defconfig
index 0b003fd..a2d21d9 100644
--- a/arch/arm/configs/msm9625_defconfig
+++ b/arch/arm/configs/msm9625_defconfig
@@ -40,6 +40,7 @@
 CONFIG_MSM_SMD=y
 CONFIG_MSM_SMD_PKG4=y
 CONFIG_MSM_BAM_DMUX=y
+CONFIG_MSM_IPC_LOGGING=y
 CONFIG_MSM_IPC_ROUTER=y
 CONFIG_MSM_IPC_ROUTER_SMD_XPRT=y
 CONFIG_MSM_RPM_REGULATOR_SMD=y
@@ -238,6 +239,7 @@
 CONFIG_VFAT_FS=y
 CONFIG_TMPFS=y
 CONFIG_YAFFS_FS=y
+CONFIG_EXT3_FS=y
 CONFIG_YAFFS_DISABLE_TAGS_ECC=y
 CONFIG_NLS_CODEPAGE_437=y
 CONFIG_NLS_ASCII=y
diff --git a/arch/arm/mach-msm/Kconfig b/arch/arm/mach-msm/Kconfig
index 989d80e..83a5fb0 100644
--- a/arch/arm/mach-msm/Kconfig
+++ b/arch/arm/mach-msm/Kconfig
@@ -184,6 +184,7 @@
 	select ARM_USE_USER_ACCESSIBLE_TIMERS
 	select MSM_USE_USER_ACCESSIBLE_TIMERS
 	select MSM_CPU_PWRCTL
+	select MSM_LPM_TEST
 
 config ARCH_MSM8930
 	bool "MSM8930"
@@ -346,6 +347,7 @@
 	select MSM_RUN_QUEUE_STATS
 	select MIGHT_HAVE_CACHE_L2X0
 	select ARM_HAS_SG_CHAIN
+	select CPU_HAS_L2_PMU
 
 config ARCH_MSM9625
 	bool "MSM9625"
@@ -373,6 +375,7 @@
 	select MSM_QDSP6V2_CODECS
 	select MSM_AUDIO_QDSP6V2 if SND_SOC
 	select CPU_HAS_L2_PMU
+	select MSM_JTAG_MM if MSM_QDSS
 
 config ARCH_MSM8910
 	bool "MSM8910"
@@ -482,6 +485,7 @@
 	select ARCH_MSM_CORTEXMP
 	select MIGHT_HAVE_CACHE_L2X0
 	select ARM_HAS_SG_CHAIN
+	select CPU_HAS_L2_PMU
 
 config  MSM_VIC
 	bool
@@ -520,6 +524,17 @@
 	  enables the MPM driver that supports initialization from a device
 	  tree
 
+config MSM_LPM_TEST
+	bool "Low Power Mode test framework"
+	depends on MSM_RPM
+	depends on MSM_PM8X60
+	help
+	  LPM_TEST is a test framework that assists in exercising the low
+	  power mode algorithm on MSM targets. This test framework tracks
+	  notifications sent during entry/exit of the low power modes and
+	  processes them to measure various stats including latency
+	  measurement.
+
 config MSM_XO
 	bool
 
@@ -1566,6 +1581,16 @@
 	  to perform QMI message marshaling and transport them over IPC
 	  Router.
 
+config MSM_TEST_QMI_CLIENT
+	depends on MSM_QMI_INTERFACE
+	bool "MSM TEST QMI CLIENT"
+	help
+	  The sample QMI client provides a test code for QMI usage. The
+	  test_service client driver uses QMI interface library to send
+	  and receive QMI messages over IPC Router. The test code sends
+	  a synchronous QMI request to the test_service and handles the
+	  QMI responses.
+
 config MSM_ONCRPCROUTER_DEBUG
 	depends on MSM_ONCRPCROUTER
 	default y
@@ -2248,6 +2273,19 @@
 	  For production builds, you should probably say 'N' here to avoid
 	  potential power, performance and memory penalty.
 
+config MSM_JTAG_MM
+	bool "ETM trace and debug support across power collapse using memory mapped access"
+	help
+	   Enables support for kernel debugging (specifically breakpoints) and
+	   processor tracing using ETM across power collapse both for JTag and
+	   OS hosted software running on the target. Enabling this will ensure
+	   debug and ETM registers are saved and restored across power collapse.
+	   Needed on targets on which cp14 access to debug and ETM registers is
+	   not permitted and so memory mapped access is necessary.
+
+	   For production builds, you should probably say 'N' here to avoid
+	   potential power, performance and memory penalty.
+
 config MSM_ETM
 	tristate "Enable MSM ETM and ETB"
 	depends on ARCH_MSM8X60
@@ -2740,4 +2778,9 @@
 	  stand alone power collapse operation. Selecting this option
 	  ensures that they are always off.
 
+config MSM_UARTDM_Core_v14
+	bool "Use MSM BLSP based HSUART Core v1.4"
+	depends on SERIAL_MSM_HS
+	help
+		Select if BLSP based UART Core v.14 or higher is present.
 endif
diff --git a/arch/arm/mach-msm/Makefile b/arch/arm/mach-msm/Makefile
index 9d9550e..e92e4de 100644
--- a/arch/arm/mach-msm/Makefile
+++ b/arch/arm/mach-msm/Makefile
@@ -33,8 +33,12 @@
 obj-$(CONFIG_ARCH_MSM_SCORPIONMP) += perf_event_msm_l2.o
 obj-$(CONFIG_ARCH_MSM_KRAIT) += msm-krait-l2-accessors.o pmu.o perf_event_msm_krait_l2.o
 obj-$(CONFIG_ARCH_MSM_KRAIT) += krait-scm.o
-obj-$(CONFIG_ARCH_MSM7X27A) += pmu.o
+ifdef CONFIG_HW_PERF_EVENTS
+obj-$(CONFIG_ARCH_MSM7X27A) += pmu.o perf_event_msm_pl310.o
 obj-$(CONFIG_ARCH_MSM9625) += pmu.o perf_event_msm_pl310.o
+obj-$(CONFIG_ARCH_MSM8625) += pmu.o perf_event_msm_pl310.o
+obj-$(CONFIG_ARCH_MSM9615) += pmu.o perf_event_msm_pl310.o
+endif
 
 ifndef CONFIG_MSM_SMP
 obj-$(CONFIG_ARCH_MSM_SCORPION) += msm_fault_handlers.o
@@ -56,6 +60,7 @@
 obj-$(CONFIG_CPU_V6) += idle-v6.o
 obj-$(CONFIG_CPU_V7) += idle-v7.o
 obj-$(CONFIG_MSM_JTAG) += jtag.o
+obj-$(CONFIG_MSM_JTAG_MM) +=  jtag-mm.o
 
 msm-etm-objs := etm.o
 obj-$(CONFIG_MSM_ETM) += msm-etm.o
@@ -134,6 +139,7 @@
 obj-$(CONFIG_MSM_IPC_ROUTER)+= ipc_socket.o
 obj-$(CONFIG_MSM_IPC_ROUTER_SECURITY)+= msm_ipc_router_security.o
 obj-$(CONFIG_MSM_QMI_INTERFACE) += msm_qmi_interface.o
+obj-$(CONFIG_MSM_TEST_QMI_CLIENT) += kernel_test_service_v01.o test_qmi_client.o
 obj-$(CONFIG_DEBUG_FS) += smd_rpc_sym.o
 obj-$(CONFIG_MSM_ONCRPCROUTER) += smd_rpcrouter_servers.o
 obj-$(CONFIG_MSM_ONCRPCROUTER) += smd_rpcrouter_clients.o
@@ -323,6 +329,7 @@
 	obj-$(CONFIG_ARCH_MSM8960) += rpm_resources.o
 	obj-$(CONFIG_ARCH_MSM8X60) += rpm_resources.o
 	obj-$(CONFIG_ARCH_MSM9615) += rpm_resources.o
+	obj-$(CONFIG_MSM_LPM_TEST) += test-lpm.o
 endif
 ifdef CONFIG_MSM_RPM_SMD
 	obj-$(CONFIG_ARCH_MSM8974) += lpm_levels.o lpm_resources.o
diff --git a/arch/arm/mach-msm/acpuclock-8064.c b/arch/arm/mach-msm/acpuclock-8064.c
index db77a34..359a156 100644
--- a/arch/arm/mach-msm/acpuclock-8064.c
+++ b/arch/arm/mach-msm/acpuclock-8064.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2011-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -122,7 +122,7 @@
 	[3]  = { {  540000, HFPLL, 2, 0x28 }, 1050000, 1050000, 2 },
 	[4]  = { {  594000, HFPLL, 1, 0x16 }, 1050000, 1050000, 2 },
 	[5]  = { {  648000, HFPLL, 1, 0x18 }, 1050000, 1050000, 4 },
-	[6]  = { {  702000, HFPLL, 1, 0x1A }, 1050000, 1050000, 4 },
+	[6]  = { {  702000, HFPLL, 1, 0x1A }, 1150000, 1150000, 4 },
 	[7]  = { {  756000, HFPLL, 1, 0x1C }, 1150000, 1150000, 4 },
 	[8]  = { {  810000, HFPLL, 1, 0x1E }, 1150000, 1150000, 4 },
 	[9]  = { {  864000, HFPLL, 1, 0x20 }, 1150000, 1150000, 4 },
@@ -137,18 +137,18 @@
 
 static struct acpu_level tbl_slow[] __initdata = {
 	{ 1, {   384000, PLL_8, 0, 0x00 }, L2(0),   950000 },
-	{ 0, {   432000, HFPLL, 2, 0x20 }, L2(6),   975000 },
-	{ 1, {   486000, HFPLL, 2, 0x24 }, L2(6),   975000 },
-	{ 0, {   540000, HFPLL, 2, 0x28 }, L2(6),  1000000 },
-	{ 1, {   594000, HFPLL, 1, 0x16 }, L2(6),  1000000 },
-	{ 0, {   648000, HFPLL, 1, 0x18 }, L2(6),  1025000 },
-	{ 1, {   702000, HFPLL, 1, 0x1A }, L2(6),  1025000 },
-	{ 0, {   756000, HFPLL, 1, 0x1C }, L2(6),  1075000 },
-	{ 1, {   810000, HFPLL, 1, 0x1E }, L2(6),  1075000 },
-	{ 0, {   864000, HFPLL, 1, 0x20 }, L2(6),  1100000 },
-	{ 1, {   918000, HFPLL, 1, 0x22 }, L2(6),  1100000 },
-	{ 0, {   972000, HFPLL, 1, 0x24 }, L2(6),  1125000 },
-	{ 1, {  1026000, HFPLL, 1, 0x26 }, L2(6),  1125000 },
+	{ 0, {   432000, HFPLL, 2, 0x20 }, L2(5),   975000 },
+	{ 1, {   486000, HFPLL, 2, 0x24 }, L2(5),   975000 },
+	{ 0, {   540000, HFPLL, 2, 0x28 }, L2(5),  1000000 },
+	{ 1, {   594000, HFPLL, 1, 0x16 }, L2(5),  1000000 },
+	{ 0, {   648000, HFPLL, 1, 0x18 }, L2(5),  1025000 },
+	{ 1, {   702000, HFPLL, 1, 0x1A }, L2(5),  1025000 },
+	{ 0, {   756000, HFPLL, 1, 0x1C }, L2(5),  1075000 },
+	{ 1, {   810000, HFPLL, 1, 0x1E }, L2(5),  1075000 },
+	{ 0, {   864000, HFPLL, 1, 0x20 }, L2(5),  1100000 },
+	{ 1, {   918000, HFPLL, 1, 0x22 }, L2(5),  1100000 },
+	{ 0, {   972000, HFPLL, 1, 0x24 }, L2(5),  1125000 },
+	{ 1, {  1026000, HFPLL, 1, 0x26 }, L2(5),  1125000 },
 	{ 0, {  1080000, HFPLL, 1, 0x28 }, L2(15), 1175000 },
 	{ 1, {  1134000, HFPLL, 1, 0x2A }, L2(15), 1175000 },
 	{ 0, {  1188000, HFPLL, 1, 0x2C }, L2(15), 1200000 },
@@ -163,18 +163,18 @@
 
 static struct acpu_level tbl_nom[] __initdata = {
 	{ 1, {   384000, PLL_8, 0, 0x00 }, L2(0),   900000 },
-	{ 0, {   432000, HFPLL, 2, 0x20 }, L2(6),   925000 },
-	{ 1, {   486000, HFPLL, 2, 0x24 }, L2(6),   925000 },
-	{ 0, {   540000, HFPLL, 2, 0x28 }, L2(6),   950000 },
-	{ 1, {   594000, HFPLL, 1, 0x16 }, L2(6),   950000 },
-	{ 0, {   648000, HFPLL, 1, 0x18 }, L2(6),   975000 },
-	{ 1, {   702000, HFPLL, 1, 0x1A }, L2(6),   975000 },
-	{ 0, {   756000, HFPLL, 1, 0x1C }, L2(6),  1025000 },
-	{ 1, {   810000, HFPLL, 1, 0x1E }, L2(6),  1025000 },
-	{ 0, {   864000, HFPLL, 1, 0x20 }, L2(6),  1050000 },
-	{ 1, {   918000, HFPLL, 1, 0x22 }, L2(6),  1050000 },
-	{ 0, {   972000, HFPLL, 1, 0x24 }, L2(6),  1075000 },
-	{ 1, {  1026000, HFPLL, 1, 0x26 }, L2(6),  1075000 },
+	{ 0, {   432000, HFPLL, 2, 0x20 }, L2(5),   925000 },
+	{ 1, {   486000, HFPLL, 2, 0x24 }, L2(5),   925000 },
+	{ 0, {   540000, HFPLL, 2, 0x28 }, L2(5),   950000 },
+	{ 1, {   594000, HFPLL, 1, 0x16 }, L2(5),   950000 },
+	{ 0, {   648000, HFPLL, 1, 0x18 }, L2(5),   975000 },
+	{ 1, {   702000, HFPLL, 1, 0x1A }, L2(5),   975000 },
+	{ 0, {   756000, HFPLL, 1, 0x1C }, L2(5),  1025000 },
+	{ 1, {   810000, HFPLL, 1, 0x1E }, L2(5),  1025000 },
+	{ 0, {   864000, HFPLL, 1, 0x20 }, L2(5),  1050000 },
+	{ 1, {   918000, HFPLL, 1, 0x22 }, L2(5),  1050000 },
+	{ 0, {   972000, HFPLL, 1, 0x24 }, L2(5),  1075000 },
+	{ 1, {  1026000, HFPLL, 1, 0x26 }, L2(5),  1075000 },
 	{ 0, {  1080000, HFPLL, 1, 0x28 }, L2(15), 1125000 },
 	{ 1, {  1134000, HFPLL, 1, 0x2A }, L2(15), 1125000 },
 	{ 0, {  1188000, HFPLL, 1, 0x2C }, L2(15), 1150000 },
@@ -189,18 +189,18 @@
 
 static struct acpu_level tbl_fast[] __initdata = {
 	{ 1, {   384000, PLL_8, 0, 0x00 }, L2(0),   850000 },
-	{ 0, {   432000, HFPLL, 2, 0x20 }, L2(6),   875000 },
-	{ 1, {   486000, HFPLL, 2, 0x24 }, L2(6),   875000 },
-	{ 0, {   540000, HFPLL, 2, 0x28 }, L2(6),   900000 },
-	{ 1, {   594000, HFPLL, 1, 0x16 }, L2(6),   900000 },
-	{ 0, {   648000, HFPLL, 1, 0x18 }, L2(6),   925000 },
-	{ 1, {   702000, HFPLL, 1, 0x1A }, L2(6),   925000 },
-	{ 0, {   756000, HFPLL, 1, 0x1C }, L2(6),   975000 },
-	{ 1, {   810000, HFPLL, 1, 0x1E }, L2(6),   975000 },
-	{ 0, {   864000, HFPLL, 1, 0x20 }, L2(6),  1000000 },
-	{ 1, {   918000, HFPLL, 1, 0x22 }, L2(6),  1000000 },
-	{ 0, {   972000, HFPLL, 1, 0x24 }, L2(6),  1025000 },
-	{ 1, {  1026000, HFPLL, 1, 0x26 }, L2(6),  1025000 },
+	{ 0, {   432000, HFPLL, 2, 0x20 }, L2(5),   875000 },
+	{ 1, {   486000, HFPLL, 2, 0x24 }, L2(5),   875000 },
+	{ 0, {   540000, HFPLL, 2, 0x28 }, L2(5),   900000 },
+	{ 1, {   594000, HFPLL, 1, 0x16 }, L2(5),   900000 },
+	{ 0, {   648000, HFPLL, 1, 0x18 }, L2(5),   925000 },
+	{ 1, {   702000, HFPLL, 1, 0x1A }, L2(5),   925000 },
+	{ 0, {   756000, HFPLL, 1, 0x1C }, L2(5),   975000 },
+	{ 1, {   810000, HFPLL, 1, 0x1E }, L2(5),   975000 },
+	{ 0, {   864000, HFPLL, 1, 0x20 }, L2(5),  1000000 },
+	{ 1, {   918000, HFPLL, 1, 0x22 }, L2(5),  1000000 },
+	{ 0, {   972000, HFPLL, 1, 0x24 }, L2(5),  1025000 },
+	{ 1, {  1026000, HFPLL, 1, 0x26 }, L2(5),  1025000 },
 	{ 0, {  1080000, HFPLL, 1, 0x28 }, L2(15), 1075000 },
 	{ 1, {  1134000, HFPLL, 1, 0x2A }, L2(15), 1075000 },
 	{ 0, {  1188000, HFPLL, 1, 0x2C }, L2(15), 1100000 },
@@ -215,18 +215,18 @@
 
 static struct acpu_level tbl_faster[] __initdata = {
 	{ 1, {   384000, PLL_8, 0, 0x00 }, L2(0),   850000 },
-	{ 0, {   432000, HFPLL, 2, 0x20 }, L2(6),   875000 },
-	{ 1, {   486000, HFPLL, 2, 0x24 }, L2(6),   875000 },
-	{ 0, {   540000, HFPLL, 2, 0x28 }, L2(6),   900000 },
-	{ 1, {   594000, HFPLL, 1, 0x16 }, L2(6),   900000 },
-	{ 0, {   648000, HFPLL, 1, 0x18 }, L2(6),   925000 },
-	{ 1, {   702000, HFPLL, 1, 0x1A }, L2(6),   925000 },
-	{ 0, {   756000, HFPLL, 1, 0x1C }, L2(6),   962500 },
-	{ 1, {   810000, HFPLL, 1, 0x1E }, L2(6),   962500 },
-	{ 0, {   864000, HFPLL, 1, 0x20 }, L2(6),   975000 },
-	{ 1, {   918000, HFPLL, 1, 0x22 }, L2(6),   975000 },
-	{ 0, {   972000, HFPLL, 1, 0x24 }, L2(6),  1000000 },
-	{ 1, {  1026000, HFPLL, 1, 0x26 }, L2(6),  1000000 },
+	{ 0, {   432000, HFPLL, 2, 0x20 }, L2(5),   875000 },
+	{ 1, {   486000, HFPLL, 2, 0x24 }, L2(5),   875000 },
+	{ 0, {   540000, HFPLL, 2, 0x28 }, L2(5),   900000 },
+	{ 1, {   594000, HFPLL, 1, 0x16 }, L2(5),   900000 },
+	{ 0, {   648000, HFPLL, 1, 0x18 }, L2(5),   925000 },
+	{ 1, {   702000, HFPLL, 1, 0x1A }, L2(5),   925000 },
+	{ 0, {   756000, HFPLL, 1, 0x1C }, L2(5),   962500 },
+	{ 1, {   810000, HFPLL, 1, 0x1E }, L2(5),   962500 },
+	{ 0, {   864000, HFPLL, 1, 0x20 }, L2(5),   975000 },
+	{ 1, {   918000, HFPLL, 1, 0x22 }, L2(5),   975000 },
+	{ 0, {   972000, HFPLL, 1, 0x24 }, L2(5),  1000000 },
+	{ 1, {  1026000, HFPLL, 1, 0x26 }, L2(5),  1000000 },
 	{ 0, {  1080000, HFPLL, 1, 0x28 }, L2(15), 1050000 },
 	{ 1, {  1134000, HFPLL, 1, 0x2A }, L2(15), 1050000 },
 	{ 0, {  1188000, HFPLL, 1, 0x2C }, L2(15), 1075000 },
@@ -239,14 +239,126 @@
 	{ 0, { 0 } }
 };
 
+static struct acpu_level tbl_PVS0_1512MHz[] __initdata = {
+	{ 1, {   384000, PLL_8, 0, 0x00 }, L2(0),   950000 },
+	{ 1, {   486000, HFPLL, 2, 0x24 }, L2(5),   950000 },
+	{ 1, {   594000, HFPLL, 1, 0x16 }, L2(5),   950000 },
+	{ 1, {   702000, HFPLL, 1, 0x1A }, L2(5),   962500 },
+	{ 1, {   810000, HFPLL, 1, 0x1E }, L2(5),  1000000 },
+	{ 1, {   918000, HFPLL, 1, 0x22 }, L2(5),  1025000 },
+	{ 1, {  1026000, HFPLL, 1, 0x26 }, L2(5),  1037500 },
+	{ 1, {  1134000, HFPLL, 1, 0x2A }, L2(15), 1075000 },
+	{ 1, {  1242000, HFPLL, 1, 0x2E }, L2(15), 1087500 },
+	{ 1, {  1350000, HFPLL, 1, 0x32 }, L2(15), 1125000 },
+	{ 1, {  1458000, HFPLL, 1, 0x36 }, L2(15), 1150000 },
+	{ 1, {  1512000, HFPLL, 1, 0x38 }, L2(15), 1162500 },
+	{ 0, { 0 } }
+};
+
+static struct acpu_level tbl_PVS1_1512MHz[] __initdata = {
+	{ 1, {   384000, PLL_8, 0, 0x00 }, L2(0),   950000 },
+	{ 1, {   486000, HFPLL, 2, 0x24 }, L2(5),   950000 },
+	{ 1, {   594000, HFPLL, 1, 0x16 }, L2(5),   950000 },
+	{ 1, {   702000, HFPLL, 1, 0x1A }, L2(5),   962500 },
+	{ 1, {   810000, HFPLL, 1, 0x1E }, L2(5),   975000 },
+	{ 1, {   918000, HFPLL, 1, 0x22 }, L2(5),  1000000 },
+	{ 1, {  1026000, HFPLL, 1, 0x26 }, L2(5),  1012500 },
+	{ 1, {  1134000, HFPLL, 1, 0x2A }, L2(15), 1037500 },
+	{ 1, {  1242000, HFPLL, 1, 0x2E }, L2(15), 1050000 },
+	{ 1, {  1350000, HFPLL, 1, 0x32 }, L2(15), 1087500 },
+	{ 1, {  1458000, HFPLL, 1, 0x36 }, L2(15), 1112500 },
+	{ 1, {  1512000, HFPLL, 1, 0x38 }, L2(15), 1125000 },
+	{ 0, { 0 } }
+};
+
+static struct acpu_level tbl_PVS2_1512MHz[] __initdata = {
+	{ 1, {   384000, PLL_8, 0, 0x00 }, L2(0),   925000 },
+	{ 1, {   486000, HFPLL, 2, 0x24 }, L2(5),   925000 },
+	{ 1, {   594000, HFPLL, 1, 0x16 }, L2(5),   925000 },
+	{ 1, {   702000, HFPLL, 1, 0x1A }, L2(5),   925000 },
+	{ 1, {   810000, HFPLL, 1, 0x1E }, L2(5),   937500 },
+	{ 1, {   918000, HFPLL, 1, 0x22 }, L2(5),   950000 },
+	{ 1, {  1026000, HFPLL, 1, 0x26 }, L2(5),   975000 },
+	{ 1, {  1134000, HFPLL, 1, 0x2A }, L2(15), 1000000 },
+	{ 1, {  1242000, HFPLL, 1, 0x2E }, L2(15), 1012500 },
+	{ 1, {  1350000, HFPLL, 1, 0x32 }, L2(15), 1037500 },
+	{ 1, {  1458000, HFPLL, 1, 0x36 }, L2(15), 1075000 },
+	{ 1, {  1512000, HFPLL, 1, 0x38 }, L2(15), 1087500 },
+	{ 0, { 0 } }
+};
+
+static struct acpu_level tbl_PVS3_1512MHz[] __initdata = {
+	{ 1, {   384000, PLL_8, 0, 0x00 }, L2(0),   900000 },
+	{ 1, {   486000, HFPLL, 2, 0x24 }, L2(5),   900000 },
+	{ 1, {   594000, HFPLL, 1, 0x16 }, L2(5),   900000 },
+	{ 1, {   702000, HFPLL, 1, 0x1A }, L2(5),   900000 },
+	{ 1, {   810000, HFPLL, 1, 0x1E }, L2(5),   900000 },
+	{ 1, {   918000, HFPLL, 1, 0x22 }, L2(5),   925000 },
+	{ 1, {  1026000, HFPLL, 1, 0x26 }, L2(5),   950000 },
+	{ 1, {  1134000, HFPLL, 1, 0x2A }, L2(15),  975000 },
+	{ 1, {  1242000, HFPLL, 1, 0x2E }, L2(15),  987500 },
+	{ 1, {  1350000, HFPLL, 1, 0x32 }, L2(15), 1000000 },
+	{ 1, {  1458000, HFPLL, 1, 0x36 }, L2(15), 1037500 },
+	{ 1, {  1512000, HFPLL, 1, 0x38 }, L2(15), 1050000 },
+	{ 0, { 0 } }
+};
+
+static struct acpu_level tbl_PVS4_1512MHz[] __initdata = {
+	{ 1, {   384000, PLL_8, 0, 0x00 }, L2(0),   875000 },
+	{ 1, {   486000, HFPLL, 2, 0x24 }, L2(5),   875000 },
+	{ 1, {   594000, HFPLL, 1, 0x16 }, L2(5),   875000 },
+	{ 1, {   702000, HFPLL, 1, 0x1A }, L2(5),   875000 },
+	{ 1, {   810000, HFPLL, 1, 0x1E }, L2(5),   887500 },
+	{ 1, {   918000, HFPLL, 1, 0x22 }, L2(5),   900000 },
+	{ 1, {  1026000, HFPLL, 1, 0x26 }, L2(5),   925000 },
+	{ 1, {  1134000, HFPLL, 1, 0x2A }, L2(15),  950000 },
+	{ 1, {  1242000, HFPLL, 1, 0x2E }, L2(15),  962500 },
+	{ 1, {  1350000, HFPLL, 1, 0x32 }, L2(15),  975000 },
+	{ 1, {  1458000, HFPLL, 1, 0x36 }, L2(15), 1000000 },
+	{ 1, {  1512000, HFPLL, 1, 0x38 }, L2(15), 1012500 },
+	{ 0, { 0 } }
+};
+
+static struct acpu_level tbl_PVS5_1512MHz[] __initdata = {
+	{ 1, {   384000, PLL_8, 0, 0x00 }, L2(0),   875000 },
+	{ 1, {   486000, HFPLL, 2, 0x24 }, L2(5),   875000 },
+	{ 1, {   594000, HFPLL, 1, 0x16 }, L2(5),   875000 },
+	{ 1, {   702000, HFPLL, 1, 0x1A }, L2(5),   875000 },
+	{ 1, {   810000, HFPLL, 1, 0x1E }, L2(5),   887500 },
+	{ 1, {   918000, HFPLL, 1, 0x22 }, L2(5),   900000 },
+	{ 1, {  1026000, HFPLL, 1, 0x26 }, L2(5),   925000 },
+	{ 1, {  1134000, HFPLL, 1, 0x2A }, L2(15),  937500 },
+	{ 1, {  1242000, HFPLL, 1, 0x2E }, L2(15),  950000 },
+	{ 1, {  1350000, HFPLL, 1, 0x32 }, L2(15),  962500 },
+	{ 1, {  1458000, HFPLL, 1, 0x36 }, L2(15),  987500 },
+	{ 1, {  1512000, HFPLL, 1, 0x38 }, L2(15), 1000000 },
+	{ 0, { 0 } }
+};
+
+static struct acpu_level tbl_PVS6_1512MHz[] __initdata = {
+	{ 1, {   384000, PLL_8, 0, 0x00 }, L2(0),   875000 },
+	{ 1, {   486000, HFPLL, 2, 0x24 }, L2(5),   875000 },
+	{ 1, {   594000, HFPLL, 1, 0x16 }, L2(5),   875000 },
+	{ 1, {   702000, HFPLL, 1, 0x1A }, L2(5),   875000 },
+	{ 1, {   810000, HFPLL, 1, 0x1E }, L2(5),   887500 },
+	{ 1, {   918000, HFPLL, 1, 0x22 }, L2(5),   900000 },
+	{ 1, {  1026000, HFPLL, 1, 0x26 }, L2(5),   925000 },
+	{ 1, {  1134000, HFPLL, 1, 0x2A }, L2(15),  937500 },
+	{ 1, {  1242000, HFPLL, 1, 0x2E }, L2(15),  950000 },
+	{ 1, {  1350000, HFPLL, 1, 0x32 }, L2(15),  962500 },
+	{ 1, {  1458000, HFPLL, 1, 0x36 }, L2(15),  975000 },
+	{ 1, {  1512000, HFPLL, 1, 0x38 }, L2(15),  987500 },
+	{ 0, { 0 } }
+};
+
 static struct acpu_level tbl_PVS0_1700MHz[] __initdata = {
 	{ 1, {   384000, PLL_8, 0, 0x00 }, L2(0),   950000 },
-	{ 1, {   486000, HFPLL, 2, 0x24 }, L2(6),   950000 },
-	{ 1, {   594000, HFPLL, 1, 0x16 }, L2(6),   950000 },
-	{ 1, {   702000, HFPLL, 1, 0x1A }, L2(6),   962500 },
-	{ 1, {   810000, HFPLL, 1, 0x1E }, L2(6),  1000000 },
-	{ 1, {   918000, HFPLL, 1, 0x22 }, L2(6),  1025000 },
-	{ 1, {  1026000, HFPLL, 1, 0x26 }, L2(6),  1037500 },
+	{ 1, {   486000, HFPLL, 2, 0x24 }, L2(5),   950000 },
+	{ 1, {   594000, HFPLL, 1, 0x16 }, L2(5),   950000 },
+	{ 1, {   702000, HFPLL, 1, 0x1A }, L2(5),   962500 },
+	{ 1, {   810000, HFPLL, 1, 0x1E }, L2(5),  1000000 },
+	{ 1, {   918000, HFPLL, 1, 0x22 }, L2(5),  1025000 },
+	{ 1, {  1026000, HFPLL, 1, 0x26 }, L2(5),  1037500 },
 	{ 1, {  1134000, HFPLL, 1, 0x2A }, L2(15), 1075000 },
 	{ 1, {  1242000, HFPLL, 1, 0x2E }, L2(15), 1087500 },
 	{ 1, {  1350000, HFPLL, 1, 0x32 }, L2(15), 1125000 },
@@ -259,12 +371,12 @@
 
 static struct acpu_level tbl_PVS1_1700MHz[] __initdata = {
 	{ 1, {   384000, PLL_8, 0, 0x00 }, L2(0),   950000 },
-	{ 1, {   486000, HFPLL, 2, 0x24 }, L2(6),   950000 },
-	{ 1, {   594000, HFPLL, 1, 0x16 }, L2(6),   950000 },
-	{ 1, {   702000, HFPLL, 1, 0x1A }, L2(6),   962500 },
-	{ 1, {   810000, HFPLL, 1, 0x1E }, L2(6),   975000 },
-	{ 1, {   918000, HFPLL, 1, 0x22 }, L2(6),  1000000 },
-	{ 1, {  1026000, HFPLL, 1, 0x26 }, L2(6),  1012500 },
+	{ 1, {   486000, HFPLL, 2, 0x24 }, L2(5),   950000 },
+	{ 1, {   594000, HFPLL, 1, 0x16 }, L2(5),   950000 },
+	{ 1, {   702000, HFPLL, 1, 0x1A }, L2(5),   962500 },
+	{ 1, {   810000, HFPLL, 1, 0x1E }, L2(5),   975000 },
+	{ 1, {   918000, HFPLL, 1, 0x22 }, L2(5),  1000000 },
+	{ 1, {  1026000, HFPLL, 1, 0x26 }, L2(5),  1012500 },
 	{ 1, {  1134000, HFPLL, 1, 0x2A }, L2(15), 1037500 },
 	{ 1, {  1242000, HFPLL, 1, 0x2E }, L2(15), 1050000 },
 	{ 1, {  1350000, HFPLL, 1, 0x32 }, L2(15), 1087500 },
@@ -277,12 +389,12 @@
 
 static struct acpu_level tbl_PVS2_1700MHz[] __initdata = {
 	{ 1, {   384000, PLL_8, 0, 0x00 }, L2(0),   925000 },
-	{ 1, {   486000, HFPLL, 2, 0x24 }, L2(6),   925000 },
-	{ 1, {   594000, HFPLL, 1, 0x16 }, L2(6),   925000 },
-	{ 1, {   702000, HFPLL, 1, 0x1A }, L2(6),   925000 },
-	{ 1, {   810000, HFPLL, 1, 0x1E }, L2(6),   937500 },
-	{ 1, {   918000, HFPLL, 1, 0x22 }, L2(6),   950000 },
-	{ 1, {  1026000, HFPLL, 1, 0x26 }, L2(6),   975000 },
+	{ 1, {   486000, HFPLL, 2, 0x24 }, L2(5),   925000 },
+	{ 1, {   594000, HFPLL, 1, 0x16 }, L2(5),   925000 },
+	{ 1, {   702000, HFPLL, 1, 0x1A }, L2(5),   925000 },
+	{ 1, {   810000, HFPLL, 1, 0x1E }, L2(5),   937500 },
+	{ 1, {   918000, HFPLL, 1, 0x22 }, L2(5),   950000 },
+	{ 1, {  1026000, HFPLL, 1, 0x26 }, L2(5),   975000 },
 	{ 1, {  1134000, HFPLL, 1, 0x2A }, L2(15), 1000000 },
 	{ 1, {  1242000, HFPLL, 1, 0x2E }, L2(15), 1012500 },
 	{ 1, {  1350000, HFPLL, 1, 0x32 }, L2(15), 1037500 },
@@ -295,12 +407,12 @@
 
 static struct acpu_level tbl_PVS3_1700MHz[] __initdata = {
 	{ 1, {   384000, PLL_8, 0, 0x00 }, L2(0),   900000 },
-	{ 1, {   486000, HFPLL, 2, 0x24 }, L2(6),   900000 },
-	{ 1, {   594000, HFPLL, 1, 0x16 }, L2(6),   900000 },
-	{ 1, {   702000, HFPLL, 1, 0x1A }, L2(6),   900000 },
-	{ 1, {   810000, HFPLL, 1, 0x1E }, L2(6),   900000 },
-	{ 1, {   918000, HFPLL, 1, 0x22 }, L2(6),   925000 },
-	{ 1, {  1026000, HFPLL, 1, 0x26 }, L2(6),   950000 },
+	{ 1, {   486000, HFPLL, 2, 0x24 }, L2(5),   900000 },
+	{ 1, {   594000, HFPLL, 1, 0x16 }, L2(5),   900000 },
+	{ 1, {   702000, HFPLL, 1, 0x1A }, L2(5),   900000 },
+	{ 1, {   810000, HFPLL, 1, 0x1E }, L2(5),   900000 },
+	{ 1, {   918000, HFPLL, 1, 0x22 }, L2(5),   925000 },
+	{ 1, {  1026000, HFPLL, 1, 0x26 }, L2(5),   950000 },
 	{ 1, {  1134000, HFPLL, 1, 0x2A }, L2(15),  975000 },
 	{ 1, {  1242000, HFPLL, 1, 0x2E }, L2(15),  987500 },
 	{ 1, {  1350000, HFPLL, 1, 0x32 }, L2(15), 1000000 },
@@ -313,12 +425,12 @@
 
 static struct acpu_level tbl_PVS4_1700MHz[] __initdata = {
 	{ 1, {   384000, PLL_8, 0, 0x00 }, L2(0),   875000 },
-	{ 1, {   486000, HFPLL, 2, 0x24 }, L2(6),   875000 },
-	{ 1, {   594000, HFPLL, 1, 0x16 }, L2(6),   875000 },
-	{ 1, {   702000, HFPLL, 1, 0x1A }, L2(6),   875000 },
-	{ 1, {   810000, HFPLL, 1, 0x1E }, L2(6),   887500 },
-	{ 1, {   918000, HFPLL, 1, 0x22 }, L2(6),   900000 },
-	{ 1, {  1026000, HFPLL, 1, 0x26 }, L2(6),   925000 },
+	{ 1, {   486000, HFPLL, 2, 0x24 }, L2(5),   875000 },
+	{ 1, {   594000, HFPLL, 1, 0x16 }, L2(5),   875000 },
+	{ 1, {   702000, HFPLL, 1, 0x1A }, L2(5),   875000 },
+	{ 1, {   810000, HFPLL, 1, 0x1E }, L2(5),   887500 },
+	{ 1, {   918000, HFPLL, 1, 0x22 }, L2(5),   900000 },
+	{ 1, {  1026000, HFPLL, 1, 0x26 }, L2(5),   925000 },
 	{ 1, {  1134000, HFPLL, 1, 0x2A }, L2(15),  950000 },
 	{ 1, {  1242000, HFPLL, 1, 0x2E }, L2(15),  962500 },
 	{ 1, {  1350000, HFPLL, 1, 0x32 }, L2(15),  975000 },
@@ -331,12 +443,12 @@
 
 static struct acpu_level tbl_PVS5_1700MHz[] __initdata = {
 	{ 1, {   384000, PLL_8, 0, 0x00 }, L2(0),   875000 },
-	{ 1, {   486000, HFPLL, 2, 0x24 }, L2(6),   875000 },
-	{ 1, {   594000, HFPLL, 1, 0x16 }, L2(6),   875000 },
-	{ 1, {   702000, HFPLL, 1, 0x1A }, L2(6),   875000 },
-	{ 1, {   810000, HFPLL, 1, 0x1E }, L2(6),   887500 },
-	{ 1, {   918000, HFPLL, 1, 0x22 }, L2(6),   900000 },
-	{ 1, {  1026000, HFPLL, 1, 0x26 }, L2(6),   925000 },
+	{ 1, {   486000, HFPLL, 2, 0x24 }, L2(5),   875000 },
+	{ 1, {   594000, HFPLL, 1, 0x16 }, L2(5),   875000 },
+	{ 1, {   702000, HFPLL, 1, 0x1A }, L2(5),   875000 },
+	{ 1, {   810000, HFPLL, 1, 0x1E }, L2(5),   887500 },
+	{ 1, {   918000, HFPLL, 1, 0x22 }, L2(5),   900000 },
+	{ 1, {  1026000, HFPLL, 1, 0x26 }, L2(5),   925000 },
 	{ 1, {  1134000, HFPLL, 1, 0x2A }, L2(15),  937500 },
 	{ 1, {  1242000, HFPLL, 1, 0x2E }, L2(15),  950000 },
 	{ 1, {  1350000, HFPLL, 1, 0x32 }, L2(15),  962500 },
@@ -349,12 +461,12 @@
 
 static struct acpu_level tbl_PVS6_1700MHz[] __initdata = {
 	{ 1, {   384000, PLL_8, 0, 0x00 }, L2(0),   875000 },
-	{ 1, {   486000, HFPLL, 2, 0x24 }, L2(6),   875000 },
-	{ 1, {   594000, HFPLL, 1, 0x16 }, L2(6),   875000 },
-	{ 1, {   702000, HFPLL, 1, 0x1A }, L2(6),   875000 },
-	{ 1, {   810000, HFPLL, 1, 0x1E }, L2(6),   887500 },
-	{ 1, {   918000, HFPLL, 1, 0x22 }, L2(6),   900000 },
-	{ 1, {  1026000, HFPLL, 1, 0x26 }, L2(6),   925000 },
+	{ 1, {   486000, HFPLL, 2, 0x24 }, L2(5),   875000 },
+	{ 1, {   594000, HFPLL, 1, 0x16 }, L2(5),   875000 },
+	{ 1, {   702000, HFPLL, 1, 0x1A }, L2(5),   875000 },
+	{ 1, {   810000, HFPLL, 1, 0x1E }, L2(5),   887500 },
+	{ 1, {   918000, HFPLL, 1, 0x22 }, L2(5),   900000 },
+	{ 1, {  1026000, HFPLL, 1, 0x26 }, L2(5),   925000 },
 	{ 1, {  1134000, HFPLL, 1, 0x2A }, L2(15),  937500 },
 	{ 1, {  1242000, HFPLL, 1, 0x2E }, L2(15),  950000 },
 	{ 1, {  1350000, HFPLL, 1, 0x32 }, L2(15),  962500 },
@@ -367,12 +479,12 @@
 
 static struct acpu_level tbl_PVS0_2000MHz[] __initdata = {
 	{ 1, {   384000, PLL_8, 0, 0x00 }, L2(0),   950000 },
-	{ 1, {   486000, HFPLL, 2, 0x24 }, L2(6),   950000 },
-	{ 1, {   594000, HFPLL, 1, 0x16 }, L2(6),   950000 },
-	{ 1, {   702000, HFPLL, 1, 0x1A }, L2(6),   950000 },
-	{ 1, {   810000, HFPLL, 1, 0x1E }, L2(6),   962500 },
-	{ 1, {   918000, HFPLL, 1, 0x22 }, L2(6),   975000 },
-	{ 1, {  1026000, HFPLL, 1, 0x26 }, L2(6),  1000000 },
+	{ 1, {   486000, HFPLL, 2, 0x24 }, L2(5),   950000 },
+	{ 1, {   594000, HFPLL, 1, 0x16 }, L2(5),   950000 },
+	{ 1, {   702000, HFPLL, 1, 0x1A }, L2(5),   950000 },
+	{ 1, {   810000, HFPLL, 1, 0x1E }, L2(5),   962500 },
+	{ 1, {   918000, HFPLL, 1, 0x22 }, L2(5),   975000 },
+	{ 1, {  1026000, HFPLL, 1, 0x26 }, L2(5),  1000000 },
 	{ 1, {  1134000, HFPLL, 1, 0x2A }, L2(15), 1025000 },
 	{ 1, {  1242000, HFPLL, 1, 0x2E }, L2(15), 1037500 },
 	{ 1, {  1350000, HFPLL, 1, 0x32 }, L2(15), 1062500 },
@@ -386,12 +498,12 @@
 
 static struct acpu_level tbl_PVS1_2000MHz[] __initdata = {
 	{ 1, {   384000, PLL_8, 0, 0x00 }, L2(0),   925000 },
-	{ 1, {   486000, HFPLL, 2, 0x24 }, L2(6),   925000 },
-	{ 1, {   594000, HFPLL, 1, 0x16 }, L2(6),   925000 },
-	{ 1, {   702000, HFPLL, 1, 0x1A }, L2(6),   925000 },
-	{ 1, {   810000, HFPLL, 1, 0x1E }, L2(6),   937500 },
-	{ 1, {   918000, HFPLL, 1, 0x22 }, L2(6),   950000 },
-	{ 1, {  1026000, HFPLL, 1, 0x26 }, L2(6),   975000 },
+	{ 1, {   486000, HFPLL, 2, 0x24 }, L2(5),   925000 },
+	{ 1, {   594000, HFPLL, 1, 0x16 }, L2(5),   925000 },
+	{ 1, {   702000, HFPLL, 1, 0x1A }, L2(5),   925000 },
+	{ 1, {   810000, HFPLL, 1, 0x1E }, L2(5),   937500 },
+	{ 1, {   918000, HFPLL, 1, 0x22 }, L2(5),   950000 },
+	{ 1, {  1026000, HFPLL, 1, 0x26 }, L2(5),   975000 },
 	{ 1, {  1134000, HFPLL, 1, 0x2A }, L2(15), 1000000 },
 	{ 1, {  1242000, HFPLL, 1, 0x2E }, L2(15), 1012500 },
 	{ 1, {  1350000, HFPLL, 1, 0x32 }, L2(15), 1037500 },
@@ -405,12 +517,12 @@
 
 static struct acpu_level tbl_PVS2_2000MHz[] __initdata = {
 	{ 1, {   384000, PLL_8, 0, 0x00 }, L2(0),   900000 },
-	{ 1, {   486000, HFPLL, 2, 0x24 }, L2(6),   900000 },
-	{ 1, {   594000, HFPLL, 1, 0x16 }, L2(6),   900000 },
-	{ 1, {   702000, HFPLL, 1, 0x1A }, L2(6),   900000 },
-	{ 1, {   810000, HFPLL, 1, 0x1E }, L2(6),   912500 },
-	{ 1, {   918000, HFPLL, 1, 0x22 }, L2(6),   925000 },
-	{ 1, {  1026000, HFPLL, 1, 0x26 }, L2(6),   950000 },
+	{ 1, {   486000, HFPLL, 2, 0x24 }, L2(5),   900000 },
+	{ 1, {   594000, HFPLL, 1, 0x16 }, L2(5),   900000 },
+	{ 1, {   702000, HFPLL, 1, 0x1A }, L2(5),   900000 },
+	{ 1, {   810000, HFPLL, 1, 0x1E }, L2(5),   912500 },
+	{ 1, {   918000, HFPLL, 1, 0x22 }, L2(5),   925000 },
+	{ 1, {  1026000, HFPLL, 1, 0x26 }, L2(5),   950000 },
 	{ 1, {  1134000, HFPLL, 1, 0x2A }, L2(15),  975000 },
 	{ 1, {  1242000, HFPLL, 1, 0x2E }, L2(15),  987500 },
 	{ 1, {  1350000, HFPLL, 1, 0x32 }, L2(15), 1012500 },
@@ -424,12 +536,12 @@
 
 static struct acpu_level tbl_PVS3_2000MHz[] __initdata = {
 	{ 1, {   384000, PLL_8, 0, 0x00 }, L2(0),   900000 },
-	{ 1, {   486000, HFPLL, 2, 0x24 }, L2(6),   900000 },
-	{ 1, {   594000, HFPLL, 1, 0x16 }, L2(6),   900000 },
-	{ 1, {   702000, HFPLL, 1, 0x1A }, L2(6),   900000 },
-	{ 1, {   810000, HFPLL, 1, 0x1E }, L2(6),   900000 },
-	{ 1, {   918000, HFPLL, 1, 0x22 }, L2(6),   912500 },
-	{ 1, {  1026000, HFPLL, 1, 0x26 }, L2(6),   937500 },
+	{ 1, {   486000, HFPLL, 2, 0x24 }, L2(5),   900000 },
+	{ 1, {   594000, HFPLL, 1, 0x16 }, L2(5),   900000 },
+	{ 1, {   702000, HFPLL, 1, 0x1A }, L2(5),   900000 },
+	{ 1, {   810000, HFPLL, 1, 0x1E }, L2(5),   900000 },
+	{ 1, {   918000, HFPLL, 1, 0x22 }, L2(5),   912500 },
+	{ 1, {  1026000, HFPLL, 1, 0x26 }, L2(5),   937500 },
 	{ 1, {  1134000, HFPLL, 1, 0x2A }, L2(15),  962500 },
 	{ 1, {  1242000, HFPLL, 1, 0x2E }, L2(15),  975000 },
 	{ 1, {  1350000, HFPLL, 1, 0x32 }, L2(15), 1000000 },
@@ -443,12 +555,12 @@
 
 static struct acpu_level tbl_PVS4_2000MHz[] __initdata = {
 	{ 1, {   384000, PLL_8, 0, 0x00 }, L2(0),   875000 },
-	{ 1, {   486000, HFPLL, 2, 0x24 }, L2(6),   875000 },
-	{ 1, {   594000, HFPLL, 1, 0x16 }, L2(6),   875000 },
-	{ 1, {   702000, HFPLL, 1, 0x1A }, L2(6),   875000 },
-	{ 1, {   810000, HFPLL, 1, 0x1E }, L2(6),   887500 },
-	{ 1, {   918000, HFPLL, 1, 0x22 }, L2(6),   900000 },
-	{ 1, {  1026000, HFPLL, 1, 0x26 }, L2(6),   925000 },
+	{ 1, {   486000, HFPLL, 2, 0x24 }, L2(5),   875000 },
+	{ 1, {   594000, HFPLL, 1, 0x16 }, L2(5),   875000 },
+	{ 1, {   702000, HFPLL, 1, 0x1A }, L2(5),   875000 },
+	{ 1, {   810000, HFPLL, 1, 0x1E }, L2(5),   887500 },
+	{ 1, {   918000, HFPLL, 1, 0x22 }, L2(5),   900000 },
+	{ 1, {  1026000, HFPLL, 1, 0x26 }, L2(5),   925000 },
 	{ 1, {  1134000, HFPLL, 1, 0x2A }, L2(15),  950000 },
 	{ 1, {  1242000, HFPLL, 1, 0x2E }, L2(15),  962500 },
 	{ 1, {  1350000, HFPLL, 1, 0x32 }, L2(15),  975000 },
@@ -462,12 +574,12 @@
 
 static struct acpu_level tbl_PVS5_2000MHz[] __initdata = {
 	{ 1, {   384000, PLL_8, 0, 0x00 }, L2(0),   875000 },
-	{ 1, {   486000, HFPLL, 2, 0x24 }, L2(6),   875000 },
-	{ 1, {   594000, HFPLL, 1, 0x16 }, L2(6),   875000 },
-	{ 1, {   702000, HFPLL, 1, 0x1A }, L2(6),   875000 },
-	{ 1, {   810000, HFPLL, 1, 0x1E }, L2(6),   887500 },
-	{ 1, {   918000, HFPLL, 1, 0x22 }, L2(6),   900000 },
-	{ 1, {  1026000, HFPLL, 1, 0x26 }, L2(6),   925000 },
+	{ 1, {   486000, HFPLL, 2, 0x24 }, L2(5),   875000 },
+	{ 1, {   594000, HFPLL, 1, 0x16 }, L2(5),   875000 },
+	{ 1, {   702000, HFPLL, 1, 0x1A }, L2(5),   875000 },
+	{ 1, {   810000, HFPLL, 1, 0x1E }, L2(5),   887500 },
+	{ 1, {   918000, HFPLL, 1, 0x22 }, L2(5),   900000 },
+	{ 1, {  1026000, HFPLL, 1, 0x26 }, L2(5),   925000 },
 	{ 1, {  1134000, HFPLL, 1, 0x2A }, L2(15),  937500 },
 	{ 1, {  1242000, HFPLL, 1, 0x2E }, L2(15),  950000 },
 	{ 1, {  1350000, HFPLL, 1, 0x32 }, L2(15),  962500 },
@@ -481,12 +593,12 @@
 
 static struct acpu_level tbl_PVS6_2000MHz[] __initdata = {
 	{ 1, {   384000, PLL_8, 0, 0x00 }, L2(0),   875000 },
-	{ 1, {   486000, HFPLL, 2, 0x24 }, L2(6),   875000 },
-	{ 1, {   594000, HFPLL, 1, 0x16 }, L2(6),   875000 },
-	{ 1, {   702000, HFPLL, 1, 0x1A }, L2(6),   875000 },
-	{ 1, {   810000, HFPLL, 1, 0x1E }, L2(6),   887500 },
-	{ 1, {   918000, HFPLL, 1, 0x22 }, L2(6),   900000 },
-	{ 1, {  1026000, HFPLL, 1, 0x26 }, L2(6),   925000 },
+	{ 1, {   486000, HFPLL, 2, 0x24 }, L2(5),   875000 },
+	{ 1, {   594000, HFPLL, 1, 0x16 }, L2(5),   875000 },
+	{ 1, {   702000, HFPLL, 1, 0x1A }, L2(5),   875000 },
+	{ 1, {   810000, HFPLL, 1, 0x1E }, L2(5),   887500 },
+	{ 1, {   918000, HFPLL, 1, 0x22 }, L2(5),   900000 },
+	{ 1, {  1026000, HFPLL, 1, 0x26 }, L2(5),   925000 },
 	{ 1, {  1134000, HFPLL, 1, 0x2A }, L2(15),  937500 },
 	{ 1, {  1242000, HFPLL, 1, 0x2E }, L2(15),  950000 },
 	{ 1, {  1350000, HFPLL, 1, 0x32 }, L2(15),  962500 },
@@ -519,6 +631,14 @@
 	[2][4] = { tbl_PVS4_2000MHz, sizeof(tbl_PVS4_2000MHz),     25000 },
 	[2][5] = { tbl_PVS5_2000MHz, sizeof(tbl_PVS5_2000MHz),     25000 },
 	[2][6] = { tbl_PVS6_2000MHz, sizeof(tbl_PVS6_2000MHz),     25000 },
+
+	[14][0] = { tbl_PVS0_1512MHz, sizeof(tbl_PVS0_1512MHz),     0 },
+	[14][1] = { tbl_PVS1_1512MHz, sizeof(tbl_PVS1_1512MHz),     25000 },
+	[14][2] = { tbl_PVS2_1512MHz, sizeof(tbl_PVS2_1512MHz),     25000 },
+	[14][3] = { tbl_PVS3_1512MHz, sizeof(tbl_PVS3_1512MHz),     25000 },
+	[14][4] = { tbl_PVS4_1512MHz, sizeof(tbl_PVS4_1512MHz),     25000 },
+	[14][5] = { tbl_PVS5_1512MHz, sizeof(tbl_PVS5_1512MHz),     25000 },
+	[14][6] = { tbl_PVS6_1512MHz, sizeof(tbl_PVS6_1512MHz),     25000 },
 };
 
 static struct acpuclk_krait_params acpuclk_8064_params __initdata = {
diff --git a/arch/arm/mach-msm/board-8064-gpiomux.c b/arch/arm/mach-msm/board-8064-gpiomux.c
index 9e34f47..67760ee 100644
--- a/arch/arm/mach-msm/board-8064-gpiomux.c
+++ b/arch/arm/mach-msm/board-8064-gpiomux.c
@@ -917,38 +917,38 @@
 
 static struct gpiomux_setting ap2mdm_cfg = {
 	.func = GPIOMUX_FUNC_GPIO,
-	.drv = GPIOMUX_DRV_8MA,
+	.drv = GPIOMUX_DRV_4MA,
 	.pull = GPIOMUX_PULL_DOWN,
 };
 
 static struct gpiomux_setting mdm2ap_status_cfg = {
 	.func = GPIOMUX_FUNC_GPIO,
-	.drv = GPIOMUX_DRV_8MA,
+	.drv = GPIOMUX_DRV_2MA,
 	.pull = GPIOMUX_PULL_DOWN,
 };
 
 static struct gpiomux_setting mdm2ap_errfatal_cfg = {
 	.func = GPIOMUX_FUNC_GPIO,
-	.drv = GPIOMUX_DRV_16MA,
+	.drv = GPIOMUX_DRV_2MA,
 	.pull = GPIOMUX_PULL_DOWN,
 };
 
 static struct gpiomux_setting mdm2ap_pblrdy = {
 	.func = GPIOMUX_FUNC_GPIO,
-	.drv = GPIOMUX_DRV_16MA,
+	.drv = GPIOMUX_DRV_2MA,
 	.pull = GPIOMUX_PULL_DOWN,
 };
 
 
 static struct gpiomux_setting ap2mdm_soft_reset_cfg = {
 	.func = GPIOMUX_FUNC_GPIO,
-	.drv = GPIOMUX_DRV_8MA,
+	.drv = GPIOMUX_DRV_4MA,
 	.pull = GPIOMUX_PULL_DOWN,
 };
 
 static struct gpiomux_setting ap2mdm_wakeup = {
 	.func = GPIOMUX_FUNC_GPIO,
-	.drv = GPIOMUX_DRV_8MA,
+	.drv = GPIOMUX_DRV_4MA,
 	.pull = GPIOMUX_PULL_DOWN,
 };
 
diff --git a/arch/arm/mach-msm/board-8064-pmic.c b/arch/arm/mach-msm/board-8064-pmic.c
index f6dd2ea..aef937a 100644
--- a/arch/arm/mach-msm/board-8064-pmic.c
+++ b/arch/arm/mach-msm/board-8064-pmic.c
@@ -183,6 +183,8 @@
 /* Initial PM8XXX MPP configurations */
 static struct pm8xxx_mpp_init pm8xxx_mpps[] __initdata = {
 	PM8921_MPP_INIT(3, D_OUTPUT, PM8921_MPP_DIG_LEVEL_VPH, DOUT_CTRL_LOW),
+	/* External 5V regulator enable; shared by HDMI and USB_OTG switches. */
+	PM8921_MPP_INIT(7, D_OUTPUT, PM8921_MPP_DIG_LEVEL_VPH, DOUT_CTRL_LOW),
 	PM8921_MPP_INIT(8, D_OUTPUT, PM8921_MPP_DIG_LEVEL_S4, DOUT_CTRL_LOW),
 	/*MPP9 is used to detect docking station connection/removal on Liquid*/
 	PM8921_MPP_INIT(9, D_INPUT, PM8921_MPP_DIG_LEVEL_S4, DIN_TO_INT),
diff --git a/arch/arm/mach-msm/board-8064-regulator.c b/arch/arm/mach-msm/board-8064-regulator.c
index 1a8e7e4..16b53fb 100644
--- a/arch/arm/mach-msm/board-8064-regulator.c
+++ b/arch/arm/mach-msm/board-8064-regulator.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011-2012, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2011-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -190,6 +190,7 @@
 	REGULATOR_SUPPLY("vddp",		"0-0048"),
 	REGULATOR_SUPPLY("hdmi_lvl_tsl",	"hdmi_msm.0"),
 	REGULATOR_SUPPLY("vdd-io",		"spi0.2"),
+	REGULATOR_SUPPLY("sata_pmp_pwr",	"msm_sata.0"),
 };
 VREG_CONSUMERS(S5) = {
 	REGULATOR_SUPPLY("8921_s5",		NULL),
@@ -260,12 +261,15 @@
 	REGULATOR_SUPPLY("dsi1_vccs_3p3v",      "mipi_dsi.1"),
 	REGULATOR_SUPPLY("hdmi_mux_vdd",        "hdmi_msm.0"),
 	REGULATOR_SUPPLY("pcie_ext_3p3v",       "msm_pcie"),
-	REGULATOR_SUPPLY("sata_ext_3p3v",       "ahci.0"),
 };
 VREG_CONSUMERS(EXT_TS_SW) = {
 	REGULATOR_SUPPLY("ext_ts_sw",		NULL),
 	REGULATOR_SUPPLY("vdd_ana",		"3-005b"),
 };
+VREG_CONSUMERS(EXT_SATA_PWR) = {
+	REGULATOR_SUPPLY("ext_sata_pwr",	NULL),
+	REGULATOR_SUPPLY("sata_ext_3p3v",       "msm_sata.0"),
+};
 VREG_CONSUMERS(AVC_1P2V) = {
 	REGULATOR_SUPPLY("avc_1p2v",	NULL),
 };
@@ -299,7 +303,6 @@
 };
 VREG_CONSUMERS(EXT_5V) = {
 	REGULATOR_SUPPLY("ext_5v",		NULL),
-	REGULATOR_SUPPLY("ext_ddr3",		NULL),
 	REGULATOR_SUPPLY("vbus",		"msm_ehci_host.0"),
 };
 
@@ -437,7 +440,8 @@
 		.pin_ctrl	= _pin_ctrl, \
 	}
 
-#define GPIO_VREG(_id, _reg_name, _gpio_label, _gpio, _supply_regulator) \
+#define GPIO_VREG(_id, _reg_name, _gpio_label, _gpio, _supply_regulator, \
+		_active_low) \
 	[GPIO_VREG_ID_##_id] = { \
 		.init_data = { \
 			.constraints = { \
@@ -451,6 +455,7 @@
 		.regulator_name = _reg_name, \
 		.gpio_label	= _gpio_label, \
 		.gpio		= _gpio, \
+		.active_low	= _active_low, \
 	}
 
 #define SAW_VREG_INIT(_id, _name, _min_uV, _max_uV) \
@@ -566,25 +571,30 @@
 /* GPIO regulator constraints */
 struct gpio_regulator_platform_data
 apq8064_gpio_regulator_pdata[] __devinitdata = {
-	/*        ID      vreg_name gpio_label   gpio                  supply */
-	GPIO_VREG(EXT_5V, "ext_5v", "ext_5v_en", PM8921_MPP_PM_TO_SYS(7), NULL),
+	/*        ID      vreg_name gpio_label   gpio   supply   active_low */
+	GPIO_VREG(EXT_5V, "ext_5v", "ext_5v_en",
+			PM8921_MPP_PM_TO_SYS(7), NULL, 0),
 	GPIO_VREG(EXT_3P3V, "ext_3p3v", "ext_3p3v_en",
-		  APQ8064_EXT_3P3V_REG_EN_GPIO, NULL),
+		  APQ8064_EXT_3P3V_REG_EN_GPIO, NULL, 0),
 	GPIO_VREG(EXT_TS_SW, "ext_ts_sw", "ext_ts_sw_en",
-		  PM8921_GPIO_PM_TO_SYS(23), "ext_3p3v"),
+		  PM8921_GPIO_PM_TO_SYS(23), "ext_3p3v", 0),
 	GPIO_VREG(EXT_MPP8, "ext_mpp8", "ext_mpp8_en",
-			PM8921_MPP_PM_TO_SYS(8), NULL),
+			PM8921_MPP_PM_TO_SYS(8), NULL, 0),
+	GPIO_VREG(EXT_SATA_PWR, "ext_sata_pwr", "ext_sata_pwr_en",
+			PM8921_MPP_PM_TO_SYS(4), "ext_3p3v", 1),
 };
 
 struct gpio_regulator_platform_data
 mpq8064_gpio_regulator_pdata[] __devinitdata = {
-	GPIO_VREG(AVC_1P2V, "avc_1p2v", "avc_1p2v_en", SX150X_GPIO(4, 2), NULL),
-	GPIO_VREG(AVC_1P8V, "avc_1p8v", "avc_1p8v_en", SX150X_GPIO(4, 4), NULL),
+	GPIO_VREG(AVC_1P2V, "avc_1p2v", "avc_1p2v_en",
+			SX150X_GPIO(4, 2), NULL, 0),
+	GPIO_VREG(AVC_1P8V, "avc_1p8v", "avc_1p8v_en",
+			SX150X_GPIO(4, 4), NULL, 0),
 	GPIO_VREG(AVC_2P2V, "avc_2p2v", "avc_2p2v_en",
-						 SX150X_GPIO(4, 14), NULL),
-	GPIO_VREG(AVC_5V, "avc_5v", "avc_5v_en", SX150X_GPIO(4, 3), NULL),
+						 SX150X_GPIO(4, 14), NULL, 0),
+	GPIO_VREG(AVC_5V, "avc_5v", "avc_5v_en", SX150X_GPIO(4, 3), NULL, 0),
 	GPIO_VREG(AVC_3P3V, "avc_3p3v", "avc_3p3v_en",
-					SX150X_GPIO(4, 15), "avc_5v"),
+					SX150X_GPIO(4, 15), "avc_5v", 0),
 };
 
 /* SAW regulator constraints */
diff --git a/arch/arm/mach-msm/board-8064.c b/arch/arm/mach-msm/board-8064.c
index f782dfe..3fe0838 100644
--- a/arch/arm/mach-msm/board-8064.c
+++ b/arch/arm/mach-msm/board-8064.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011-2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2011-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -10,6 +10,7 @@
  * GNU General Public License for more details.
  *
  */
+#include <linux/err.h>
 #include <linux/kernel.h>
 #include <linux/bitops.h>
 #include <linux/platform_device.h>
@@ -2072,7 +2073,8 @@
 {
 	msm_shared_ram_phys = MSM_SHARED_RAM_PHYS;
 	msm_map_apq8064_io();
-	if (socinfo_init() < 0)
+
+	if (IS_ERR_OR_NULL(socinfo_init()))
 		pr_err("socinfo_init() failed!\n");
 }
 
@@ -2528,6 +2530,16 @@
 	},
 };
 
+static struct platform_device
+apq8064_device_ext_3p3v_mpp4_vreg __devinitdata = {
+	.name	= GPIO_REGULATOR_DEV_NAME,
+	.id	= PM8921_MPP_PM_TO_SYS(4),
+	.dev	= {
+		.platform_data =
+		&apq8064_gpio_regulator_pdata[GPIO_VREG_ID_EXT_SATA_PWR],
+	},
+};
+
 static struct platform_device apq8064_device_rpm_regulator __devinitdata = {
 	.name	= "rpm-regulator",
 	.id	= 0,
@@ -3538,20 +3550,6 @@
 
 }
 
-static void enable_ddr3_regulator(void)
-{
-	static struct regulator *ext_ddr3;
-
-	/* Use MPP7 output state as a flag for PCDDR3 presence. */
-	if (gpio_get_value_cansleep(PM8921_MPP_PM_TO_SYS(7)) > 0) {
-		ext_ddr3 = regulator_get(NULL, "ext_ddr3");
-		if (IS_ERR(ext_ddr3) || ext_ddr3 == NULL)
-			pr_err("Could not get MPP7 regulator\n");
-		else
-			regulator_enable(ext_ddr3);
-	}
-}
-
 static void enable_avc_i2c_bus(void)
 {
 	int avc_i2c_en_mpp = PM8921_MPP_PM_TO_SYS(8);
@@ -3582,7 +3580,7 @@
 	platform_device_register(&msm_gpio_device);
 	msm_tsens_early_init(&apq_tsens_pdata);
 	msm_thermal_init(&msm_thermal_pdata);
-	if (socinfo_init() < 0)
+	if (IS_ERR_OR_NULL(socinfo_init()))
 		pr_err("socinfo_init() failed!\n");
 	BUG_ON(msm_rpm_init(&apq8064_rpm_data));
 	BUG_ON(msm_rpmrs_levels_init(&msm_rpmrs_data));
@@ -3656,7 +3654,6 @@
 			ARRAY_SIZE(common_i2s_devices));
 	}
 
-	enable_ddr3_regulator();
 	rpmrs_level =
 		msm_rpmrs_levels[MSM_PM_SLEEP_MODE_WAIT_FOR_INTERRUPT];
 	msm_hsic_pdata.swfi_latency = rpmrs_level.latency_us;
@@ -3774,6 +3771,23 @@
 	if (machine_is_mpq8064_cdp() || machine_is_mpq8064_hrd() ||
 		machine_is_mpq8064_dtv())
 		platform_device_register(&msm_dev_avtimer_device);
+
+	if (machine_is_apq8064_cdp() || machine_is_mpq8064_hrd()) {
+		int ret;
+		struct pm8xxx_mpp_config_data sata_pwr_cfg = {
+			.type = PM8XXX_MPP_TYPE_D_OUTPUT,
+			.level = PM8921_MPP_DIG_LEVEL_VPH,
+			.control = PM8XXX_MPP_DOUT_CTRL_HIGH,
+		};
+
+		/* Apply MPP-4 init only when it is used to control SATA PWR */
+		ret = pm8xxx_mpp_config(PM8921_MPP_PM_TO_SYS(4), &sata_pwr_cfg);
+		if (ret)
+			pr_err("%s: pm8921 MPP %d init config failed(%d)\n",
+					__func__, PM8921_MPP_PM_TO_SYS(4), ret);
+		platform_device_register(&apq8064_device_ext_3p3v_mpp4_vreg);
+		platform_device_register(&apq8064_device_sata);
+	}
 }
 
 MACHINE_START(APQ8064_CDP, "QCT APQ8064 CDP")
diff --git a/arch/arm/mach-msm/board-8064.h b/arch/arm/mach-msm/board-8064.h
index 2bc0981..4cdf939 100644
--- a/arch/arm/mach-msm/board-8064.h
+++ b/arch/arm/mach-msm/board-8064.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011-2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2011-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -16,7 +16,6 @@
 #include <linux/regulator/msm-gpio-regulator.h>
 #include <linux/mfd/pm8xxx/pm8921.h>
 #include <linux/mfd/pm8xxx/pm8821.h>
-#include <linux/ahci_platform.h>
 #include <mach/msm_memtypes.h>
 #include <mach/irqs.h>
 #include <mach/rpm-regulator.h>
@@ -50,6 +49,7 @@
 #define GPIO_VREG_ID_EXT_3P3V		1
 #define GPIO_VREG_ID_EXT_TS_SW		2
 #define GPIO_VREG_ID_EXT_MPP8		3
+#define GPIO_VREG_ID_EXT_SATA_PWR	4
 
 #define GPIO_VREG_ID_AVC_1P2V		0
 #define GPIO_VREG_ID_AVC_1P8V		1
@@ -81,7 +81,6 @@
 		struct mmc_platform_data *plat);
 
 void apq8064_init_mmc(void);
-int __init apq8064_add_ahci(struct ahci_platform_data *platd);
 void apq8064_init_gpiomux(void);
 void apq8064_init_pmic(void);
 
diff --git a/arch/arm/mach-msm/board-8092.c b/arch/arm/mach-msm/board-8092.c
index cbd257f..c7d01bf 100644
--- a/arch/arm/mach-msm/board-8092.c
+++ b/arch/arm/mach-msm/board-8092.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -10,6 +10,7 @@
  * GNU General Public License for more details.
  */
 
+#include <linux/err.h>
 #include <linux/kernel.h>
 #include <linux/errno.h>
 #include <linux/of.h>
@@ -78,9 +79,6 @@
 static void __init mpq8092_map_io(void)
 {
 	msm_map_mpq8092_io();
-	if (socinfo_init() < 0)
-		pr_err("%s: socinfo_init() failed\n", __func__);
-
 }
 
 static struct of_dev_auxdata mpq8092_auxdata_lookup[] __initdata = {
@@ -98,6 +96,11 @@
 static void __init mpq8092_init(void)
 {
 	struct of_dev_auxdata *adata = mpq8092_auxdata_lookup;
+	struct device *parent;
+
+	parent = socinfo_init();
+	if (IS_ERR_OR_NULL(parent))
+		pr_err("%s: socinfo_init() failed\n", __func__);
 
 	mpq8092_init_gpiomux();
 	msm_clock_init(&mpq8092_clock_init_data);
diff --git a/arch/arm/mach-msm/board-8226-gpiomux.c b/arch/arm/mach-msm/board-8226-gpiomux.c
index 7a53b24..e58cee7 100644
--- a/arch/arm/mach-msm/board-8226-gpiomux.c
+++ b/arch/arm/mach-msm/board-8226-gpiomux.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -25,11 +25,6 @@
 	.drv = GPIOMUX_DRV_2MA,
 	.func = GPIOMUX_FUNC_GPIO,
 };
-static struct gpiomux_setting gpio_spi_config = {
-	.func = GPIOMUX_FUNC_1,
-	.drv = GPIOMUX_DRV_8MA,
-	.pull = GPIOMUX_PULL_NONE,
-};
 
 static struct msm_gpiomux_config msm_eth_configs[] = {
 	{
@@ -39,6 +34,19 @@
 		}
 	},
 };
+#endif
+
+static struct gpiomux_setting gpio_spi_config = {
+	.func = GPIOMUX_FUNC_1,
+	.drv = GPIOMUX_DRV_8MA,
+	.pull = GPIOMUX_PULL_NONE,
+};
+
+static struct gpiomux_setting gpio_i2c_config = {
+	.func = GPIOMUX_FUNC_3,
+	.drv = GPIOMUX_DRV_2MA,
+	.pull = GPIOMUX_PULL_NONE,
+};
 
 static struct msm_gpiomux_config msm_blsp_configs[] __initdata = {
 	{
@@ -65,8 +73,19 @@
 			[GPIOMUX_SUSPENDED] = &gpio_spi_config,
 		},
 	},
+	{
+		.gpio      = 14,		/* BLSP-1 QUP-4 I2C_SDA */
+		.settings = {
+			[GPIOMUX_SUSPENDED] = &gpio_i2c_config,
+		},
+	},
+	{
+		.gpio      = 15,		/* BLSP-1 QUP-4 I2C_SCL */
+		.settings = {
+			[GPIOMUX_SUSPENDED] = &gpio_i2c_config,
+		},
+	},
 };
-#endif
 
 void __init msm8226_init_gpiomux(void)
 {
@@ -77,8 +96,10 @@
 		pr_err("%s failed %d\n", __func__, rc);
 		return;
 	}
+
 #if defined(CONFIG_KS8851) || defined(CONFIG_KS8851_MODULE)
 	msm_gpiomux_install(msm_eth_configs, ARRAY_SIZE(msm_eth_configs));
-	msm_gpiomux_install(msm_blsp_configs, ARRAY_SIZE(msm_blsp_configs));
 #endif
+
+	msm_gpiomux_install(msm_blsp_configs, ARRAY_SIZE(msm_blsp_configs));
 }
diff --git a/arch/arm/mach-msm/board-8226.c b/arch/arm/mach-msm/board-8226.c
index 2f2eb2c..0f8bfd4 100644
--- a/arch/arm/mach-msm/board-8226.c
+++ b/arch/arm/mach-msm/board-8226.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -10,6 +10,7 @@
  * GNU General Public License for more details.
  */
 
+#include <linux/err.h>
 #include <linux/kernel.h>
 #include <linux/errno.h>
 #include <linux/platform_device.h>
@@ -61,6 +62,8 @@
 	return MEMTYPE_EBI1;
 }
 static struct clk_lookup msm_clocks_dummy[] = {
+	CLK_DUMMY("core_clk",   NULL,           "f9926000.i2c", OFF),
+	CLK_DUMMY("iface_clk",  NULL,           "f9926000.i2c", OFF),
 	CLK_DUMMY("core_clk",   BLSP1_UART_CLK, "f991f000.serial", OFF),
 	CLK_DUMMY("iface_clk",  BLSP1_UART_CLK, "f991f000.serial", OFF),
 	CLK_DUMMY("iface_clk",  HSUSB_IFACE_CLK, "f9a55000.usb", OFF),
@@ -75,6 +78,18 @@
 	CLK_DUMMY("bus_clk",	NULL,		"msm_sdcc.2", OFF),
 	CLK_DUMMY("core_clk",	NULL,		"f9928000.spi", OFF),
 	CLK_DUMMY("iface_clk",	NULL,		"f9928000.spi", OFF),
+	CLK_DUMMY("iface_clk",		NULL, "fda64000.qcom,iommu", OFF),
+	CLK_DUMMY("core_clk",		NULL, "fda64000.qcom,iommu", OFF),
+	CLK_DUMMY("iface_clk",		NULL, "fda44000.qcom,iommu", OFF),
+	CLK_DUMMY("core_clk",		NULL, "fda44000.qcom,iommu", OFF),
+	CLK_DUMMY("iface_clk",		NULL, "fd928000.qcom,iommu", OFF),
+	CLK_DUMMY("core_clk",		NULL, "fd928000.qcom,iommu", OFF),
+	CLK_DUMMY("core_clk",		NULL, "fdb10000.qcom,iommu", OFF),
+	CLK_DUMMY("iface_clk",		NULL, "fdb10000.qcom,iommu", OFF),
+	CLK_DUMMY("alt_core_clk",	NULL, "fdb10000.qcom,iommu", OFF),
+	CLK_DUMMY("iface_clk",		NULL, "fdc84000.qcom,iommu", OFF),
+	CLK_DUMMY("alt_core_clk",	NULL, "fdc84000.qcom,iommu", OFF),
+	CLK_DUMMY("core_clk",		NULL, "fdc84000.qcom,iommu", OFF),
 };
 
 static struct clock_init_data msm_dummy_clock_init_data __initdata = {
@@ -109,14 +124,15 @@
 void __init msm8226_init(void)
 {
 	struct of_dev_auxdata *adata = msm8226_auxdata_lookup;
+	struct device *parent;
+
+	parent = socinfo_init();
+	if (IS_ERR_OR_NULL(parent))
+		pr_err("%s: socinfo_init() failed\n", __func__);
 
 	msm8226_init_gpiomux();
 
 	msm_clock_init(&msm_dummy_clock_init_data);
-
-	if (socinfo_init() < 0)
-		pr_err("%s: socinfo_init() failed\n", __func__);
-
 	of_platform_populate(NULL, of_default_bus_match_table, adata, NULL);
 }
 
diff --git a/arch/arm/mach-msm/board-8910.c b/arch/arm/mach-msm/board-8910.c
index 2ff4567..f779c1f 100644
--- a/arch/arm/mach-msm/board-8910.c
+++ b/arch/arm/mach-msm/board-8910.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -10,6 +10,7 @@
  * GNU General Public License for more details.
  */
 
+#include <linux/err.h>
 #include <linux/kernel.h>
 #include <linux/errno.h>
 #include <linux/platform_device.h>
@@ -86,6 +87,11 @@
 void __init msm8910_init(void)
 {
 	struct of_dev_auxdata *adata = msm8910_auxdata_lookup;
+	struct device *parent;
+
+	parent = socinfo_init();
+	if (IS_ERR_OR_NULL(parent))
+		pr_err("%s: socinfo_init() failed\n", __func__);
 
 	msm8910_init_gpiomux();
 
@@ -93,10 +99,6 @@
 		msm_clock_init(&msm8910_rumi_clock_init_data);
 	else
 		msm_clock_init(&msm8910_clock_init_data);
-
-	if (socinfo_init() < 0)
-		pr_err("%s: socinfo_init() failed\n", __func__);
-
 	of_platform_populate(NULL, of_default_bus_match_table, adata, NULL);
 }
 
diff --git a/arch/arm/mach-msm/board-8930.c b/arch/arm/mach-msm/board-8930.c
index 3785fb2..3afa9c0 100644
--- a/arch/arm/mach-msm/board-8930.c
+++ b/arch/arm/mach-msm/board-8930.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011-2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2011-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -10,6 +10,7 @@
  * GNU General Public License for more details.
  *
  */
+#include <linux/err.h>
 #include <linux/kernel.h>
 #include <linux/platform_device.h>
 #include <linux/io.h>
@@ -1464,8 +1465,9 @@
 	msm_shared_ram_phys = MSM_SHARED_RAM_PHYS;
 	msm_map_msm8930_io();
 
-	if (socinfo_init() < 0)
+	if (IS_ERR_OR_NULL(socinfo_init()))
 		pr_err("socinfo_init() failed!\n");
+
 }
 
 static void __init msm8930_init_irq(void)
@@ -2491,6 +2493,7 @@
 	&msm_pcm_hostless,
 	&msm_multi_ch_pcm,
 	&msm_lowlatency_pcm,
+	&msm_fm_loopback,
 };
 
 static void __init msm8930_i2c_init(void)
diff --git a/arch/arm/mach-msm/board-8960.c b/arch/arm/mach-msm/board-8960.c
index f64bf18..f4e7880 100644
--- a/arch/arm/mach-msm/board-8960.c
+++ b/arch/arm/mach-msm/board-8960.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011-2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2011-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -10,6 +10,7 @@
  * GNU General Public License for more details.
  *
  */
+#include <linux/err.h>
 #include <linux/kernel.h>
 #include <linux/platform_device.h>
 #include <linux/io.h>
@@ -1486,9 +1487,9 @@
 {
 	msm_shared_ram_phys = MSM_SHARED_RAM_PHYS;
 	msm_map_msm8960_io();
-
-	if (socinfo_init() < 0)
+	if (IS_ERR_OR_NULL(socinfo_init()))
 		pr_err("socinfo_init() failed!\n");
+
 }
 
 static void __init msm8960_init_irq(void)
diff --git a/arch/arm/mach-msm/board-8974-gpiomux.c b/arch/arm/mach-msm/board-8974-gpiomux.c
index fdad2e5..6672f49 100644
--- a/arch/arm/mach-msm/board-8974-gpiomux.c
+++ b/arch/arm/mach-msm/board-8974-gpiomux.c
@@ -88,7 +88,12 @@
 
 static struct gpiomux_setting gpio_i2c_config = {
 	.func = GPIOMUX_FUNC_3,
-	.drv = GPIOMUX_DRV_8MA,
+	/*
+	 * Please keep I2C GPIOs drive-strength at minimum (2ma). It is a
+	 * workaround for HW issue of glitches caused by rapid GPIO current-
+	 * change.
+	 */
+	.drv = GPIOMUX_DRV_2MA,
 	.pull = GPIOMUX_PULL_NONE,
 };
 
diff --git a/arch/arm/mach-msm/board-8974.c b/arch/arm/mach-msm/board-8974.c
index 2f6d3d0..b90d75b 100644
--- a/arch/arm/mach-msm/board-8974.c
+++ b/arch/arm/mach-msm/board-8974.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2011-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -10,6 +10,7 @@
  * GNU General Public License for more details.
  */
 
+#include <linux/err.h>
 #include <linux/kernel.h>
 #include <linux/platform_device.h>
 #include <linux/io.h>
@@ -358,18 +359,20 @@
 static void __init msm8974_map_io(void)
 {
 	msm_map_8974_io();
-	if (socinfo_init() < 0)
-		pr_err("%s: socinfo_init() failed\n", __func__);
 }
 
 void __init msm8974_init(void)
 {
 	struct of_dev_auxdata *adata = msm8974_auxdata_lookup;
+	struct device *parent;
+
+	parent = socinfo_init();
+	if (IS_ERR_OR_NULL(parent))
+		pr_err("%s: socinfo_init() failed\n", __func__);
 
 	msm_8974_init_gpiomux();
 	regulator_has_full_constraints();
 	of_platform_populate(NULL, of_default_bus_match_table, adata, NULL);
-
 	msm8974_add_drivers();
 }
 
diff --git a/arch/arm/mach-msm/board-9615.c b/arch/arm/mach-msm/board-9615.c
index 2392f57..d6b8a97 100644
--- a/arch/arm/mach-msm/board-9615.c
+++ b/arch/arm/mach-msm/board-9615.c
@@ -254,6 +254,8 @@
 		ADC_DECIMATION_TYPE2, ADC_SCALE_DEFAULT},
 	{"pa_therm0", ADC_MPP_1_AMUX3, CHAN_PATH_SCALING1, AMUX_RSV1,
 		ADC_DECIMATION_TYPE2, ADC_SCALE_PA_THERM},
+	{"xo_therm", CHANNEL_MUXOFF, CHAN_PATH_SCALING1, AMUX_RSV0,
+		ADC_DECIMATION_TYPE2, ADC_SCALE_XOTHERM},
 };
 
 static struct pm8xxx_adc_properties pm8018_adc_data = {
diff --git a/arch/arm/mach-msm/board-9625-gpiomux.c b/arch/arm/mach-msm/board-9625-gpiomux.c
index 4465440..b39dc27 100644
--- a/arch/arm/mach-msm/board-9625-gpiomux.c
+++ b/arch/arm/mach-msm/board-9625-gpiomux.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2012-2013, 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
diff --git a/arch/arm/mach-msm/board-9625.c b/arch/arm/mach-msm/board-9625.c
index f6a354f..07c37dd 100644
--- a/arch/arm/mach-msm/board-9625.c
+++ b/arch/arm/mach-msm/board-9625.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -10,6 +10,7 @@
  * GNU General Public License for more details.
  */
 
+#include <linux/err.h>
 #include <linux/kernel.h>
 #include <linux/platform_device.h>
 #include <linux/io.h>
@@ -236,7 +237,10 @@
 
 void __init msm9625_init(void)
 {
-	if (socinfo_init() < 0)
+	struct device *parent;
+
+	parent = socinfo_init();
+	if (IS_ERR_OR_NULL(parent))
 		pr_err("%s: socinfo_init() failed\n", __func__);
 
 	msm9625_init_gpiomux();
diff --git a/arch/arm/mach-msm/board-fsm9xxx.c b/arch/arm/mach-msm/board-fsm9xxx.c
index 274b338..16740b2 100644
--- a/arch/arm/mach-msm/board-fsm9xxx.c
+++ b/arch/arm/mach-msm/board-fsm9xxx.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011-2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2011-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -1002,10 +1002,8 @@
 {
 	msm_shared_ram_phys = 0x00100000;
 	msm_map_fsm9xxx_io();
-	if (socinfo_init() < 0)
-		pr_err("%s: socinfo_init() failed!\n",
-		       __func__);
-
+	if (IS_ERR_OR_NULL(socinfo_init()))
+		pr_err("socinfo_init() failed!\n");
 }
 
 MACHINE_START(FSM9XXX_SURF, "QCT FSM9XXX")
diff --git a/arch/arm/mach-msm/board-msm7627a-bt.c b/arch/arm/mach-msm/board-msm7627a-bt.c
index 1c2d8a2..5f29adb 100644
--- a/arch/arm/mach-msm/board-msm7627a-bt.c
+++ b/arch/arm/mach-msm/board-msm7627a-bt.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2011-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -602,10 +602,10 @@
 				__func__, (p+i)->reg,
 				value, (p+i)->mask);
 		value = 0;
-		rc = marimba_read_bit_mask(&config,
+		/* Ignoring the read failure as it is only for check */
+		if (marimba_read_bit_mask(&config,
 				(p+i)->reg, &value,
-				sizeof((p+i)->value), (p+i)->mask);
-		if (rc < 0)
+				sizeof((p+i)->value), (p+i)->mask) < 0)
 			dev_err(&msm_bt_power_device.dev,
 				"%s marimba_read_bit_mask- error",
 				__func__);
@@ -678,7 +678,6 @@
 			dev_err(&msm_bt_power_device.dev,
 				"%s: could not %sable regulator %s: %d\n",
 					__func__, "dis", bt_vregs[i].name, rc);
-			goto reg_disable;
 		}
 	}
 
@@ -687,8 +686,8 @@
 	if (on)
 		regulator_disable(bt_vregs[i].reg);
 reg_disable:
-	while (i) {
-		if (on) {
+	if (on) {
+		while (i) {
 			i--;
 			regulator_disable(bt_vregs[i].reg);
 			regulator_put(bt_vregs[i].reg);
@@ -835,7 +834,10 @@
 	int pin, rc = 0;
 	const char *id = "BTPW";
 	int cid = 0;
+	int bt_state = 0;
+	struct marimba config = { .mod_id =  SLAVE_ID_BAHAMA};
 
+	pr_debug("%s: on = %d\n", __func__, on);
 	cid = adie_get_detected_connectivity_type();
 	if (cid != BAHAMA_ID) {
 		pr_err("%s: unexpected adie connectivity type: %d\n",
@@ -854,7 +856,7 @@
 		if (rc < 0) {
 			pr_err("%s: bluetooth_switch_regulators rc = %d",
 					__func__, rc);
-			goto exit;
+			goto fail_gpio;
 		}
 		/*setup BT GPIO lines*/
 		for (pin = 0; pin < ARRAY_SIZE(bt_config_power_on);
@@ -874,7 +876,7 @@
 			PMAPP_CLOCK_VOTE_ON);
 		if (rc < 0) {
 			pr_err("Failed to vote for TCXO_D1 ON\n");
-			goto fail_clock;
+			goto fail_gpio_cfg;
 		}
 		msleep(20);
 
@@ -882,7 +884,7 @@
 		rc = bahama_bt(1);
 		if (rc < 0) {
 			pr_err("%s: bahama_bt rc = %d", __func__, rc);
-			goto fail_i2c;
+			goto fail_clock;
 		}
 		msleep(20);
 
@@ -891,7 +893,7 @@
 		if (rc < 0) {
 			pr_err("%s: msm_bahama_setup_pcm_i2s , rc =%d\n",
 				__func__, rc);
-				goto fail_power;
+			goto fail_i2c;
 			}
 		rc = pmapp_clock_vote(id, PMAPP_CLOCK_ID_D1,
 				  PMAPP_CLOCK_VOTE_PIN_CTRL);
@@ -900,26 +902,28 @@
 					__func__, rc);
 
 	} else {
-		rc = bahama_bt(0);
-		if (rc < 0)
-			pr_err("%s: bahama_bt rc = %d", __func__, rc);
+		bt_state = marimba_get_bt_status(&config);
+		if (!bt_state) {
+			pr_err("%s: BT is already turned OFF.\n", __func__);
+			return 0;
+		}
 
 		rc = msm_bahama_setup_pcm_i2s(BT_PCM_OFF);
 		if (rc < 0) {
 			pr_err("%s: msm_bahama_setup_pcm_i2s, rc =%d\n",
 				__func__, rc);
 		}
-		rc = bt_set_gpio(on);
-		if (rc) {
-			pr_err("%s: bt_set_gpio = %d\n",
-					__func__, rc);
-		}
 fail_i2c:
+		rc = bahama_bt(0);
+		if (rc < 0)
+			pr_err("%s: bahama_bt rc = %d", __func__, rc);
+
+fail_clock:
 		rc = pmapp_clock_vote(id, PMAPP_CLOCK_ID_D1,
 				  PMAPP_CLOCK_VOTE_OFF);
 		if (rc < 0)
 			pr_err("%s: Failed to vote Off D1\n", __func__);
-fail_clock:
+fail_gpio_cfg:
 		for (pin = 0; pin < ARRAY_SIZE(bt_config_power_off);
 			pin++) {
 			rc = gpio_tlmm_config(bt_config_power_off[pin],
@@ -936,6 +940,12 @@
 		if (rc < 0) {
 			pr_err("%s: switch_regulators : rc = %d",\
 				__func__, rc);
+		}
+fail_gpio:
+		rc = bt_set_gpio(0);
+		if (rc) {
+			pr_err("%s: bt_set_gpio = %d\n",
+					__func__, rc);
 			goto exit;
 		}
 	}
diff --git a/arch/arm/mach-msm/board-msm7x30.c b/arch/arm/mach-msm/board-msm7x30.c
index 9822aa9..752c99a 100644
--- a/arch/arm/mach-msm/board-msm7x30.c
+++ b/arch/arm/mach-msm/board-msm7x30.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2009-2012, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2009-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -11,6 +11,7 @@
  *
  */
 
+#include <linux/err.h>
 #include <linux/kernel.h>
 #include <linux/irq.h>
 #include <linux/gpio.h>
@@ -7348,9 +7349,8 @@
 {
 	msm_shared_ram_phys = 0x00100000;
 	msm_map_msm7x30_io();
-	if (socinfo_init() < 0)
-		printk(KERN_ERR "%s: socinfo_init() failed!\n",
-		       __func__);
+	if (IS_ERR_OR_NULL(socinfo_init()))
+		pr_err("socinfo_init() failed!\n");
 }
 
 static void __init msm7x30_init_early(void)
diff --git a/arch/arm/mach-msm/board-msm8x60.c b/arch/arm/mach-msm/board-msm8x60.c
index d4205bd..e678dfb 100644
--- a/arch/arm/mach-msm/board-msm8x60.c
+++ b/arch/arm/mach-msm/board-msm8x60.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2010-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -11,6 +11,7 @@
  *
  */
 
+#include <linux/err.h>
 #include <linux/kernel.h>
 #include <linux/platform_device.h>
 #include <linux/gpio.h>
@@ -7540,9 +7541,9 @@
 {
 	msm_shared_ram_phys = MSM_SHARED_RAM_PHYS;
 	msm_map_msm8x60_io();
-
-	if (socinfo_init() < 0)
+	if (IS_ERR_OR_NULL(socinfo_init()))
 		pr_err("socinfo_init() failed!\n");
+
 }
 
 /*
diff --git a/arch/arm/mach-msm/board-qsd8x50.c b/arch/arm/mach-msm/board-qsd8x50.c
index 146c8a8..57c548e 100644
--- a/arch/arm/mach-msm/board-qsd8x50.c
+++ b/arch/arm/mach-msm/board-qsd8x50.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2008-2012, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2008-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -2521,9 +2521,8 @@
 	msm_shared_ram_phys = MSM_SHARED_RAM_PHYS;
 	msm_map_qsd8x50_io();
 	qsd8x50_allocate_memory_regions();
-	if (socinfo_init() < 0)
-		printk(KERN_ERR "%s: socinfo_init() failed!\n",
-		       __func__);
+	if (IS_ERR_OR_NULL(socinfo_init()))
+		pr_err("socinfo_init() failed!\n");
 }
 
 MACHINE_START(QSD8X50_SURF, "QCT QSD8X50 SURF")
diff --git a/arch/arm/mach-msm/clock-8960.c b/arch/arm/mach-msm/clock-8960.c
index 7038b06..928b5aa 100644
--- a/arch/arm/mach-msm/clock-8960.c
+++ b/arch/arm/mach-msm/clock-8960.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2009-2012, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2009-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -114,6 +114,7 @@
 #define SATA_RXOOB_CLK_CTL_REG			REG(0x2C0C)
 #define SATA_PMALIVE_CLK_CTL_REG		REG(0x2C10)
 #define SATA_PHY_REF_CLK_CTL_REG		REG(0x2C14)
+#define SATA_RESET				REG(0x2C1C)
 #define SATA_ACLK_CTL_REG			REG(0x2C20)
 #define SATA_PHY_CFG_CLK_CTL_REG		REG(0x2C40)
 #define USB_FSn_HCLK_CTL_REG(n)			REG(0x2960+(0x20*((n)-1)))
@@ -2085,6 +2086,8 @@
 		.en_mask = BIT(4),
 		.halt_reg = CLK_HALT_MSS_SMPSS_MISC_STATE_REG,
 		.halt_bit = 27,
+		.reset_reg = SATA_RESET,
+		.reset_mask = BIT(0),
 	},
 	.c = {
 		.dbg_name = "sata_p_clk",
@@ -5311,14 +5314,14 @@
 	CLK_LOOKUP("src_clk",		usb_fs1_src_clk.c,	""),
 	CLK_LOOKUP("alt_core_clk",	usb_fs1_xcvr_clk.c,	""),
 	CLK_LOOKUP("sys_clk",		usb_fs1_sys_clk.c,	""),
-	CLK_LOOKUP("ref_clk",		sata_phy_ref_clk.c,	""),
-	CLK_LOOKUP("cfg_clk",		sata_phy_cfg_clk.c,	""),
-	CLK_LOOKUP("src_clk",		sata_src_clk.c,		""),
-	CLK_LOOKUP("core_rxoob_clk",	sata_rxoob_clk.c,	""),
-	CLK_LOOKUP("core_pmalive_clk",	sata_pmalive_clk.c,	""),
-	CLK_LOOKUP("bus_clk",		sata_a_clk.c,		""),
-	CLK_LOOKUP("iface_clk",		sata_p_clk.c,		""),
-	CLK_LOOKUP("slave_iface_clk",	sfab_sata_s_p_clk.c,	""),
+	CLK_LOOKUP("ref_clk",		sata_phy_ref_clk.c,	"msm_sata.0"),
+	CLK_LOOKUP("cfg_clk",		sata_phy_cfg_clk.c,	"msm_sata.0"),
+	CLK_LOOKUP("src_clk",		sata_src_clk.c,		"msm_sata.0"),
+	CLK_LOOKUP("core_rxoob_clk",	sata_rxoob_clk.c,	"msm_sata.0"),
+	CLK_LOOKUP("core_pmalive_clk",	sata_pmalive_clk.c,	"msm_sata.0"),
+	CLK_LOOKUP("bus_clk",		sata_a_clk.c,		"msm_sata.0"),
+	CLK_LOOKUP("iface_clk",		sata_p_clk.c,		"msm_sata.0"),
+	CLK_LOOKUP("slave_iface_clk",	sfab_sata_s_p_clk.c,	"msm_sata.0"),
 	CLK_LOOKUP("iface_clk",		ce3_p_clk.c,		"qce.0"),
 	CLK_LOOKUP("iface_clk",		ce3_p_clk.c,		"qcrypto.0"),
 	CLK_LOOKUP("core_clk",		ce3_core_clk.c,		"qce.0"),
diff --git a/arch/arm/mach-msm/clock-8974.c b/arch/arm/mach-msm/clock-8974.c
index 1b0ac74..435cc7d 100644
--- a/arch/arm/mach-msm/clock-8974.c
+++ b/arch/arm/mach-msm/clock-8974.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -662,9 +662,9 @@
 
 #define D0_ID		 1
 #define D1_ID		 2
-#define A0_ID		 3
-#define A1_ID		 4
-#define A2_ID		 5
+#define A0_ID		 4
+#define A1_ID		 5
+#define A2_ID		 6
 #define DIFF_CLK_ID	 7
 #define DIV_CLK1_ID	11
 #define DIV_CLK2_ID	12
@@ -2550,6 +2550,7 @@
 	F_MM(133330000, mmpll0,   6,   0,   0),
 	F_MM(160000000, mmpll0,   5,   0,   0),
 	F_MM(200000000, mmpll0,   4,   0,   0),
+	F_MM(240000000,  gpll0, 2.5,   0,   0),
 	F_MM(266670000, mmpll0,   3,   0,   0),
 	F_MM(320000000, mmpll0, 2.5,   0,   0),
 	F_END
@@ -5139,6 +5140,7 @@
 	/* Multimedia clocks */
 	CLK_LOOKUP("bus_clk_src", axi_clk_src.c, ""),
 	CLK_LOOKUP("bus_clk", mmss_mmssnoc_axi_clk.c, ""),
+	CLK_LOOKUP("bus_clk", mmssnoc_ahb_clk.c, ""),
 	CLK_LOOKUP("core_clk", mdss_edpaux_clk.c, "fd923400.qcom,mdss_edp"),
 	CLK_LOOKUP("pixel_clk", mdss_edppixel_clk.c, "fd923400.qcom,mdss_edp"),
 	CLK_LOOKUP("link_clk", mdss_edplink_clk.c, "fd923400.qcom,mdss_edp"),
@@ -5281,6 +5283,7 @@
 						"fda64000.qcom,iommu"),
 	CLK_LOOKUP("core_clk", camss_jpeg_jpeg_axi_clk.c,
 						"fda64000.qcom,iommu"),
+	CLK_LOOKUP("alt_core_clk", camss_top_ahb_clk.c, "fda64000.qcom,iommu"),
 	CLK_LOOKUP("bus_clk0", camss_jpeg_jpeg_axi_clk.c, "fda1c000.qcom,jpeg"),
 	CLK_LOOKUP("bus_clk0", camss_jpeg_jpeg_axi_clk.c, "fda20000.qcom,jpeg"),
 	CLK_LOOKUP("bus_clk0", camss_jpeg_jpeg_axi_clk.c, "fda24000.qcom,jpeg"),
@@ -5297,8 +5300,9 @@
 	CLK_LOOKUP("camss_top_ahb_clk", camss_top_ahb_clk.c,
 						"fda24000.qcom,jpeg"),
 	CLK_LOOKUP("iface_clk", camss_micro_ahb_clk.c, ""),
-	CLK_LOOKUP("iface_clk", camss_vfe_cpp_ahb_clk.c, "fda44000.qcom,iommu"),
-	CLK_LOOKUP("core_clk", camss_vfe_cpp_clk.c, "fda44000.qcom,iommu"),
+	CLK_LOOKUP("iface_clk", camss_vfe_vfe_ahb_clk.c, "fda44000.qcom,iommu"),
+	CLK_LOOKUP("core_clk", camss_vfe_vfe_axi_clk.c, "fda44000.qcom,iommu"),
+	CLK_LOOKUP("alt_core_clk", camss_top_ahb_clk.c, "fda44000.qcom,iommu"),
 	CLK_LOOKUP("iface_clk", mdss_ahb_clk.c, "mdp.0"),
 	CLK_LOOKUP("iface_clk", mdss_ahb_clk.c, "mdss_dsi_clk_ctrl"),
 	CLK_LOOKUP("iface_clk", mdss_ahb_clk.c, "fd923400.qcom,mdss_edp"),
@@ -5451,56 +5455,6 @@
 	CLK_LOOKUP("krait3_m_clk",	krait3_m_clk, ""),
 };
 
-static struct pll_config_regs gpll0_regs __initdata = {
-	.l_reg = (void __iomem *)GPLL0_L_REG,
-	.m_reg = (void __iomem *)GPLL0_M_REG,
-	.n_reg = (void __iomem *)GPLL0_N_REG,
-	.config_reg = (void __iomem *)GPLL0_USER_CTL_REG,
-	.mode_reg = (void __iomem *)GPLL0_MODE_REG,
-	.base = &virt_bases[GCC_BASE],
-};
-
-/* GPLL0 at 600 MHz, main output enabled. */
-static struct pll_config gpll0_config __initdata = {
-	.l = 0x1f,
-	.m = 0x1,
-	.n = 0x4,
-	.vco_val = 0x0,
-	.vco_mask = BM(21, 20),
-	.pre_div_val = 0x0,
-	.pre_div_mask = BM(14, 12),
-	.post_div_val = 0x0,
-	.post_div_mask = BM(9, 8),
-	.mn_ena_val = BIT(24),
-	.mn_ena_mask = BIT(24),
-	.main_output_val = BIT(0),
-	.main_output_mask = BIT(0),
-};
-
-static struct pll_config_regs gpll1_regs __initdata = {
-	.l_reg = (void __iomem *)GPLL1_L_REG,
-	.m_reg = (void __iomem *)GPLL1_M_REG,
-	.n_reg = (void __iomem *)GPLL1_N_REG,
-	.config_reg = (void __iomem *)GPLL1_USER_CTL_REG,
-	.mode_reg = (void __iomem *)GPLL1_MODE_REG,
-	.base = &virt_bases[GCC_BASE],
-};
-
-/* GPLL1 at 480 MHz, main output enabled. */
-static struct pll_config gpll1_config __initdata = {
-	.l = 0x19,
-	.m = 0x0,
-	.n = 0x1,
-	.vco_val = 0x0,
-	.vco_mask = BM(21, 20),
-	.pre_div_val = 0x0,
-	.pre_div_mask = BM(14, 12),
-	.post_div_val = 0x0,
-	.post_div_mask = BM(9, 8),
-	.main_output_val = BIT(0),
-	.main_output_mask = BIT(0),
-};
-
 static struct pll_config_regs mmpll0_regs __initdata = {
 	.l_reg = (void __iomem *)MMPLL0_L_REG,
 	.m_reg = (void __iomem *)MMPLL0_M_REG,
@@ -5605,9 +5559,6 @@
 	.main_output_mask = BIT(0),
 };
 
-#define PLL_AUX_OUTPUT_BIT 1
-#define PLL_AUX2_OUTPUT_BIT 2
-
 #define PWR_ON_MASK		BIT(31)
 #define EN_REST_WAIT_MASK	(0xF << 20)
 #define EN_FEW_WAIT_MASK	(0xF << 16)
@@ -5627,24 +5578,11 @@
 	u32 regval, status;
 	int ret;
 
-	if (!(readl_relaxed(GCC_REG_BASE(GPLL0_STATUS_REG))
-			& gpll0_clk_src.status_mask))
-		configure_sr_hpm_lp_pll(&gpll0_config, &gpll0_regs, 1);
-
-	if (!(readl_relaxed(GCC_REG_BASE(GPLL1_STATUS_REG))
-			& gpll1_clk_src.status_mask))
-		configure_sr_hpm_lp_pll(&gpll1_config, &gpll1_regs, 1);
-
 	configure_sr_hpm_lp_pll(&mmpll0_config, &mmpll0_regs, 1);
 	configure_sr_hpm_lp_pll(&mmpll1_config, &mmpll1_regs, 1);
 	configure_sr_hpm_lp_pll(&mmpll3_config, &mmpll3_regs, 0);
 	configure_sr_hpm_lp_pll(&lpapll0_config, &lpapll0_regs, 1);
 
-	/* Enable GPLL0's aux outputs. */
-	regval = readl_relaxed(GCC_REG_BASE(GPLL0_USER_CTL_REG));
-	regval |= BIT(PLL_AUX_OUTPUT_BIT) | BIT(PLL_AUX2_OUTPUT_BIT);
-	writel_relaxed(regval, GCC_REG_BASE(GPLL0_USER_CTL_REG));
-
 	/* Vote for GPLL0 to turn on. Needed by acpuclock. */
 	regval = readl_relaxed(GCC_REG_BASE(APCS_GPLL_ENA_VOTE_REG));
 	regval |= BIT(0);
diff --git a/arch/arm/mach-msm/clock-9625.c b/arch/arm/mach-msm/clock-9625.c
index f4c045c..c4cbdfd 100644
--- a/arch/arm/mach-msm/clock-9625.c
+++ b/arch/arm/mach-msm/clock-9625.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -2097,10 +2097,10 @@
 
 	CLK_LOOKUP("iface_clk", gcc_usb_hs_ahb_clk.c,     "f9a55000.usb"),
 	CLK_LOOKUP("core_clk", gcc_usb_hs_system_clk.c,   "f9a55000.usb"),
-	CLK_LOOKUP("iface_clk", gcc_usb_hsic_ahb_clk.c,	  "f9a15000.hsic"),
-	CLK_LOOKUP("phy_clk", gcc_usb_hsic_clk.c,	  "f9a15000.hsic"),
-	CLK_LOOKUP("cal_clk", gcc_usb_hsic_io_cal_clk.c,  "f9a15000.hsic"),
-	CLK_LOOKUP("core_clk", gcc_usb_hsic_system_clk.c, "f9a15000.hsic"),
+	CLK_LOOKUP("iface_clk", gcc_usb_hsic_ahb_clk.c,	  "msm_hsic_host"),
+	CLK_LOOKUP("phy_clk", gcc_usb_hsic_clk.c,	  "msm_hsic_host"),
+	CLK_LOOKUP("cal_clk", gcc_usb_hsic_io_cal_clk.c,  "msm_hsic_host"),
+	CLK_LOOKUP("core_clk", gcc_usb_hsic_system_clk.c, "msm_hsic_host"),
 	CLK_LOOKUP("alt_core_clk", gcc_usb_hsic_xcvr_fs_clk.c, ""),
 
 	CLK_LOOKUP("core_clk", gcc_ce1_clk.c, "fd400000.qcom,qcedev"),
@@ -2125,10 +2125,14 @@
 		   "msm-dai-q6-mi2s.0"),
 	CLK_LOOKUP("ibit_clk", audio_core_lpaif_pri_ibit_clk.c,
 		   "msm-dai-q6-mi2s.0"),
-	CLK_LOOKUP("core_clk", audio_core_lpaif_sec_clk_src.c, ""),
-	CLK_LOOKUP("osr_clk", audio_core_lpaif_sec_osr_clk.c, ""),
-	CLK_LOOKUP("ebit_clk", audio_core_lpaif_sec_ebit_clk.c, ""),
-	CLK_LOOKUP("ibit_clk", audio_core_lpaif_sec_ibit_clk.c, ""),
+	CLK_LOOKUP("core_clk", audio_core_lpaif_sec_clk_src.c,
+		   "msm-dai-q6-mi2s.1"),
+	CLK_LOOKUP("osr_clk", audio_core_lpaif_sec_osr_clk.c,
+		   "msm-dai-q6-mi2s.1"),
+	CLK_LOOKUP("ebit_clk", audio_core_lpaif_sec_ebit_clk.c,
+		   "msm-dai-q6-mi2s.1"),
+	CLK_LOOKUP("ibit_clk", audio_core_lpaif_sec_ibit_clk.c,
+		   "msm-dai-q6-mi2s.1"),
 	CLK_LOOKUP("core_clk", audio_core_lpaif_pcm0_clk_src.c, ""),
 	CLK_LOOKUP("ebit_clk", audio_core_lpaif_pcm0_ebit_clk.c, ""),
 	CLK_LOOKUP("ibit_clk", audio_core_lpaif_pcm0_ibit_clk.c, ""),
@@ -2171,6 +2175,7 @@
 	CLK_LOOKUP("core_clk", qdss_clk.c, "fc31a000.funnel"),
 	CLK_LOOKUP("core_clk", qdss_clk.c, "fc321000.stm"),
 	CLK_LOOKUP("core_clk", qdss_clk.c, "fc332000.etm"),
+	CLK_LOOKUP("core_clk", qdss_clk.c, "fc332000.jtagmm"),
 
 	CLK_LOOKUP("core_a_clk", qdss_clk.c, "fc322000.tmc"),
 	CLK_LOOKUP("core_a_clk", qdss_clk.c, "fc318000.tpiu"),
@@ -2181,6 +2186,7 @@
 	CLK_LOOKUP("core_a_clk", qdss_clk.c, "fc31a000.funnel"),
 	CLK_LOOKUP("core_a_clk", qdss_clk.c, "fc321000.stm"),
 	CLK_LOOKUP("core_a_clk", qdss_clk.c, "fc332000.etm"),
+	CLK_LOOKUP("core_a_clk", qdss_clk.c, "fc332000.jtagmm"),
 
 };
 
diff --git a/arch/arm/mach-msm/devices-8064.c b/arch/arm/mach-msm/devices-8064.c
index dcd90d0..67485dc 100644
--- a/arch/arm/mach-msm/devices-8064.c
+++ b/arch/arm/mach-msm/devices-8064.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011-2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2011-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -20,7 +20,6 @@
 #include <linux/dma-mapping.h>
 #include <linux/coresight.h>
 #include <linux/avtimer.h>
-#include <linux/ahci_platform.h>
 #include <mach/irqs-8064.h>
 #include <mach/board.h>
 #include <mach/msm_iomap.h>
@@ -1779,9 +1778,11 @@
 }
 
 #define MSM_SATA_AHCI_BASE	0x29000000
-#define MSM_SATA_AHCI_REGS_SZ	0x17C
+#define MSM_SATA_AHCI_REGS_SZ	0x180
+#define MSM_SATA_PHY_BASE	0x1B400000
+#define MSM_SATA_PHY_REGS_SZ	0x200
 
-static struct resource resources_ahci[] = {
+static struct resource resources_sata[] = {
 	{
 		.name	= "ahci_mem",
 		.flags	= IORESOURCE_MEM,
@@ -1794,31 +1795,25 @@
 		.start	= SATA_CONTROLLER_IRQ,
 		.end	= SATA_CONTROLLER_IRQ,
 	},
-};
-
-static u64 ahci_dma_mask = DMA_BIT_MASK(32);
-static struct platform_device apq8064_device_ahci = {
-	.name		= "ahci",
-	.id		= 0,
-	.num_resources	= ARRAY_SIZE(resources_ahci),
-	.resource	= resources_ahci,
-	.dev		= {
-		.dma_mask		= &ahci_dma_mask,
-		.coherent_dma_mask	= DMA_BIT_MASK(32),
+	{
+		.name	= "phy_mem",
+		.flags	= IORESOURCE_MEM,
+		.start	= MSM_SATA_PHY_BASE,
+		.end	= MSM_SATA_PHY_BASE + MSM_SATA_PHY_REGS_SZ - 1,
 	},
 };
 
-int __init apq8064_add_ahci(struct ahci_platform_data *platd)
-{
-	struct platform_device	*pdev;
-
-	if (!platd)
-		return -EINVAL;
-
-	pdev = &apq8064_device_ahci;
-	pdev->dev.platform_data = platd;
-	return platform_device_register(pdev);
-}
+static u64 sata_dma_mask = DMA_BIT_MASK(32);
+struct platform_device apq8064_device_sata = {
+	.name		= "msm_sata",
+	.id		= 0,
+	.num_resources	= ARRAY_SIZE(resources_sata),
+	.resource	= resources_sata,
+	.dev		= {
+		.dma_mask		= &sata_dma_mask,
+		.coherent_dma_mask	= DMA_BIT_MASK(32),
+	},
+};
 
 static struct resource resources_sps[] = {
 	{
diff --git a/arch/arm/mach-msm/devices-8960.c b/arch/arm/mach-msm/devices-8960.c
index 446f3f2..8762aa1 100644
--- a/arch/arm/mach-msm/devices-8960.c
+++ b/arch/arm/mach-msm/devices-8960.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011-2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2011-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -2459,6 +2459,11 @@
 	.id	= -1,
 };
 
+struct platform_device msm_fm_loopback = {
+	.name	= "msm-pcm-loopback",
+	.id	= -1,
+};
+
 static struct fs_driver_data gfx2d0_fs_data = {
 	.clks = (struct fs_clk_data[]){
 		{ .name = "core_clk" },
diff --git a/arch/arm/mach-msm/devices-9615.c b/arch/arm/mach-msm/devices-9615.c
index cec57fd..15994565 100644
--- a/arch/arm/mach-msm/devices-9615.c
+++ b/arch/arm/mach-msm/devices-9615.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011-2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2011-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -11,6 +11,7 @@
  *
  */
 
+#include <linux/err.h>
 #include <linux/kernel.h>
 #include <linux/platform_device.h>
 #include <linux/irq.h>
@@ -1545,7 +1546,7 @@
 	msm_shared_ram_phys = MSM_SHARED_RAM_PHYS;
 	msm_map_msm9615_io();
 	l2x0_cache_init();
-	if (socinfo_init() < 0)
+	if (IS_ERR_OR_NULL(socinfo_init()))
 		pr_err("socinfo_init() failed!\n");
 }
 
diff --git a/arch/arm/mach-msm/devices-msm7x27a.c b/arch/arm/mach-msm/devices-msm7x27a.c
index cf456f7..c8b160c 100644
--- a/arch/arm/mach-msm/devices-msm7x27a.c
+++ b/arch/arm/mach-msm/devices-msm7x27a.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2011-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -1667,7 +1667,7 @@
 	},
 	{
 		.name   = "l2_irq",
-		.start  = MSM8625_INT_L2CC_INTR,
+		.start  = MSM8625_INT_SC_SICL2PERFMONIRPTREQ,
 		.flags  = IORESOURCE_IRQ,
 	},
 };
@@ -2096,7 +2096,7 @@
 		msm_cpr_init();
 
 	if (!cpu_is_msm8625() && !cpu_is_msm8625q())
-		pl310_resources[1].start = INT_L2CC_INTR;
+		pl310_resources[1].start = SC_SICL2PERFMONIRPTREQ;
 
 	platform_device_register(&pl310_erp_device);
 
@@ -2147,8 +2147,8 @@
 void __init msm_common_io_init(void)
 {
 	msm_map_common_io();
-	if (socinfo_init() < 0)
-		pr_err("%s: socinfo_init() failed!\n", __func__);
+	if (IS_ERR_OR_NULL(socinfo_init()))
+		pr_err("socinfo_init() failed!\n");
 	msm7x27x_cache_init();
 }
 
@@ -2163,8 +2163,8 @@
 {
 	msm_map_msm8625_io();
 
-	if (socinfo_init() < 0)
-		pr_err("%s: socinfo_init() failed!\n", __func__);
+	if (IS_ERR_OR_NULL(socinfo_init()))
+		pr_err("socinfo_init() failed!\n");
 	msm7x27x_cache_init();
 }
 
diff --git a/arch/arm/mach-msm/devices.h b/arch/arm/mach-msm/devices.h
index 2339706..3471a30 100644
--- a/arch/arm/mach-msm/devices.h
+++ b/arch/arm/mach-msm/devices.h
@@ -1,7 +1,7 @@
 /* linux/arch/arm/mach-msm/devices.h
  *
  * Copyright (C) 2008 Google, Inc.
- * Copyright (c) 2009-2012, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2009-2013, The Linux Foundation. All rights reserved.
  *
  * This software is licensed under the terms of the GNU General Public
  * License version 2, as published by the Free Software Foundation, and
@@ -95,6 +95,7 @@
 extern struct platform_device apq8064_device_ssbi_pmic1;
 extern struct platform_device apq8064_device_ssbi_pmic2;
 extern struct platform_device apq8064_device_cache_erp;
+extern struct platform_device apq8064_device_sata;
 
 extern struct platform_device msm9615_device_uart_gsbi4;
 extern struct platform_device msm9615_device_qup_i2c_gsbi5;
@@ -252,6 +253,7 @@
 extern struct platform_device msm_i2s_cpudai4;
 extern struct platform_device msm_i2s_cpudai5;
 extern struct platform_device msm_cpudai_stub;
+extern struct platform_device msm_fm_loopback;
 
 extern struct platform_device msm_pil_q6v3;
 extern struct platform_device msm_pil_modem;
diff --git a/arch/arm/mach-msm/idle-v7.S b/arch/arm/mach-msm/idle-v7.S
index 9a22996..6840f1c 100644
--- a/arch/arm/mach-msm/idle-v7.S
+++ b/arch/arm/mach-msm/idle-v7.S
@@ -2,7 +2,7 @@
  * Idle processing for ARMv7-based Qualcomm SoCs.
  *
  * Copyright (C) 2007 Google, Inc.
- * Copyright (c) 2007-2009, 2011-2012 Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2007-2009, 2011-2013 The Linux Foundation. All rights reserved.
  *
  * This software is licensed under the terms of the GNU General Public
  * License version 2, as published by the Free Software Foundation, and
@@ -97,7 +97,7 @@
 	mrc     p15, 0, ip, c13, c0, 1 /* context ID */
 	stmia   r0!, {r1-r9, ip}
 
-#ifdef CONFIG_MSM_JTAG
+#if defined(CONFIG_MSM_JTAG) || defined(CONFIG_MSM_JTAG_MM)
 	bl      msm_jtag_save_state
 #endif
 
@@ -185,7 +185,7 @@
 	blxne	r1
 	dmb
 
-#ifdef CONFIG_MSM_JTAG
+#if defined(CONFIG_MSM_JTAG) || defined(CONFIG_MSM_JTAG_MM)
 	bl	msm_jtag_restore_state
 #endif
 	ldr     r0, =msm_saved_state	/* address of msm_saved_state ptr */
@@ -286,7 +286,7 @@
 	stmfd   sp!, {lr}
 	blxne	r1
 	dmb
-#ifdef CONFIG_MSM_JTAG
+#if defined(CONFIG_MSM_JTAG) || defined(CONFIG_MSM_JTAG_MM)
 	bl      msm_jtag_restore_state
 #endif
 	ldmfd   sp!, {lr}
diff --git a/arch/arm/mach-msm/include/mach/iommu.h b/arch/arm/mach-msm/include/mach/iommu.h
index 8b39e34..9e2c24e 100644
--- a/arch/arm/mach-msm/include/mach/iommu.h
+++ b/arch/arm/mach-msm/include/mach/iommu.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2010-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -94,6 +94,7 @@
  * @bfb_settings: Optional BFB performance tuning parameters
  * @dev:	Struct device this hardware instance is tied to
  * @list:	List head to link all iommus together
+ * @clk_reg_virt: Optional clock register virtual address.
  *
  * A msm_iommu_drvdata holds the global driver data about a single piece
  * of an IOMMU hardware instance.
@@ -108,10 +109,12 @@
 	struct clk *aclk;
 	const char *name;
 	struct regulator *gdsc;
+	struct regulator *alt_gdsc;
 	struct msm_iommu_bfb_settings *bfb_settings;
 	int sec_id;
 	struct device *dev;
 	struct list_head list;
+	void __iomem *clk_reg_virt;
 };
 
 void msm_iommu_add_drv(struct msm_iommu_drvdata *drv);
diff --git a/arch/arm/mach-msm/include/mach/irqs-7xxx.h b/arch/arm/mach-msm/include/mach/irqs-7xxx.h
index c90b4ee..97ca682 100644
--- a/arch/arm/mach-msm/include/mach/irqs-7xxx.h
+++ b/arch/arm/mach-msm/include/mach/irqs-7xxx.h
@@ -75,7 +75,7 @@
 /* 22-31 are reserved except 7x27a*/
 #if defined(CONFIG_ARCH_MSM7X27A)
 #define INT_L2CC_EM          (32 + 22)
-#define INT_L2CC_INTR        (32 + 23)
+#define SC_SICL2PERFMONIRPTREQ (32 + 23)
 #define INT_CE_IRQ           (32 + 24)
 #endif
 
diff --git a/arch/arm/mach-msm/include/mach/irqs-8625.h b/arch/arm/mach-msm/include/mach/irqs-8625.h
index a83dd2e..7083390 100644
--- a/arch/arm/mach-msm/include/mach/irqs-8625.h
+++ b/arch/arm/mach-msm/include/mach/irqs-8625.h
@@ -83,7 +83,7 @@
 #define MSM8625_INT_UART2DM_IRQ		(GIC_SPI_START + 32 + 20)
 #define MSM8625_INT_UART2DM_RX		(GIC_SPI_START + 32 + 21)
 #define MSM8625_INT_L2CC_EM		(GIC_SPI_START + 32 + 22)
-#define MSM8625_INT_L2CC_INTR		(GIC_SPI_START + 32 + 23)
+#define MSM8625_INT_SC_SICL2PERFMONIRPTREQ	(GIC_SPI_START + 32 + 23)
 #define MSM8625_INT_CE_IRQ		(GIC_SPI_START + 32 + 24)
 #define MSM8625_INT_CPR_IRQ0		(GIC_SPI_START + 32 + 25)
 #define MSM8625_INT_CPR_IRQ1		(GIC_SPI_START + 32 + 26)
diff --git a/arch/arm/mach-msm/include/mach/jtag.h b/arch/arm/mach-msm/include/mach/jtag.h
index 3850eff..2131be6 100644
--- a/arch/arm/mach-msm/include/mach/jtag.h
+++ b/arch/arm/mach-msm/include/mach/jtag.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -13,7 +13,7 @@
 #ifndef __MACH_JTAG_H
 #define __MACH_JTAG_H
 
-#ifdef CONFIG_MSM_JTAG
+#if defined(CONFIG_MSM_JTAG) || defined(CONFIG_MSM_JTAG_MM)
 extern void msm_jtag_save_state(void);
 extern void msm_jtag_restore_state(void);
 #else
diff --git a/arch/arm/mach-msm/include/mach/msm_ipc_logging.h b/arch/arm/mach-msm/include/mach/msm_ipc_logging.h
index 0a203a5..ec9fdb0 100644
--- a/arch/arm/mach-msm/include/mach/msm_ipc_logging.h
+++ b/arch/arm/mach-msm/include/mach/msm_ipc_logging.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -185,47 +185,49 @@
 				      struct decode_context *));
 #else
 
-void *ipc_log_context_create(int max_num_pages, const char *modname)
+static inline void *ipc_log_context_create(int max_num_pages,
+	const char *modname)
 { return NULL; }
 
-void msg_encode_start(struct encode_context *ectxt, uint32_t type) { }
+static inline void msg_encode_start(struct encode_context *ectxt,
+	uint32_t type) { }
 
-int tsv_timestamp_write(struct encode_context *ectxt)
+static inline int tsv_timestamp_write(struct encode_context *ectxt)
 { return -EINVAL; }
 
-int tsv_pointer_write(struct encode_context *ectxt, void *pointer)
+static inline int tsv_pointer_write(struct encode_context *ectxt, void *pointer)
 { return -EINVAL; }
 
-int tsv_int32_write(struct encode_context *ectxt, int32_t n)
+static inline int tsv_int32_write(struct encode_context *ectxt, int32_t n)
 { return -EINVAL; }
 
-int tsv_byte_array_write(struct encode_context *ectxt,
+static inline int tsv_byte_array_write(struct encode_context *ectxt,
 			 void *data, int data_size)
 { return -EINVAL; }
 
-void msg_encode_end(struct encode_context *ectxt) { }
+static inline void msg_encode_end(struct encode_context *ectxt) { }
 
-void ipc_log_write(void *ctxt, struct encode_context *ectxt) { }
+static inline void ipc_log_write(void *ctxt, struct encode_context *ectxt) { }
 
-int ipc_log_string(void *ilctxt, const char *fmt, ...)
+static inline int ipc_log_string(void *ilctxt, const char *fmt, ...)
 { return -EINVAL; }
 
 #define IPC_SPRINTF_DECODE(dctxt, args...) do { } while (0)
 
-void tsv_timestamp_read(struct encode_context *ectxt,
+static inline void tsv_timestamp_read(struct encode_context *ectxt,
 			struct decode_context *dctxt, const char *format) { }
 
-void tsv_pointer_read(struct encode_context *ectxt,
+static inline void tsv_pointer_read(struct encode_context *ectxt,
 		      struct decode_context *dctxt, const char *format) { }
 
-int32_t tsv_int32_read(struct encode_context *ectxt,
+static inline int32_t tsv_int32_read(struct encode_context *ectxt,
 		       struct decode_context *dctxt, const char *format)
 { return 0; }
 
-void tsv_byte_array_read(struct encode_context *ectxt,
+static inline void tsv_byte_array_read(struct encode_context *ectxt,
 			 struct decode_context *dctxt, const char *format) { }
 
-int add_deserialization_func(void *ctxt, int type,
+static inline int add_deserialization_func(void *ctxt, int type,
 			void (*dfunc)(struct encode_context *,
 				      struct decode_context *))
 { return 0; }
diff --git a/arch/arm/mach-msm/include/mach/qdsp5/audio_acdb_def.h b/arch/arm/mach-msm/include/mach/qdsp5/audio_acdb_def.h
index e1fc0cd..5fc87e0 100644
--- a/arch/arm/mach-msm/include/mach/qdsp5/audio_acdb_def.h
+++ b/arch/arm/mach-msm/include/mach/qdsp5/audio_acdb_def.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -48,4 +48,5 @@
 /* ID used for virtual devices */
 #define PSEUDO_ACDB_ID					0xFFFF
 
+int is_acdb_enabled(void);
 #endif /* _MACH_QDSP5_V2_AUDIO_ACDB_DEF_H */
diff --git a/arch/arm/mach-msm/include/mach/remote_spinlock.h b/arch/arm/mach-msm/include/mach/remote_spinlock.h
index 75b70f3..72e7337 100644
--- a/arch/arm/mach-msm/include/mach/remote_spinlock.h
+++ b/arch/arm/mach-msm/include/mach/remote_spinlock.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2009, 2011 Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2009, 2011, 2013 The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -39,7 +39,7 @@
 typedef raw_remote_spinlock_t *_remote_spinlock_t;
 
 #define remote_spinlock_id_t const char *
-#define SMEM_SPINLOCK_PID_APPS 1
+#define SPINLOCK_PID_APPS 1
 
 static inline void __raw_remote_ex_spin_lock(raw_remote_spinlock_t *lock)
 {
@@ -52,7 +52,7 @@
 "	teqeq	%0, #0\n"
 "	bne	1b"
 	: "=&r" (tmp)
-	: "r" (&lock->lock), "r" (1)
+	: "r" (&lock->lock), "r" (SPINLOCK_PID_APPS)
 	: "cc");
 
 	smp_mb();
@@ -67,7 +67,7 @@
 "	teq	%0, #0\n"
 "	strexeq	%0, %2, [%1]\n"
 	: "=&r" (tmp)
-	: "r" (&lock->lock), "r" (1)
+	: "r" (&lock->lock), "r" (SPINLOCK_PID_APPS)
 	: "cc");
 
 	if (tmp == 0) {
@@ -79,7 +79,14 @@
 
 static inline void __raw_remote_ex_spin_unlock(raw_remote_spinlock_t *lock)
 {
+	int lock_owner;
+
 	smp_mb();
+	lock_owner = readl_relaxed(&lock->lock);
+	if (lock_owner != SPINLOCK_PID_APPS) {
+		pr_err("%s: spinlock not owned by Apps (actual owner is %d)\n",
+				__func__, lock_owner);
+	}
 
 	__asm__ __volatile__(
 "	str	%1, [%0]\n"
@@ -122,7 +129,14 @@
 
 static inline void __raw_remote_swp_spin_unlock(raw_remote_spinlock_t *lock)
 {
+	int lock_owner;
+
 	smp_mb();
+	lock_owner = readl_relaxed(&lock->lock);
+	if (lock_owner != SPINLOCK_PID_APPS) {
+		pr_err("%s: spinlock not owned by Apps (actual owner is %d)\n",
+				__func__, lock_owner);
+	}
 
 	__asm__ __volatile__(
 "	str	%1, [%0]"
@@ -178,15 +192,20 @@
 static inline int __raw_remote_dek_spin_release(raw_remote_spinlock_t *lock,
 		uint32_t pid)
 {
-	return -EINVAL;
+	return -EPERM;
+}
+
+static inline int __raw_remote_dek_spin_owner(raw_remote_spinlock_t *lock)
+{
+	return -EPERM;
 }
 
 static inline void __raw_remote_sfpb_spin_lock(raw_remote_spinlock_t *lock)
 {
 	do {
-		writel_relaxed(SMEM_SPINLOCK_PID_APPS, lock);
+		writel_relaxed(SPINLOCK_PID_APPS, lock);
 		smp_mb();
-	} while (readl_relaxed(lock) != SMEM_SPINLOCK_PID_APPS);
+	} while (readl_relaxed(lock) != SPINLOCK_PID_APPS);
 }
 
 static inline int __raw_remote_sfpb_spin_trylock(raw_remote_spinlock_t *lock)
@@ -196,6 +215,14 @@
 
 static inline void __raw_remote_sfpb_spin_unlock(raw_remote_spinlock_t *lock)
 {
+	int lock_owner;
+
+	lock_owner = readl_relaxed(lock);
+	if (lock_owner != SPINLOCK_PID_APPS) {
+		pr_err("%s: spinlock not owned by Apps (actual owner is %d)\n",
+				__func__, lock_owner);
+	}
+
 	writel_relaxed(0, lock);
 	smp_mb();
 }
@@ -206,8 +233,8 @@
  * This is only to be used for situations where the processor owning
  * the spinlock has crashed and the spinlock must be released.
  *
- * @lock - lock structure
- * @pid - processor ID of processor to release
+ * @lock: lock structure
+ * @pid: processor ID of processor to release
  */
 static inline int __raw_remote_gen_spin_release(raw_remote_spinlock_t *lock,
 		uint32_t pid)
@@ -222,6 +249,20 @@
 	return ret;
 }
 
+/**
+ * Return owner of the spinlock.
+ *
+ * @lock: pointer to lock structure
+ * @returns: >= 0 owned PID; < 0 for error case
+ *
+ * Used for testing.  PID's are assumed to be 31 bits or less.
+ */
+static inline int __raw_remote_gen_spin_owner(raw_remote_spinlock_t *lock)
+{
+	rmb();
+	return readl_relaxed(&lock->lock);
+}
+
 #if defined(CONFIG_MSM_SMD) || defined(CONFIG_MSM_REMOTE_SPINLOCK_SFPB)
 int _remote_spin_lock_init(remote_spinlock_id_t, _remote_spinlock_t *lock);
 void _remote_spin_release_all(uint32_t pid);
@@ -242,6 +283,7 @@
 #define _remote_spin_trylock(lock)	__raw_remote_dek_spin_trylock(*lock)
 #define _remote_spin_release(lock, pid)	__raw_remote_dek_spin_release(*lock,\
 		pid)
+#define _remote_spin_owner(lock) __raw_remote_dek_spin_owner(*lock)
 #elif defined(CONFIG_MSM_REMOTE_SPINLOCK_SWP)
 /* Use SWP-based locks when LDREX/STREX are unavailable for shared memory. */
 #define _remote_spin_lock(lock)		__raw_remote_swp_spin_lock(*lock)
@@ -249,6 +291,7 @@
 #define _remote_spin_trylock(lock)	__raw_remote_swp_spin_trylock(*lock)
 #define _remote_spin_release(lock, pid)	__raw_remote_gen_spin_release(*lock,\
 		pid)
+#define _remote_spin_owner(lock) __raw_remote_gen_spin_owner(*lock)
 #elif defined(CONFIG_MSM_REMOTE_SPINLOCK_SFPB)
 /* Use SFPB Hardware Mutex Registers */
 #define _remote_spin_lock(lock)		__raw_remote_sfpb_spin_lock(*lock)
@@ -256,6 +299,7 @@
 #define _remote_spin_trylock(lock)	__raw_remote_sfpb_spin_trylock(*lock)
 #define _remote_spin_release(lock, pid)	__raw_remote_gen_spin_release(*lock,\
 		pid)
+#define _remote_spin_owner(lock) __raw_remote_gen_spin_owner(*lock)
 #else
 /* Use LDREX/STREX for shared memory locking, when available */
 #define _remote_spin_lock(lock)		__raw_remote_ex_spin_lock(*lock)
@@ -263,6 +307,7 @@
 #define _remote_spin_trylock(lock)	__raw_remote_ex_spin_trylock(*lock)
 #define _remote_spin_release(lock, pid)	__raw_remote_gen_spin_release(*lock, \
 		pid)
+#define _remote_spin_owner(lock) __raw_remote_gen_spin_owner(*lock)
 #endif
 
 /* Remote mutex definitions. */
diff --git a/arch/arm/mach-msm/include/mach/socinfo.h b/arch/arm/mach-msm/include/mach/socinfo.h
index c0624bb..345f09c 100644
--- a/arch/arm/mach-msm/include/mach/socinfo.h
+++ b/arch/arm/mach-msm/include/mach/socinfo.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2009-2012, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2009-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -147,7 +147,7 @@
 uint32_t socinfo_get_platform_version(void);
 enum pmic_model socinfo_get_pmic_model(void);
 uint32_t socinfo_get_pmic_die_revision(void);
-int __init socinfo_init(void) __must_check;
+struct device * __init socinfo_init(void) __must_check;
 const int read_msm_cpu_type(void);
 const int get_core_count(void);
 const int cpu_is_krait(void);
diff --git a/arch/arm/mach-msm/include/mach/sps.h b/arch/arm/mach-msm/include/mach/sps.h
index a000c3e..d61d07d 100644
--- a/arch/arm/mach-msm/include/mach/sps.h
+++ b/arch/arm/mach-msm/include/mach/sps.h
@@ -77,6 +77,8 @@
 #define SPS_BAM_OPT_IRQ_WAKEUP      (1UL << 3)
 /* Ignore external block pipe reset */
 #define SPS_BAM_NO_EXT_P_RST        (1UL << 4)
+/* Don't enable local clock gating */
+#define SPS_BAM_NO_LOCAL_CLK_GATING (1UL << 5)
 
 /* BAM device management flags */
 
@@ -1253,13 +1255,13 @@
  *
  * @tb_sel - testbus selection
  *
- * @pre_level - prescreening level
+ * @desc_sel - selection of descriptors
  *
  * @return 0 on success, negative value on error
  *
  */
 int sps_get_bam_debug_info(u32 dev, u32 option, u32 para,
-		u32 tb_sel, u8 pre_level);
+		u32 tb_sel, u8 desc_sel);
 
 #else
 static inline int sps_register_bam_device(const struct sps_bam_props
diff --git a/arch/arm/mach-msm/jtag-mm.c b/arch/arm/mach-msm/jtag-mm.c
new file mode 100644
index 0000000..af05995
--- /dev/null
+++ b/arch/arm/mach-msm/jtag-mm.c
@@ -0,0 +1,747 @@
+/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/err.h>
+#include <linux/slab.h>
+#include <linux/smp.h>
+#include <linux/export.h>
+#include <linux/printk.h>
+#include <linux/ratelimit.h>
+#include <linux/coresight.h>
+#include <linux/io.h>
+#include <linux/platform_device.h>
+#include <linux/bitops.h>
+#include <mach/scm.h>
+#include <mach/jtag.h>
+
+/* Coresight management registers */
+#define CORESIGHT_ITCTRL	(0xF00)
+#define CORESIGHT_CLAIMSET	(0xFA0)
+#define CORESIGHT_CLAIMCLR	(0xFA4)
+#define CORESIGHT_LAR		(0xFB0)
+#define CORESIGHT_LSR		(0xFB4)
+#define CORESIGHT_AUTHSTATUS	(0xFB8)
+#define CORESIGHT_DEVID		(0xFC8)
+#define CORESIGHT_DEVTYPE	(0xFCC)
+
+#define CORESIGHT_UNLOCK	(0xC5ACCE55)
+
+#define TIMEOUT_US		(100)
+
+#define BM(lsb, msb)		((BIT(msb) - BIT(lsb)) + BIT(msb))
+#define BMVAL(val, lsb, msb)	((val & BM(lsb, msb)) >> lsb)
+#define BVAL(val, n)		((val & BIT(n)) >> n)
+
+/* Trace registers */
+#define ETMCR			(0x000)
+#define ETMCCR			(0x004)
+#define ETMTRIGGER		(0x008)
+#define ETMASICCTLR		(0x00C)
+#define ETMSR			(0x010)
+#define ETMSCR			(0x014)
+#define ETMTSSCR		(0x018)
+#define ETMTECR2		(0x01C)
+#define ETMTEEVR		(0x020)
+#define ETMTECR1		(0x024)
+#define ETMFFLR			(0x02C)
+#define ETMVDEVR		(0x030)
+#define ETMVDCR1		(0x034)
+#define ETMVDCR3		(0x03C)
+#define ETMACVRn(n)		(0x040 + (n * 4))
+#define ETMACTRn(n)		(0x080 + (n * 4))
+#define ETMDCVRn(n)		(0x0C0 + (n * 8))
+#define ETMDCMRn(n)		(0x100 + (n * 8))
+#define ETMCNTRLDVRn(n)		(0x140 + (n * 4))
+#define ETMCNTENRn(n)		(0x150 + (n * 4))
+#define ETMCNTRLDEVRn(n)	(0x160 + (n * 4))
+#define ETMCNTVRn(n)		(0x170 + (n * 4))
+#define ETMSQ12EVR		(0x180)
+#define ETMSQ21EVR		(0x184)
+#define ETMSQ23EVR		(0x188)
+#define ETMSQ31EVR		(0x18C)
+#define ETMSQ32EVR		(0x190)
+#define ETMSQ13EVR		(0x194)
+#define ETMSQR			(0x19C)
+#define ETMEXTOUTEVRn(n)	(0x1A0 + (n * 4))
+#define ETMCIDCVRn(n)		(0x1B0 + (n * 4))
+#define ETMCIDCMR		(0x1BC)
+#define ETMIMPSPEC0		(0x1C0)
+#define ETMIMPSPEC1		(0x1C4)
+#define ETMIMPSPEC2		(0x1C8)
+#define ETMIMPSPEC3		(0x1CC)
+#define ETMIMPSPEC4		(0x1D0)
+#define ETMIMPSPEC5		(0x1D4)
+#define ETMIMPSPEC6		(0x1D8)
+#define ETMIMPSPEC7		(0x1DC)
+#define ETMSYNCFR		(0x1E0)
+#define ETMIDR			(0x1E4)
+#define ETMCCER			(0x1E8)
+#define ETMEXTINSELR		(0x1EC)
+#define ETMTESSEICR		(0x1F0)
+#define ETMEIBCR		(0x1F4)
+#define ETMTSEVR		(0x1F8)
+#define ETMAUXCR		(0x1FC)
+#define ETMTRACEIDR		(0x200)
+#define ETMIDR2			(0x208)
+#define ETMVMIDCVR		(0x240)
+#define ETMCLAIMSET		(0xFA0)
+#define ETMCLAIMCLR		(0xFA4)
+/* ETM Management registers */
+#define ETMOSLAR		(0x300)
+#define ETMOSLSR		(0x304)
+#define ETMOSSRR		(0x308)
+#define ETMPDCR			(0x310)
+#define ETMPDSR			(0x314)
+
+#define ETM_MAX_ADDR_CMP	(16)
+#define ETM_MAX_CNTR		(4)
+#define ETM_MAX_CTXID_CMP	(3)
+
+/* DBG Registers */
+#define DBGDIDR			(0x0)
+#define DBGWFAR			(0x18)
+#define DBGVCR			(0x1C)
+#define DBGDTRRXext		(0x80)
+#define DBGDSCRext		(0x88)
+#define DBGDTRTXext		(0x8C)
+#define DBGDRCR			(0x90)
+#define DBGBVRn(n)		(0x100 + (n * 4))
+#define DBGBCRn(n)		(0x140 + (n * 4))
+#define DBGWVRn(n)		(0x180 + (n * 4))
+#define DBGWCRn(n)		(0x1C0 + (n * 4))
+#define DBGPRCR			(0x310)
+#define DBGITMISCOUT		(0xEF8)
+#define DBGITMISCIN		(0xEFC)
+#define DBGCLAIMSET		(0xFA0)
+#define DBGCLAIMCLR		(0xFA4)
+
+#define DBGDSCR_MASK		(0x6C30FC3C)
+
+#define MAX_DBG_STATE_SIZE	(90)
+#define MAX_ETM_STATE_SIZE	(78)
+
+#define TZ_DBG_ETM_FEAT_ID	(0x8)
+#define TZ_DBG_ETM_VER		(0x400000)
+
+#define ARCH_V3_5		(0x25)
+#define ARM_DEBUG_ARCH_V7B	(0x3)
+
+#define etm_write(etm, val, off)	\
+			__raw_writel(val, etm->base + off)
+#define etm_read(etm, off)	\
+			__raw_readl(etm->base + off)
+
+#define dbg_write(dbg, val, off)	\
+			__raw_writel(val, dbg->base + off)
+#define dbg_read(dbg, off)	\
+			__raw_readl(dbg->base + off)
+
+#define ETM_LOCK(base)						\
+do {									\
+	/* recommended by spec to ensure ETM writes are committed prior
+	 * to resuming execution
+	 */								\
+	mb();								\
+	etm_write(base, 0x0, CORESIGHT_LAR);			\
+} while (0)
+
+#define ETM_UNLOCK(base)						\
+do {									\
+	etm_write(base, CORESIGHT_UNLOCK, CORESIGHT_LAR);	\
+	/* ensure unlock and any pending writes are committed prior to
+	 * programming ETM registers
+	 */								\
+	mb();								\
+} while (0)
+
+#define DBG_LOCK(base)						\
+do {									\
+	/* recommended by spec to ensure ETM writes are committed prior
+	 * to resuming execution
+	 */								\
+	mb();								\
+	dbg_write(base, 0x0, CORESIGHT_LAR);			\
+} while (0)
+
+#define DBG_UNLOCK(base)						\
+do {									\
+	dbg_write(base, CORESIGHT_UNLOCK, CORESIGHT_LAR);	\
+	/* ensure unlock and any pending writes are committed prior to
+	 * programming ETM registers
+	 */								\
+	mb();								\
+} while (0)
+
+uint32_t msm_jtag_save_cntr[NR_CPUS];
+uint32_t msm_jtag_restore_cntr[NR_CPUS];
+
+struct dbg_cpu_ctx {
+	void __iomem		*base;
+	uint32_t		*state;
+};
+
+struct dbg_ctx {
+	uint8_t			arch;
+	uint8_t			nr_wp;
+	uint8_t			nr_bp;
+	uint8_t			nr_ctx_cmp;
+	struct dbg_cpu_ctx	*cpu_ctx[NR_CPUS];
+	bool			save_restore_enabled[NR_CPUS];
+};
+static struct dbg_ctx dbg;
+
+struct etm_cpu_ctx {
+	void __iomem		*base;
+	struct device		*dev;
+	uint32_t		*state;
+};
+
+struct etm_ctx {
+	uint8_t			arch;
+	uint8_t			nr_addr_cmp;
+	uint8_t			nr_data_cmp;
+	uint8_t			nr_cntr;
+	uint8_t			nr_ext_inp;
+	uint8_t			nr_ext_out;
+	uint8_t			nr_ctxid_cmp;
+	struct etm_cpu_ctx	*cpu_ctx[NR_CPUS];
+	bool			save_restore_enabled[NR_CPUS];
+};
+
+static struct etm_ctx etm;
+
+static struct clk *clock[NR_CPUS];
+
+static void etm_set_pwrdwn(struct etm_cpu_ctx *etmdata)
+{
+	uint32_t etmcr;
+
+	/* ensure all writes are complete before setting pwrdwn */
+	mb();
+	etmcr = etm_read(etmdata, ETMCR);
+	etmcr |= BIT(0);
+	etm_write(etmdata, etmcr, ETMCR);
+}
+
+static void etm_clr_pwrdwn(struct etm_cpu_ctx *etmdata)
+{
+	uint32_t etmcr;
+
+	etmcr = etm_read(etmdata, ETMCR);
+	etmcr &= ~BIT(0);
+	etm_write(etmdata, etmcr, ETMCR);
+	/* ensure pwrup completes before subsequent register accesses */
+	mb();
+}
+
+static void etm_set_prog(struct etm_cpu_ctx *etmdata)
+{
+	uint32_t etmcr;
+	int count;
+
+	etmcr = etm_read(etmdata, ETMCR);
+	etmcr |= BIT(10);
+	etm_write(etmdata, etmcr, ETMCR);
+	for (count = TIMEOUT_US; BVAL(etm_read(etmdata, ETMSR), 1) != 1
+				&& count > 0; count--)
+		udelay(1);
+	WARN(count == 0, "timeout while setting prog bit, ETMSR: %#x\n",
+	     etm_read(etmdata, ETMSR));
+}
+
+static inline void etm_save_state(struct etm_cpu_ctx *etmdata)
+{
+	int i, j;
+
+	i = 0;
+	ETM_UNLOCK(etmdata);
+
+	switch (etm.arch) {
+	case ETM_ARCH_V3_5:
+		etmdata->state[i++] = etm_read(etmdata, ETMTRIGGER);
+		etmdata->state[i++] = etm_read(etmdata, ETMASICCTLR);
+		etmdata->state[i++] = etm_read(etmdata, ETMSR);
+		etmdata->state[i++] = etm_read(etmdata, ETMTSSCR);
+		etmdata->state[i++] = etm_read(etmdata, ETMTECR2);
+		etmdata->state[i++] = etm_read(etmdata, ETMTEEVR);
+		etmdata->state[i++] = etm_read(etmdata, ETMTECR1);
+		etmdata->state[i++] = etm_read(etmdata, ETMFFLR);
+		etmdata->state[i++] = etm_read(etmdata, ETMVDEVR);
+		etmdata->state[i++] = etm_read(etmdata, ETMVDCR1);
+		etmdata->state[i++] = etm_read(etmdata, ETMVDCR3);
+		for (j = 0; j < etm.nr_addr_cmp; j++) {
+			etmdata->state[i++] = etm_read(etmdata,
+								ETMACVRn(j));
+			etmdata->state[i++] = etm_read(etmdata,
+								ETMACTRn(j));
+		}
+		for (j = 0; j < etm.nr_data_cmp; j++) {
+			etmdata->state[i++] = etm_read(etmdata,
+								ETMDCVRn(j));
+			etmdata->state[i++] = etm_read(etmdata,
+								ETMDCMRn(j));
+		}
+		for (j = 0; j < etm.nr_cntr; j++) {
+			etmdata->state[i++] = etm_read(etmdata,
+							ETMCNTRLDVRn(j));
+			etmdata->state[i++] = etm_read(etmdata,
+							ETMCNTENRn(j));
+			etmdata->state[i++] = etm_read(etmdata,
+							ETMCNTRLDEVRn(j));
+			etmdata->state[i++] = etm_read(etmdata,
+							ETMCNTVRn(j));
+		}
+		etmdata->state[i++] = etm_read(etmdata, ETMSQ12EVR);
+		etmdata->state[i++] = etm_read(etmdata, ETMSQ21EVR);
+		etmdata->state[i++] = etm_read(etmdata, ETMSQ23EVR);
+		etmdata->state[i++] = etm_read(etmdata, ETMSQ31EVR);
+		etmdata->state[i++] = etm_read(etmdata, ETMSQ32EVR);
+		etmdata->state[i++] = etm_read(etmdata, ETMSQ13EVR);
+		etmdata->state[i++] = etm_read(etmdata, ETMSQR);
+		for (j = 0; j < etm.nr_ext_out; j++)
+			etmdata->state[i++] = etm_read(etmdata,
+							ETMEXTOUTEVRn(j));
+		for (j = 0; j < etm.nr_ctxid_cmp; j++)
+			etmdata->state[i++] = etm_read(etmdata,
+							ETMCIDCVRn(j));
+		etmdata->state[i++] = etm_read(etmdata, ETMCIDCMR);
+		etmdata->state[i++] = etm_read(etmdata, ETMSYNCFR);
+		etmdata->state[i++] = etm_read(etmdata, ETMEXTINSELR);
+		etmdata->state[i++] = etm_read(etmdata, ETMTSEVR);
+		etmdata->state[i++] = etm_read(etmdata, ETMAUXCR);
+		etmdata->state[i++] = etm_read(etmdata, ETMTRACEIDR);
+		etmdata->state[i++] = etm_read(etmdata, ETMVMIDCVR);
+		etmdata->state[i++] = etm_read(etmdata, ETMCLAIMCLR);
+		etmdata->state[i++] = etm_read(etmdata, ETMCR);
+		break;
+	default:
+		pr_err_ratelimited("unsupported etm arch %d in %s\n", etm.arch,
+								__func__);
+	}
+
+	ETM_LOCK(etmdata);
+}
+
+static inline void etm_restore_state(struct etm_cpu_ctx *etmdata)
+{
+	int i, j;
+
+	i = 0;
+	ETM_UNLOCK(etmdata);
+
+	switch (etm.arch) {
+	case ETM_ARCH_V3_5:
+		etm_clr_pwrdwn(etmdata);
+		etm_write(etmdata, etmdata->state[i++], ETMTRIGGER);
+		etm_write(etmdata, etmdata->state[i++], ETMASICCTLR);
+		etm_write(etmdata, etmdata->state[i++], ETMSR);
+		etm_write(etmdata, etmdata->state[i++], ETMTSSCR);
+		etm_write(etmdata, etmdata->state[i++], ETMTECR2);
+		etm_write(etmdata, etmdata->state[i++], ETMTEEVR);
+		etm_write(etmdata, etmdata->state[i++], ETMTECR1);
+		etm_write(etmdata, etmdata->state[i++], ETMFFLR);
+		etm_write(etmdata, etmdata->state[i++], ETMVDEVR);
+		etm_write(etmdata, etmdata->state[i++], ETMVDCR1);
+		etm_write(etmdata, etmdata->state[i++], ETMVDCR3);
+		for (j = 0; j < etm.nr_addr_cmp; j++) {
+			etm_write(etmdata, etmdata->state[i++],
+								ETMACVRn(j));
+			etm_write(etmdata, etmdata->state[i++],
+								ETMACTRn(j));
+		}
+		for (j = 0; j < etm.nr_data_cmp; j++) {
+			etm_write(etmdata, etmdata->state[i++],
+								ETMDCVRn(j));
+			etm_write(etmdata, etmdata->state[i++],
+								ETMDCMRn(j));
+		}
+		for (j = 0; j < etm.nr_cntr; j++) {
+			etm_write(etmdata, etmdata->state[i++],
+							ETMCNTRLDVRn(j));
+			etm_write(etmdata, etmdata->state[i++],
+							ETMCNTENRn(j));
+			etm_write(etmdata, etmdata->state[i++],
+							ETMCNTRLDEVRn(j));
+			etm_write(etmdata, etmdata->state[i++],
+							ETMCNTVRn(j));
+		}
+		etm_write(etmdata, etmdata->state[i++], ETMSQ12EVR);
+		etm_write(etmdata, etmdata->state[i++], ETMSQ21EVR);
+		etm_write(etmdata, etmdata->state[i++], ETMSQ23EVR);
+		etm_write(etmdata, etmdata->state[i++], ETMSQ31EVR);
+		etm_write(etmdata, etmdata->state[i++], ETMSQ32EVR);
+		etm_write(etmdata, etmdata->state[i++], ETMSQ13EVR);
+		etm_write(etmdata, etmdata->state[i++], ETMSQR);
+		for (j = 0; j < etm.nr_ext_out; j++)
+			etm_write(etmdata, etmdata->state[i++],
+							ETMEXTOUTEVRn(j));
+		for (j = 0; j < etm.nr_ctxid_cmp; j++)
+			etm_write(etmdata, etmdata->state[i++],
+							ETMCIDCVRn(j));
+		etm_write(etmdata, etmdata->state[i++], ETMCIDCMR);
+		etm_write(etmdata, etmdata->state[i++], ETMSYNCFR);
+		etm_write(etmdata, etmdata->state[i++], ETMEXTINSELR);
+		etm_write(etmdata, etmdata->state[i++], ETMTSEVR);
+		etm_write(etmdata, etmdata->state[i++], ETMAUXCR);
+		etm_write(etmdata, etmdata->state[i++], ETMTRACEIDR);
+		etm_write(etmdata, etmdata->state[i++], ETMVMIDCVR);
+		etm_write(etmdata, etmdata->state[i++], ETMCLAIMSET);
+		/*
+		 * Set ETMCR at last as we dont know the saved status of pwrdwn
+		 * bit
+		 */
+		etm_write(etmdata, etmdata->state[i++], ETMCR);
+		break;
+	default:
+		pr_err_ratelimited("unsupported etm arch %d in %s\n", etm.arch,
+								__func__);
+	}
+
+	ETM_LOCK(etmdata);
+}
+
+static inline void dbg_save_state(struct dbg_cpu_ctx *dbgdata)
+{
+	int i, j;
+
+	i = 0;
+	DBG_UNLOCK(dbgdata);
+
+	dbgdata->state[i++] =  dbg_read(dbgdata, DBGWFAR);
+	dbgdata->state[i++] =  dbg_read(dbgdata, DBGVCR);
+	for (j = 0; j < dbg.nr_bp; j++) {
+		dbgdata->state[i++] =  dbg_read(dbgdata, DBGBVRn(j));
+		dbgdata->state[i++] =  dbg_read(dbgdata, DBGBCRn(j));
+	}
+	for (j = 0; j < dbg.nr_wp; j++) {
+		dbgdata->state[i++] =  dbg_read(dbgdata, DBGWVRn(j));
+		dbgdata->state[i++] =  dbg_read(dbgdata, DBGWCRn(j));
+	}
+	dbgdata->state[i++] =  dbg_read(dbgdata, DBGPRCR);
+	dbgdata->state[i++] =  dbg_read(dbgdata, DBGCLAIMSET);
+	dbgdata->state[i++] =  dbg_read(dbgdata, DBGCLAIMCLR);
+	dbgdata->state[i++] =  dbg_read(dbgdata, DBGDTRTXext);
+	dbgdata->state[i++] =  dbg_read(dbgdata, DBGDTRRXext);
+	dbgdata->state[i++] =  dbg_read(dbgdata, DBGDSCRext);
+
+	DBG_LOCK(dbgdata);
+}
+
+static inline void dbg_restore_state(struct dbg_cpu_ctx *dbgdata)
+{
+	int i, j;
+
+	i = 0;
+	DBG_UNLOCK(dbgdata);
+
+	dbg_write(dbgdata, dbgdata->state[i++], DBGWFAR);
+	dbg_write(dbgdata, dbgdata->state[i++], DBGVCR);
+	for (j = 0; j < dbg.nr_bp; j++) {
+		dbg_write(dbgdata, dbgdata->state[i++], DBGBVRn(j));
+		dbg_write(dbgdata, dbgdata->state[i++], DBGBCRn(j));
+	}
+	for (j = 0; j < dbg.nr_wp; j++) {
+		dbg_write(dbgdata, dbgdata->state[i++], DBGWVRn(j));
+		dbg_write(dbgdata, dbgdata->state[i++], DBGWCRn(j));
+	}
+	dbg_write(dbgdata, dbgdata->state[i++], DBGPRCR);
+	dbg_write(dbgdata, dbgdata->state[i++], DBGCLAIMSET);
+	dbg_write(dbgdata, dbgdata->state[i++], DBGCLAIMCLR);
+	dbg_write(dbgdata, dbgdata->state[i++], DBGDTRTXext);
+	dbg_write(dbgdata, dbgdata->state[i++], DBGDTRRXext);
+	dbg_write(dbgdata, dbgdata->state[i++] & DBGDSCR_MASK,
+								DBGDSCRext);
+
+	DBG_LOCK(dbgdata);
+}
+
+void msm_jtag_save_state(void)
+{
+	int cpu;
+
+	cpu = raw_smp_processor_id();
+
+	msm_jtag_save_cntr[cpu]++;
+	/* ensure counter is updated before moving forward */
+	mb();
+
+	if (dbg.save_restore_enabled[cpu])
+		dbg_save_state(dbg.cpu_ctx[cpu]);
+	if (etm.save_restore_enabled[cpu])
+		etm_save_state(etm.cpu_ctx[cpu]);
+}
+EXPORT_SYMBOL(msm_jtag_save_state);
+
+void msm_jtag_restore_state(void)
+{
+	int cpu;
+
+	cpu = raw_smp_processor_id();
+
+	/* Attempt restore only if save has been done. If power collapse
+	 * is disabled, hotplug off of non-boot core will result in WFI
+	 * and hence msm_jtag_save_state will not occur. Subsequently,
+	 * during hotplug on of non-boot core when msm_jtag_restore_state
+	 * is called via msm_platform_secondary_init, this check will help
+	 * bail us out without restoring.
+	 */
+	if (msm_jtag_save_cntr[cpu] == msm_jtag_restore_cntr[cpu])
+		return;
+	else if (msm_jtag_save_cntr[cpu] != msm_jtag_restore_cntr[cpu] + 1)
+		pr_err_ratelimited("jtag imbalance, save:%lu, restore:%lu\n",
+				   (unsigned long)msm_jtag_save_cntr[cpu],
+				   (unsigned long)msm_jtag_restore_cntr[cpu]);
+
+	msm_jtag_restore_cntr[cpu]++;
+	/* ensure counter is updated before moving forward */
+	mb();
+
+	if (dbg.save_restore_enabled[cpu])
+		dbg_restore_state(dbg.cpu_ctx[cpu]);
+	if (etm.save_restore_enabled[cpu])
+		etm_restore_state(etm.cpu_ctx[cpu]);
+}
+EXPORT_SYMBOL(msm_jtag_restore_state);
+
+static inline bool etm_arch_supported(uint8_t arch)
+{
+	switch (arch) {
+	case ETM_ARCH_V3_5:
+		break;
+	default:
+		return false;
+	}
+	return true;
+}
+
+static void __devinit etm_init_arch_data(void *info)
+{
+	uint32_t etmidr;
+	uint32_t etmccr;
+	struct etm_cpu_ctx  *etmdata = info;
+
+	/*
+	 * Clear power down bit since when this bit is set writes to
+	 * certain registers might be ignored.
+	 */
+	ETM_UNLOCK(etmdata);
+
+	etm_clr_pwrdwn(etmdata);
+	/* Set prog bit. It will be set from reset but this is included to
+	 * ensure it is set
+	 */
+	etm_set_prog(etmdata);
+
+	/* find all capabilities */
+	etmidr = etm_read(etmdata, ETMIDR);
+	etm.arch = BMVAL(etmidr, 4, 11);
+
+	etmccr = etm_read(etmdata, ETMCCR);
+	etm.nr_addr_cmp = BMVAL(etmccr, 0, 3) * 2;
+	etm.nr_data_cmp = BMVAL(etmccr, 4, 7);
+	etm.nr_cntr = BMVAL(etmccr, 13, 15);
+	etm.nr_ext_inp = BMVAL(etmccr, 17, 19);
+	etm.nr_ext_out = BMVAL(etmccr, 20, 22);
+	etm.nr_ctxid_cmp = BMVAL(etmccr, 24, 25);
+
+	etm_set_pwrdwn(etmdata);
+
+	ETM_LOCK(etmdata);
+}
+
+static int __devinit jtag_mm_etm_probe(struct platform_device *pdev,
+								uint32_t cpu)
+{
+	struct etm_cpu_ctx *etmdata;
+	struct resource *res;
+	struct device *dev = &pdev->dev;
+
+	/* Allocate memory per cpu */
+	etmdata = devm_kzalloc(dev, sizeof(struct etm_cpu_ctx), GFP_KERNEL);
+	if (!etmdata)
+		return -ENOMEM;
+
+	etm.cpu_ctx[cpu] = etmdata;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+
+	etmdata->base = devm_ioremap(dev, res->start, resource_size(res));
+	if (!etmdata->base)
+		return -EINVAL;
+
+	/* Allocate etm state save space per core */
+	etmdata->state = devm_kzalloc(dev,
+			(MAX_ETM_STATE_SIZE * sizeof(uint32_t)), GFP_KERNEL);
+	if (!etmdata->state)
+		return -ENOMEM;
+
+	smp_call_function_single(0, etm_init_arch_data, etmdata, 1);
+
+	if (etm_arch_supported(etm.arch)) {
+		if (scm_get_feat_version(TZ_DBG_ETM_FEAT_ID) < TZ_DBG_ETM_VER)
+			etm.save_restore_enabled[cpu] = true;
+		else
+			pr_info("etm save-restore supported by TZ\n");
+	} else
+		pr_info("etm arch %u not supported\n", etm.arch);
+	return 0;
+}
+
+static inline bool dbg_arch_supported(uint8_t arch)
+{
+	switch (arch) {
+	case ARM_DEBUG_ARCH_V7B:
+		break;
+	default:
+		return false;
+	}
+	return true;
+}
+
+static void __devinit dbg_init_arch_data(void *info)
+{
+	uint32_t dbgdidr;
+	struct dbg_cpu_ctx *dbgdata = info;
+
+	/* This will run on core0 so use it to populate parameters */
+	dbgdidr = dbg_read(dbgdata, DBGDIDR);
+	dbg.arch = BMVAL(dbgdidr, 16, 19);
+	dbg.nr_ctx_cmp = BMVAL(dbgdidr, 20, 23) + 1;
+	dbg.nr_bp = BMVAL(dbgdidr, 24, 27) + 1;
+	dbg.nr_wp = BMVAL(dbgdidr, 28, 31) + 1;
+}
+
+
+
+static int __devinit jtag_mm_dbg_probe(struct platform_device *pdev,
+								uint32_t cpu)
+{
+	struct dbg_cpu_ctx *dbgdata;
+	struct resource *res;
+	struct device *dev = &pdev->dev;
+
+	/* Allocate memory per cpu */
+	dbgdata = devm_kzalloc(dev, sizeof(struct dbg_cpu_ctx), GFP_KERNEL);
+	if (!dbgdata)
+		return -ENOMEM;
+
+	dbg.cpu_ctx[cpu] = dbgdata;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+
+	dbgdata->base = devm_ioremap(dev, res->start, resource_size(res));
+	if (!dbgdata->base)
+		return -EINVAL;
+
+	/* Allocate etm state save space per core */
+	dbgdata->state = devm_kzalloc(dev,
+			(MAX_DBG_STATE_SIZE * sizeof(uint32_t)), GFP_KERNEL);
+	if (!dbgdata->state)
+		return -ENOMEM;
+
+	smp_call_function_single(0, dbg_init_arch_data, dbgdata, 1);
+
+	if (dbg_arch_supported(dbg.arch)) {
+		if (scm_get_feat_version(TZ_DBG_ETM_FEAT_ID) < TZ_DBG_ETM_VER)
+			dbg.save_restore_enabled[cpu] = true;
+		else
+			pr_info("dbg save-restore supported by TZ\n");
+	} else
+		pr_info("dbg arch %u not supported\n", dbg.arch);
+	return 0;
+}
+
+static int __devinit jtag_mm_probe(struct platform_device *pdev)
+{
+	int etm_ret, dbg_ret, ret;
+	static uint32_t cpu;
+	static uint32_t count;
+	struct device *dev = &pdev->dev;
+
+	cpu = count;
+	count++;
+
+	clock[cpu] = devm_clk_get(dev, "core_clk");
+	if (IS_ERR(clock[cpu])) {
+		ret = PTR_ERR(clock[cpu]);
+		return ret;
+	}
+
+	ret = clk_set_rate(clock[cpu], CORESIGHT_CLK_RATE_TRACE);
+	if (ret)
+		return ret;
+
+	ret = clk_prepare_enable(clock[cpu]);
+	if (ret)
+		return ret;
+
+	platform_set_drvdata(pdev, clock[cpu]);
+
+	etm_ret  = jtag_mm_etm_probe(pdev, cpu);
+
+	dbg_ret = jtag_mm_dbg_probe(pdev, cpu);
+
+	/* The probe succeeds even when only one of the etm and dbg probes
+	 * succeeds. This allows us to save-restore etm and dbg registers
+	 * independently.
+	 */
+	if (etm_ret && dbg_ret) {
+		clk_disable_unprepare(clock[cpu]);
+		ret = etm_ret;
+	} else
+		ret = 0;
+	return ret;
+}
+
+static int __devexit jtag_mm_remove(struct platform_device *pdev)
+{
+	struct clk *clock = platform_get_drvdata(pdev);
+
+	clk_disable_unprepare(clock);
+	return 0;
+}
+
+static struct of_device_id msm_qdss_mm_match[] = {
+	{ .compatible = "qcom,jtag-mm"},
+	{}
+};
+
+static struct platform_driver jtag_mm_driver = {
+	.probe          = jtag_mm_probe,
+	.remove         = __devexit_p(jtag_mm_remove),
+	.driver         = {
+		.name   = "msm-jtag-mm",
+		.owner	= THIS_MODULE,
+		.of_match_table	= msm_qdss_mm_match,
+		},
+};
+
+static int __init jtag_mm_init(void)
+{
+	return platform_driver_register(&jtag_mm_driver);
+}
+module_init(jtag_mm_init);
+
+static void __exit jtag_mm_exit(void)
+{
+	platform_driver_unregister(&jtag_mm_driver);
+}
+module_exit(jtag_mm_exit);
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("Coresight debug and ETM save-restore driver");
diff --git a/arch/arm/mach-msm/kernel_test_service_v01.c b/arch/arm/mach-msm/kernel_test_service_v01.c
new file mode 100644
index 0000000..498e046
--- /dev/null
+++ b/arch/arm/mach-msm/kernel_test_service_v01.c
@@ -0,0 +1,254 @@
+/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/qmi_encdec.h>
+
+#include <mach/msm_qmi_interface.h>
+
+#include "kernel_test_service_v01.h"
+
+#define PING_REQ1_TLV_TYPE 0x1
+#define PING_RESP1_TLV_TYPE 0x2
+#define PING_OPT1_TLV_TYPE 0x10
+#define PING_OPT2_TLV_TYPE 0x11
+
+#define DATA_REQ1_TLV_TYPE 0x1
+#define DATA_RESP1_TLV_TYPE 0x2
+#define DATA_OPT1_TLV_TYPE 0x10
+#define DATA_OPT2_TLV_TYPE 0x11
+
+static struct elem_info test_name_type_v01_ei[] = {
+	{
+		.data_type      = QMI_DATA_LEN,
+		.elem_len	= 1,
+		.elem_size      = sizeof(uint8_t),
+		.is_array	= NO_ARRAY,
+		.tlv_type	= QMI_COMMON_TLV_TYPE,
+		.offset		= offsetof(struct test_name_type_v01,
+					   name_len),
+	},
+	{
+		.data_type      = QMI_UNSIGNED_1_BYTE,
+		.elem_len       = TEST_MAX_NAME_SIZE_V01,
+		.elem_size      = sizeof(char),
+		.is_array       = VAR_LEN_ARRAY,
+		.tlv_type       = QMI_COMMON_TLV_TYPE,
+		.offset         = offsetof(struct test_name_type_v01,
+					   name),
+	},
+	{
+		.data_type      = QMI_EOTI,
+		.is_array       = NO_ARRAY,
+		.tlv_type       = QMI_COMMON_TLV_TYPE,
+	},
+};
+
+struct elem_info test_ping_req_msg_v01_ei[] = {
+	{
+		.data_type      = QMI_UNSIGNED_1_BYTE,
+		.elem_len       = 4,
+		.elem_size      = sizeof(char),
+		.is_array       = STATIC_ARRAY,
+		.tlv_type       = PING_REQ1_TLV_TYPE,
+		.offset         = offsetof(struct test_ping_req_msg_v01,
+					   ping),
+	},
+	{
+		.data_type      = QMI_OPT_FLAG,
+		.elem_len       = 1,
+		.elem_size      = sizeof(uint8_t),
+		.is_array       = NO_ARRAY,
+		.tlv_type       = PING_OPT1_TLV_TYPE,
+		.offset         = offsetof(struct test_ping_req_msg_v01,
+					   client_name_valid),
+	},
+	{
+		.data_type      = QMI_STRUCT,
+		.elem_len       = 1,
+		.elem_size      = sizeof(struct test_name_type_v01),
+		.is_array       = NO_ARRAY,
+		.tlv_type       = PING_OPT1_TLV_TYPE,
+		.offset         = offsetof(struct test_ping_req_msg_v01,
+					   client_name),
+		.ei_array       = test_name_type_v01_ei,
+	},
+	{
+		.data_type      = QMI_EOTI,
+		.is_array       = NO_ARRAY,
+		.tlv_type       = QMI_COMMON_TLV_TYPE,
+	},
+};
+
+struct elem_info test_ping_resp_msg_v01_ei[] = {
+	{
+		.data_type      = QMI_STRUCT,
+		.elem_len       = 1,
+		.elem_size      = sizeof(struct qmi_response_type_v01),
+		.is_array       = NO_ARRAY,
+		.tlv_type       = PING_RESP1_TLV_TYPE,
+		.offset         = offsetof(struct test_ping_resp_msg_v01,
+					   resp),
+		.ei_array       = get_qmi_response_type_v01_ei(),
+	},
+	{
+		.data_type      = QMI_OPT_FLAG,
+		.elem_len       = 1,
+		.elem_size      = sizeof(uint8_t),
+		.is_array       = NO_ARRAY,
+		.tlv_type       = PING_OPT1_TLV_TYPE,
+		.offset         = offsetof(struct test_ping_resp_msg_v01,
+					   pong_valid),
+	},
+	{
+		.data_type      = QMI_UNSIGNED_1_BYTE,
+		.elem_len       = 4,
+		.elem_size      = sizeof(char),
+		.is_array       = STATIC_ARRAY,
+		.tlv_type       = PING_OPT1_TLV_TYPE,
+		.offset         = offsetof(struct test_ping_resp_msg_v01,
+					   pong),
+	},
+	{
+		.data_type      = QMI_OPT_FLAG,
+		.elem_len       = 1,
+		.elem_size      = sizeof(uint8_t),
+		.is_array       = NO_ARRAY,
+		.tlv_type       = PING_OPT2_TLV_TYPE,
+		.offset         = offsetof(struct test_ping_resp_msg_v01,
+					   service_name_valid),
+	},
+	{
+		.data_type      = QMI_STRUCT,
+		.elem_len       = 1,
+		.elem_size      = sizeof(struct test_name_type_v01),
+		.is_array       = NO_ARRAY,
+		.tlv_type       = PING_OPT2_TLV_TYPE,
+		.offset         = offsetof(struct test_ping_resp_msg_v01,
+					   service_name),
+		.ei_array       = test_name_type_v01_ei,
+	},
+	{
+		.data_type      = QMI_EOTI,
+		.is_array       = NO_ARRAY,
+		.tlv_type       = QMI_COMMON_TLV_TYPE,
+	},
+};
+
+struct elem_info test_data_req_msg_v01_ei[] = {
+	{
+		.data_type      = QMI_DATA_LEN,
+		.elem_len       = 1,
+		.elem_size      = sizeof(uint32_t),
+		.is_array       = NO_ARRAY,
+		.tlv_type       = DATA_REQ1_TLV_TYPE,
+		.offset         = offsetof(struct test_data_req_msg_v01,
+					   data_len),
+	},
+	{
+		.data_type      = QMI_UNSIGNED_1_BYTE,
+		.elem_len       = TEST_MED_DATA_SIZE_V01,
+		.elem_size      = sizeof(uint8_t),
+		.is_array       = VAR_LEN_ARRAY,
+		.tlv_type       = DATA_REQ1_TLV_TYPE,
+		.offset         = offsetof(struct test_data_req_msg_v01,
+					   data),
+	},
+	{
+		.data_type      = QMI_OPT_FLAG,
+		.elem_len       = 1,
+		.elem_size      = sizeof(uint8_t),
+		.is_array       = NO_ARRAY,
+		.tlv_type       = DATA_OPT1_TLV_TYPE,
+		.offset         = offsetof(struct test_data_req_msg_v01,
+					   client_name_valid),
+	},
+	{
+		.data_type      = QMI_STRUCT,
+		.elem_len       = 1,
+		.elem_size      = sizeof(struct test_name_type_v01),
+		.is_array       = NO_ARRAY,
+		.tlv_type       = DATA_OPT1_TLV_TYPE,
+		.offset         = offsetof(struct test_data_req_msg_v01,
+					   client_name),
+		.ei_array       = test_name_type_v01_ei,
+	},
+	{
+		.data_type      = QMI_EOTI,
+		.is_array       = NO_ARRAY,
+		.tlv_type       = QMI_COMMON_TLV_TYPE,
+	},
+};
+
+struct elem_info test_data_resp_msg_v01_ei[] = {
+	{
+		.data_type      = QMI_STRUCT,
+		.elem_len       = 1,
+		.elem_size      = sizeof(struct qmi_response_type_v01),
+		.is_array       = NO_ARRAY,
+		.tlv_type       = DATA_RESP1_TLV_TYPE,
+		.offset         = offsetof(struct test_data_resp_msg_v01,
+					   resp),
+		.ei_array       = get_qmi_response_type_v01_ei(),
+	},
+	{
+		.data_type      = QMI_OPT_FLAG,
+		.elem_len       = 1,
+		.elem_size      = sizeof(uint8_t),
+		.is_array       = NO_ARRAY,
+		.tlv_type       = DATA_OPT1_TLV_TYPE,
+		.offset         = offsetof(struct test_data_resp_msg_v01,
+					   data_valid),
+	},
+	{
+		.data_type      = QMI_DATA_LEN,
+		.elem_len       = 1,
+		.elem_size      = sizeof(uint32_t),
+		.is_array       = NO_ARRAY,
+		.tlv_type       = DATA_OPT1_TLV_TYPE,
+		.offset         = offsetof(struct test_data_resp_msg_v01,
+					   data_len),
+	},
+	{
+		.data_type      = QMI_UNSIGNED_1_BYTE,
+		.elem_len       = TEST_MED_DATA_SIZE_V01,
+		.elem_size      = sizeof(uint8_t),
+		.is_array       = VAR_LEN_ARRAY,
+		.tlv_type       = DATA_OPT1_TLV_TYPE,
+		.offset         = offsetof(struct test_data_resp_msg_v01,
+					   data),
+	},
+	{
+		.data_type      = QMI_OPT_FLAG,
+		.elem_len       = 1,
+		.elem_size      = sizeof(uint8_t),
+		.is_array       = NO_ARRAY,
+		.tlv_type       = DATA_OPT2_TLV_TYPE,
+		.offset         = offsetof(struct test_data_resp_msg_v01,
+					   service_name_valid),
+	},
+	{
+		.data_type      = QMI_STRUCT,
+		.elem_len       = 1,
+		.elem_size      = sizeof(struct test_name_type_v01),
+		.is_array       = NO_ARRAY,
+		.tlv_type       = DATA_OPT2_TLV_TYPE,
+		.offset         = offsetof(struct test_data_resp_msg_v01,
+					   service_name),
+		.ei_array       = test_name_type_v01_ei,
+	},
+	{
+		.data_type      = QMI_EOTI,
+		.is_array       = NO_ARRAY,
+		.tlv_type       = QMI_COMMON_TLV_TYPE,
+	},
+};
diff --git a/arch/arm/mach-msm/kernel_test_service_v01.h b/arch/arm/mach-msm/kernel_test_service_v01.h
new file mode 100644
index 0000000..79c1845
--- /dev/null
+++ b/arch/arm/mach-msm/kernel_test_service_v01.h
@@ -0,0 +1,73 @@
+/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+#ifndef MSM_QMI_TEST_SERVICE_V01_H
+#define MSM_QMI_TEST_SERVICE_V01_H
+
+#include <mach/msm_qmi_interface.h>
+
+#define TEST_MED_DATA_SIZE_V01 8192
+#define TEST_MAX_NAME_SIZE_V01 255
+
+#define TEST_PING_REQ_MSG_ID_V01 0x20
+#define TEST_DATA_REQ_MSG_ID_V01 0x21
+
+#define TEST_PING_REQ_MAX_MSG_LEN_V01 266
+#define TEST_DATA_REQ_MAX_MSG_LEN_V01 8456
+
+struct test_name_type_v01 {
+	uint32_t name_len;
+	char name[TEST_MAX_NAME_SIZE_V01];
+};
+
+struct test_ping_req_msg_v01 {
+	char ping[4];
+
+	uint8_t client_name_valid;
+	struct test_name_type_v01 client_name;
+};
+
+struct test_ping_resp_msg_v01 {
+	struct qmi_response_type_v01 resp;
+
+	uint8_t pong_valid;
+	char pong[4];
+
+	uint8_t service_name_valid;
+	struct test_name_type_v01 service_name;
+};
+
+struct test_data_req_msg_v01 {
+	uint32_t data_len;
+	uint8_t data[TEST_MED_DATA_SIZE_V01];
+
+	uint8_t client_name_valid;
+	struct test_name_type_v01 client_name;
+};
+
+struct test_data_resp_msg_v01 {
+	struct qmi_response_type_v01 resp;
+
+	uint8_t data_valid;
+	uint32_t data_len;
+	uint8_t data[TEST_MED_DATA_SIZE_V01];
+
+	uint8_t service_name_valid;
+	struct test_name_type_v01 service_name;
+};
+
+extern struct elem_info test_ping_req_msg_v01_ei[];
+extern struct elem_info test_data_req_msg_v01_ei[];
+extern struct elem_info test_ping_resp_msg_v01_ei[];
+extern struct elem_info test_data_resp_msg_v01_ei[];
+
+#endif
diff --git a/arch/arm/mach-msm/mpm-8625.c b/arch/arm/mach-msm/mpm-8625.c
index aaac476..06c0606 100644
--- a/arch/arm/mach-msm/mpm-8625.c
+++ b/arch/arm/mach-msm/mpm-8625.c
@@ -101,7 +101,7 @@
 
 static uint16_t msm_bypassed_apps_irqs[] = {
 	MSM8625_INT_CPR_IRQ0,
-	MSM8625_INT_L2CC_INTR,
+	MSM8625_INT_SC_SICL2PERFMONIRPTREQ,
 };
 
 /* Check IRQ falls into bypassed list are not */
diff --git a/arch/arm/mach-msm/msm_bus/msm_bus_fabric.c b/arch/arm/mach-msm/msm_bus/msm_bus_fabric.c
index b6870c6..2c4b434 100644
--- a/arch/arm/mach-msm/msm_bus/msm_bus_fabric.c
+++ b/arch/arm/mach-msm/msm_bus/msm_bus_fabric.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2010-2013, Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -679,7 +679,7 @@
 	return ret;
 }
 
-static int msm_bus_fabric_probe(struct platform_device *pdev)
+static int __devinit msm_bus_fabric_probe(struct platform_device *pdev)
 {
 	int ctx, ret = 0;
 	struct msm_bus_fabric *fabric;
@@ -694,7 +694,6 @@
 	INIT_LIST_HEAD(&fabric->gateways);
 	INIT_RADIX_TREE(&fabric->fab_tree, GFP_ATOMIC);
 	fabric->num_nodes = 0;
-	fabric->fabdev.id = pdev->id;
 	fabric->fabdev.visited = false;
 
 	fabric->info.node_info = kzalloc(sizeof(struct msm_bus_node_info),
@@ -704,18 +703,31 @@
 		kfree(fabric);
 		return -ENOMEM;
 	}
-	fabric->info.node_info->priv_id = fabric->fabdev.id;
-	fabric->info.node_info->id = fabric->fabdev.id;
+
 	fabric->info.num_pnodes = -1;
 	fabric->info.link_info.clk[DUAL_CTX] = 0;
 	fabric->info.link_info.bw[DUAL_CTX] = 0;
 	fabric->info.link_info.clk[ACTIVE_CTX] = 0;
 	fabric->info.link_info.bw[ACTIVE_CTX] = 0;
 
-	fabric->fabdev.id = pdev->id;
-	pdata = (struct msm_bus_fabric_registration *)pdev->dev.platform_data;
+	/* If possible, get pdata from device-tree */
+	if (pdev->dev.of_node) {
+		pdata = pdev->dev.platform_data;
+		if (IS_ERR(pdata) || ZERO_OR_NULL_PTR(pdata)) {
+			pr_err("Null platform data\n");
+			return PTR_ERR(pdata);
+		}
+		fabric->fabdev.id = pdata->id;
+	} else {
+		pdata = (struct msm_bus_fabric_registration *)pdev->
+			dev.platform_data;
+		fabric->fabdev.id = pdev->id;
+	}
+
 	fabric->fabdev.name = pdata->name;
 	fabric->fabdev.algo = &msm_bus_algo;
+	fabric->info.node_info->priv_id = fabric->fabdev.id;
+	fabric->info.node_info->id = fabric->fabdev.id;
 	ret = msm_bus_fabric_hw_init(pdata, &fabric->fabdev.hw_algo);
 	if (ret) {
 		MSM_BUS_ERR("Error initializing hardware for fabric: %d\n",
@@ -811,12 +823,18 @@
 	return ret;
 }
 
+static struct of_device_id fabric_match[] = {
+	{.compatible = "msm_bus_fabric"},
+	{}
+};
+
 static struct platform_driver msm_bus_fabric_driver = {
 	.probe = msm_bus_fabric_probe,
 	.remove = msm_bus_fabric_remove,
 	.driver = {
 		.name = "msm_bus_fabric",
 		.owner = THIS_MODULE,
+		.of_match_table = fabric_match,
 	},
 };
 
@@ -825,4 +843,4 @@
 	MSM_BUS_ERR("msm_bus_fabric_init_driver\n");
 	return platform_driver_register(&msm_bus_fabric_driver);
 }
-postcore_initcall(msm_bus_fabric_init_driver);
+subsys_initcall(msm_bus_fabric_init_driver);
diff --git a/arch/arm/mach-msm/msm_watchdog_v2.c b/arch/arm/mach-msm/msm_watchdog_v2.c
index 2a4422e..6aa14a6 100644
--- a/arch/arm/mach-msm/msm_watchdog_v2.c
+++ b/arch/arm/mach-msm/msm_watchdog_v2.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -41,6 +41,8 @@
 #define SCM_SET_REGSAVE_CMD	0x2
 #define SCM_SVC_SEC_WDOG_DIS	0x7
 
+static struct workqueue_struct *wdog_wq;
+
 struct msm_watchdog_data {
 	unsigned int __iomem phys_base;
 	size_t size;
@@ -213,7 +215,7 @@
 		work_data.wdog_dd = wdog_dd;
 		init_completion(&work_data.complete);
 		INIT_WORK_ONSTACK(&work_data.work, wdog_disable_work);
-		schedule_work_on(0, &work_data.work);
+		queue_work_on(0, wdog_wq, &work_data.work);
 		wait_for_completion(&work_data.complete);
 		mutex_unlock(&wdog_dd->disable_lock);
 	} else {
@@ -288,8 +290,8 @@
 	/* Check again before scheduling *
 	 * Could have been changed on other cpu */
 	if (enable)
-		schedule_delayed_work_on(0, &wdog_dd->dogwork_struct,
-							delay_time);
+		queue_delayed_work_on(0, wdog_wq,
+				&wdog_dd->dogwork_struct, delay_time);
 }
 
 static int msm_watchdog_remove(struct platform_device *pdev)
@@ -303,7 +305,7 @@
 		work_data.wdog_dd = wdog_dd;
 		init_completion(&work_data.complete);
 		INIT_WORK_ONSTACK(&work_data.work, wdog_disable_work);
-		schedule_work_on(0, &work_data.work);
+		queue_work_on(0, wdog_wq, &work_data.work);
 		wait_for_completion(&work_data.complete);
 	}
 	mutex_unlock(&wdog_dd->disable_lock);
@@ -311,6 +313,7 @@
 	if (wdog_dd->irq_ppi)
 		free_percpu(wdog_dd->wdog_cpu_dd);
 	printk(KERN_INFO "MSM Watchdog Exit - Deactivated\n");
+	destroy_workqueue(wdog_wq);
 	kfree(wdog_dd);
 	return 0;
 }
@@ -425,7 +428,8 @@
 	atomic_notifier_chain_register(&panic_notifier_list,
 				       &wdog_dd->panic_blk);
 	mutex_init(&wdog_dd->disable_lock);
-	schedule_delayed_work_on(0, &wdog_dd->dogwork_struct, delay_time);
+	queue_delayed_work_on(0, wdog_wq, &wdog_dd->dogwork_struct,
+			delay_time);
 	__raw_writel(1, wdog_dd->base + WDT0_EN);
 	__raw_writel(1, wdog_dd->base + WDT0_RST);
 	wdog_dd->last_pet = sched_clock();
@@ -509,6 +513,12 @@
 	int ret;
 	struct msm_watchdog_data *wdog_dd;
 
+	wdog_wq = alloc_workqueue("wdog", WQ_HIGHPRI, 0);
+	if (!wdog_wq) {
+		pr_err("Failed to allocate watchdog workqueue\n");
+		return -EIO;
+	}
+
 	if (!pdev->dev.of_node || !enable)
 		return -ENODEV;
 	wdog_dd = kzalloc(sizeof(struct msm_watchdog_data), GFP_KERNEL);
@@ -522,9 +532,10 @@
 	cpumask_clear(&wdog_dd->alive_mask);
 	INIT_WORK(&wdog_dd->init_dogwork_struct, init_watchdog_work);
 	INIT_DELAYED_WORK(&wdog_dd->dogwork_struct, pet_watchdog_work);
-	schedule_work_on(0, &wdog_dd->init_dogwork_struct);
+	queue_work_on(0, wdog_wq, &wdog_dd->init_dogwork_struct);
 	return 0;
 err:
+	destroy_workqueue(wdog_wq);
 	kzfree(wdog_dd);
 	return ret;
 }
diff --git a/arch/arm/mach-msm/ocmem_core.c b/arch/arm/mach-msm/ocmem_core.c
index 3d9639f..9782b90 100644
--- a/arch/arm/mach-msm/ocmem_core.c
+++ b/arch/arm/mach-msm/ocmem_core.c
@@ -488,7 +488,7 @@
 	if (mpu_start < 0)
 		/* Avoid underflow */
 		mpu_start = 0;
-	mpu_end = ((offset+len) >> GFX_MPU_SHIFT) - 1;
+	mpu_end = ((offset+len) >> GFX_MPU_SHIFT);
 	BUG_ON(mpu_end < 0);
 
 	pr_debug("ocmem: mpu: start %x end %x\n", mpu_start, mpu_end);
diff --git a/arch/arm/mach-msm/perf_event_msm_pl310.c b/arch/arm/mach-msm/perf_event_msm_pl310.c
index 40a2f98..e2a580f 100644
--- a/arch/arm/mach-msm/perf_event_msm_pl310.c
+++ b/arch/arm/mach-msm/perf_event_msm_pl310.c
@@ -22,6 +22,9 @@
 
 #include <asm/pmu.h>
 #include <asm/hardware/cache-l2x0.h>
+#include <mach/socinfo.h>
+
+static u32 rev1;
 
 /*
  * Store dynamic PMU type after registration,
@@ -110,6 +113,30 @@
 
 #define COUNTER_ADDR(idx)	(l2x0_base + L2X0_EVENT_CNT0_VAL - 4*idx)
 
+static u32 l2x0_read_intr_mask(void)
+{
+	return readl_relaxed(l2x0_base + L2X0_INTR_MASK);
+}
+
+static void l2x0_write_intr_mask(u32 val)
+{
+	writel_relaxed(val, l2x0_base + L2X0_INTR_MASK);
+}
+
+static void l2x0_enable_counter_interrupt(void)
+{
+	u32 intr_mask = l2x0_read_intr_mask();
+	intr_mask |= L2X0_INTR_MASK_ECNTR;
+	l2x0_write_intr_mask(intr_mask);
+}
+
+static void l2x0_disable_counter_interrupt(void)
+{
+	u32 intr_mask = l2x0_read_intr_mask();
+	intr_mask &= ~L2X0_INTR_MASK_ECNTR;
+	l2x0_write_intr_mask(intr_mask);
+}
+
 static void l2x0_clear_interrupts(u32 flags)
 {
 	writel_relaxed(flags, l2x0_base + L2X0_INTR_CLEAR);
@@ -190,10 +217,8 @@
 
 	raw_spin_lock_irqsave(&l2x0pmu_hw_events.pmu_lock, flags);
 
-	/*
-	 * TODO: Enable counter interrupt,
-	 * once we know it works on this chip.
-	 */
+	if (!rev1)
+		l2x0_enable_counter_interrupt();
 
 	val = l2x0pmu_read_ctrl();
 
@@ -214,10 +239,8 @@
 	val &= ~L2X0_EVENT_CNT_ENABLE_MASK;
 	l2x0pmu_write_ctrl(val);
 
-	/*
-	 * TODO: Disable counter interrupt,
-	 * once we know it works on this chip.
-	 */
+	if (!rev1)
+		l2x0_disable_counter_interrupt();
 
 	raw_spin_unlock_irqrestore(&l2x0pmu_hw_events.pmu_lock, flags);
 }
@@ -401,6 +424,9 @@
 
 static int __init register_pmu_driver(void)
 {
+	if (machine_is_msm9625())
+		rev1 = 1;
+
 	return platform_driver_register(&l2x0pmu_driver);
 }
 device_initcall(register_pmu_driver);
diff --git a/arch/arm/mach-msm/peripheral-loader.c b/arch/arm/mach-msm/peripheral-loader.c
index c903b72..affb451 100644
--- a/arch/arm/mach-msm/peripheral-loader.c
+++ b/arch/arm/mach-msm/peripheral-loader.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2010-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -680,7 +680,7 @@
 	struct pil_priv *priv;
 	int id;
 	void __iomem *addr;
-	size_t len;
+	char buf[sizeof(priv->info->name)];
 
 	/* Ignore users who don't make any sense */
 	WARN(desc->ops->proxy_unvote && !desc->proxy_timeout,
@@ -703,9 +703,8 @@
 	addr = PIL_IMAGE_INFO_BASE + sizeof(struct pil_image_info) * id;
 	priv->info = (struct pil_image_info __iomem *)addr;
 
-	len = min(strlen(desc->name), sizeof(priv->info->name));
-	memset_io(priv->info->name, 0, sizeof(priv->info->name));
-	memcpy_toio(priv->info->name, desc->name, len);
+	strncpy(buf, desc->name, sizeof(buf));
+	__iowrite32_copy(priv->info->name, buf, sizeof(buf) / 4);
 
 	snprintf(priv->wname, sizeof(priv->wname), "pil-%s", desc->name);
 	wake_lock_init(&priv->wlock, WAKE_LOCK_SUSPEND, priv->wname);
diff --git a/arch/arm/mach-msm/pil-pronto.c b/arch/arm/mach-msm/pil-pronto.c
index cfcf5dc..9c89f2d 100644
--- a/arch/arm/mach-msm/pil-pronto.c
+++ b/arch/arm/mach-msm/pil-pronto.c
@@ -235,6 +235,12 @@
 	return pas_init_image(PAS_WCNSS, metadata, size);
 }
 
+static int pil_pronto_mem_setup_trusted(struct pil_desc *pil, phys_addr_t addr,
+			       size_t size)
+{
+	return pas_mem_setup(PAS_WCNSS, addr, size);
+}
+
 static int pil_pronto_reset_trusted(struct pil_desc *pil)
 {
 	return pas_auth_and_reset(PAS_WCNSS);
@@ -247,6 +253,7 @@
 
 static struct pil_reset_ops pil_pronto_ops_trusted = {
 	.init_image = pil_pronto_init_image_trusted,
+	.mem_setup = pil_pronto_mem_setup_trusted,
 	.auth_and_reset = pil_pronto_reset_trusted,
 	.shutdown = pil_pronto_shutdown_trusted,
 	.proxy_vote = pil_pronto_make_proxy_vote,
diff --git a/arch/arm/mach-msm/pil-q6v5-lpass.c b/arch/arm/mach-msm/pil-q6v5-lpass.c
index 5e03aa8..5c498ec 100644
--- a/arch/arm/mach-msm/pil-q6v5-lpass.c
+++ b/arch/arm/mach-msm/pil-q6v5-lpass.c
@@ -153,6 +153,12 @@
 	return pas_init_image(PAS_Q6, metadata, size);
 }
 
+static int pil_lpass_mem_setup_trusted(struct pil_desc *pil, phys_addr_t addr,
+			       size_t size)
+{
+	return pas_mem_setup(PAS_Q6, addr, size);
+}
+
 static int pil_lpass_reset_trusted(struct pil_desc *pil)
 {
 	return pas_auth_and_reset(PAS_Q6);
@@ -165,6 +171,7 @@
 
 static struct pil_reset_ops pil_lpass_ops_trusted = {
 	.init_image = pil_lpass_init_image_trusted,
+	.mem_setup = pil_lpass_mem_setup_trusted,
 	.proxy_vote = pil_q6v5_make_proxy_votes,
 	.proxy_unvote = pil_q6v5_remove_proxy_votes,
 	.auth_and_reset = pil_lpass_reset_trusted,
diff --git a/arch/arm/mach-msm/pil-venus.c b/arch/arm/mach-msm/pil-venus.c
index eb222e3..1fcd3ba 100644
--- a/arch/arm/mach-msm/pil-venus.c
+++ b/arch/arm/mach-msm/pil-venus.c
@@ -401,6 +401,12 @@
 	return pas_init_image(PAS_VIDC, metadata, size);
 }
 
+static int pil_venus_mem_setup_trusted(struct pil_desc *pil, phys_addr_t addr,
+			       size_t size)
+{
+	return pas_mem_setup(PAS_VIDC, addr, size);
+}
+
 static int pil_venus_reset_trusted(struct pil_desc *pil)
 {
 	int rc;
@@ -442,6 +448,7 @@
 
 static struct pil_reset_ops pil_venus_ops_trusted = {
 	.init_image = pil_venus_init_image_trusted,
+	.mem_setup =  pil_venus_mem_setup_trusted,
 	.auth_and_reset = pil_venus_reset_trusted,
 	.shutdown = pil_venus_shutdown_trusted,
 	.proxy_vote = pil_venus_make_proxy_vote,
diff --git a/arch/arm/mach-msm/pm-8x60.c b/arch/arm/mach-msm/pm-8x60.c
index b42ad94..e35d843 100644
--- a/arch/arm/mach-msm/pm-8x60.c
+++ b/arch/arm/mach-msm/pm-8x60.c
@@ -779,7 +779,7 @@
 {
 	int i;
 	unsigned int power_usage = -1;
-	int ret = 0;
+	int ret = MSM_PM_SLEEP_MODE_NOT_SELECTED;
 	uint32_t modified_time_us = 0;
 	struct msm_pm_time_params time_param;
 
@@ -948,9 +948,14 @@
 		break;
 	}
 
+	case MSM_PM_SLEEP_MODE_NOT_SELECTED:
+		goto cpuidle_enter_bail;
+		break;
+
 	default:
 		__WARN();
 		goto cpuidle_enter_bail;
+		break;
 	}
 
 	time = ktime_to_ns(ktime_get()) - time;
diff --git a/arch/arm/mach-msm/pm.h b/arch/arm/mach-msm/pm.h
index bd61feb..86d8f98 100644
--- a/arch/arm/mach-msm/pm.h
+++ b/arch/arm/mach-msm/pm.h
@@ -52,7 +52,8 @@
 	MSM_PM_SLEEP_MODE_RETENTION = MSM_PM_SLEEP_MODE_APPS_SLEEP,
 	MSM_PM_SLEEP_MODE_POWER_COLLAPSE_SUSPEND = 5,
 	MSM_PM_SLEEP_MODE_POWER_COLLAPSE_NO_XO_SHUTDOWN = 6,
-	MSM_PM_SLEEP_MODE_NR
+	MSM_PM_SLEEP_MODE_NR = 7,
+	MSM_PM_SLEEP_MODE_NOT_SELECTED,
 };
 
 #define MSM_PM_MODE(cpu, mode_nr)  ((cpu) * MSM_PM_SLEEP_MODE_NR + (mode_nr))
diff --git a/arch/arm/mach-msm/pmu.c b/arch/arm/mach-msm/pmu.c
index f0b83f9..21f65f8 100644
--- a/arch/arm/mach-msm/pmu.c
+++ b/arch/arm/mach-msm/pmu.c
@@ -137,6 +137,21 @@
 	.resource	= msm8625_cpu_pmu_resource,
 	.num_resources	= ARRAY_SIZE(msm8625_cpu_pmu_resource),
 };
+
+static struct resource msm8625_l2_pmu_resource[] = {
+	{
+		.start = MSM8625_INT_SC_SICL2PERFMONIRPTREQ,
+		.end = MSM8625_INT_SC_SICL2PERFMONIRPTREQ,
+		.flags = IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device msm8625_l2_pmu_device = {
+	.name		= "l2-arm-pmu",
+	.id		= ARM_PMU_DEVICE_L2CC,
+	.resource	= msm8625_l2_pmu_resource,
+	.num_resources	= ARRAY_SIZE(msm8625_l2_pmu_resource),
+};
 #endif
 
 static struct platform_device *pmu_devices[] = {
@@ -166,8 +181,9 @@
 	 * and point to the appropriate 'struct resource'.
 	 */
 #ifdef CONFIG_ARCH_MSM8625
-	if (cpu_is_msm8625()) {
+	if (cpu_is_msm8625() || cpu_is_msm8625q()) {
 		pmu_devices[0] = &msm8625_cpu_pmu_device;
+		pmu_devices[1] = &msm8625_l2_pmu_device;
 		msm8625_cpu_pmu_device.dev.platform_data = &multicore_data;
 	}
 #endif
diff --git a/arch/arm/mach-msm/qdsp5/audio_acdb.c b/arch/arm/mach-msm/qdsp5/audio_acdb.c
index d7a4607..681b41c 100644
--- a/arch/arm/mach-msm/qdsp5/audio_acdb.c
+++ b/arch/arm/mach-msm/qdsp5/audio_acdb.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -1301,6 +1301,15 @@
 }
 EXPORT_SYMBOL(acdb_get_calibration_data);
 
+int is_acdb_enabled()
+{
+	if (acdb_data.handle != NULL)
+		return 1;
+	else
+		return 0;
+}
+EXPORT_SYMBOL(is_acdb_enabled);
+
 static u8 check_device_info_already_present(
 		struct dev_evt_msg device_info,
 			struct acdb_cache_node *acdb_cache_free_node)
@@ -1522,7 +1531,7 @@
 			result = -EINVAL;
 			goto done;
 		} else
-			MM_DBG("AUDPP is calibrated with IIR parameters");
+			MM_DBG("AUDPP is calibrated with IIR parameters\n");
 	}
 	result = acdb_fill_audpp_mbadrc();
 	if (!IS_ERR_VALUE(result)) {
@@ -2270,13 +2279,9 @@
 		if (ret == 1) {
 			MM_DBG("got device ready call back for another "\
 					"audplay task sessions on same COPP\n");
-			/*stream_id is used to keep track of number of active*/
-			/*sessions active on this device*/
-			acdb_cache_free_node->stream_id++;
 			mutex_unlock(&acdb_data.acdb_mutex);
 			goto done;
 		}
-		acdb_cache_free_node->stream_id++;
 	}
 	update_acdb_data_struct(acdb_cache_free_node);
 	acdb_data.device_cb_compl = 1;
@@ -2317,6 +2322,9 @@
 		}
 		goto done;
 	}
+	/*stream_id is used to keep track of number of active*/
+	/*sessions active on this device*/
+	acdb_cache_rx.stream_id++;
 
 	acdb_data.acdb_state |= AUDPP_READY;
 	acdb_data.audpp_cb_compl = 1;
diff --git a/arch/arm/mach-msm/qdsp5/audio_out.c b/arch/arm/mach-msm/qdsp5/audio_out.c
index 6f3bf91..fee7404 100644
--- a/arch/arm/mach-msm/qdsp5/audio_out.c
+++ b/arch/arm/mach-msm/qdsp5/audio_out.c
@@ -4,7 +4,7 @@
  *
  * Copyright (C) 2008 Google, Inc.
  * Copyright (C) 2008 HTC Corporation
- * Copyright (c) 2012 Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
  *
  * This software is licensed under the terms of the GNU General Public
  * License version 2, as published by the Free Software Foundation, and
@@ -39,6 +39,7 @@
 
 #include "audmgr.h"
 
+#include <mach/qdsp5/audio_acdb_def.h>
 #include <mach/qdsp5/qdsp5audppcmdi.h>
 #include <mach/qdsp5/qdsp5audppmsg.h>
 #include <mach/qdsp5/qdsp5audpp.h>
@@ -298,19 +299,20 @@
 	if (!audio_copp->status)
 		return;
 
-	audpp_dsp_set_mbadrc(COMMON_OBJ_ID, audio_copp->mbadrc_enable,
+	if (!is_acdb_enabled()) {
+		audpp_dsp_set_mbadrc(COMMON_OBJ_ID, audio_copp->mbadrc_enable,
 						&audio_copp->mbadrc);
 
-	audpp_dsp_set_eq(COMMON_OBJ_ID, audio_copp->eq_enable,
+		audpp_dsp_set_eq(COMMON_OBJ_ID, audio_copp->eq_enable,
 						&audio_copp->eq);
-
-	audpp_dsp_set_rx_iir(COMMON_OBJ_ID, audio_copp->rx_iir_enable,
+		audpp_dsp_set_rx_iir(COMMON_OBJ_ID, audio_copp->rx_iir_enable,
 							&audio_copp->iir);
-	audpp_dsp_set_vol_pan(COMMON_OBJ_ID, &audio_copp->vol_pan);
+		audpp_dsp_set_vol_pan(COMMON_OBJ_ID, &audio_copp->vol_pan);
 
-	audpp_dsp_set_qconcert_plus(COMMON_OBJ_ID,
+		audpp_dsp_set_qconcert_plus(COMMON_OBJ_ID,
 				audio_copp->qconcert_plus_enable,
 				&audio_copp->qconcert_plus);
+	}
 	audio_enable_srs_trumedia(audio_copp, true);
 }
 EXPORT_SYMBOL(audio_commit_pending_pp_params);
diff --git a/arch/arm/mach-msm/qdsp5/audio_pcm_in.c b/arch/arm/mach-msm/qdsp5/audio_pcm_in.c
index 7b2090d..c5787fd 100644
--- a/arch/arm/mach-msm/qdsp5/audio_pcm_in.c
+++ b/arch/arm/mach-msm/qdsp5/audio_pcm_in.c
@@ -2,7 +2,7 @@
  *
  * pcm audio input device
  *
- * Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2011-2013, The Linux Foundation. All rights reserved.
  *
  * This code is based in part on arch/arm/mach-msm/qdsp5v2/audio_pcm_in.c,
  * Copyright (C) 2008 Google, Inc.
@@ -42,6 +42,7 @@
 
 #include "audmgr.h"
 
+#include <mach/qdsp5/audio_acdb_def.h>
 #include <mach/qdsp5/qdsp5audpreproc.h>
 #include <mach/qdsp5/qdsp5audpreproccmdi.h>
 #include <mach/qdsp5/qdsp5audpreprocmsg.h>
@@ -346,6 +347,8 @@
 	case AUDREC_MSG_CMD_AREC_PARAM_CFG_DONE_MSG: {
 		MM_INFO("PARAM CFG DONE\n");
 		audio->running = 1;
+		if (is_acdb_enabled())
+			break;
 		audio_dsp_set_tx_agc(audio);
 		audio_dsp_set_ns(audio);
 		audio_dsp_set_iir(audio);
@@ -914,6 +917,12 @@
 	mutex_lock(&audio->lock);
 	switch (cmd) {
 	case AUDIO_ENABLE_AUDPRE:
+
+		if (is_acdb_enabled()) {
+			MM_INFO("Audpp is supported via acdb\n");
+			rc = -EFAULT;
+			break;
+		}
 		if (copy_from_user(&enable_mask, (void *) arg,
 						sizeof(enable_mask))) {
 			rc = -EFAULT;
diff --git a/arch/arm/mach-msm/qdsp5/audmgr.c b/arch/arm/mach-msm/qdsp5/audmgr.c
index f2a84aa..fb51240 100644
--- a/arch/arm/mach-msm/qdsp5/audmgr.c
+++ b/arch/arm/mach-msm/qdsp5/audmgr.c
@@ -158,8 +158,10 @@
 			return;
 		if (am->state != STATE_ENABLED)
 			am->state = STATE_ENABLED;
-		if (!amg->cad)
+		if (!amg->cad) {
+			wake_up(&am->wait);
 			break;
+		}
 
 		if (am->evt.session_info == SESSION_PLAYBACK &&
 			am->evt.dev_type.rx_device != amg->rx_device) {
diff --git a/arch/arm/mach-msm/rpm_resources.c b/arch/arm/mach-msm/rpm_resources.c
index 43073d3..78c5ae0 100644
--- a/arch/arm/mach-msm/rpm_resources.c
+++ b/arch/arm/mach-msm/rpm_resources.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2010-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
@@ -21,6 +21,7 @@
 #include <linux/spinlock.h>
 #include <linux/cpu.h>
 #include <linux/hrtimer.h>
+#include <linux/platform_device.h>
 #include <mach/rpm.h>
 #include <mach/msm_iomap.h>
 #include <asm/mach-types.h>
@@ -71,6 +72,10 @@
 static int vdd_mem_vlevels[MSM_RPMRS_VDD_MEM_LAST];
 static int vdd_mask;
 
+static DEFINE_PER_CPU(uint32_t , msm_lpm_sleep_time);
+static DEFINE_PER_CPU(int , lpm_permitted_level);
+static DEFINE_PER_CPU(struct atomic_notifier_head, lpm_notify_head);
+
 #define MSM_RPMRS_MAX_RS_REGISTER_COUNT 2
 
 #define RPMRS_ATTR(_name) \
@@ -869,6 +874,13 @@
 	spin_unlock_irqrestore(&msm_rpmrs_lock, flags);
 }
 
+static bool lpm_level_permitted(int cur_level_count)
+{
+	if (__get_cpu_var(lpm_permitted_level) == msm_rpmrs_level_count + 1)
+		return true;
+	return (__get_cpu_var(lpm_permitted_level) == cur_level_count);
+}
+
 s32 msm_cpuidle_get_deep_idle_latency(void)
 {
 	int i;
@@ -904,6 +916,7 @@
 	uint32_t pwr;
 	uint32_t next_wakeup_us = time_param->sleep_us;
 	bool modify_event_timer;
+	int best_level_iter = msm_rpmrs_level_count + 1;
 
 	if (sleep_mode == MSM_PM_SLEEP_MODE_POWER_COLLAPSE) {
 		irqs_detectable = msm_mpm_irqs_detectable(from_idle);
@@ -968,6 +981,7 @@
 			level->rs_limits.latency_us[cpu] = level->latency_us;
 			level->rs_limits.power[cpu] = pwr;
 			best_level = level;
+			best_level_iter = i;
 			if (power)
 				*power = pwr;
 			if (modify_event_timer && best_level->latency_us > 1)
@@ -978,6 +992,12 @@
 				time_param->modified_time_us = 0;
 		}
 	}
+	if (best_level && !lpm_level_permitted(best_level_iter))
+		best_level = NULL;
+	else
+		per_cpu(msm_lpm_sleep_time, cpu) =
+			time_param->modified_time_us ?
+			time_param->modified_time_us : time_param->sleep_us;
 
 	return best_level ? &best_level->rs_limits : NULL;
 }
@@ -986,6 +1006,12 @@
 		bool from_idle, bool notify_rpm)
 {
 	int rc = 0;
+	struct msm_lpm_sleep_data sleep_data;
+
+	sleep_data.limits = limits;
+	sleep_data.kernel_sleep = __get_cpu_var(msm_lpm_sleep_time);
+	atomic_notifier_call_chain(&__get_cpu_var(lpm_notify_head),
+		MSM_LPM_STATE_ENTER, &sleep_data);
 
 	if (notify_rpm) {
 		rc = msm_rpmrs_flush_buffer(sclk_count, limits, from_idle);
@@ -1009,6 +1035,9 @@
 
 	if (msm_rpmrs_use_mpm(limits))
 		msm_mpm_exit_sleep(from_idle);
+
+	atomic_notifier_call_chain(&__get_cpu_var(lpm_notify_head),
+			MSM_LPM_STATE_EXIT, NULL);
 }
 
 static int rpmrs_cpu_callback(struct notifier_block *nfb,
@@ -1033,6 +1062,16 @@
 	return NOTIFY_OK;
 }
 
+static struct lpm_test_platform_data lpm_test_pdata;
+
+static struct platform_device msm_lpm_test_device = {
+	.name		= "lpm_test",
+	.id		= -1,
+	.dev		= {
+		.platform_data = &lpm_test_pdata,
+	},
+};
+
 static struct notifier_block __refdata rpmrs_cpu_notifier = {
 	.notifier_call = rpmrs_cpu_callback,
 };
@@ -1041,6 +1080,7 @@
 {
 	int i, k;
 	struct msm_rpmrs_level *levels = data->levels;
+	unsigned int m_cpu = 0;
 
 	msm_rpmrs_level_count = data->num_levels;
 
@@ -1052,6 +1092,16 @@
 	memcpy(msm_rpmrs_levels, levels,
 			msm_rpmrs_level_count * sizeof(struct msm_rpmrs_level));
 
+	lpm_test_pdata.use_qtimer = 0;
+	lpm_test_pdata.msm_lpm_test_levels = msm_rpmrs_levels,
+	lpm_test_pdata.msm_lpm_test_level_count = msm_rpmrs_level_count;
+
+	for_each_possible_cpu(m_cpu)
+		per_cpu(lpm_permitted_level, m_cpu) =
+				msm_rpmrs_level_count + 1;
+
+	platform_device_register(&msm_lpm_test_device);
+
 	memcpy(vdd_dig_vlevels, data->vdd_dig_levels,
 		(MSM_RPMRS_VDD_DIG_MAX + 1) * sizeof(vdd_dig_vlevels[0]));
 
@@ -1087,6 +1137,41 @@
 	return 0;
 }
 
+uint32_t msm_pm_get_pxo(struct msm_rpmrs_limits *limits)
+{
+	return limits->pxo;
+}
+
+uint32_t msm_pm_get_l2_cache(struct msm_rpmrs_limits *limits)
+{
+	return limits->l2_cache;
+}
+
+uint32_t msm_pm_get_vdd_mem(struct msm_rpmrs_limits *limits)
+{
+	return limits->vdd_mem;
+}
+
+uint32_t msm_pm_get_vdd_dig(struct msm_rpmrs_limits *limits)
+{
+	return limits->vdd_dig;
+}
+
+int msm_lpm_register_notifier(int cpu, int level_iter,
+			struct notifier_block *nb, bool is_latency_measure)
+{
+	per_cpu(lpm_permitted_level, cpu) = level_iter;
+	return atomic_notifier_chain_register(&per_cpu(lpm_notify_head,
+			cpu), nb);
+}
+
+int msm_lpm_unregister_notifier(int cpu, struct notifier_block *nb)
+{
+	per_cpu(lpm_permitted_level, cpu) = msm_rpmrs_level_count + 1;
+	return atomic_notifier_chain_unregister(&per_cpu(lpm_notify_head, cpu),
+				nb);
+}
+
 static int __init msm_rpmrs_init(void)
 {
 	struct msm_rpm_iv_pair req;
diff --git a/arch/arm/mach-msm/rpm_resources.h b/arch/arm/mach-msm/rpm_resources.h
index 46d6d94..0a180fb 100644
--- a/arch/arm/mach-msm/rpm_resources.h
+++ b/arch/arm/mach-msm/rpm_resources.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2010-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
@@ -15,7 +15,9 @@
 #define __ARCH_ARM_MACH_MSM_RPM_RESOURCES_H
 
 #include <mach/rpm.h>
+#include <linux/notifier.h>
 #include "pm.h"
+#include "test-lpm.h"
 
 enum {
 	MSM_RPMRS_ID_PXO_CLK = 0,
@@ -102,6 +104,94 @@
 	unsigned int rpmrs_target_id[MSM_RPMRS_ID_LAST];
 };
 
+enum {
+	MSM_LPM_STATE_ENTER = 0,
+	MSM_LPM_STATE_EXIT = 1,
+};
+
+/**
+ * struct msm_lpm_sleep_data - abstraction to get sleep data
+ * @limits:	pointer to the msm_rpmrs_limits structure
+ * @kernel_sleep:	kernel sleep time as decided by the power calculation
+ *			algorithm
+ *
+ * This structure is an abstraction to get the limits and kernel sleep time
+ * during enter sleep.
+ */
+
+struct msm_lpm_sleep_data {
+	struct msm_rpmrs_limits *limits;
+	uint32_t kernel_sleep;
+};
+
+#define MSM_PM(field) MSM_RPMRS_##field
+
+/**
+ * msm_pm_get_pxo() -  get the limits for pxo
+ * @limits:            pointer to the msm_rpmrs_limits structure
+ *
+ * This function gets the limits to the resource pxo on
+ * 8960
+ */
+
+uint32_t msm_pm_get_pxo(struct msm_rpmrs_limits *limits);
+
+/**
+ * msm_pm_get_l2_cache() -  get the limits for l2 cache
+ * @limits:            pointer to the msm_rpmrs_limits structure
+ *
+ * This function gets the limits to the resource l2 cache
+ * on 8960
+ */
+
+uint32_t msm_pm_get_l2_cache(struct msm_rpmrs_limits *limits);
+
+/**
+ * msm_pm_get_vdd_mem() -  get the limits for pxo
+ * @limits:            pointer to the msm_rpmrs_limits structure
+ *
+ * This function gets the limits to the resource vdd mem
+ * on 8960
+ */
+
+uint32_t msm_pm_get_vdd_mem(struct msm_rpmrs_limits *limits);
+
+/**
+ * msm_pm_get_vdd_dig() -  get the limits for vdd dig
+ * @limits:            pointer to the msm_rpmrs_limits structure
+ *
+ * This function gets the limits to the resource vdd dig
+ * on 8960
+ */
+
+uint32_t msm_pm_get_vdd_dig(struct msm_rpmrs_limits *limits);
+
+/**
+ * msm_lpm_register_notifier() - register for notifications
+ * @cpu:               cpu to debug
+ * @level_iter:        low power level index to debug
+ * @nb:       notifier block to callback on notifications
+ * @is_latency_measure: is it latency measure
+ *
+ * This function sets the permitted level to the index of the
+ * level under test and registers notifier for callback.
+ */
+
+int msm_lpm_register_notifier(int cpu, int level_iter,
+		struct notifier_block *nb, bool is_latency_measure);
+
+/**
+ * msm_lpm_unregister_notifier() - unregister from notifications
+ * @cpu:               cpu to debug
+ * @nb:       notifier block to callback on notifications
+ *
+ * This function sets the permitted level to a value one more than
+ * available levels count which indicates that all levels are
+ * permitted and it also unregisters notifier for callback.
+ */
+
+int msm_lpm_unregister_notifier(int cpu, struct notifier_block *nb);
+
 #if defined(CONFIG_MSM_RPM)
 
 int msm_rpmrs_set(int ctx, struct msm_rpm_iv_pair *req, int count);
diff --git a/arch/arm/mach-msm/sdio_al_dloader.c b/arch/arm/mach-msm/sdio_al_dloader.c
index f48c32b..b0cb88f 100644
--- a/arch/arm/mach-msm/sdio_al_dloader.c
+++ b/arch/arm/mach-msm/sdio_al_dloader.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2011-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
@@ -21,6 +21,7 @@
 #include <linux/module.h>
 #include <linux/delay.h>
 #include <linux/wakelock.h>
+#include <linux/workqueue.h>
 #include <linux/mmc/card.h>
 #include <linux/dma-mapping.h>
 #include <mach/dma.h>
@@ -87,6 +88,8 @@
 		const char __user *buf, size_t count, loff_t *ppos);
 #endif
 
+static void sdio_dld_tear_down(struct work_struct *work);
+DECLARE_WORK(cleanup, sdio_dld_tear_down);
 
 /* STRUCTURES AND TYPES */
 enum sdio_dld_op_mode {
@@ -224,6 +227,8 @@
 static DEFINE_SPINLOCK(lock2);
 static unsigned long lock_flags2;
 
+static atomic_t sdio_dld_in_use = ATOMIC_INIT(0);
+
 /*
  * sdio_op_mode sets the operation mode of the sdio_dloader -
  * it may be in NORMAL_MODE, BOOT_TEST_MODE or AMSS_TEST_MODE
@@ -1108,6 +1113,10 @@
 		REAL_FUNC_TO_FUNC_IN_ARRAY(sdio_dld->sdioc_boot_func);
 	struct sdio_func *str_func = sdio_dld->card->sdio_func[func_in_array];
 
+	if (atomic_read(&sdio_dld_in_use) == 1)
+		return -EBUSY;
+
+	atomic_set(&sdio_dld_in_use, 1);
 	sdio_dld->tty_str = tty;
 	sdio_dld->tty_str->low_latency = 1;
 	sdio_dld->tty_str->icanon = 0;
@@ -1185,7 +1194,6 @@
   */
 static void sdio_dld_close(struct tty_struct *tty, struct file *file)
 {
-	int status = 0;
 	struct sdioc_reg_chunk *reg = &sdio_dld->sdio_dloader_data.sdioc_reg;
 
 	/* informing the SDIOC that it can exit boot phase */
@@ -1200,20 +1208,6 @@
 		   sdio_dld->dld_main_thread.exit_wait.wake_up_signal);
 	pr_debug(MODULE_NAME ": %s - CLOSING - WOKE UP...", __func__);
 
-	del_timer_sync(&sdio_dld->timer);
-	del_timer_sync(&sdio_dld->push_timer);
-
-	sdio_dld_dealloc_local_buffers();
-
-	tty_unregister_device(sdio_dld->tty_drv, 0);
-
-	status = tty_unregister_driver(sdio_dld->tty_drv);
-
-	if (status) {
-		pr_err(MODULE_NAME ": %s - tty_unregister_driver() failed\n",
-		       __func__);
-	}
-
 #ifdef CONFIG_DEBUG_FS
 	gd.curr_i = curr_index;
 	gd.duration_ms = sdio_dld_info.time_msec;
@@ -1263,9 +1257,8 @@
 	if (sdio_dld->done_callback)
 		sdio_dld->done_callback();
 
-	pr_info(MODULE_NAME ": %s - Freeing sdio_dld data structure, and "
-		" returning...", __func__);
-	kfree(sdio_dld);
+	schedule_work(&cleanup);
+	pr_info(MODULE_NAME ": %s - Bootloader done, returning...", __func__);
 }
 
 /**
@@ -2392,6 +2385,9 @@
 	struct sdio_func *str_func = NULL;
 	struct device *tty_dev;
 
+	if (atomic_read(&sdio_dld_in_use) == 1)
+		return -EBUSY;
+
 	if (num_of_devices == 0 || num_of_devices > MAX_NUM_DEVICES) {
 		pr_err(MODULE_NAME ": %s - invalid number of devices\n",
 		       __func__);
@@ -2534,6 +2530,28 @@
 	return status;
 }
 
+static void sdio_dld_tear_down(struct work_struct *work)
+{
+	int status = 0;
+
+	del_timer_sync(&sdio_dld->timer);
+	del_timer_sync(&sdio_dld->push_timer);
+
+	sdio_dld_dealloc_local_buffers();
+
+	tty_unregister_device(sdio_dld->tty_drv, 0);
+
+	status = tty_unregister_driver(sdio_dld->tty_drv);
+
+	if (status) {
+		pr_err(MODULE_NAME ": %s - tty_unregister_driver() failed\n",
+		       __func__);
+	}
+
+	kfree(sdio_dld);
+	atomic_set(&sdio_dld_in_use, 0);
+}
+
 MODULE_LICENSE("GPL v2");
 MODULE_DESCRIPTION("SDIO Downloader");
 MODULE_AUTHOR("Yaniv Gardi <ygardi@codeaurora.org>");
diff --git a/arch/arm/mach-msm/smd_pkt.c b/arch/arm/mach-msm/smd_pkt.c
index 73ebdf6..8e7a1f5 100644
--- a/arch/arm/mach-msm/smd_pkt.c
+++ b/arch/arm/mach-msm/smd_pkt.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2008-2012, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2008-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -855,6 +855,12 @@
 				r = PTR_ERR(smd_pkt_devp->pil);
 				pr_err("%s failed on smd_pkt_dev id:%d - subsystem_get failed for %s\n",
 					__func__, smd_pkt_devp->i, peripheral);
+				/*
+				 * Sleep inorder to reduce the frequency of
+				 * retry by user-space modules and to avoid
+				 * possible watchdog bite.
+				 */
+				msleep((smd_pkt_devp->open_modem_wait * 1000));
 				goto release_pd;
 			}
 
diff --git a/arch/arm/mach-msm/socinfo.c b/arch/arm/mach-msm/socinfo.c
index 2743547..1ab1f71 100644
--- a/arch/arm/mach-msm/socinfo.c
+++ b/arch/arm/mach-msm/socinfo.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2009-2012, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2009-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -15,9 +15,17 @@
  *
  */
 
-#include <linux/types.h>
+#include <linux/err.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/sys_soc.h>
+#include <linux/slab.h>
+#include <linux/stat.h>
 #include <linux/sysdev.h>
+#include <linux/types.h>
+
 #include <asm/mach-types.h>
+
 #include <mach/socinfo.h>
 
 #include "smd_private.h"
@@ -399,6 +407,11 @@
 		: 0;
 }
 
+static uint32_t socinfo_get_format(void)
+{
+	return socinfo ? socinfo->v1.format : 0;
+}
+
 enum msm_cpu socinfo_get_msm_cpu(void)
 {
 	return cur_cpu;
@@ -607,6 +620,100 @@
 		socinfo_get_pmic_die_revision());
 }
 
+static ssize_t
+msm_get_vendor(struct device *dev,
+		struct device_attribute *attr,
+		char *buf)
+{
+	return snprintf(buf, PAGE_SIZE, "Qualcomm\n");
+}
+
+static ssize_t
+msm_get_raw_id(struct device *dev,
+		struct device_attribute *attr,
+		char *buf)
+{
+	return snprintf(buf, PAGE_SIZE, "%u\n",
+		socinfo_get_raw_id());
+}
+
+static ssize_t
+msm_get_raw_version(struct device *dev,
+		     struct device_attribute *attr,
+		     char *buf)
+{
+	return snprintf(buf, PAGE_SIZE, "%u\n",
+		socinfo_get_raw_version());
+}
+
+static ssize_t
+msm_get_build_id(struct device *dev,
+		   struct device_attribute *attr,
+		   char *buf)
+{
+	return snprintf(buf, PAGE_SIZE, "%-.32s\n",
+			socinfo_get_build_id());
+}
+
+static ssize_t
+msm_get_hw_platform(struct device *dev,
+			struct device_attribute *attr,
+			char *buf)
+{
+	uint32_t hw_type;
+	hw_type = socinfo_get_platform_type();
+
+	return snprintf(buf, PAGE_SIZE, "%-.32s\n",
+			hw_platform[hw_type]);
+}
+
+static ssize_t
+msm_get_platform_version(struct device *dev,
+				struct device_attribute *attr,
+				char *buf)
+{
+	return snprintf(buf, PAGE_SIZE, "%u\n",
+		socinfo_get_platform_version());
+}
+
+static ssize_t
+msm_get_accessory_chip(struct device *dev,
+				struct device_attribute *attr,
+				char *buf)
+{
+	return snprintf(buf, PAGE_SIZE, "%u\n",
+		socinfo_get_accessory_chip());
+}
+
+static ssize_t
+msm_get_platform_subtype(struct device *dev,
+			struct device_attribute *attr,
+			char *buf)
+{
+	uint32_t hw_subtype;
+	hw_subtype = socinfo_get_platform_subtype();
+	return snprintf(buf, PAGE_SIZE, "%-.32s\n",
+		hw_platform_subtype[hw_subtype]);
+}
+
+static ssize_t
+msm_get_pmic_model(struct device *dev,
+			struct device_attribute *attr,
+			char *buf)
+{
+	return snprintf(buf, PAGE_SIZE, "%u\n",
+		socinfo_get_pmic_model());
+}
+
+static ssize_t
+msm_get_pmic_die_revision(struct device *dev,
+			       struct device_attribute *attr,
+			       char *buf)
+{
+	return snprintf(buf, PAGE_SIZE, "%u\n",
+			 socinfo_get_pmic_die_revision());
+}
+
 static struct sysdev_attribute socinfo_v1_files[] = {
 	_SYSDEV_ATTR(id, 0444, socinfo_show_id, NULL),
 	_SYSDEV_ATTR(version, 0444, socinfo_show_version, NULL),
@@ -644,6 +751,42 @@
 			socinfo_show_pmic_die_revision, NULL),
 };
 
+static struct device_attribute msm_soc_attr_raw_version =
+	__ATTR(raw_version, S_IRUGO, msm_get_raw_version,  NULL);
+
+static struct device_attribute msm_soc_attr_raw_id =
+	__ATTR(raw_id, S_IRUGO, msm_get_raw_id,  NULL);
+
+static struct device_attribute msm_soc_attr_vendor =
+	__ATTR(vendor, S_IRUGO, msm_get_vendor,  NULL);
+
+static struct device_attribute msm_soc_attr_build_id =
+	__ATTR(build_id, S_IRUGO, msm_get_build_id, NULL);
+
+static struct device_attribute msm_soc_attr_hw_platform =
+	__ATTR(hw_platform, S_IRUGO, msm_get_hw_platform, NULL);
+
+
+static struct device_attribute msm_soc_attr_platform_version =
+	__ATTR(platform_version, S_IRUGO,
+			msm_get_platform_version, NULL);
+
+static struct device_attribute msm_soc_attr_accessory_chip =
+	__ATTR(accessory_chip, S_IRUGO,
+			msm_get_accessory_chip, NULL);
+
+static struct device_attribute msm_soc_attr_platform_subtype =
+	__ATTR(platform_subtype, S_IRUGO,
+			msm_get_platform_subtype, NULL);
+
+static struct device_attribute msm_soc_attr_pmic_model =
+	__ATTR(pmic_model, S_IRUGO,
+			msm_get_pmic_model, NULL);
+
+static struct device_attribute msm_soc_attr_pmic_die_revision =
+	__ATTR(pmic_die_revision, S_IRUGO,
+			msm_get_pmic_die_revision, NULL);
+
 static struct sysdev_class soc_sysdev_class = {
 	.name = "soc",
 };
@@ -764,47 +907,63 @@
 	return (void *) &dummy_socinfo;
 }
 
-int __init socinfo_init(void)
+static void __init populate_soc_sysfs_files(struct device *msm_soc_device)
 {
-	socinfo = smem_alloc(SMEM_HW_SW_BUILD_ID, sizeof(struct socinfo_v7));
+	uint32_t legacy_format = socinfo_get_format();
 
-	if (!socinfo)
-		socinfo = smem_alloc(SMEM_HW_SW_BUILD_ID,
-				sizeof(struct socinfo_v6));
+	device_create_file(msm_soc_device, &msm_soc_attr_vendor);
 
-	if (!socinfo)
-		socinfo = smem_alloc(SMEM_HW_SW_BUILD_ID,
-				sizeof(struct socinfo_v5));
-
-	if (!socinfo)
-		socinfo = smem_alloc(SMEM_HW_SW_BUILD_ID,
-				sizeof(struct socinfo_v4));
-
-	if (!socinfo)
-		socinfo = smem_alloc(SMEM_HW_SW_BUILD_ID,
-				sizeof(struct socinfo_v3));
-
-	if (!socinfo)
-		socinfo = smem_alloc(SMEM_HW_SW_BUILD_ID,
-				sizeof(struct socinfo_v2));
-
-	if (!socinfo)
-		socinfo = smem_alloc(SMEM_HW_SW_BUILD_ID,
-				sizeof(struct socinfo_v1));
-
-	if (!socinfo) {
-		pr_warn("%s: Can't find SMEM_HW_SW_BUILD_ID; falling back on "
-			"dummy values.\n", __func__);
-		socinfo = setup_dummy_socinfo();
+	switch (legacy_format) {
+	case 7:
+		device_create_file(msm_soc_device,
+					&msm_soc_attr_pmic_model);
+		device_create_file(msm_soc_device,
+					&msm_soc_attr_pmic_die_revision);
+	case 6:
+		device_create_file(msm_soc_device,
+					&msm_soc_attr_platform_subtype);
+	case 5:
+		device_create_file(msm_soc_device,
+					&msm_soc_attr_accessory_chip);
+	case 4:
+		device_create_file(msm_soc_device,
+					&msm_soc_attr_platform_version);
+	case 3:
+		device_create_file(msm_soc_device,
+					&msm_soc_attr_hw_platform);
+	case 2:
+		device_create_file(msm_soc_device,
+					&msm_soc_attr_raw_id);
+		device_create_file(msm_soc_device,
+					&msm_soc_attr_raw_version);
+	case 1:
+		device_create_file(msm_soc_device,
+					&msm_soc_attr_build_id);
+		break;
+	default:
+		pr_err("%s:Unknown socinfo format:%u\n", __func__,
+				legacy_format);
+		break;
 	}
 
-	WARN(!socinfo_get_id(), "Unknown SOC ID!\n");
-	WARN(socinfo_get_id() >= ARRAY_SIZE(cpu_of_id),
-		"New IDs added! ID => CPU mapping might need an update.\n");
+	return;
+}
 
-	if (socinfo->v1.id < ARRAY_SIZE(cpu_of_id))
-		cur_cpu = cpu_of_id[socinfo->v1.id];
+static void  __init soc_info_populate(struct soc_device_attribute *soc_dev_attr)
+{
+	uint32_t soc_version = socinfo_get_version();
 
+	soc_dev_attr->soc_id   = kasprintf(GFP_KERNEL, "%d", socinfo_get_id());
+	soc_dev_attr->machine  = "Snapdragon";
+	soc_dev_attr->revision = kasprintf(GFP_KERNEL, "%u.%u",
+			SOCINFO_VERSION_MAJOR(soc_version),
+			SOCINFO_VERSION_MINOR(soc_version));
+	return;
+
+}
+
+static void socinfo_print(void)
+{
 	switch (socinfo->v1.format) {
 	case 1:
 		pr_info("%s: v%u, id=%u, ver=%u.%u\n",
@@ -880,8 +1039,69 @@
 		pr_err("%s: Unknown format found\n", __func__);
 		break;
 	}
+}
 
-	return 0;
+struct device *  __init socinfo_init(void)
+{
+	struct device *msm_soc_device;
+	struct soc_device *soc_dev;
+	struct soc_device_attribute *soc_dev_attr;
+
+	socinfo = smem_alloc(SMEM_HW_SW_BUILD_ID, sizeof(struct socinfo_v7));
+
+	if (!socinfo)
+		socinfo = smem_alloc(SMEM_HW_SW_BUILD_ID,
+				sizeof(struct socinfo_v6));
+
+	if (!socinfo)
+		socinfo = smem_alloc(SMEM_HW_SW_BUILD_ID,
+				sizeof(struct socinfo_v5));
+
+	if (!socinfo)
+		socinfo = smem_alloc(SMEM_HW_SW_BUILD_ID,
+				sizeof(struct socinfo_v4));
+
+	if (!socinfo)
+		socinfo = smem_alloc(SMEM_HW_SW_BUILD_ID,
+				sizeof(struct socinfo_v3));
+
+	if (!socinfo)
+		socinfo = smem_alloc(SMEM_HW_SW_BUILD_ID,
+				sizeof(struct socinfo_v2));
+
+	if (!socinfo)
+		socinfo = smem_alloc(SMEM_HW_SW_BUILD_ID,
+				sizeof(struct socinfo_v1));
+
+	if (!socinfo) {
+		pr_warn("%s: Can't find SMEM_HW_SW_BUILD_ID; falling back on dummy values.\n",
+				__func__);
+		socinfo = setup_dummy_socinfo();
+	}
+
+	WARN(!socinfo_get_id(), "Unknown SOC ID!\n");
+	WARN(socinfo_get_id() >= ARRAY_SIZE(cpu_of_id),
+		"New IDs added! ID => CPU mapping might need an update.\n");
+
+	if (socinfo->v1.id < ARRAY_SIZE(cpu_of_id))
+		cur_cpu = cpu_of_id[socinfo->v1.id];
+
+	socinfo_print();
+	soc_dev_attr = kzalloc(sizeof(*soc_dev_attr), GFP_KERNEL);
+	if (!soc_dev_attr)
+		return ERR_PTR(-ENOMEM);
+
+	soc_info_populate(soc_dev_attr);
+	soc_dev = soc_device_register(soc_dev_attr);
+	if (IS_ERR_OR_NULL(soc_dev)) {
+		kfree(soc_dev_attr);
+		return ERR_PTR(-EIO);
+	}
+
+	msm_soc_device = soc_device_to_device(soc_dev);
+	populate_soc_sysfs_files(msm_soc_device);
+
+	return msm_soc_device;
 }
 
 const int get_core_count(void)
@@ -921,6 +1141,7 @@
 		return MSM_CPU_8064;
 
 	case 0x511F06F1:
+	case 0x511F06F2:
 	case 0x512F06F0:
 		return MSM_CPU_8974;
 
@@ -972,6 +1193,7 @@
 	case 0x512F04D0:
 	case 0x511F06F0:
 	case 0x511F06F1:
+	case 0x511F06F2:
 	case 0x510F05D0:
 		return 1;
 
diff --git a/arch/arm/mach-msm/test-lpm.c b/arch/arm/mach-msm/test-lpm.c
new file mode 100644
index 0000000..dbc8100
--- /dev/null
+++ b/arch/arm/mach-msm/test-lpm.c
@@ -0,0 +1,696 @@
+/* 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.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/pm.h>
+#include <linux/mutex.h>
+#include <linux/uaccess.h>
+#include <linux/debugfs.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/ctype.h>
+#include <linux/moduleparam.h>
+#include <linux/platform_device.h>
+#include <mach/socinfo.h>
+#if defined(CONFIG_MSM_RPM)
+#include "rpm_resources.h"
+#endif
+#include "timer.h"
+#include "test-lpm.h"
+
+#define LPM_STATS_RESET "reset"
+#define LPM_TEST_ALL_LEVELS "lpm"
+#define LPM_TEST_LATENCIES "latency"
+#define LPM_TEST_CLEAR "clear"
+#define BUF_SIZE 200
+#define STAT_BUF_EXTRA_SIZE 500
+#define WAIT_FOR_XO 1
+#define COMM_BUF_SIZE 15
+#define INPUT_COUNT_BUF 10
+#define LPM_DEFAULT_CPU 0
+
+#define SNPRINTF(buf, size, format, ...) \
+{ \
+	if (size > 0) { \
+		int ret; \
+		ret = snprintf(buf, size, format, ## __VA_ARGS__); \
+		if (ret > size) { \
+			buf += size; \
+			size = 0; \
+		} else { \
+			buf += ret; \
+			size -= ret; \
+		} \
+	} \
+} \
+
+static DEFINE_MUTEX(lpm_stats_mutex);
+
+struct lpm_level_stat {
+	char level_name[BUF_SIZE];
+	int64_t min_time;
+	int64_t max_time;
+	int64_t avg_time;
+	int64_t exit_early;
+	int64_t count;
+	unsigned long min_threshold;
+	uint32_t kernel_sleep_time;
+	bool entered;
+};
+
+static DEFINE_PER_CPU(struct lpm_level_stat *, lpm_levels);
+
+static struct dentry *lpm_stat;
+static struct dentry *lpm_ext_comm;
+static struct msm_rpmrs_level *lpm_supp_level;
+static int lpm_level_count;
+static int lpm_level_iter;
+static bool msm_lpm_use_qtimer;
+static unsigned long lpm_sleep_time;
+static bool lpm_latency_test;
+
+static unsigned int timer_interval = 5000;
+module_param_named(lpm_timer_interval_msec, timer_interval, uint,
+	S_IRUGO | S_IWUSR | S_IWGRP);
+
+static unsigned int latency_test_interval = 50;
+module_param_named(lpm_latency_timer_interval_usec, latency_test_interval, uint,
+	S_IRUGO | S_IWUSR | S_IWGRP);
+
+static unsigned int cpu_to_debug = LPM_DEFAULT_CPU;
+static int lpm_cpu_update(const char *val, const struct kernel_param *kp)
+{
+	int ret = 0;
+	unsigned int debug_val;
+
+	ret = kstrtouint(val, 10, &debug_val);
+	if ((ret < 0) || (debug_val >= num_possible_cpus()))
+		return -EINVAL;
+	cpu_to_debug = debug_val;
+	return ret;
+}
+
+static struct kernel_param_ops cpu_debug_events = {
+	.set = lpm_cpu_update,
+};
+
+module_param_cb(cpu_to_debug, &cpu_debug_events, &cpu_to_debug,
+			S_IRUGO | S_IWUSR | S_IWGRP);
+
+static void lpm_populate_name(struct lpm_level_stat *stat,
+		struct msm_rpmrs_level *supp)
+{
+	char nm[BUF_SIZE] = {0};
+	char default_buf[20];
+
+	switch (supp->sleep_mode) {
+	case MSM_PM_SLEEP_MODE_WAIT_FOR_INTERRUPT:
+		strlcat(nm, "WFI ", BUF_SIZE);
+		break;
+	case MSM_PM_SLEEP_MODE_RAMP_DOWN_AND_WAIT_FOR_INTERRUPT:
+		strlcat(nm, "WFI voltage Rampdown ", BUF_SIZE);
+		break;
+	case MSM_PM_SLEEP_MODE_RETENTION:
+		strlcat(nm, "Retention ", BUF_SIZE);
+		break;
+	case MSM_PM_SLEEP_MODE_POWER_COLLAPSE_STANDALONE:
+		strlcat(nm, "Standalone Power collapse ", BUF_SIZE);
+		break;
+	case MSM_PM_SLEEP_MODE_POWER_COLLAPSE:
+		strlcat(nm, "Idle Power collapse ", BUF_SIZE);
+		break;
+	case MSM_PM_SLEEP_MODE_POWER_COLLAPSE_SUSPEND:
+		strlcat(nm, "Suspend Power collapse ", BUF_SIZE);
+		break;
+	default:
+		strlcat(nm, "Invalid Mode ", BUF_SIZE);
+		break;
+	}
+
+	switch (msm_pm_get_pxo(&(supp->rs_limits))) {
+	case MSM_PM(PXO_OFF):
+		strlcat(nm, "XO: OFF ", BUF_SIZE);
+		break;
+	case MSM_PM(PXO_ON):
+		strlcat(nm, "XO: ON ", BUF_SIZE);
+		break;
+	default:
+		snprintf(default_buf, sizeof(default_buf),
+			"XO : %d ", msm_pm_get_pxo(&(supp->rs_limits)));
+		strlcat(nm, default_buf , BUF_SIZE);
+		break;
+	}
+
+	switch (msm_pm_get_l2_cache(&(supp->rs_limits))) {
+	case MSM_PM(L2_CACHE_HSFS_OPEN):
+		strlcat(nm, "L2: HSFS ", BUF_SIZE);
+		break;
+	case MSM_PM(L2_CACHE_GDHS):
+		strlcat(nm, "L2: GDHS ", BUF_SIZE);
+		break;
+	case MSM_PM(L2_CACHE_RETENTION):
+		strlcat(nm, "L2: Retention ", BUF_SIZE);
+		break;
+	case MSM_PM(L2_CACHE_ACTIVE):
+		strlcat(nm, "L2: Active ", BUF_SIZE);
+		break;
+	default:
+		snprintf(default_buf, sizeof(default_buf),
+			"L2 : %d ", msm_pm_get_l2_cache(&(supp->rs_limits)));
+		strlcat(nm, default_buf , BUF_SIZE);
+		break;
+	}
+
+	snprintf(default_buf, sizeof(default_buf),
+		"Vdd_mem : %d ", msm_pm_get_vdd_mem(&(supp->rs_limits)));
+	strlcat(nm, default_buf , BUF_SIZE);
+
+	snprintf(default_buf, sizeof(default_buf),
+		"Vdd_dig : %d ", msm_pm_get_vdd_dig(&(supp->rs_limits)));
+	strlcat(nm, default_buf , BUF_SIZE);
+
+	strlcpy(stat->level_name, nm, strnlen(nm, BUF_SIZE));
+}
+
+static int64_t msm_lpm_get_time(void)
+{
+	if (msm_lpm_use_qtimer)
+		return ktime_to_ns(ktime_get());
+
+	return msm_timer_get_sclk_time(NULL);
+}
+
+static bool lpm_get_level(void *v, unsigned int *ct)
+{
+	bool ret = false;
+	int it;
+	struct msm_rpmrs_level *level_enter;
+
+	level_enter = container_of(((struct msm_lpm_sleep_data *)v)->limits,
+			struct msm_rpmrs_level, rs_limits);
+	if (level_enter) {
+		for (it = 0; it < lpm_level_count; it++)
+			if (!memcmp(level_enter , lpm_supp_level + it,
+					sizeof(struct msm_rpmrs_level))) {
+				*ct = it;
+				ret = true;
+				break;
+			}
+	}
+	return ret;
+}
+
+static int lpm_callback(struct notifier_block *self, unsigned long cmd,
+				void *sleep_data)
+{
+	static int64_t time;
+	unsigned int ct;
+	struct lpm_level_stat *stats;
+	stats = per_cpu(lpm_levels, cpu_to_debug);
+	/* Update the stats and get the start/stop time */
+	if (cmd == MSM_LPM_STATE_ENTER && !lpm_latency_test) {
+		time = msm_lpm_get_time();
+		stats[lpm_level_iter].entered = true;
+	} else if ((cmd == MSM_LPM_STATE_EXIT) && (time)
+			&& (!lpm_latency_test)) {
+		int64_t time1;
+		time1 = msm_lpm_get_time();
+		time = time1 - time;
+
+		if ((time < stats[lpm_level_iter].min_time) ||
+			(!stats[lpm_level_iter].min_time))
+			stats[lpm_level_iter].min_time = time;
+
+		if (time > stats[lpm_level_iter].max_time)
+			stats[lpm_level_iter].max_time = time;
+
+		time1 = stats[lpm_level_iter].avg_time *
+			stats[lpm_level_iter].count + time;
+		do_div(time1, ++(stats[lpm_level_iter].count));
+
+		stats[lpm_level_iter].avg_time = time1;
+		do_div(time, NSEC_PER_USEC);
+		if (time < lpm_supp_level[lpm_level_iter].
+				time_overhead_us)
+			stats[lpm_level_iter].exit_early++;
+		time = 0;
+	} else if (cmd == MSM_LPM_STATE_ENTER && lpm_latency_test) {
+
+		struct msm_lpm_sleep_data *data = sleep_data;
+		if ((lpm_get_level(sleep_data, &ct)) &&
+		(stats[ct].min_threshold == 0) &&
+		data->kernel_sleep <= lpm_sleep_time) {
+
+			stats[ct].min_threshold = lpm_sleep_time;
+			stats[ct].kernel_sleep_time =
+				data->kernel_sleep;
+		}
+	}
+	return 0;
+}
+
+static struct notifier_block lpm_idle_nb = {
+	.notifier_call = lpm_callback,
+};
+
+static void lpm_test_initiate(int lpm_level_test)
+{
+	int test_ret;
+
+	/* This will communicate to 'stat' debugfs to skip latency printing*/
+	lpm_sleep_time = 0;
+	lpm_latency_test = false;
+	/* Unregister any infinitely registered level*/
+	msm_lpm_unregister_notifier(cpu_to_debug, &lpm_idle_nb);
+
+	/* Register/Unregister for Notification */
+	while (lpm_level_iter < lpm_level_count) {
+		test_ret = msm_lpm_register_notifier(cpu_to_debug,
+				lpm_level_iter, &lpm_idle_nb, false);
+		if (test_ret < 0) {
+			pr_err("%s: Registering notifier failed\n", __func__);
+			return;
+		}
+		if (!timer_interval)
+			break;
+		msleep(timer_interval);
+		msm_lpm_unregister_notifier(cpu_to_debug, &lpm_idle_nb);
+		if (lpm_level_test == lpm_level_count)
+			lpm_level_iter++;
+		else
+			break;
+	}
+}
+
+static void lpm_latency_test_initiate(unsigned long max_time)
+{
+	int test_ret;
+	lpm_latency_test = true;
+	lpm_sleep_time = latency_test_interval;
+
+	msm_lpm_unregister_notifier(cpu_to_debug, &lpm_idle_nb);
+	if (max_time > lpm_sleep_time) {
+
+		do {
+			test_ret = msm_lpm_register_notifier(cpu_to_debug,
+					lpm_level_count + 1,
+					&lpm_idle_nb, true);
+			if (test_ret) {
+				pr_err("%s: Registering notifier failed\n",
+						__func__);
+				return;
+			}
+			usleep(lpm_sleep_time);
+			/*Unregister to ensure that we dont update the latency
+			during the timer value transistion*/
+			msm_lpm_unregister_notifier(cpu_to_debug,
+				&lpm_idle_nb);
+			lpm_sleep_time += latency_test_interval;
+		} while (lpm_sleep_time < max_time);
+	} else
+		pr_err("%s: Invalid time interval specified\n", __func__);
+
+	lpm_latency_test = false;
+}
+
+static ssize_t lpm_test_comm_read(struct file *fp, char __user *user_buffer,
+				size_t buffer_length, loff_t *position)
+{
+	int i = 0;
+	int count = buffer_length;
+	int alloc_size = 100 * lpm_level_count;
+	char *temp_buf;
+	char *comm_buf;
+	ssize_t ret;
+
+	comm_buf = kzalloc(alloc_size, GFP_KERNEL);
+	if (!comm_buf) {
+		pr_err("%s:Memory alloc failed\n", __func__);
+		ret = 0;
+		goto com_read_failed;
+	}
+	temp_buf = comm_buf;
+
+	SNPRINTF(temp_buf, count, "Low power modes available:\n");
+
+	for (i = 0; i < lpm_level_count; i++)
+		SNPRINTF(temp_buf, count, "%d. %s\n", i,
+			per_cpu(lpm_levels, cpu_to_debug)[i].level_name);
+
+	SNPRINTF(temp_buf, count, "%d. MSM test all lpm\n", i++);
+	SNPRINTF(temp_buf, count, "%d. MSM determine latency\n", i);
+
+	ret = simple_read_from_buffer(user_buffer, buffer_length - count,
+					position, comm_buf, alloc_size);
+	kfree(comm_buf);
+
+com_read_failed:
+	return ret;
+}
+
+char *trimspaces(char *time_buf)
+{
+	int len;
+	char *tail;
+
+	len = strnlen(time_buf, INPUT_COUNT_BUF);
+	tail = time_buf + len;
+	while (isspace(*time_buf) && (time_buf != tail))
+		time_buf++;
+	if (time_buf == tail) {
+		time_buf = NULL;
+		goto exit_trim_spaces;
+	}
+	len = strnlen(time_buf, INPUT_COUNT_BUF);
+	tail = time_buf + len - 1;
+	while (isspace(*tail) && tail != time_buf) {
+		*tail = '\0';
+		tail--;
+	}
+exit_trim_spaces:
+	return time_buf;
+}
+
+static ssize_t lpm_test_comm_write(struct file *fp, const char __user
+			*user_buffer, size_t count, loff_t *position)
+{
+	ssize_t ret;
+	int str_ret;
+	int lpm_level_test;
+	char *new_ptr;
+	char *comm_buf;
+
+	comm_buf = kzalloc(COMM_BUF_SIZE, GFP_KERNEL);
+	if (!comm_buf) {
+		pr_err("\'%s\': kzalloc failed\n", __func__);
+		return -EINVAL;
+	}
+
+	memset(comm_buf, '\0', COMM_BUF_SIZE);
+
+	ret = simple_write_to_buffer(comm_buf, COMM_BUF_SIZE, position,
+					user_buffer, count);
+	new_ptr = trimspaces(comm_buf);
+	if (!new_ptr) {
+		pr_err("%s: Test case number input invalid\n", __func__);
+		goto write_com_failed;
+	}
+
+	if (!memcmp(comm_buf, LPM_TEST_ALL_LEVELS,
+			sizeof(LPM_TEST_ALL_LEVELS) - 1)) {
+		lpm_level_test = lpm_level_count;
+		lpm_level_iter = 0;
+		lpm_test_initiate(lpm_level_test);
+		goto write_com_success;
+	} else if (!memcmp(comm_buf, LPM_TEST_LATENCIES,
+			sizeof(LPM_TEST_LATENCIES) - 1)) {
+		lpm_level_test = lpm_level_count + 1;
+		lpm_latency_test_initiate(timer_interval * USEC_PER_MSEC);
+		goto write_com_success;
+	} else if (!memcmp(comm_buf, LPM_TEST_CLEAR,
+			sizeof(LPM_TEST_CLEAR) - 1)) {
+		msm_lpm_unregister_notifier(cpu_to_debug, &lpm_idle_nb);
+		goto write_com_success;
+	}
+
+	str_ret = kstrtoint(new_ptr, 10, &lpm_level_test);
+	if ((str_ret) || (lpm_level_test > (lpm_level_count + 1)) ||
+		(lpm_level_test < 0))
+		goto write_com_failed;
+
+	lpm_level_iter = lpm_level_test;
+	lpm_test_initiate(lpm_level_test);
+	goto write_com_success;
+
+write_com_failed:
+	ret = -EINVAL;
+write_com_success:
+	kfree(comm_buf);
+	return ret;
+}
+
+static ssize_t lpm_test_stat_read(struct file *fp, char __user *user_buffer,
+				size_t buffer_length, loff_t *position)
+{
+	int i = 0;
+	int j = 0;
+	int count = buffer_length;
+	char *stat_buf;
+	char *stat_buf_start;
+	size_t stat_buf_size;
+	ssize_t ret;
+	int64_t min_ns;
+	int64_t max_ns;
+	int64_t avg_ns;
+	uint32_t min_ms;
+	uint32_t max_ms;
+	uint32_t avg_ms;
+
+	stat_buf_size = ((sizeof(struct lpm_level_stat) * lpm_level_count) +
+				STAT_BUF_EXTRA_SIZE);
+	stat_buf = kzalloc(stat_buf_size, GFP_KERNEL);
+	if (!stat_buf) {
+		pr_err("\'%s\': kzalloc failed\n", __func__);
+		return -EINVAL;
+	}
+	stat_buf_start = stat_buf;
+	mutex_lock(&lpm_stats_mutex);
+	memset(stat_buf, '\0', stat_buf_size);
+	SNPRINTF(stat_buf, count, "\n\nStats for CPU: %d\nTotal Levels: %d\n",
+			cpu_to_debug, lpm_level_count);
+	if (!lpm_sleep_time) {
+		SNPRINTF(stat_buf, count, "Level(s) failed: ");
+		for (i = 0 ; i < lpm_level_count; i++) {
+			if (per_cpu(lpm_levels, cpu_to_debug)[i].entered)
+				continue;
+			else {
+				SNPRINTF(stat_buf, count,
+					"\n%d. %s", ++j, per_cpu(lpm_levels,
+					cpu_to_debug)[i].level_name);
+			}
+		}
+		SNPRINTF(stat_buf, count, "\n\nSTATS:");
+		for (i = 0; i < lpm_level_count; i++) {
+			min_ns = per_cpu(lpm_levels, cpu_to_debug)[i].min_time;
+			min_ms = do_div(min_ns, NSEC_PER_MSEC);
+			max_ns = per_cpu(lpm_levels, cpu_to_debug)[i].max_time;
+			max_ms = do_div(max_ns, NSEC_PER_MSEC);
+			avg_ns = per_cpu(lpm_levels, cpu_to_debug)[i].avg_time;
+			avg_ms = do_div(avg_ns, NSEC_PER_MSEC);
+			SNPRINTF(stat_buf, count, "\nLEVEL: %s\n"
+				"Entered : %lld\n"
+				"Early wakeup : %lld\n"
+				"Min Time (mSec): %lld.%06u\n"
+				"Max Time (mSec): %lld.%06u\n"
+				"Avg Time (mSec): %lld.%06u\n",
+				per_cpu(lpm_levels, cpu_to_debug)[i].level_name,
+				per_cpu(lpm_levels, cpu_to_debug)[i].count,
+				per_cpu(lpm_levels, cpu_to_debug)[i].exit_early,
+				min_ns, min_ms,
+				max_ns, max_ms,
+				avg_ns, avg_ms);
+		}
+	} else {
+		for (i = 0; i < lpm_level_count; i++) {
+			SNPRINTF(stat_buf, count, "\nLEVEL: %s\n"
+				"Min Timer value (uSec): %lu\n"
+				"Kernel sleep time (uSec): %u\n",
+				per_cpu(lpm_levels, cpu_to_debug)[i].level_name,
+				per_cpu(lpm_levels, cpu_to_debug)[i].
+				min_threshold,
+				per_cpu(lpm_levels,
+				cpu_to_debug)[i].kernel_sleep_time);
+		}
+	}
+
+	ret = simple_read_from_buffer(user_buffer, buffer_length - count,
+				position, stat_buf_start, stat_buf_size);
+
+	mutex_unlock(&lpm_stats_mutex);
+	kfree(stat_buf_start);
+	return ret;
+}
+
+static ssize_t lpm_test_stat_write(struct file *fp, const char __user
+				*user_buffer, size_t count, loff_t *position)
+{
+	char buf[sizeof(LPM_STATS_RESET)];
+	int ret;
+	int i;
+	struct lpm_level_stat *stats;
+
+	if (count > sizeof(LPM_STATS_RESET)) {
+		ret = -EINVAL;
+		goto write_debug_failed;
+	}
+
+	simple_write_to_buffer(buf, sizeof(LPM_STATS_RESET), position,
+				user_buffer, count);
+
+	if (memcmp(buf, LPM_STATS_RESET, sizeof(LPM_STATS_RESET) - 1)) {
+		ret = -EINVAL;
+		goto write_debug_failed;
+	}
+
+	mutex_lock(&lpm_stats_mutex);
+	stats = per_cpu(lpm_levels, cpu_to_debug);
+	for (i = 0 ; i < lpm_level_count; i++) {
+		stats[i].entered = 0;
+		stats[i].min_time = 0;
+		stats[i].max_time = 0;
+		stats[i].avg_time = 0;
+		stats[i].count = 0;
+		stats[i].exit_early = 0;
+		stats[i].min_threshold = 0;
+		stats[i].kernel_sleep_time = 0;
+	}
+	mutex_unlock(&lpm_stats_mutex);
+	return count;
+write_debug_failed:
+	return ret;
+}
+
+static void lpm_init_rpm_levels(int test_lpm_level_count,
+		struct msm_rpmrs_level *test_levels)
+{
+	int i = 0;
+	unsigned int m_cpu = 0;
+	struct lpm_level_stat *stat_levels = NULL;
+
+	if (test_lpm_level_count < 0)
+		return;
+
+	lpm_level_count = test_lpm_level_count;
+
+	lpm_supp_level = test_levels;
+	for_each_possible_cpu(m_cpu) {
+		stat_levels = kzalloc(sizeof(struct lpm_level_stat) *
+				lpm_level_count, GFP_KERNEL);
+		if (!stat_levels) {
+			for (i = m_cpu - 1; i >= 0; i--)
+				kfree(per_cpu(lpm_levels, i));
+			return;
+		}
+
+		for (i = 0; i < lpm_level_count; i++)
+			lpm_populate_name(&stat_levels[i], &lpm_supp_level[i]);
+
+		per_cpu(lpm_levels, m_cpu) = stat_levels;
+	}
+}
+
+static const struct file_operations fops_stat = {
+	.read = lpm_test_stat_read,
+	.write = lpm_test_stat_write,
+};
+
+static const struct file_operations fops_comm = {
+	.read = lpm_test_comm_read,
+	.write = lpm_test_comm_write,
+};
+
+static int __devinit lpm_test_init(int test_lpm_level_count,
+		struct msm_rpmrs_level *test_levels)
+{
+	int filevalue;
+	int lpm_comm;
+	int ret = -EINVAL;
+	struct dentry *parent_dir = NULL;
+
+	parent_dir = debugfs_create_dir("msm_lpm_debug", NULL);
+	if (!parent_dir) {
+		pr_err("%s: debugfs directory creation failed\n",
+				__func__);
+		goto init_err;
+	}
+
+	lpm_stat = debugfs_create_file("stat",
+			S_IRUGO | S_IWUSR | S_IWGRP, parent_dir,
+			&filevalue, &fops_stat);
+	if (!lpm_stat) {
+		pr_err("%s: lpm_stats debugfs creation failed\n",
+				__func__);
+		goto init_err;
+	}
+
+	lpm_ext_comm = debugfs_create_file("comm",
+			S_IRUGO | S_IWUSR | S_IWGRP, parent_dir, &lpm_comm,
+			&fops_comm);
+	if (!lpm_ext_comm) {
+		pr_err("%s: lpm_comm debugfs creation failed\n",
+			__func__);
+		debugfs_remove(lpm_stat);
+		goto init_err;
+	}
+
+	/*Query RPM resources and allocate the data sturctures*/
+	lpm_init_rpm_levels(test_lpm_level_count, test_levels);
+	ret = 0;
+
+init_err:
+	return ret;
+}
+
+static int  __devexit lpm_test_exit(struct platform_device *pdev)
+{
+	unsigned int m_cpu = 0;
+
+	kfree(lpm_supp_level);
+	for_each_possible_cpu(m_cpu)
+		kfree(per_cpu(lpm_levels, m_cpu));
+	debugfs_remove(lpm_stat);
+	debugfs_remove(lpm_ext_comm);
+	return 0;
+}
+
+static int __devinit lpm_test_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct lpm_test_platform_data *pdata;
+	struct msm_rpmrs_level *test_levels;
+	int test_lpm_level_count;
+
+	pdata = pdev->dev.platform_data;
+
+	if (!pdata) {
+		dev_err(dev, "no platform data specified\n");
+		return -EINVAL;
+	}
+
+	test_levels = pdata->msm_lpm_test_levels;
+	test_lpm_level_count = pdata->msm_lpm_test_level_count;
+
+	if (pdata->use_qtimer)
+		msm_lpm_use_qtimer = true;
+
+	lpm_test_init(test_lpm_level_count, test_levels);
+
+	return 0;
+}
+
+static struct platform_driver lpm_test_driver = {
+	.probe = lpm_test_probe,
+	.remove = lpm_test_exit,
+	.driver = {
+		.name = "lpm_test",
+		.owner = THIS_MODULE,
+	},
+};
+
+static int __init lpm_test_platform_driver_init(void)
+{
+	return platform_driver_register(&lpm_test_driver);
+}
+
+late_initcall(lpm_test_platform_driver_init);
diff --git a/arch/arm/mach-msm/test-lpm.h b/arch/arm/mach-msm/test-lpm.h
new file mode 100644
index 0000000..1486f88
--- /dev/null
+++ b/arch/arm/mach-msm/test-lpm.h
@@ -0,0 +1,22 @@
+/* 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 __ARCH_ARM_MACH_MSM_TEST_LPM_H
+#define __ARCH_ARM_MACH_MSM_TEST_LPM_H
+
+struct lpm_test_platform_data {
+	struct msm_rpmrs_level *msm_lpm_test_levels;
+	int msm_lpm_test_level_count;
+	bool use_qtimer;
+};
+#endif
diff --git a/arch/arm/mach-msm/test_qmi_client.c b/arch/arm/mach-msm/test_qmi_client.c
new file mode 100644
index 0000000..d070e37
--- /dev/null
+++ b/arch/arm/mach-msm/test_qmi_client.c
@@ -0,0 +1,344 @@
+/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/errno.h>
+#include <linux/delay.h>
+#include <linux/debugfs.h>
+#include <linux/qmi_encdec.h>
+
+#include <asm/uaccess.h>
+
+#include <mach/msm_qmi_interface.h>
+
+#include "kernel_test_service_v01.h"
+
+#define TEST_SERVICE_SVC_ID 0x0000000f
+#define TEST_SERVICE_INS_ID 1
+
+static int test_rep_cnt = 10;
+module_param_named(rep_cnt, test_rep_cnt, int, S_IRUGO | S_IWUSR | S_IWGRP);
+
+static int test_data_sz = 50;
+module_param_named(data_sz, test_data_sz, int, S_IRUGO | S_IWUSR | S_IWGRP);
+
+static int test_clnt_debug_mask;
+module_param_named(debug_mask, test_clnt_debug_mask,
+		   int, S_IRUGO | S_IWUSR | S_IWGRP);
+
+#define D(x...) do { \
+	if (test_clnt_debug_mask) \
+		pr_debug(x); \
+} while (0)
+
+/* Variable to initiate the test through debugfs interface */
+static struct dentry *test_dent;
+
+/* Test client port for IPC Router */
+static struct qmi_handle *test_clnt;
+static int test_clnt_reset;
+
+/* Reader thread to receive responses & indications */
+static void test_clnt_recv_msg(struct work_struct *work);
+static DECLARE_DELAYED_WORK(work_recv_msg, test_clnt_recv_msg);
+static void test_clnt_svc_arrive(struct work_struct *work);
+static DECLARE_DELAYED_WORK(work_svc_arrive, test_clnt_svc_arrive);
+static void test_clnt_svc_exit(struct work_struct *work);
+static DECLARE_DELAYED_WORK(work_svc_exit, test_clnt_svc_exit);
+static struct workqueue_struct *test_clnt_workqueue;
+
+/* Variable to hold the test result */
+static int test_res;
+
+static int test_qmi_ping_pong_send_sync_msg(void)
+{
+	struct test_ping_req_msg_v01 req;
+	struct test_ping_resp_msg_v01 resp;
+	struct msg_desc req_desc, resp_desc;
+	int rc;
+
+	memcpy(req.ping, "ping", sizeof(req.ping));
+	req.client_name_valid = 0;
+
+	req_desc.max_msg_len = TEST_PING_REQ_MAX_MSG_LEN_V01;
+	req_desc.msg_id = TEST_PING_REQ_MSG_ID_V01;
+	req_desc.ei_array = test_ping_req_msg_v01_ei;
+
+	resp_desc.max_msg_len = TEST_PING_REQ_MAX_MSG_LEN_V01;
+	resp_desc.msg_id = TEST_PING_REQ_MSG_ID_V01;
+	resp_desc.ei_array = test_ping_resp_msg_v01_ei;
+
+	rc = qmi_send_req_wait(test_clnt, &req_desc, &req, sizeof(req),
+			       &resp_desc, &resp, sizeof(resp), 0);
+	if (rc < 0) {
+		pr_err("%s: send req failed %d\n", __func__, rc);
+		return rc;
+	}
+
+	D("%s: Received %s response\n", __func__, resp.pong);
+	return rc;
+}
+
+static int test_qmi_data_send_sync_msg(unsigned int data_len)
+{
+	struct test_data_req_msg_v01 *req;
+	struct test_data_resp_msg_v01 *resp;
+	struct msg_desc req_desc, resp_desc;
+	int rc, i;
+
+	req = kzalloc(sizeof(struct test_data_req_msg_v01), GFP_KERNEL);
+	if (!req) {
+		pr_err("%s: Data req msg alloc failed\n", __func__);
+		return -ENOMEM;
+	}
+
+	resp = kzalloc(sizeof(struct test_data_resp_msg_v01), GFP_KERNEL);
+	if (!resp) {
+		pr_err("%s: Data resp msg alloc failed\n", __func__);
+		kfree(req);
+		return -ENOMEM;
+	}
+
+	req->data_len = data_len;
+	for (i = 0; i < data_len; i = i + sizeof(int))
+		memcpy(req->data + i, (uint8_t *)&i, sizeof(int));
+	req->client_name_valid = 0;
+
+	req_desc.max_msg_len = TEST_DATA_REQ_MAX_MSG_LEN_V01;
+	req_desc.msg_id = TEST_DATA_REQ_MSG_ID_V01;
+	req_desc.ei_array = test_data_req_msg_v01_ei;
+
+	resp_desc.max_msg_len = TEST_DATA_REQ_MAX_MSG_LEN_V01;
+	resp_desc.msg_id = TEST_DATA_REQ_MSG_ID_V01;
+	resp_desc.ei_array = test_data_resp_msg_v01_ei;
+
+	rc = qmi_send_req_wait(test_clnt, &req_desc, req, sizeof(*req),
+			       &resp_desc, resp, sizeof(*resp), 0);
+	if (rc < 0) {
+		pr_err("%s: send req failed\n", __func__);
+		goto data_send_err;
+	}
+
+	D("%s: data_valid %d\n", __func__, resp->data_valid);
+	D("%s: data_len %d\n", __func__, resp->data_len);
+data_send_err:
+	kfree(resp);
+	kfree(req);
+	return rc;
+}
+
+static void test_clnt_recv_msg(struct work_struct *work)
+{
+	int rc;
+
+	rc = qmi_recv_msg(test_clnt);
+	if (rc < 0)
+		pr_err("%s: Error receiving message\n", __func__);
+}
+
+static void test_clnt_notify(struct qmi_handle *handle,
+			     enum qmi_event_type event, void *notify_priv)
+{
+	switch (event) {
+	case QMI_RECV_MSG:
+		queue_delayed_work(test_clnt_workqueue,
+				   &work_recv_msg, 0);
+		break;
+	default:
+		break;
+	}
+}
+
+static void test_clnt_svc_arrive(struct work_struct *work)
+{
+	int rc;
+
+	D("%s begins\n", __func__);
+
+	/* Create a Local client port for QMI communication */
+	test_clnt = qmi_handle_create(test_clnt_notify, NULL);
+	if (!test_clnt) {
+		pr_err("%s: QMI client handle alloc failed\n", __func__);
+		return;
+	}
+
+	D("%s: Lookup server name\n", __func__);
+	rc = qmi_connect_to_service(test_clnt, TEST_SERVICE_SVC_ID,
+				    TEST_SERVICE_INS_ID);
+	if (rc < 0) {
+		pr_err("%s: Server not found\n", __func__);
+		qmi_handle_destroy(test_clnt);
+		test_clnt = NULL;
+		return;
+	}
+	test_clnt_reset = 0;
+	D("%s complete\n", __func__);
+}
+
+static void test_clnt_svc_exit(struct work_struct *work)
+{
+	D("%s begins\n", __func__);
+
+	qmi_handle_destroy(test_clnt);
+	test_clnt_reset = 1;
+	test_clnt = NULL;
+
+	D("%s complete\n", __func__);
+}
+
+static int test_clnt_svc_event_notify(struct notifier_block *this,
+				      unsigned long code,
+				      void *_cmd)
+{
+	D("%s: event %ld\n", __func__, code);
+	switch (code) {
+	case QMI_SERVER_ARRIVE:
+		queue_delayed_work(test_clnt_workqueue,
+				   &work_svc_arrive, 0);
+		break;
+	case QMI_SERVER_EXIT:
+		queue_delayed_work(test_clnt_workqueue,
+				   &work_svc_exit, 0);
+		break;
+	default:
+		break;
+	}
+	return 0;
+}
+
+static int test_qmi_open(struct inode *ip, struct file *fp)
+{
+	if (!test_clnt) {
+		pr_err("%s Test client is not initialized\n", __func__);
+		return -ENODEV;
+	}
+	return 0;
+}
+
+static ssize_t test_qmi_read(struct file *fp, char __user *buf,
+		size_t count, loff_t *pos)
+{
+	char _buf[16];
+	snprintf(_buf, sizeof(_buf), "%d\n", test_res);
+	test_res = 0;
+	return simple_read_from_buffer(buf, count, pos,
+				       _buf, strnlen(_buf, 16));
+}
+
+static int test_qmi_release(struct inode *ip, struct file *fp)
+{
+	return 0;
+}
+
+static ssize_t test_qmi_write(struct file *fp, const char __user *buf,
+			size_t count, loff_t *pos)
+{
+	unsigned char cmd[64];
+	int len;
+	int i;
+
+	if (count < 1)
+		return 0;
+
+	len = min(count, (sizeof(cmd) - 1));
+
+	if (copy_from_user(cmd, buf, len))
+		return -EFAULT;
+
+	cmd[len] = 0;
+	if (cmd[len-1] == '\n') {
+		cmd[len-1] = 0;
+		len--;
+	}
+
+	if (!strncmp(cmd, "ping_pong", sizeof(cmd))) {
+		for (i = 0; i < test_rep_cnt; i++) {
+			test_res = test_qmi_ping_pong_send_sync_msg();
+			if (test_res == -ENETRESET || test_clnt_reset) {
+				do {
+					msleep(50);
+				} while (test_clnt_reset);
+			}
+		}
+	} else if (!strncmp(cmd, "data", sizeof(cmd))) {
+		for (i = 0; i < test_rep_cnt; i++) {
+			test_res = test_qmi_data_send_sync_msg(test_data_sz);
+			if (test_res == -ENETRESET || test_clnt_reset) {
+				do {
+					msleep(50);
+				} while (test_clnt_reset);
+			}
+		}
+	} else {
+		test_res = -EINVAL;
+	}
+	return count;
+}
+
+static struct notifier_block test_clnt_nb = {
+	.notifier_call = test_clnt_svc_event_notify,
+};
+
+static const struct file_operations debug_ops = {
+	.owner = THIS_MODULE,
+	.open = test_qmi_open,
+	.read = test_qmi_read,
+	.write = test_qmi_write,
+	.release = test_qmi_release,
+};
+
+static int __init test_qmi_init(void)
+{
+	int rc;
+
+	test_clnt_workqueue = create_singlethread_workqueue("test_clnt");
+	if (!test_clnt_workqueue)
+		return -EFAULT;
+
+	rc = qmi_svc_event_notifier_register(TEST_SERVICE_SVC_ID,
+				TEST_SERVICE_INS_ID, &test_clnt_nb);
+	if (rc < 0) {
+		pr_err("%s: notifier register failed\n", __func__);
+		destroy_workqueue(test_clnt_workqueue);
+		return rc;
+	}
+
+	test_dent = debugfs_create_file("test_qmi_client", 0444, 0,
+					 NULL, &debug_ops);
+	if (IS_ERR(test_dent)) {
+		pr_err("%s: unable to create debugfs %ld\n",
+			__func__, IS_ERR(test_dent));
+		test_dent = NULL;
+		qmi_svc_event_notifier_unregister(TEST_SERVICE_SVC_ID,
+					TEST_SERVICE_INS_ID, &test_clnt_nb);
+		destroy_workqueue(test_clnt_workqueue);
+		return -EFAULT;
+	}
+
+	return 0;
+}
+
+static void __exit test_qmi_exit(void)
+{
+	qmi_svc_event_notifier_unregister(TEST_SERVICE_SVC_ID,
+					TEST_SERVICE_INS_ID, &test_clnt_nb);
+	destroy_workqueue(test_clnt_workqueue);
+	debugfs_remove(test_dent);
+}
+
+module_init(test_qmi_init);
+module_exit(test_qmi_exit);
+
+MODULE_DESCRIPTION("TEST QMI Client Driver");
+MODULE_LICENSE("GPL v2");
diff --git a/block/test-iosched.c b/block/test-iosched.c
index d2716c84..12f56bd 100644
--- a/block/test-iosched.c
+++ b/block/test-iosched.c
@@ -364,6 +364,8 @@
 	test_rq->req_completed = false;
 	test_rq->req_result = -EINVAL;
 	test_rq->rq = rq;
+	if (ptd->test_info.get_rq_disk_fn)
+		test_rq->rq->rq_disk = ptd->test_info.get_rq_disk_fn();
 	test_rq->is_err_expected = is_err_expcted;
 	rq->elv.priv[0] = (void *)test_rq;
 
diff --git a/drivers/ata/ahci_platform.c b/drivers/ata/ahci_platform.c
index 82d19e0..ced7a80 100644
--- a/drivers/ata/ahci_platform.c
+++ b/drivers/ata/ahci_platform.c
@@ -73,7 +73,7 @@
 	AHCI_SHT("ahci_platform"),
 };
 
-static int __init ahci_probe(struct platform_device *pdev)
+static int __devinit ahci_probe(struct platform_device *pdev)
 {
 	struct device *dev = &pdev->dev;
 	struct ahci_platform_data *pdata = dev_get_platdata(dev);
@@ -287,6 +287,7 @@
 MODULE_DEVICE_TABLE(of, ahci_of_match);
 
 static struct platform_driver ahci_driver = {
+	.probe	= ahci_probe,
 	.remove = __devexit_p(ahci_remove),
 	.driver = {
 		.name = "ahci",
@@ -301,7 +302,7 @@
 
 static int __init ahci_init(void)
 {
-	return platform_driver_probe(&ahci_driver, ahci_probe);
+	return platform_driver_register(&ahci_driver);
 }
 module_init(ahci_init);
 
diff --git a/drivers/char/diag/diagchar.h b/drivers/char/diag/diagchar.h
index 0b395c5..79f20a4 100644
--- a/drivers/char/diag/diagchar.h
+++ b/drivers/char/diag/diagchar.h
@@ -321,4 +321,8 @@
 
 extern struct diag_bridge_dev *diag_bridge;
 extern struct diagchar_dev *driver;
+
+extern int wrap_enabled;
+extern uint16_t wrap_count;
+
 #endif
diff --git a/drivers/char/diag/diagchar_core.c b/drivers/char/diag/diagchar_core.c
index 6a7f55f..8a3a645 100644
--- a/drivers/char/diag/diagchar_core.c
+++ b/drivers/char/diag/diagchar_core.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2008-2012, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2008-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -84,11 +84,23 @@
 static int token_list[MAX_PROC] = {0, -1, -2, -3, -4, -5, -6, -7, -8, -9};
 
 #define DIAGPKT_MAX_DELAYED_RSP 0xFFFF
-/* This macro gets the next delayed respose id. Once it reaches
- DIAGPKT_MAX_DELAYED_RSP, it stays at DIAGPKT_MAX_DELAYED_RSP */
 
-#define DIAGPKT_NEXT_DELAYED_RSP_ID(x) 				\
-((x < DIAGPKT_MAX_DELAYED_RSP) ? x++ : DIAGPKT_MAX_DELAYED_RSP)
+/* returns the next delayed rsp id - rollsover the id if wrapping is
+   enabled. */
+uint16_t diagpkt_next_delayed_rsp_id(uint16_t rspid)
+{
+	if (rspid < DIAGPKT_MAX_DELAYED_RSP)
+		rspid++;
+	else {
+		if (wrap_enabled) {
+			rspid = 1;
+			wrap_count++;
+		} else
+			rspid = DIAGPKT_MAX_DELAYED_RSP;
+	}
+	delayed_rsp_id = rspid;
+	return delayed_rsp_id;
+}
 
 #define COPY_USER_SPACE_OR_EXIT(buf, data, length)		\
 do {								\
@@ -534,7 +546,7 @@
 		if ((delay_params.rsp_ptr) &&
 		 (delay_params.size == sizeof(delayed_rsp_id)) &&
 				 (delay_params.num_bytes_ptr)) {
-			interim_rsp_id = DIAGPKT_NEXT_DELAYED_RSP_ID(
+			interim_rsp_id = diagpkt_next_delayed_rsp_id(
 							delayed_rsp_id);
 			if (copy_to_user((void *)delay_params.rsp_ptr,
 					 &interim_rsp_id, sizeof(uint16_t)))
@@ -1261,6 +1273,13 @@
 		ret = -ENOMEM;
 		goto fail_free_hdlc;
 	}
+	if (HDLC_OUT_BUF_SIZE < (2*payload_size) + 3) {
+		pr_err("diag: Dropping packet, HDLC encoded packet payload size crosses buffer limit. Current payload size %d\n",
+				((2*payload_size) + 3));
+		driver->dropped_count++;
+		ret = -EBADMSG;
+		goto fail_free_hdlc;
+	}
 	if (HDLC_OUT_BUF_SIZE - driver->used <= (2*payload_size) + 3) {
 		err = diag_device_write(buf_hdlc, APPS_DATA, NULL);
 		if (err) {
@@ -1331,8 +1350,8 @@
 		driver->used = 0;
 	}
 
-	mutex_unlock(&driver->diagchar_mutex);
 	diagmem_free(driver, buf_copy, POOL_TYPE_COPY);
+	mutex_unlock(&driver->diagchar_mutex);
 	if (!timer_in_progress)	{
 		timer_in_progress = 1;
 		ret = mod_timer(&drain_timer, jiffies + msecs_to_jiffies(500));
diff --git a/drivers/char/diag/diagfwd.c b/drivers/char/diag/diagfwd.c
index 6b4c337..0bd26cf 100644
--- a/drivers/char/diag/diagfwd.c
+++ b/drivers/char/diag/diagfwd.c
@@ -51,6 +51,8 @@
 struct diag_master_table entry;
 struct diag_send_desc_type send = { NULL, NULL, DIAG_STATE_START, 0 };
 struct diag_hdlc_dest_type enc = { NULL, NULL, 0 };
+int wrap_enabled;
+uint16_t wrap_count;
 
 void encode_rsp_and_send(int buf_length)
 {
@@ -896,6 +898,23 @@
 			return 0;
 		}
 	}
+	/* Return the Delayed Response Wrap Status */
+	else if ((*buf == 0x4b) && (*(buf+1) == 0x32) &&
+		(*(buf+2) == 0x04) && (*(buf+3) == 0x0)) {
+		memcpy(driver->apps_rsp_buf, buf, 4);
+		driver->apps_rsp_buf[4] = wrap_enabled;
+		encode_rsp_and_send(4);
+		return 0;
+	}
+	/* Wrap the Delayed Rsp ID */
+	else if ((*buf == 0x4b) && (*(buf+1) == 0x32) &&
+		(*(buf+2) == 0x05) && (*(buf+3) == 0x0)) {
+		wrap_enabled = true;
+		memcpy(driver->apps_rsp_buf, buf, 4);
+		driver->apps_rsp_buf[4] = wrap_count;
+		encode_rsp_and_send(5);
+		return 0;
+	}
 	 /* Check for ID for NO MODEM present */
 	else if (chk_polling_response()) {
 		/* respond to 0x0 command */
@@ -1449,6 +1468,8 @@
 	int success;
 	int i;
 
+	wrap_enabled = 0;
+	wrap_count = 0;
 	diag_debug_buf_idx = 0;
 	driver->read_len_legacy = 0;
 	driver->use_device_tree = has_device_tree();
diff --git a/drivers/coresight/coresight-etm.c b/drivers/coresight/coresight-etm.c
index 9f96b19..b569aed 100644
--- a/drivers/coresight/coresight-etm.c
+++ b/drivers/coresight/coresight-etm.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011-2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2011-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -91,75 +91,87 @@
  */
 
 /* Trace registers (0x000-0x2FC) */
-#define ETMCR			(0x000)
-#define ETMCCR			(0x004)
-#define ETMTRIGGER		(0x008)
-#define ETMSR			(0x010)
-#define ETMSCR			(0x014)
-#define ETMTSSCR		(0x018)
-#define ETMTEEVR		(0x020)
-#define ETMTECR1		(0x024)
-#define ETMFFLR			(0x02C)
-#define ETMACVRn(n)		(0x040 + (n * 4))
-#define ETMACTRn(n)		(0x080 + (n * 4))
-#define ETMCNTRLDVRn(n)		(0x140 + (n * 4))
-#define ETMCNTENRn(n)		(0x150 + (n * 4))
-#define ETMCNTRLDEVRn(n)	(0x160 + (n * 4))
-#define ETMCNTVRn(n)		(0x170 + (n * 4))
-#define ETMSQ12EVR		(0x180)
-#define ETMSQ21EVR		(0x184)
-#define ETMSQ23EVR		(0x188)
-#define ETMSQ31EVR		(0x18C)
-#define ETMSQ32EVR		(0x190)
-#define ETMSQ13EVR		(0x194)
-#define ETMSQR			(0x19C)
-#define ETMEXTOUTEVRn(n)	(0x1A0 + (n * 4))
-#define ETMCIDCVRn(n)		(0x1B0 + (n * 4))
-#define ETMCIDCMR		(0x1BC)
-#define ETMIMPSPEC0		(0x1C0)
-#define ETMIMPSPEC1		(0x1C4)
-#define ETMIMPSPEC2		(0x1C8)
-#define ETMIMPSPEC3		(0x1CC)
-#define ETMIMPSPEC4		(0x1D0)
-#define ETMIMPSPEC5		(0x1D4)
-#define ETMIMPSPEC6		(0x1D8)
-#define ETMIMPSPEC7		(0x1DC)
-#define ETMSYNCFR		(0x1E0)
-#define ETMIDR			(0x1E4)
-#define ETMCCER			(0x1E8)
-#define ETMEXTINSELR		(0x1EC)
-#define ETMTESSEICR		(0x1F0)
-#define ETMEIBCR		(0x1F4)
-#define ETMTSEVR		(0x1F8)
-#define ETMAUXCR		(0x1FC)
-#define ETMTRACEIDR		(0x200)
-#define ETMVMIDCVR		(0x240)
+#define ETMCR				(0x000)
+#define ETMCCR				(0x004)
+#define ETMTRIGGER			(0x008)
+#define ETMASSICCTLR			(0x00C)
+#define ETMSR				(0x010)
+#define ETMSCR				(0x014)
+#define ETMTSSCR			(0x018)
+#define ETMTECR2			(0x01C)
+#define ETMTEEVR			(0x020)
+#define ETMTECR1			(0x024)
+#define ETMFFLR				(0x02C)
+#define ETMVDEVR			(0x030)
+#define ETMVDCR1			(0x034)
+#define ETMVDCR3			(0x03C)
+#define ETMACVRn(n)			(0x040 + (n * 4))
+#define ETMACTRn(n)			(0x080 + (n * 4))
+#define ETMDCVRn(n)			(0x0C0 + (n * 8))
+#define ETMDCMRn(n)			(0x100 + (n * 8))
+#define ETMCNTRLDVRn(n)			(0x140 + (n * 4))
+#define ETMCNTENRn(n)			(0x150 + (n * 4))
+#define ETMCNTRLDEVRn(n)		(0x160 + (n * 4))
+#define ETMCNTVRn(n)			(0x170 + (n * 4))
+#define ETMSQ12EVR			(0x180)
+#define ETMSQ21EVR			(0x184)
+#define ETMSQ23EVR			(0x188)
+#define ETMSQ31EVR			(0x18C)
+#define ETMSQ32EVR			(0x190)
+#define ETMSQ13EVR			(0x194)
+#define ETMSQR				(0x19C)
+#define ETMEXTOUTEVRn(n)		(0x1A0 + (n * 4))
+#define ETMCIDCVRn(n)			(0x1B0 + (n * 4))
+#define ETMCIDCMR			(0x1BC)
+#define ETMIMPSPEC0			(0x1C0)
+#define ETMIMPSPEC1			(0x1C4)
+#define ETMIMPSPEC2			(0x1C8)
+#define ETMIMPSPEC3			(0x1CC)
+#define ETMIMPSPEC4			(0x1D0)
+#define ETMIMPSPEC5			(0x1D4)
+#define ETMIMPSPEC6			(0x1D8)
+#define ETMIMPSPEC7			(0x1DC)
+#define ETMSYNCFR			(0x1E0)
+#define ETMIDR				(0x1E4)
+#define ETMCCER				(0x1E8)
+#define ETMEXTINSELR			(0x1EC)
+#define ETMTESSEICR			(0x1F0)
+#define ETMEIBCR			(0x1F4)
+#define ETMTSEVR			(0x1F8)
+#define ETMAUXCR			(0x1FC)
+#define ETMTRACEIDR			(0x200)
+#define ETMIDR2				(0x208)
+#define ETMVMIDCVR			(0x240)
 /* Management registers (0x300-0x314) */
-#define ETMOSLAR		(0x300)
-#define ETMOSLSR		(0x304)
-#define ETMOSSRR		(0x308)
-#define ETMPDCR			(0x310)
-#define ETMPDSR			(0x314)
+#define ETMOSLAR			(0x300)
+#define ETMOSLSR			(0x304)
+#define ETMOSSRR			(0x308)
+#define ETMPDCR				(0x310)
+#define ETMPDSR				(0x314)
 
-#define ETM_MAX_ADDR_CMP	(16)
-#define ETM_MAX_CNTR		(4)
-#define ETM_MAX_CTXID_CMP	(3)
+#define ETM_MAX_ADDR_CMP		(16)
+#define ETM_MAX_CNTR			(4)
+#define ETM_MAX_CTXID_CMP		(3)
 
-#define ETM_MODE_EXCLUDE	BIT(0)
-#define ETM_MODE_CYCACC		BIT(1)
-#define ETM_MODE_STALL		BIT(2)
-#define ETM_MODE_TIMESTAMP	BIT(3)
-#define ETM_MODE_CTXID		BIT(4)
-#define ETM_MODE_ALL		(0x1F)
+#define ETM_MODE_EXCLUDE		BIT(0)
+#define ETM_MODE_CYCACC			BIT(1)
+#define ETM_MODE_STALL			BIT(2)
+#define ETM_MODE_TIMESTAMP		BIT(3)
+#define ETM_MODE_CTXID			BIT(4)
+#define ETM_MODE_DATA_TRACE_VAL		BIT(5)
+#define ETM_MODE_DATA_TRACE_ADDR	BIT(6)
+#define ETM_MODE_ALL			(0x7F)
 
-#define ETM_EVENT_MASK		(0x1FFFF)
-#define ETM_SYNC_MASK		(0xFFF)
-#define ETM_ALL_MASK		(0xFFFFFFFF)
+#define ETM_DATACMP_ENABLE		(0x2)
 
-#define ETM_SEQ_STATE_MAX_VAL	(0x2)
+#define ETM_EVENT_MASK			(0x1FFFF)
+#define ETM_SYNC_MASK			(0xFFF)
+#define ETM_ALL_MASK			(0xFFFFFFFF)
 
-#define ETM_REG_DUMP_VER_OFF	(4)
-#define ETM_REG_DUMP_VER	(1)
+#define ETM_SEQ_STATE_MAX_VAL		(0x2)
+
+#define ETM_REG_DUMP_VER_OFF		(4)
+#define ETM_REG_DUMP_VER		(1)
 
 enum etm_addr_type {
 	ETM_ADDR_TYPE_NONE,
@@ -203,6 +215,7 @@
 	uint8_t				nr_ext_inp;
 	uint8_t				nr_ext_out;
 	uint8_t				nr_ctxid_cmp;
+	uint8_t				nr_data_cmp;
 	uint8_t				reset;
 	uint32_t			mode;
 	uint32_t			ctrl;
@@ -210,11 +223,18 @@
 	uint32_t			startstop_ctrl;
 	uint32_t			enable_event;
 	uint32_t			enable_ctrl1;
+	uint32_t			enable_ctrl2;
 	uint32_t			fifofull_level;
 	uint8_t				addr_idx;
 	uint32_t			addr_val[ETM_MAX_ADDR_CMP];
 	uint32_t			addr_acctype[ETM_MAX_ADDR_CMP];
 	uint32_t			addr_type[ETM_MAX_ADDR_CMP];
+	bool				data_trace_support;
+	uint32_t			data_val[ETM_MAX_ADDR_CMP];
+	uint32_t			data_mask[ETM_MAX_ADDR_CMP];
+	uint32_t			viewdata_event;
+	uint32_t			viewdata_ctrl1;
+	uint32_t			viewdata_ctrl3;
 	uint8_t				cntr_idx;
 	uint32_t			cntr_rld_val[ETM_MAX_CNTR];
 	uint32_t			cntr_event[ETM_MAX_CNTR];
@@ -247,8 +267,10 @@
  */
 static void etm_os_unlock(void *info)
 {
-	etm_writel_cp14(0x0, ETMOSLAR);
-	isb();
+	if (cpu_is_krait()) {
+		etm_writel_cp14(0x0, ETMOSLAR);
+		isb();
+	}
 }
 
 /*
@@ -382,6 +404,14 @@
 	ETM_LOCK(drvdata);
 }
 
+static bool etm_version_gte(uint8_t arch, uint8_t base_arch)
+{
+	if (arch >= base_arch && ((arch & PFT_ARCH_MAJOR) != PFT_ARCH_MAJOR))
+		return true;
+	else
+		return false;
+}
+
 static void __etm_enable(void *info)
 {
 	int i;
@@ -409,13 +439,24 @@
 	etm_writel(drvdata, drvdata->ctrl | etmcr, ETMCR);
 	etm_writel(drvdata, drvdata->trigger_event, ETMTRIGGER);
 	etm_writel(drvdata, drvdata->startstop_ctrl, ETMTSSCR);
+	if (etm_version_gte(drvdata->arch, ETM_ARCH_V1_2))
+		etm_writel(drvdata, drvdata->enable_ctrl2, ETMTECR2);
 	etm_writel(drvdata, drvdata->enable_event, ETMTEEVR);
 	etm_writel(drvdata, drvdata->enable_ctrl1, ETMTECR1);
 	etm_writel(drvdata, drvdata->fifofull_level, ETMFFLR);
+	if (drvdata->data_trace_support == true) {
+		etm_writel(drvdata, drvdata->viewdata_event, ETMVDEVR);
+		etm_writel(drvdata, drvdata->viewdata_ctrl1, ETMVDCR1);
+		etm_writel(drvdata, drvdata->viewdata_ctrl3, ETMVDCR3);
+	}
 	for (i = 0; i < drvdata->nr_addr_cmp; i++) {
 		etm_writel(drvdata, drvdata->addr_val[i], ETMACVRn(i));
 		etm_writel(drvdata, drvdata->addr_acctype[i], ETMACTRn(i));
 	}
+	for (i = 0; i < drvdata->nr_data_cmp; i++) {
+		etm_writel(drvdata, drvdata->data_val[i], ETMDCVRn(i));
+		etm_writel(drvdata, drvdata->data_mask[i], ETMDCMRn(i));
+	}
 	for (i = 0; i < drvdata->nr_cntr; i++) {
 		etm_writel(drvdata, drvdata->cntr_rld_val[i], ETMCNTRLDVRn(i));
 		etm_writel(drvdata, drvdata->cntr_event[i], ETMCNTENRn(i));
@@ -594,21 +635,37 @@
 	if (val) {
 		drvdata->mode = ETM_MODE_EXCLUDE;
 		drvdata->ctrl = 0x0;
+		if (etm_version_gte(drvdata->arch, ETM_ARCH_V1_0))
+			drvdata->ctrl |= BIT(11);
 		if (cpu_is_krait_v1()) {
 			drvdata->mode |= ETM_MODE_CYCACC;
 			drvdata->ctrl |= BIT(12);
 		}
 		drvdata->trigger_event = 0x406F;
 		drvdata->startstop_ctrl = 0x0;
+		if (etm_version_gte(drvdata->arch, ETM_ARCH_V1_2))
+			drvdata->enable_ctrl2 = 0x0;
 		drvdata->enable_event = 0x6F;
 		drvdata->enable_ctrl1 = 0x1000000;
 		drvdata->fifofull_level = 0x28;
+		if (drvdata->data_trace_support == true) {
+			drvdata->mode |= (ETM_MODE_DATA_TRACE_VAL |
+						ETM_MODE_DATA_TRACE_ADDR);
+			drvdata->ctrl |= BIT(2) | BIT(3);
+			drvdata->viewdata_event = 0x6F;
+			drvdata->viewdata_ctrl1 = 0x0;
+			drvdata->viewdata_ctrl3 = 0x10000;
+		}
 		drvdata->addr_idx = 0x0;
 		for (i = 0; i < drvdata->nr_addr_cmp; i++) {
 			drvdata->addr_val[i] = 0x0;
 			drvdata->addr_acctype[i] = 0x0;
 			drvdata->addr_type[i] = ETM_ADDR_TYPE_NONE;
 		}
+		for (i = 0; i < drvdata->nr_data_cmp; i++) {
+			drvdata->data_val[i] = 0;
+			drvdata->data_mask[i] = ~(0);
+		}
 		drvdata->cntr_idx = 0x0;
 		for (i = 0; i < drvdata->nr_cntr; i++) {
 			drvdata->cntr_rld_val[i] = 0x0;
@@ -684,6 +741,17 @@
 		drvdata->ctrl |= (BIT(14) | BIT(15));
 	else
 		drvdata->ctrl &= ~(BIT(14) | BIT(15));
+	if (etm_version_gte(drvdata->arch, ETM_ARCH_V1_0)) {
+		if (drvdata->mode & ETM_MODE_DATA_TRACE_VAL)
+			drvdata->ctrl |= BIT(2);
+		else
+			drvdata->ctrl &= ~(BIT(2));
+
+		if (drvdata->mode & ETM_MODE_DATA_TRACE_ADDR)
+			drvdata->ctrl |= (BIT(3));
+		else
+			drvdata->ctrl &= ~(BIT(3));
+	}
 	spin_unlock(&drvdata->spinlock);
 
 	return size;
@@ -839,6 +907,8 @@
 
 	drvdata->addr_val[idx] = val;
 	drvdata->addr_type[idx] = ETM_ADDR_TYPE_SINGLE;
+	if (etm_version_gte(drvdata->arch, ETM_ARCH_V1_2))
+		drvdata->enable_ctrl2 |= (1 << idx);
 	spin_unlock(&drvdata->spinlock);
 	return size;
 }
@@ -1039,6 +1109,138 @@
 static DEVICE_ATTR(addr_acctype, S_IRUGO | S_IWUSR, etm_show_addr_acctype,
 		   etm_store_addr_acctype);
 
+static ssize_t etm_show_data_val(struct device *dev,
+				struct device_attribute *attr, char *buf)
+{
+	struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
+	unsigned long val;
+	uint8_t idx;
+
+	spin_lock(&drvdata->spinlock);
+	idx = drvdata->addr_idx;
+	if (idx % 2 != 0) {
+		spin_unlock(&drvdata->spinlock);
+		return -EPERM;
+	}
+	idx = idx >> 1;
+	if (idx >= drvdata->nr_data_cmp) {
+		spin_unlock(&drvdata->spinlock);
+		return -EPERM;
+	}
+
+	val = drvdata->data_val[idx];
+	spin_unlock(&drvdata->spinlock);
+	return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
+}
+
+static ssize_t etm_store_data_val(struct device *dev,
+				struct device_attribute *attr,
+				const char *buf, size_t size)
+{
+	struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
+	unsigned long val;
+	uint8_t idx, data_idx;
+
+	if (sscanf(buf, "%lx", &val) != 1)
+		return -EINVAL;
+
+	spin_lock(&drvdata->spinlock);
+	idx = drvdata->addr_idx;
+	/* Adjust index to use the correct data comparator */
+	data_idx = idx >> 1;
+	/* Only idx = 0, 2, 4, 6... are valid */
+	if (idx % 2 != 0) {
+		spin_unlock(&drvdata->spinlock);
+		return -EPERM;
+	}
+	if (data_idx >= drvdata->nr_data_cmp) {
+		spin_unlock(&drvdata->spinlock);
+		return -EPERM;
+	}
+	if (!BVAL(drvdata->addr_acctype[idx], ETM_DATACMP_ENABLE)) {
+		spin_unlock(&drvdata->spinlock);
+		return -EPERM;
+	}
+	if (drvdata->addr_type[idx] == ETM_ADDR_TYPE_RANGE) {
+		if (!BVAL(drvdata->addr_acctype[idx + 1], ETM_DATACMP_ENABLE)) {
+			spin_unlock(&drvdata->spinlock);
+			return -EPERM;
+		}
+	}
+
+	drvdata->data_val[data_idx] = val;
+	spin_unlock(&drvdata->spinlock);
+	return size;
+}
+static DEVICE_ATTR(data_val, S_IRUGO | S_IWUSR, etm_show_data_val,
+			etm_store_data_val);
+
+static ssize_t etm_show_data_mask(struct device *dev,
+				struct device_attribute *attr, char *buf)
+{
+	struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
+	unsigned long mask;
+	uint8_t idx;
+
+	spin_lock(&drvdata->spinlock);
+	idx = drvdata->addr_idx;
+	if (idx % 2 != 0) {
+		spin_unlock(&drvdata->spinlock);
+		return -EPERM;
+	}
+	idx = idx >> 1;
+	if (idx >= drvdata->nr_data_cmp) {
+		spin_unlock(&drvdata->spinlock);
+		return -EPERM;
+	}
+
+	mask = drvdata->data_mask[idx];
+	spin_unlock(&drvdata->spinlock);
+	return scnprintf(buf, PAGE_SIZE, "%#lx\n", mask);
+}
+
+static ssize_t etm_store_data_mask(struct device *dev,
+				struct device_attribute *attr,
+				const char *buf, size_t size)
+{
+	struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
+	unsigned long mask;
+	uint8_t idx, data_idx;
+
+	if (sscanf(buf, "%lx", &mask) != 1)
+		return -EINVAL;
+
+	spin_lock(&drvdata->spinlock);
+	idx = drvdata->addr_idx;
+	/* Adjust index to use the correct data comparator */
+	data_idx = idx >> 1;
+	/* Only idx = 0, 2, 4, 6... are valid */
+	if (idx % 2 != 0) {
+		spin_unlock(&drvdata->spinlock);
+		return -EPERM;
+	}
+	if (data_idx >= drvdata->nr_data_cmp) {
+		spin_unlock(&drvdata->spinlock);
+		return -EPERM;
+	}
+	if (!BVAL(drvdata->addr_acctype[idx], ETM_DATACMP_ENABLE)) {
+		spin_unlock(&drvdata->spinlock);
+		return -EPERM;
+	}
+	if (drvdata->addr_type[idx] == ETM_ADDR_TYPE_RANGE) {
+		if (!BVAL(drvdata->addr_acctype[idx + 1], ETM_DATACMP_ENABLE)) {
+			spin_unlock(&drvdata->spinlock);
+			return -EPERM;
+		}
+	}
+
+	drvdata->data_mask[data_idx] = mask;
+	spin_unlock(&drvdata->spinlock);
+	return size;
+}
+static DEVICE_ATTR(data_mask, S_IRUGO | S_IWUSR, etm_show_data_mask,
+			etm_store_data_mask);
+
 static ssize_t etm_show_cntr_idx(struct device *dev,
 				 struct device_attribute *attr, char *buf)
 {
@@ -1604,6 +1806,8 @@
 	&dev_attr_addr_start.attr,
 	&dev_attr_addr_stop.attr,
 	&dev_attr_addr_acctype.attr,
+	&dev_attr_data_val.attr,
+	&dev_attr_data_mask.attr,
 	&dev_attr_cntr_idx.attr,
 	&dev_attr_cntr_rld_val.attr,
 	&dev_attr_cntr_event.attr,
@@ -1681,6 +1885,8 @@
 	switch (arch) {
 	case PFT_ARCH_V1_1:
 		break;
+	case ETM_ARCH_V3_5:
+		break;
 	default:
 		return false;
 	}
@@ -1691,6 +1897,7 @@
 {
 	uint32_t etmidr;
 	uint32_t etmccr;
+	uint32_t etmcr;
 	struct etm_drvdata *drvdata = info;
 
 	ETM_UNLOCK(drvdata);
@@ -1721,6 +1928,19 @@
 	drvdata->nr_ext_inp = BMVAL(etmccr, 17, 19);
 	drvdata->nr_ext_out = BMVAL(etmccr, 20, 22);
 	drvdata->nr_ctxid_cmp = BMVAL(etmccr, 24, 25);
+	drvdata->nr_data_cmp = BMVAL(etmccr, 4, 7);
+
+	if (etm_version_gte(drvdata->arch, ETM_ARCH_V1_0)) {
+		etmcr = etm_readl(drvdata, ETMCR);
+		etmcr |= (BIT(2) | BIT(3));
+		etm_writel(drvdata, etmcr, ETMCR);
+		etmcr = etm_readl(drvdata, ETMCR);
+		if (BVAL(etmcr, 2) || BVAL(etmcr, 3))
+			drvdata->data_trace_support = true;
+		else
+			drvdata->data_trace_support = false;
+	} else
+		drvdata->data_trace_support = false;
 
 	etm_set_pwrdwn(drvdata);
 	ETM_LOCK(drvdata);
@@ -1734,6 +1954,8 @@
 	drvdata->nr_ext_inp = etmdrvdata[0]->nr_ext_inp;
 	drvdata->nr_ext_out = etmdrvdata[0]->nr_ext_out;
 	drvdata->nr_ctxid_cmp = etmdrvdata[0]->nr_ctxid_cmp;
+	drvdata->nr_data_cmp = etmdrvdata[0]->nr_data_cmp;
+	drvdata->data_trace_support = etmdrvdata[0]->data_trace_support;
 }
 
 static void __devinit etm_init_default_data(struct etm_drvdata *drvdata)
@@ -1749,6 +1971,10 @@
 		drvdata->addr_val[1] = (uint32_t) _etext;
 		drvdata->addr_type[0] = ETM_ADDR_TYPE_RANGE;
 		drvdata->addr_type[1] = ETM_ADDR_TYPE_RANGE;
+		if (etm_version_gte(drvdata->arch, ETM_ARCH_V1_0)) {
+			drvdata->addr_acctype[0] = 0x19;
+			drvdata->addr_acctype[1] = 0x19;
+		}
 	}
 	for (i = 0; i < drvdata->nr_cntr; i++) {
 		drvdata->cntr_event[i] = 0x406F;
@@ -1781,6 +2007,23 @@
 			drvdata->addr_type[i] = ETM_ADDR_TYPE_NONE;
 		}
 	}
+
+	if (etm_version_gte(drvdata->arch, ETM_ARCH_V1_0))
+		drvdata->ctrl |= BIT(11);
+	if (etm_version_gte(drvdata->arch, ETM_ARCH_V1_2))
+		drvdata->enable_ctrl2 = 0x0;
+	if (drvdata->data_trace_support == true) {
+		drvdata->mode |= (ETM_MODE_DATA_TRACE_VAL |
+						ETM_MODE_DATA_TRACE_ADDR);
+		drvdata->ctrl |= BIT(2) | BIT(3);
+		drvdata->viewdata_ctrl1 = 0x0;
+		drvdata->viewdata_ctrl3 = 0x10000;
+		drvdata->viewdata_event = 0x6F;
+	}
+	for (i = 0; i < drvdata->nr_data_cmp; i++) {
+		drvdata->data_val[i] = 0;
+		drvdata->data_mask[i] = ~(0);
+	}
 }
 
 static int __devinit etm_probe(struct platform_device *pdev)
diff --git a/drivers/crypto/msm/qce.c b/drivers/crypto/msm/qce.c
index 4a9729c..7f8460b 100644
--- a/drivers/crypto/msm/qce.c
+++ b/drivers/crypto/msm/qce.c
@@ -1,6 +1,6 @@
 /* Qualcomm Crypto Engine driver.
  *
- * Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2010-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -474,11 +474,37 @@
 {
 	int i;
 
-	for (i = 0; nbytes > 0; i++, sg = sg_next(sg))
+	for (i = 0; nbytes > 0; i++, sg = scatterwalk_sg_next(sg))
 		nbytes -= sg->length;
 	return i;
 }
 
+static int qce_dma_map_sg(struct device *dev, struct scatterlist *sg, int nents,
+	enum dma_data_direction direction)
+{
+	int i;
+
+	for (i = 0; i < nents; ++i) {
+		dma_map_sg(dev, sg, 1, direction);
+		sg = scatterwalk_sg_next(sg);
+	}
+
+	return nents;
+}
+
+static int qce_dma_unmap_sg(struct device *dev, struct scatterlist *sg,
+	int nents, enum dma_data_direction direction)
+{
+	int i;
+
+	for (i = 0; i < nents; ++i) {
+		dma_unmap_sg(dev, sg, 1, direction);
+		sg = scatterwalk_sg_next(sg);
+	}
+
+	return nents;
+}
+
 static int dma_map_pmem_sg(struct buf_info *pmem, unsigned entries,
 						struct scatterlist *sg)
 {
@@ -917,15 +943,15 @@
 	ivsize = crypto_aead_ivsize(aead);
 
 	if (areq->src != areq->dst) {
-		dma_unmap_sg(pce_dev->pdev, areq->dst, pce_dev->dst_nents,
+		qce_dma_unmap_sg(pce_dev->pdev, areq->dst, pce_dev->dst_nents,
 					DMA_FROM_DEVICE);
 	}
-	dma_unmap_sg(pce_dev->pdev, areq->src, pce_dev->src_nents,
+	qce_dma_unmap_sg(pce_dev->pdev, areq->src, pce_dev->src_nents,
 			(areq->src == areq->dst) ? DMA_BIDIRECTIONAL :
 							DMA_TO_DEVICE);
 	dma_unmap_single(pce_dev->pdev, pce_dev->phy_iv_in,
 			ivsize, DMA_TO_DEVICE);
-	dma_unmap_sg(pce_dev->pdev, areq->assoc, pce_dev->assoc_nents,
+	qce_dma_unmap_sg(pce_dev->pdev, areq->assoc, pce_dev->assoc_nents,
 			DMA_TO_DEVICE);
 
 	/* check ce error status */
@@ -975,7 +1001,7 @@
 	uint32_t status;
 
 	areq = (struct ahash_request *) pce_dev->areq;
-	dma_unmap_sg(pce_dev->pdev, areq->src, pce_dev->src_nents,
+	qce_dma_unmap_sg(pce_dev->pdev, areq->src, pce_dev->src_nents,
 				DMA_TO_DEVICE);
 
 	/* check ce error status */
@@ -1014,10 +1040,10 @@
 	areq = (struct ablkcipher_request *) pce_dev->areq;
 
 	if (areq->src != areq->dst) {
-		dma_unmap_sg(pce_dev->pdev, areq->dst,
+		qce_dma_unmap_sg(pce_dev->pdev, areq->dst,
 			pce_dev->dst_nents, DMA_FROM_DEVICE);
 	}
-	dma_unmap_sg(pce_dev->pdev, areq->src, pce_dev->src_nents,
+	qce_dma_unmap_sg(pce_dev->pdev, areq->src, pce_dev->src_nents,
 		(areq->src == areq->dst) ? DMA_BIDIRECTIONAL :
 						DMA_TO_DEVICE);
 
@@ -1178,7 +1204,7 @@
 			}
 		}
 		if (nbytes > 0)
-			sg = sg_next(sg);
+			sg = scatterwalk_sg_next(sg);
 	}
 	return 0;
 }
@@ -1341,7 +1367,7 @@
 			}
 		}
 		if (nbytes > 0)
-			sg = sg_next(sg);
+			sg = scatterwalk_sg_next(sg);
 	}
 	return 0;
 }
@@ -2041,7 +2067,7 @@
 	pce_dev->dst_nents = 0;
 
 	pce_dev->assoc_nents = count_sg(areq->assoc, areq->assoclen);
-	dma_map_sg(pce_dev->pdev, areq->assoc, pce_dev->assoc_nents,
+	qce_dma_map_sg(pce_dev->pdev, areq->assoc, pce_dev->assoc_nents,
 					 DMA_TO_DEVICE);
 	if (_chain_sg_buffer_in(pce_dev, areq->assoc, areq->assoclen) < 0) {
 		rc = -ENOMEM;
@@ -2065,7 +2091,7 @@
 
 	/* cipher input       */
 	pce_dev->src_nents = count_sg(areq->src, q_req->cryptlen);
-	dma_map_sg(pce_dev->pdev, areq->src, pce_dev->src_nents,
+	qce_dma_map_sg(pce_dev->pdev, areq->src, pce_dev->src_nents,
 			(areq->src == areq->dst) ? DMA_BIDIRECTIONAL :
 							DMA_TO_DEVICE);
 	if (_chain_sg_buffer_in(pce_dev, areq->src, q_req->cryptlen) < 0) {
@@ -2076,7 +2102,7 @@
 	/* cipher output      */
 	if (areq->src != areq->dst) {
 		pce_dev->dst_nents = count_sg(areq->dst, q_req->cryptlen);
-		dma_map_sg(pce_dev->pdev, areq->dst, pce_dev->dst_nents,
+		qce_dma_map_sg(pce_dev->pdev, areq->dst, pce_dev->dst_nents,
 				DMA_FROM_DEVICE);
 	};
 	if (_chain_sg_buffer_out(pce_dev, areq->dst, q_req->cryptlen) < 0) {
@@ -2119,20 +2145,20 @@
 		return 0;
 bad:
 	if (pce_dev->assoc_nents) {
-		dma_unmap_sg(pce_dev->pdev, areq->assoc, pce_dev->assoc_nents,
-				DMA_TO_DEVICE);
+		qce_dma_unmap_sg(pce_dev->pdev, areq->assoc,
+				pce_dev->assoc_nents, DMA_TO_DEVICE);
 	}
 	if (pce_dev->phy_iv_in) {
 		dma_unmap_single(pce_dev->pdev, pce_dev->phy_iv_in,
 				ivsize, DMA_TO_DEVICE);
 	}
 	if (pce_dev->src_nents) {
-		dma_unmap_sg(pce_dev->pdev, areq->src, pce_dev->src_nents,
+		qce_dma_unmap_sg(pce_dev->pdev, areq->src, pce_dev->src_nents,
 				(areq->src == areq->dst) ? DMA_BIDIRECTIONAL :
 								DMA_TO_DEVICE);
 	}
 	if (pce_dev->dst_nents) {
-		dma_unmap_sg(pce_dev->pdev, areq->dst, pce_dev->dst_nents,
+		qce_dma_unmap_sg(pce_dev->pdev, areq->dst, pce_dev->dst_nents,
 				DMA_FROM_DEVICE);
 	}
 	return rc;
@@ -2158,7 +2184,7 @@
 	pce_dev->src_nents = count_sg(areq->src, areq->nbytes);
 
 	if (c_req->use_pmem != 1)
-		dma_map_sg(pce_dev->pdev, areq->src, pce_dev->src_nents,
+		qce_dma_map_sg(pce_dev->pdev, areq->src, pce_dev->src_nents,
 			(areq->src == areq->dst) ? DMA_BIDIRECTIONAL :
 								DMA_TO_DEVICE);
 	else
@@ -2174,8 +2200,8 @@
 	if (areq->src != areq->dst) {
 		pce_dev->dst_nents = count_sg(areq->dst, areq->nbytes);
 		if (c_req->use_pmem != 1)
-			dma_map_sg(pce_dev->pdev, areq->dst, pce_dev->dst_nents,
-							DMA_FROM_DEVICE);
+			qce_dma_map_sg(pce_dev->pdev, areq->dst,
+					pce_dev->dst_nents, DMA_FROM_DEVICE);
 		else
 			dma_map_pmem_sg(&c_req->pmem->dst[0],
 					pce_dev->dst_nents, areq->dst);
@@ -2233,11 +2259,11 @@
 bad:
 	if (c_req->use_pmem != 1) {
 		if (pce_dev->dst_nents) {
-			dma_unmap_sg(pce_dev->pdev, areq->dst,
+			qce_dma_unmap_sg(pce_dev->pdev, areq->dst,
 				pce_dev->dst_nents, DMA_FROM_DEVICE);
 		}
 		if (pce_dev->src_nents) {
-			dma_unmap_sg(pce_dev->pdev, areq->src,
+			qce_dma_unmap_sg(pce_dev->pdev, areq->src,
 					pce_dev->src_nents,
 					(areq->src == areq->dst) ?
 						DMA_BIDIRECTIONAL :
@@ -2257,7 +2283,7 @@
 
 	_chain_buffer_in_init(pce_dev);
 	pce_dev->src_nents = count_sg(sreq->src, sreq->size);
-	dma_map_sg(pce_dev->pdev, sreq->src, pce_dev->src_nents,
+	qce_dma_map_sg(pce_dev->pdev, sreq->src, pce_dev->src_nents,
 							DMA_TO_DEVICE);
 
 	if (_chain_sg_buffer_in(pce_dev, sreq->src, sreq->size) < 0) {
@@ -2293,7 +2319,7 @@
 		return 0;
 bad:
 	if (pce_dev->src_nents) {
-		dma_unmap_sg(pce_dev->pdev, sreq->src,
+		qce_dma_unmap_sg(pce_dev->pdev, sreq->src,
 				pce_dev->src_nents, DMA_TO_DEVICE);
 	}
 
diff --git a/drivers/crypto/msm/qce40.c b/drivers/crypto/msm/qce40.c
index de060cc..84d41da 100644
--- a/drivers/crypto/msm/qce40.c
+++ b/drivers/crypto/msm/qce40.c
@@ -1,6 +1,6 @@
 /* Qualcomm Crypto Engine driver.
  *
- * Copyright (c) 2011 - 2012, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2011 - 2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -107,11 +107,37 @@
 {
 	int i;
 
-	for (i = 0; nbytes > 0; i++, sg = sg_next(sg))
+	for (i = 0; nbytes > 0; i++, sg = scatterwalk_sg_next(sg))
 		nbytes -= sg->length;
 	return i;
 }
 
+static int qce_dma_map_sg(struct device *dev, struct scatterlist *sg, int nents,
+	enum dma_data_direction direction)
+{
+	int i;
+
+	for (i = 0; i < nents; ++i) {
+		dma_map_sg(dev, sg, 1, direction);
+		sg = scatterwalk_sg_next(sg);
+	}
+
+	return nents;
+}
+
+static int qce_dma_unmap_sg(struct device *dev, struct scatterlist *sg,
+	int nents, enum dma_data_direction direction)
+{
+	int i;
+
+	for (i = 0; i < nents; ++i) {
+		dma_unmap_sg(dev, sg, 1, direction);
+		sg = scatterwalk_sg_next(sg);
+	}
+
+	return nents;
+}
+
 static int dma_map_pmem_sg(struct buf_info *pmem, unsigned entries,
 						struct scatterlist *sg)
 {
@@ -670,14 +696,14 @@
 	areq = (struct aead_request *) pce_dev->areq;
 
 	if (areq->src != areq->dst) {
-		dma_unmap_sg(pce_dev->pdev, areq->dst, pce_dev->dst_nents,
+		qce_dma_unmap_sg(pce_dev->pdev, areq->dst, pce_dev->dst_nents,
 					DMA_FROM_DEVICE);
 	}
-	dma_unmap_sg(pce_dev->pdev, areq->src, pce_dev->src_nents,
+	qce_dma_unmap_sg(pce_dev->pdev, areq->src, pce_dev->src_nents,
 			(areq->src == areq->dst) ? DMA_BIDIRECTIONAL :
 							DMA_TO_DEVICE);
 
-	dma_unmap_sg(pce_dev->pdev, areq->assoc, pce_dev->assoc_nents,
+	qce_dma_unmap_sg(pce_dev->pdev, areq->assoc, pce_dev->assoc_nents,
 			DMA_TO_DEVICE);
 
 	/* check MAC */
@@ -700,7 +726,7 @@
 	struct ahash_request *areq;
 
 	areq = (struct ahash_request *) pce_dev->areq;
-	dma_unmap_sg(pce_dev->pdev, areq->src, pce_dev->src_nents,
+	qce_dma_unmap_sg(pce_dev->pdev, areq->src, pce_dev->src_nents,
 				DMA_TO_DEVICE);
 
 	pce_dev->qce_cb(areq,  pce_dev->ce_dm.buffer.auth_result,
@@ -716,10 +742,10 @@
 	areq = (struct ablkcipher_request *) pce_dev->areq;
 
 	if (areq->src != areq->dst) {
-		dma_unmap_sg(pce_dev->pdev, areq->dst,
+		qce_dma_unmap_sg(pce_dev->pdev, areq->dst,
 			pce_dev->dst_nents, DMA_FROM_DEVICE);
 	}
-	dma_unmap_sg(pce_dev->pdev, areq->src, pce_dev->src_nents,
+	qce_dma_unmap_sg(pce_dev->pdev, areq->src, pce_dev->src_nents,
 		(areq->src == areq->dst) ? DMA_BIDIRECTIONAL :
 						DMA_TO_DEVICE);
 
@@ -826,7 +852,7 @@
 					&pce_dev->ce_dm.ce_in_src_desc_index);
 		}
 		if (nbytes > 0)
-			sg = sg_next(sg);
+			sg = scatterwalk_sg_next(sg);
 	}
 	return 0;
 }
@@ -989,7 +1015,7 @@
 
 		}
 		if (nbytes > 0)
-			sg = sg_next(sg);
+			sg = scatterwalk_sg_next(sg);
 	}
 	return 0;
 }
@@ -2149,7 +2175,7 @@
 
 	/* associated data input */
 	pce_dev->assoc_nents = count_sg(areq->assoc, areq->assoclen);
-	dma_map_sg(pce_dev->pdev, areq->assoc, pce_dev->assoc_nents,
+	qce_dma_map_sg(pce_dev->pdev, areq->assoc, pce_dev->assoc_nents,
 					 DMA_TO_DEVICE);
 	if (_chain_sg_buffer_in(pce_dev, areq->assoc, areq->assoclen) < 0) {
 		rc = -ENOMEM;
@@ -2157,7 +2183,7 @@
 	}
 	/* cipher input */
 	pce_dev->src_nents = count_sg(areq->src, areq->cryptlen);
-	dma_map_sg(pce_dev->pdev, areq->src, pce_dev->src_nents,
+	qce_dma_map_sg(pce_dev->pdev, areq->src, pce_dev->src_nents,
 			(areq->src == areq->dst) ? DMA_BIDIRECTIONAL :
 							DMA_TO_DEVICE);
 	if (_chain_sg_buffer_in(pce_dev, areq->src, areq->cryptlen) < 0) {
@@ -2182,7 +2208,7 @@
 	/* cipher + mac output  for encryption    */
 	if (areq->src != areq->dst) {
 		pce_dev->dst_nents = count_sg(areq->dst, out_len);
-		dma_map_sg(pce_dev->pdev, areq->dst, pce_dev->dst_nents,
+		qce_dma_map_sg(pce_dev->pdev, areq->dst, pce_dev->dst_nents,
 				DMA_FROM_DEVICE);
 	};
 	if (_chain_sg_buffer_out(pce_dev, areq->dst, out_len) < 0) {
@@ -2222,17 +2248,17 @@
 		return 0;
 bad:
 	if (pce_dev->assoc_nents) {
-		dma_unmap_sg(pce_dev->pdev, areq->assoc, pce_dev->assoc_nents,
-				DMA_TO_DEVICE);
+		qce_dma_unmap_sg(pce_dev->pdev, areq->assoc,
+				pce_dev->assoc_nents, DMA_TO_DEVICE);
 	}
 
 	if (pce_dev->src_nents) {
-		dma_unmap_sg(pce_dev->pdev, areq->src, pce_dev->src_nents,
+		qce_dma_unmap_sg(pce_dev->pdev, areq->src, pce_dev->src_nents,
 				(areq->src == areq->dst) ? DMA_BIDIRECTIONAL :
 								DMA_TO_DEVICE);
 	}
 	if (pce_dev->dst_nents) {
-		dma_unmap_sg(pce_dev->pdev, areq->dst, pce_dev->dst_nents,
+		qce_dma_unmap_sg(pce_dev->pdev, areq->dst, pce_dev->dst_nents,
 				DMA_FROM_DEVICE);
 	}
 	return rc;
@@ -2259,7 +2285,7 @@
 	pce_dev->src_nents = count_sg(areq->src, areq->nbytes);
 
 	if (c_req->use_pmem != 1)
-		dma_map_sg(pce_dev->pdev, areq->src, pce_dev->src_nents,
+		qce_dma_map_sg(pce_dev->pdev, areq->src, pce_dev->src_nents,
 			(areq->src == areq->dst) ? DMA_BIDIRECTIONAL :
 								DMA_TO_DEVICE);
 	else
@@ -2275,8 +2301,8 @@
 	if (areq->src != areq->dst) {
 		pce_dev->dst_nents = count_sg(areq->dst, areq->nbytes);
 		if (c_req->use_pmem != 1)
-			dma_map_sg(pce_dev->pdev, areq->dst, pce_dev->dst_nents,
-							DMA_FROM_DEVICE);
+			qce_dma_map_sg(pce_dev->pdev, areq->dst,
+					pce_dev->dst_nents, DMA_FROM_DEVICE);
 		else
 			dma_map_pmem_sg(&c_req->pmem->dst[0],
 					pce_dev->dst_nents, areq->dst);
@@ -2333,11 +2359,11 @@
 bad:
 	if (c_req->use_pmem != 1) {
 			if (pce_dev->dst_nents) {
-				dma_unmap_sg(pce_dev->pdev, areq->dst,
+				qce_dma_unmap_sg(pce_dev->pdev, areq->dst,
 				pce_dev->dst_nents, DMA_FROM_DEVICE);
 			}
 		if (pce_dev->src_nents) {
-			dma_unmap_sg(pce_dev->pdev, areq->src,
+			qce_dma_unmap_sg(pce_dev->pdev, areq->src,
 					pce_dev->src_nents,
 					(areq->src == areq->dst) ?
 						DMA_BIDIRECTIONAL :
@@ -2358,7 +2384,7 @@
 
 	_chain_buffer_in_init(pce_dev);
 	pce_dev->src_nents = count_sg(sreq->src, sreq->size);
-	dma_map_sg(pce_dev->pdev, sreq->src, pce_dev->src_nents,
+	qce_dma_map_sg(pce_dev->pdev, sreq->src, pce_dev->src_nents,
 							DMA_TO_DEVICE);
 
 	if (_chain_sg_buffer_in(pce_dev, sreq->src, sreq->size) < 0) {
@@ -2392,7 +2418,7 @@
 		return 0;
 bad:
 	if (pce_dev->src_nents) {
-		dma_unmap_sg(pce_dev->pdev, sreq->src,
+		qce_dma_unmap_sg(pce_dev->pdev, sreq->src,
 				pce_dev->src_nents, DMA_TO_DEVICE);
 	}
 
diff --git a/drivers/crypto/msm/qcrypto.c b/drivers/crypto/msm/qcrypto.c
index 10f83f3..b64368d 100644
--- a/drivers/crypto/msm/qcrypto.c
+++ b/drivers/crypto/msm/qcrypto.c
@@ -1,6 +1,6 @@
 /* Qualcomm Crypto driver
  *
- * Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2010-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -1043,7 +1043,7 @@
 	}
 	adata += len;
 	qreq->assoclen = ALIGN((alen + len), 16);
-	for (l = alen; l > 0; sg = sg_next(sg)) {
+	for (l = alen; l > 0; sg = scatterwalk_sg_next(sg)) {
 		memcpy(adata, sg_virt(sg), sg->length);
 		l -= sg->length;
 		adata += sg->length;
@@ -2118,7 +2118,7 @@
 {
 	int i;
 
-	for (i = 0; nbytes > 0; i++, sg = sg_next(sg))
+	for (i = 0; nbytes > 0; i++, sg = scatterwalk_sg_next(sg))
 		nbytes -= sg->length;
 
 	return i;
diff --git a/drivers/gpu/ion/ion_cp_heap.c b/drivers/gpu/ion/ion_cp_heap.c
index d96b755..8f5addd 100644
--- a/drivers/gpu/ion/ion_cp_heap.c
+++ b/drivers/gpu/ion/ion_cp_heap.c
@@ -2,7 +2,7 @@
  * drivers/gpu/ion/ion_cp_heap.c
  *
  * Copyright (C) 2011 Google, Inc.
- * Copyright (c) 2011-2012, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2011-2013, The Linux Foundation. All rights reserved.
  *
  * This software is licensed under the terms of the GNU General Public
  * License version 2, as published by the Free Software Foundation, and
@@ -469,6 +469,7 @@
 {
 	unsigned long offset;
 	unsigned long secure_allocation = flags & ION_SECURE;
+	unsigned long force_contig = flags & ION_FORCE_CONTIGUOUS;
 
 	struct ion_cp_heap *cp_heap =
 		container_of(heap, struct ion_cp_heap, heap);
@@ -481,7 +482,8 @@
 		return ION_CP_ALLOCATE_FAIL;
 	}
 
-	if (!secure_allocation && cp_heap->disallow_non_secure_allocation) {
+	if (!force_contig && !secure_allocation &&
+	     cp_heap->disallow_non_secure_allocation) {
 		mutex_unlock(&cp_heap->lock);
 		pr_debug("%s: non-secure allocation disallowed from this heap\n",
 			__func__);
diff --git a/drivers/gpu/msm/adreno.c b/drivers/gpu/msm/adreno.c
index 24be1b0..3c73c36 100644
--- a/drivers/gpu/msm/adreno.c
+++ b/drivers/gpu/msm/adreno.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2002,2007-2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2002,2007-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -1342,7 +1342,7 @@
 			adreno_context->flags |= CTXT_FLAGS_GPU_HANG;
 		} else if (KGSL_CTX_STAT_GUILTY_CONTEXT_RESET_EXT !=
 			context->reset_status) {
-			if (adreno_context->flags & (CTXT_FLAGS_GPU_HANG ||
+			if (adreno_context->flags & (CTXT_FLAGS_GPU_HANG |
 				CTXT_FLAGS_GPU_HANG_RECOVERED))
 				context->reset_status =
 				KGSL_CTX_STAT_GUILTY_CONTEXT_RESET_EXT;
@@ -1622,6 +1622,11 @@
 			KGSL_MEMSTORE_OFFSET(KGSL_MEMSTORE_GLOBAL,
 			eoptimestamp),
 			rb->timestamp[KGSL_MEMSTORE_GLOBAL]);
+
+	/* switch to NULL ctxt */
+	if (adreno_dev->drawctxt_active != NULL)
+		adreno_drawctxt_switch(adreno_dev, NULL, 0);
+
 done:
 	adreno_set_max_ts_for_bad_ctxs(device);
 	adreno_mark_context_status(device, ret);
@@ -2142,125 +2147,89 @@
 	return context_id;
 }
 
-static void adreno_next_event(struct kgsl_device *device,
-		struct kgsl_event *event)
-{
-	int status;
-	unsigned int ref_ts, enableflag;
-	unsigned int context_id = _get_context_id(event->context);
-	struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
-
-	status = kgsl_check_timestamp(device, event->context, event->timestamp);
-	if (!status) {
-		kgsl_sharedmem_readl(&device->memstore, &enableflag,
-			KGSL_MEMSTORE_OFFSET(context_id, ts_cmp_enable));
-		/*
-		 * Barrier is needed here to make sure the read from memstore
-		 * has posted
-		 */
-
-		mb();
-
-		if (enableflag) {
-			kgsl_sharedmem_readl(&device->memstore, &ref_ts,
-				KGSL_MEMSTORE_OFFSET(context_id,
-					ref_wait_ts));
-
-			/* Make sure the memstore read has posted */
-			mb();
-			if (timestamp_cmp(ref_ts, event->timestamp) >= 0) {
-				kgsl_sharedmem_writel(&device->memstore,
-				KGSL_MEMSTORE_OFFSET(context_id,
-					ref_wait_ts), event->timestamp);
-				/* Make sure the memstore write is posted */
-				wmb();
-			}
-		} else {
-			unsigned int cmds[2];
-			kgsl_sharedmem_writel(&device->memstore,
-				KGSL_MEMSTORE_OFFSET(context_id,
-					ref_wait_ts), event->timestamp);
-			enableflag = 1;
-			kgsl_sharedmem_writel(&device->memstore,
-				KGSL_MEMSTORE_OFFSET(context_id,
-					ts_cmp_enable), enableflag);
-
-			/* Make sure the memstore write gets posted */
-			wmb();
-
-			/*
-			 * submit a dummy packet so that even if all
-			 * commands upto timestamp get executed we will still
-			 * get an interrupt
-			 */
-			cmds[0] = cp_type3_packet(CP_NOP, 1);
-			cmds[1] = 0;
-
-			if (adreno_dev->drawctxt_active)
-				adreno_ringbuffer_issuecmds_intr(device,
-						event->context, &cmds[0], 2);
-		}
-	}
-}
-
-static int kgsl_check_interrupt_timestamp(struct kgsl_device *device,
+static unsigned int adreno_check_hw_ts(struct kgsl_device *device,
 		struct kgsl_context *context, unsigned int timestamp)
 {
-	int status;
+	int status = 0;
 	unsigned int ref_ts, enableflag;
-	unsigned int context_id;
+	unsigned int context_id = _get_context_id(context);
 
-	mutex_lock(&device->mutex);
-	context_id = _get_context_id(context);
 	/*
 	 * If the context ID is invalid, we are in a race with
 	 * the context being destroyed by userspace so bail.
 	 */
 	if (context_id == KGSL_CONTEXT_INVALID) {
 		KGSL_DRV_WARN(device, "context was detached");
-		status = -EINVAL;
-		goto unlock;
+		return -EINVAL;
 	}
 
 	status = kgsl_check_timestamp(device, context, timestamp);
-	if (!status) {
-		kgsl_sharedmem_readl(&device->memstore, &enableflag,
-			KGSL_MEMSTORE_OFFSET(context_id, ts_cmp_enable));
-		mb();
+	if (status)
+		return status;
 
-		if (enableflag) {
-			kgsl_sharedmem_readl(&device->memstore, &ref_ts,
+	kgsl_sharedmem_readl(&device->memstore, &enableflag,
+			KGSL_MEMSTORE_OFFSET(context_id, ts_cmp_enable));
+	/*
+	 * Barrier is needed here to make sure the read from memstore
+	 * has posted
+	 */
+
+	mb();
+
+	if (enableflag) {
+		kgsl_sharedmem_readl(&device->memstore, &ref_ts,
 				KGSL_MEMSTORE_OFFSET(context_id,
 					ref_wait_ts));
-			mb();
-			if (timestamp_cmp(ref_ts, timestamp) >= 0) {
-				kgsl_sharedmem_writel(&device->memstore,
+
+		/* Make sure the memstore read has posted */
+		mb();
+		if (timestamp_cmp(ref_ts, timestamp) >= 0) {
+			kgsl_sharedmem_writel(&device->memstore,
+					KGSL_MEMSTORE_OFFSET(context_id,
+						ref_wait_ts), timestamp);
+			/* Make sure the memstore write is posted */
+			wmb();
+		}
+	} else {
+		kgsl_sharedmem_writel(&device->memstore,
 				KGSL_MEMSTORE_OFFSET(context_id,
 					ref_wait_ts), timestamp);
-				wmb();
-			}
-		} else {
-			unsigned int cmds[2];
-			kgsl_sharedmem_writel(&device->memstore,
-				KGSL_MEMSTORE_OFFSET(context_id,
-					ref_wait_ts), timestamp);
-			enableflag = 1;
-			kgsl_sharedmem_writel(&device->memstore,
+		enableflag = 1;
+		kgsl_sharedmem_writel(&device->memstore,
 				KGSL_MEMSTORE_OFFSET(context_id,
 					ts_cmp_enable), enableflag);
-			wmb();
-			/* submit a dummy packet so that even if all
-			* commands upto timestamp get executed we will still
-			* get an interrupt */
-			cmds[0] = cp_type3_packet(CP_NOP, 1);
-			cmds[1] = 0;
 
-			if (context)
-				adreno_ringbuffer_issuecmds_intr(device,
-						context, &cmds[0], 2);
+		/* Make sure the memstore write gets posted */
+		wmb();
+
+		/*
+		 * submit a dummy packet so that even if all
+		 * commands upto timestamp get executed we will still
+		 * get an interrupt
+		 */
+
+		if (context) {
+			adreno_ringbuffer_issuecmds(device, context->devctxt,
+					KGSL_CMD_FLAGS_NONE, NULL, 0);
 		}
 	}
-unlock:
+
+	return 0;
+}
+
+static void adreno_next_event(struct kgsl_device *device,
+		struct kgsl_event *event)
+{
+	adreno_check_hw_ts(device, event->context, event->timestamp);
+}
+
+static int adreno_check_interrupt_timestamp(struct kgsl_device *device,
+		struct kgsl_context *context, unsigned int timestamp)
+{
+	int status;
+
+	mutex_lock(&device->mutex);
+	status = adreno_check_hw_ts(device, context, timestamp);
 	mutex_unlock(&device->mutex);
 
 	return status;
@@ -2497,7 +2466,7 @@
 		/* Wait for a timestamp event */
 		status = kgsl_wait_event_interruptible_timeout(
 			device->wait_queue,
-			kgsl_check_interrupt_timestamp(device, context,
+			adreno_check_interrupt_timestamp(device, context,
 				timestamp), msecs_to_jiffies(wait), io);
 
 		mutex_lock(&device->mutex);
diff --git a/drivers/gpu/msm/adreno_a3xx_snapshot.c b/drivers/gpu/msm/adreno_a3xx_snapshot.c
index de95951..713ef1a 100644
--- a/drivers/gpu/msm/adreno_a3xx_snapshot.c
+++ b/drivers/gpu/msm/adreno_a3xx_snapshot.c
@@ -24,6 +24,22 @@
 #define SHADER_MEMORY_SIZE 0x4000
 
 /**
+ * _rbbm_debug_bus_read - Helper function to read data from the RBBM
+ * debug bus.
+ * @device - GPU device to read/write registers
+ * @block_id - Debug bus block to read from
+ * @index - Index in the debug bus block to read
+ * @ret - Value of the register read
+ */
+static void _rbbm_debug_bus_read(struct kgsl_device *device,
+	unsigned int block_id, unsigned int index, unsigned int *val)
+{
+	unsigned int block = (block_id << 8) | 1 << 16;
+	adreno_regwrite(device, A3XX_RBBM_DEBUG_BUS_CTL, block | index);
+	adreno_regread(device, A3XX_RBBM_DEBUG_BUS_DATA_STATUS, val);
+}
+
+/**
  * a3xx_snapshot_shader_memory - Helper function to dump the GPU shader
  * memory to the snapshot buffer.
  * @device - GPU device whose shader memory is to be dumped
@@ -260,7 +276,6 @@
 
 	struct kgsl_snapshot_debugbus *header = snapshot;
 	struct debugbus_block *block = priv;
-	unsigned int val;
 	int i;
 	unsigned int *data = snapshot + sizeof(*header);
 	unsigned int dwords;
@@ -282,16 +297,11 @@
 		return 0;
 	}
 
-	val = (block->block_id << 8) | (1 << 16);
-
 	header->id = block->block_id;
 	header->count = dwords;
 
-	for (i = 0; i < dwords; i++) {
-		adreno_regwrite(device, A3XX_RBBM_DEBUG_BUS_CTL, val | i);
-		adreno_regread(device, A3XX_RBBM_DEBUG_BUS_DATA_STATUS,
-			&data[i]);
-	}
+	for (i = 0; i < dwords; i++)
+		_rbbm_debug_bus_read(device, block->block_id, i, &data[i]);
 
 	return size;
 }
@@ -353,18 +363,58 @@
 	struct kgsl_snapshot_registers_list *list,
 	struct adreno_device *adreno_dev)
 {
-	/* HLSQ specific registers */
+	struct kgsl_device *device = &adreno_dev->dev;
+
 	/*
-	 * Don't dump any a3xx HLSQ registers just yet.  Reading the HLSQ
-	 * registers can cause the device to hang if the HLSQ block is
-	 * busy.  Add specific checks for each a3xx core as the requirements
-	 * are discovered.  Disable by default for now.
+	 * Trying to read HLSQ registers when the HLSQ block is busy
+	 * will cause the device to hang.  The RBBM_DEBUG_BUS has information
+	 * that will tell us if the HLSQ block is busy or not.  Read values
+	 * from the debug bus to ensure the HLSQ block is not busy (this
+	 * is hardware dependent).  If the HLSQ block is busy do not
+	 * dump the registers, otherwise dump the HLSQ registers.
 	 */
-	if (!adreno_is_a3xx(adreno_dev)) {
-		regs[list->count].regs = (unsigned int *) a3xx_hlsq_registers;
-		regs[list->count].count = a3xx_hlsq_registers_count;
-		list->count++;
+
+	if (adreno_is_a330(adreno_dev)) {
+		/*
+		 * stall_ctxt_full status bit: RBBM_BLOCK_ID_HLSQ index 49 [27]
+		 *
+		 * if (!stall_context_full)
+		 * then dump HLSQ registers
+		 */
+		unsigned int stall_context_full = 0;
+
+		_rbbm_debug_bus_read(device, RBBM_BLOCK_ID_HLSQ, 49,
+				&stall_context_full);
+		stall_context_full &= 0x08000000;
+
+		if (stall_context_full)
+			return;
+	} else {
+		/*
+		 * tpif status bits: RBBM_BLOCK_ID_HLSQ index 4 [4:0]
+		 * spif status bits: RBBM_BLOCK_ID_HLSQ index 7 [5:0]
+		 *
+		 * if ((tpif == 0, 1, 28) && (spif == 0, 1, 10))
+		 * then dump HLSQ registers
+		 */
+		unsigned int next_pif = 0;
+
+		/* check tpif */
+		_rbbm_debug_bus_read(device, RBBM_BLOCK_ID_HLSQ, 4, &next_pif);
+		next_pif &= 0x1f;
+		if (next_pif != 0 && next_pif != 1 && next_pif != 28)
+			return;
+
+		/* check spif */
+		_rbbm_debug_bus_read(device, RBBM_BLOCK_ID_HLSQ, 7, &next_pif);
+		next_pif &= 0x3f;
+		if (next_pif != 0 && next_pif != 1 && next_pif != 10)
+			return;
 	}
+
+	regs[list->count].regs = (unsigned int *) a3xx_hlsq_registers;
+	regs[list->count].count = a3xx_hlsq_registers_count;
+	list->count++;
 }
 
 static void _snapshot_a330_regs(struct kgsl_snapshot_registers *regs,
diff --git a/drivers/gpu/msm/adreno_ringbuffer.c b/drivers/gpu/msm/adreno_ringbuffer.c
index 97b35b0..5272faa 100644
--- a/drivers/gpu/msm/adreno_ringbuffer.c
+++ b/drivers/gpu/msm/adreno_ringbuffer.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2002,2007-2012, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2002,2007-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -745,30 +745,6 @@
 	return timestamp;
 }
 
-void
-adreno_ringbuffer_issuecmds_intr(struct kgsl_device *device,
-						struct kgsl_context *k_ctxt,
-						unsigned int *cmds,
-						int sizedwords)
-{
-	struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
-	struct adreno_ringbuffer *rb = &adreno_dev->ringbuffer;
-	struct adreno_context *a_ctxt = NULL;
-
-	if (!k_ctxt)
-		return;
-
-	a_ctxt = k_ctxt->devctxt;
-
-	if (k_ctxt->id == KGSL_CONTEXT_INVALID ||
-		a_ctxt == NULL ||
-		device->state & KGSL_STATE_HUNG)
-		return;
-
-	adreno_ringbuffer_addcmds(rb, a_ctxt, KGSL_CMD_FLAGS_INTERNAL_ISSUE,
-					cmds, sizedwords, 0);
-}
-
 unsigned int
 adreno_ringbuffer_issuecmds(struct kgsl_device *device,
 						struct adreno_context *drawctxt,
diff --git a/drivers/gpu/msm/adreno_ringbuffer.h b/drivers/gpu/msm/adreno_ringbuffer.h
index 50d9c25..e87b506 100644
--- a/drivers/gpu/msm/adreno_ringbuffer.h
+++ b/drivers/gpu/msm/adreno_ringbuffer.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2002,2007-2012, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2002,2007-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -110,11 +110,6 @@
 					unsigned int *cmdaddr,
 					int sizedwords);
 
-void adreno_ringbuffer_issuecmds_intr(struct kgsl_device *device,
-					struct kgsl_context *k_ctxt,
-					unsigned int *cmdaddr,
-					int sizedwords);
-
 void adreno_ringbuffer_submit(struct adreno_ringbuffer *rb);
 
 void kgsl_cp_intrcallback(struct kgsl_device *device);
diff --git a/drivers/gpu/msm/kgsl.c b/drivers/gpu/msm/kgsl.c
index 9cde1d7..6337071 100644
--- a/drivers/gpu/msm/kgsl.c
+++ b/drivers/gpu/msm/kgsl.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2008-2012, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2008-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -690,7 +690,7 @@
 			INIT_COMPLETION(device->hwaccess_gate);
 			device->ftbl->suspend_context(device);
 			device->ftbl->stop(device);
-			pm_qos_update_request(&device->pm_qos_req_dma,
+			pm_qos_update_request(&device->pwrctrl.pm_qos_req_dma,
 						PM_QOS_DEFAULT_VALUE);
 			kgsl_pwrctrl_set_state(device, KGSL_STATE_SUSPEND);
 			break;
@@ -3136,7 +3136,8 @@
 		goto error_close_mmu;
 	}
 
-	pm_qos_add_request(&device->pm_qos_req_dma, PM_QOS_CPU_DMA_LATENCY,
+	pm_qos_add_request(&device->pwrctrl.pm_qos_req_dma,
+				PM_QOS_CPU_DMA_LATENCY,
 				PM_QOS_DEFAULT_VALUE);
 
 	/* Initalize the snapshot engine */
@@ -3247,7 +3248,7 @@
 	kgsl_cffdump_close(device->id);
 	kgsl_pwrctrl_uninit_sysfs(device);
 
-	pm_qos_remove_request(&device->pm_qos_req_dma);
+	pm_qos_remove_request(&device->pwrctrl.pm_qos_req_dma);
 
 	idr_destroy(&device->context_idr);
 
diff --git a/drivers/gpu/msm/kgsl_device.h b/drivers/gpu/msm/kgsl_device.h
index ce3820c..eab4dbd 100644
--- a/drivers/gpu/msm/kgsl_device.h
+++ b/drivers/gpu/msm/kgsl_device.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2002,2007-2012, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2002,2007-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -212,7 +212,6 @@
 	int pwr_log;
 	struct kgsl_pwrscale pwrscale;
 	struct kobject pwrscale_kobj;
-	struct pm_qos_request pm_qos_req_dma;
 	struct work_struct ts_expired_ws;
 	struct list_head events;
 	s64 on_time;
diff --git a/drivers/gpu/msm/kgsl_pwrctrl.c b/drivers/gpu/msm/kgsl_pwrctrl.c
index 73c8df1..0462aba 100644
--- a/drivers/gpu/msm/kgsl_pwrctrl.c
+++ b/drivers/gpu/msm/kgsl_pwrctrl.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2010-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -30,7 +30,6 @@
 #define KGSL_PWRFLAGS_AXI_ON   2
 #define KGSL_PWRFLAGS_IRQ_ON   3
 
-#define GPU_SWFI_LATENCY	3
 #define UPDATE_BUSY_VAL		1000000
 #define UPDATE_BUSY		50
 
@@ -555,6 +554,42 @@
 		device->pwrctrl.interval_timeout);
 }
 
+static int kgsl_pwrctrl_pmqos_latency_store(struct device *dev,
+					struct device_attribute *attr,
+					const char *buf, size_t count)
+{
+	char temp[20];
+	unsigned long val;
+	struct kgsl_device *device = kgsl_device_from_dev(dev);
+	int rc;
+
+	if (device == NULL)
+		return 0;
+
+	snprintf(temp, sizeof(temp), "%.*s",
+			(int)min(count, sizeof(temp) - 1), buf);
+	rc = kstrtoul(temp, 0, &val);
+	if (rc)
+		return rc;
+
+	mutex_lock(&device->mutex);
+	device->pwrctrl.pm_qos_latency = val;
+	mutex_unlock(&device->mutex);
+
+	return count;
+}
+
+static int kgsl_pwrctrl_pmqos_latency_show(struct device *dev,
+					   struct device_attribute *attr,
+					   char *buf)
+{
+	struct kgsl_device *device = kgsl_device_from_dev(dev);
+	if (device == NULL)
+		return 0;
+	return snprintf(buf, PAGE_SIZE, "%d\n",
+		device->pwrctrl.pm_qos_latency);
+}
+
 static int kgsl_pwrctrl_gpubusy_show(struct device *dev,
 					struct device_attribute *attr,
 					char *buf)
@@ -641,6 +676,9 @@
 DEVICE_ATTR(num_pwrlevels, 0444,
 	kgsl_pwrctrl_num_pwrlevels_show,
 	NULL);
+DEVICE_ATTR(pmqos_latency, 0644,
+	kgsl_pwrctrl_pmqos_latency_show,
+	kgsl_pwrctrl_pmqos_latency_store);
 
 static const struct device_attribute *pwrctrl_attr_list[] = {
 	&dev_attr_gpuclk,
@@ -654,6 +692,7 @@
 	&dev_attr_min_pwrlevel,
 	&dev_attr_thermal_pwrlevel,
 	&dev_attr_num_pwrlevels,
+	&dev_attr_pmqos_latency,
 	NULL
 };
 
@@ -951,6 +990,8 @@
 		}
 	}
 
+	/* Set the CPU latency to 501usec to allow low latency PC modes */
+	pwr->pm_qos_latency = 501;
 
 	pm_runtime_enable(device->parentdev);
 	register_early_suspend(&device->display_off);
@@ -1147,7 +1188,7 @@
 		_sleep_accounting(device);
 		kgsl_pwrctrl_clk(device, KGSL_PWRFLAGS_OFF, KGSL_STATE_SLEEP);
 		kgsl_pwrctrl_set_state(device, KGSL_STATE_SLEEP);
-		pm_qos_update_request(&device->pm_qos_req_dma,
+		pm_qos_update_request(&device->pwrctrl.pm_qos_req_dma,
 					PM_QOS_DEFAULT_VALUE);
 		break;
 	case KGSL_STATE_SLEEP:
@@ -1181,7 +1222,7 @@
 		device->ftbl->stop(device);
 		_sleep_accounting(device);
 		kgsl_pwrctrl_set_state(device, KGSL_STATE_SLUMBER);
-		pm_qos_update_request(&device->pm_qos_req_dma,
+		pm_qos_update_request(&device->pwrctrl.pm_qos_req_dma,
 						PM_QOS_DEFAULT_VALUE);
 		break;
 	case KGSL_STATE_SLUMBER:
@@ -1267,8 +1308,8 @@
 		/* Re-enable HW access */
 		mod_timer(&device->idle_timer,
 				jiffies + device->pwrctrl.interval_timeout);
-		pm_qos_update_request(&device->pm_qos_req_dma,
-					GPU_SWFI_LATENCY);
+		pm_qos_update_request(&device->pwrctrl.pm_qos_req_dma,
+				device->pwrctrl.pm_qos_latency);
 	case KGSL_STATE_ACTIVE:
 		kgsl_pwrctrl_request_state(device, KGSL_STATE_NONE);
 		break;
diff --git a/drivers/gpu/msm/kgsl_pwrctrl.h b/drivers/gpu/msm/kgsl_pwrctrl.h
index e51ec54..72ad4d1 100644
--- a/drivers/gpu/msm/kgsl_pwrctrl.h
+++ b/drivers/gpu/msm/kgsl_pwrctrl.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2010-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -60,6 +60,8 @@
  * @irq_name - resource name for the IRQ
  * @restore_slumber - Flag to indicate that we are in a suspend/restore sequence
  * @clk_stats - structure of clock statistics
+ * @pm_qos_req_dma - the power management quality of service structure
+ * @pm_qos_latency - allowed CPU latency in microseconds
  */
 
 struct kgsl_pwrctrl {
@@ -85,6 +87,8 @@
 	s64 time;
 	unsigned int restore_slumber;
 	struct kgsl_clk_stats clk_stats;
+	struct pm_qos_request pm_qos_req_dma;
+	unsigned int pm_qos_latency;
 };
 
 void kgsl_pwrctrl_irq(struct kgsl_device *device, int state);
diff --git a/drivers/hwmon/pm8xxx-adc-scale.c b/drivers/hwmon/pm8xxx-adc-scale.c
index 4a1f58c..56c352a 100644
--- a/drivers/hwmon/pm8xxx-adc-scale.c
+++ b/drivers/hwmon/pm8xxx-adc-scale.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2011-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -271,172 +271,174 @@
 };
 
 static const struct pm8xxx_adc_map_pt adcmap_ntcg_104ef_104fb[] = {
-	{696483,	-40960},
-	{649148,	-39936},
-	{605368,	-38912},
-	{564809,	-37888},
-	{527215,	-36864},
-	{492322,	-35840},
-	{460007,	-34816},
-	{429982,	-33792},
-	{402099,	-32768},
-	{376192,	-31744},
-	{352075,	-30720},
-	{329714,	-29696},
-	{308876,	-28672},
-	{289480,	-27648},
-	{271417,	-26624},
-	{254574,	-25600},
-	{238903,	-24576},
-	{224276,	-23552},
-	{210631,	-22528},
-	{197896,	-21504},
-	{186007,	-20480},
-	{174899,	-19456},
-	{164521,	-18432},
-	{154818,	-17408},
-	{145744,	-16384},
-	{137265,	-15360},
-	{129307,	-14336},
-	{121866,	-13312},
-	{114896,	-12288},
-	{108365,	-11264},
-	{102252,	-10240},
-	{96499,		-9216},
-	{91111,		-8192},
-	{86055,		-7168},
-	{81308,		-6144},
-	{76857,		-5120},
-	{72660,		-4096},
-	{68722,		-3072},
-	{65020,		-2048},
-	{61538,		-1024},
-	{58261,		0},
-	{55177,		1024},
-	{52274,		2048},
-	{49538,		3072},
-	{46962,		4096},
-	{44531,		5120},
-	{42243,		6144},
-	{40083,		7168},
-	{38045,		8192},
-	{36122,		9216},
-	{34308,		10240},
-	{32592,		11264},
-	{30972,		12288},
-	{29442,		13312},
-	{27995,		14336},
-	{26624,		15360},
-	{25333,		16384},
-	{24109,		17408},
-	{22951,		18432},
-	{21854,		19456},
-	{20807,		20480},
-	{19831,		21504},
-	{18899,		22528},
-	{18016,		23552},
-	{17178,		24576},
-	{16384,		25600},
-	{15631,		26624},
-	{14916,		27648},
-	{14237,		28672},
-	{13593,		29696},
-	{12976,		30720},
-	{12400,		31744},
-	{11848,		32768},
-	{11324,		33792},
-	{10825,		34816},
-	{10354,		35840},
-	{9900,		36864},
-	{9471,		37888},
-	{9062,		38912},
-	{8674,		39936},
-	{8306,		40960},
-	{7951,		41984},
-	{7616,		43008},
-	{7296,		44032},
-	{6991,		45056},
-	{6701,		46080},
-	{6424,		47104},
-	{6160,		48128},
-	{5908,		49152},
-	{5667,		50176},
-	{5439,		51200},
-	{5219,		52224},
-	{5010,		53248},
-	{4810,		54272},
-	{4619,		55296},
-	{4440,		56320},
-	{4263,		57344},
-	{4097,		58368},
-	{3938,		59392},
-	{3785,		60416},
-	{3637,		61440},
-	{3501,		62464},
-	{3368,		63488},
-	{3240,		64512},
-	{3118,		65536},
-	{2998,		66560},
-	{2889,		67584},
-	{2782,		68608},
-	{2680,		69632},
-	{2581,		70656},
-	{2490,		71680},
-	{2397,		72704},
-	{2310,		73728},
-	{2227,		74752},
-	{2147,		75776},
-	{2064,		76800},
-	{1998,		77824},
-	{1927,		78848},
-	{1860,		79872},
-	{1795,		80896},
-	{1736,		81920},
-	{1673,		82944},
-	{1615,		83968},
-	{1560,		84992},
-	{1507,		86016},
-	{1456,		87040},
-	{1407,		88064},
-	{1360,		89088},
-	{1314,		90112},
-	{1271,		91136},
-	{1228,		92160},
-	{1189,		93184},
-	{1150,		94208},
-	{1112,		95232},
-	{1076,		96256},
-	{1042,		97280},
-	{1008,		98304},
-	{976,		99328},
-	{945,		100352},
-	{915,		101376},
+	{374682,	-40960},
+	{360553,	-39936},
+	{346630,	-38912},
+	{332940,	-37888},
+	{319510,	-36864},
+	{306363,	-35840},
+	{293521,	-34816},
+	{281001,	-33792},
+	{268818,	-32768},
+	{256987,	-31744},
+	{245516,	-30720},
+	{234413,	-29696},
+	{223685,	-28672},
+	{213333,	-27648},
+	{203360,	-26624},
+	{193763,	-25600},
+	{184541,	-24576},
+	{175691,	-23552},
+	{167205,	-22528},
+	{159079,	-21504},
+	{151304,	-20480},
+	{143872,	-19456},
+	{136775,	-18432},
+	{130001,	-17408},
+	{123542,	-16384},
+	{117387,	-15360},
+	{111526,	-14336},
+	{105946,	-13312},
+	{100639,	-12288},
+	{95592,		-11264},
+	{90795,		-10240},
+	{86238,		-9216},
+	{81909,		-8192},
+	{77800,		-7168},
+	{73899,		-6144},
+	{70197,		-5120},
+	{66685,		-4096},
+	{63354,		-3072},
+	{60194,		-2048},
+	{57198,		-1024},
+	{54356,		0},
+	{51662,		1024},
+	{49108,		2048},
+	{46687,		3072},
+	{44391,		4096},
+	{42215,		5120},
+	{40151,		6144},
+	{38195,		7168},
+	{36340,		8192},
+	{34582,		9216},
+	{32914,		10240},
+	{31333,		11264},
+	{29833,		12288},
+	{28410,		13312},
+	{27061,		14336},
+	{25781,		15360},
+	{24566,		16384},
+	{23413,		17408},
+	{22319,		18432},
+	{21280,		19456},
+	{20294,		20480},
+	{19358,		21504},
+	{18469,		22528},
+	{17624,		23552},
+	{16822,		24576},
+	{16060,		25600},
+	{15335,		26624},
+	{14646,		27648},
+	{13992,		28672},
+	{13369,		29696},
+	{12777,		30720},
+	{12214,		31744},
+	{11678,		32768},
+	{11168,		33792},
+	{10682,		34816},
+	{10220,		35840},
+	{9780,		36864},
+	{9361,		37888},
+	{8962,		38912},
+	{8582,		39936},
+	{8219,		40960},
+	{7874,		41984},
+	{7545,		43008},
+	{7231,		44032},
+	{6931,		45056},
+	{6646,		46080},
+	{6373,		47104},
+	{6113,		48128},
+	{5865,		49152},
+	{5628,		50176},
+	{5402,		51200},
+	{5185,		52224},
+	{4979,		53248},
+	{4782,		54272},
+	{4593,		55296},
+	{4413,		56320},
+	{4241,		57344},
+	{4076,		58368},
+	{3919,		59392},
+	{3768,		60416},
+	{3624,		61440},
+	{3486,		62464},
+	{3354,		63488},
+	{3227,		64512},
+	{3106,		65536},
+	{2990,		66560},
+	{2879,		67584},
+	{2773,		68608},
+	{2671,		69632},
+	{2573,		70656},
+	{2479,		71680},
+	{2390,		72704},
+	{2303,		73728},
+	{2221,		74752},
+	{2142,		75776},
+	{2066,		76800},
+	{1993,		77824},
+	{1923,		78848},
+	{1855,		79872},
+	{1791,		80896},
+	{1729,		81920},
+	{1669,		82944},
+	{1612,		83968},
+	{1557,		84992},
+	{1504,		86016},
+	{1453,		87040},
+	{1404,		88064},
+	{1357,		89088},
+	{1312,		90112},
+	{1269,		91136},
+	{1227,		92160},
+	{1187,		93184},
+	{1148,		94208},
+	{1111,		95232},
+	{1075,		96256},
+	{1040,		97280},
+	{1007,		98304},
+	{975,		99328},
+	{944,		100352},
+	{914,		101376},
 	{886,		102400},
-	{859,		103424},
-	{832,		104448},
-	{807,		105472},
-	{782,		106496},
-	{756,		107520},
-	{735,		108544},
+	{858,		103424},
+	{831,		104448},
+	{806,		105472},
+	{781,		106496},
+	{757,		107520},
+	{734,		108544},
 	{712,		109568},
-	{691,		110592},
+	{690,		110592},
 	{670,		111616},
 	{650,		112640},
-	{631,		113664},
+	{630,		113664},
 	{612,		114688},
 	{594,		115712},
-	{577,		116736},
-	{560,		117760},
-	{544,		118784},
-	{528,		119808},
-	{513,		120832},
+	{576,		116736},
+	{559,		117760},
+	{543,		118784},
+	{527,		119808},
+	{512,		120832},
 	{498,		121856},
 	{483,		122880},
 	{470,		123904},
-	{457,		124928},
+	{456,		124928},
 	{444,		125952},
 	{431,		126976},
-	{419,		128000}
+	{419,		128000},
+	{408,		129024},
+	{396,		130048}
 };
 
 static int32_t pm8xxx_adc_map_linear(const struct pm8xxx_adc_map_pt *pts,
@@ -716,6 +718,10 @@
 		struct pm8xxx_adc_chan_result *adc_chan_result)
 {
 	int64_t xo_thm = 0;
+	uint32_t num1 = 0;
+	uint32_t num2 = 0;
+	uint32_t dnum = 0;
+	uint32_t rt_r25 = 0;
 
 	if (!chan_properties || !chan_properties->offset_gain_numerator ||
 		!chan_properties->offset_gain_denominator || !adc_properties
@@ -724,10 +730,21 @@
 
 	xo_thm = pm8xxx_adc_scale_ratiometric_calib(adc_code,
 			adc_properties, chan_properties);
-	xo_thm <<= 4;
+	if (xo_thm < 0)
+		xo_thm = -xo_thm;
+
+	num1 = xo_thm << 14;
+	num2 = (adc_properties->adc_vdd_reference - xo_thm) >> 1;
+	dnum = (adc_properties->adc_vdd_reference - xo_thm);
+
+	if (dnum == 0)
+		rt_r25 = 0x7FFFFFFF ;
+	else
+		rt_r25 = (num1 + num2)/dnum ;
+
 	pm8xxx_adc_map_linear(adcmap_ntcg_104ef_104fb,
 		ARRAY_SIZE(adcmap_ntcg_104ef_104fb),
-		xo_thm, &adc_chan_result->physical);
+		rt_r25, &adc_chan_result->physical);
 
 	return 0;
 }
diff --git a/drivers/hwmon/pm8xxx-adc.c b/drivers/hwmon/pm8xxx-adc.c
index 181a97e..1a163a4 100644
--- a/drivers/hwmon/pm8xxx-adc.c
+++ b/drivers/hwmon/pm8xxx-adc.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2011-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -1075,7 +1075,7 @@
 
 	return 0;
 }
-DEFINE_SIMPLE_ATTRIBUTE(reg_fops, get_adc, NULL, "%llu\n");
+DEFINE_SIMPLE_ATTRIBUTE(reg_fops, get_adc, NULL, "%lld\n");
 
 #ifdef CONFIG_DEBUG_FS
 static void create_debugfs_entries(void)
diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c
index bb505d8..2e807ac 100644
--- a/drivers/input/touchscreen/atmel_mxt_ts.c
+++ b/drivers/input/touchscreen/atmel_mxt_ts.c
@@ -233,14 +233,26 @@
 #define MXT_BOOT_VALUE		0xa5
 #define MXT_BACKUP_VALUE	0x55
 #define MXT_BACKUP_TIME		25	/* msec */
-#define MXT224_RESET_TIME	65	/* msec */
-#define MXT224E_RESET_TIME	150	/* msec */
-#define MXT1386_RESET_TIME	250	/* msec */
+
+/* Software reset delay */
+#define MXT224_RESET_TIME	64	/* msec */
+#define MXT224E_RESET_TIME	21	/* msec */
 #define MXT336S_RESET_TIME	25	/* msec */
-#define MXT1664S_RESET_TIME	65	/* msec */
+#define MXT1386_RESET_TIME	250	/* msec */
+#define MXT1386E_RESET_TIME	229	/* msec */
+#define MXT1664S_RESET_TIME	280	/* msec */
 #define MXT_RESET_TIME		250	/* msec */
 #define MXT_RESET_NOCHGREAD	400	/* msec */
 
+/* Power on delay */
+#define MXT224_POWER_ON_TIME	40	/* msec */
+#define MXT224E_POWER_ON_TIME	21	/* msec */
+#define MXT336S_POWER_ON_TIME	25	/* msec */
+#define MXT1386_POWER_ON_TIME	90	/* msec */
+#define MXT1386E_POWER_ON_TIME	81	/* msec */
+#define MXT1664S_POWER_ON_TIME	65	/* msec */
+#define MXT_POWER_ON_TIME	100	/* msec */
+
 #define MXT_FWRESET_TIME	1000	/* msec */
 
 #define MXT_WAKE_TIME		25
@@ -1291,6 +1303,42 @@
 	return 0;
 }
 
+static void mxt_power_on_delay(struct mxt_data *data)
+{
+	const struct mxt_platform_data *pdata = data->pdata;
+	const struct mxt_config_info *cfg_info;
+	u32 delay = 0;
+	int i;
+
+	for (i = 0; i < pdata->config_array_size; i++) {
+		cfg_info = &pdata->config_array[i];
+
+		switch (cfg_info->family_id) {
+		case MXT224_ID:
+			delay = max_t(u32, delay, MXT224_POWER_ON_TIME);
+			break;
+		case MXT224E_ID:
+			delay = max_t(u32, delay, MXT224E_POWER_ON_TIME);
+			break;
+		case MXT336S_ID:
+			delay = max_t(u32, delay, MXT336S_POWER_ON_TIME);
+			break;
+		case MXT1386_ID:
+			delay = max_t(u32, delay,
+					max_t(u32, MXT1386_POWER_ON_TIME,
+						MXT1386E_POWER_ON_TIME));
+			break;
+		case MXT1664S_ID:
+			delay = max_t(u32, delay, MXT1664S_POWER_ON_TIME);
+			break;
+		default:
+			delay = max_t(u32, delay, MXT_POWER_ON_TIME);
+		}
+	}
+
+	msleep(delay);
+}
+
 static void mxt_reset_delay(struct mxt_data *data)
 {
 	struct mxt_info *info = &data->info;
@@ -1304,8 +1352,10 @@
 		break;
 	case MXT336S_ID:
 		msleep(MXT336S_RESET_TIME);
+		break;
 	case MXT1386_ID:
-		msleep(MXT1386_RESET_TIME);
+		msleep(max_t(u32, MXT1386_RESET_TIME, MXT1386E_RESET_TIME));
+		break;
 	case MXT1664S_ID:
 		msleep(MXT1664S_RESET_TIME);
 		break;
@@ -2715,10 +2765,12 @@
 		}
 	}
 
-	mxt_reset_delay(data);
+	mxt_power_on_delay(data);
+
 	error = mxt_initialize(data);
 	if (error)
 		goto err_reset_gpio_req;
+
 	error = request_threaded_irq(client->irq, NULL, mxt_interrupt,
 			pdata->irqflags, client->dev.driver->name, data);
 	if (error) {
diff --git a/drivers/input/touchscreen/cyttsp-i2c-qc.c b/drivers/input/touchscreen/cyttsp-i2c-qc.c
index 6eba5d1..6c4e6b7 100644
--- a/drivers/input/touchscreen/cyttsp-i2c-qc.c
+++ b/drivers/input/touchscreen/cyttsp-i2c-qc.c
@@ -2881,17 +2881,17 @@
 
 	cyttsp_debug("Wake Up\n");
 
-	if (ts->is_suspended == false) {
-		pr_err("%s: in wakeup state\n", __func__);
-		return 0;
-	}
-
 	if (device_may_wakeup(dev)) {
 		if (ts->client->irq)
 			disable_irq_wake(ts->client->irq);
 		return 0;
 	}
 
+	if (ts->is_suspended == false) {
+		pr_err("%s: in wakeup state\n", __func__);
+		return 0;
+	}
+
 	/* re-enable the interrupt prior to wake device */
 	if (ts->client->irq)
 		enable_irq(ts->client->irq);
@@ -2952,6 +2952,12 @@
 
 	cyttsp_debug("Enter Sleep\n");
 
+	if (device_may_wakeup(dev)) {
+		if (ts->client->irq)
+			enable_irq_wake(ts->client->irq);
+		return 0;
+	}
+
 	if (ts->is_suspended == true) {
 		pr_err("%s: in sleep state\n", __func__);
 		return 0;
@@ -2966,11 +2972,6 @@
 	}
 	mutex_unlock(&ts->mutex);
 
-	if (device_may_wakeup(dev)) {
-		if (ts->client->irq)
-			enable_irq_wake(ts->client->irq);
-		return 0;
-	}
 
 	if (ts->client->irq == 0)
 		del_timer(&ts->timer);
diff --git a/drivers/iommu/Kconfig b/drivers/iommu/Kconfig
index 86703e0..6fb11e1 100644
--- a/drivers/iommu/Kconfig
+++ b/drivers/iommu/Kconfig
@@ -16,7 +16,7 @@
 # MSM IOMMU support
 config MSM_IOMMU
 	bool "MSM IOMMU Support"
-	depends on ARCH_MSM8X60 || ARCH_MSM8960 || ARCH_APQ8064 || ARCH_MSM8974 || ARCH_MPQ8092 || ARCH_MSM8910
+	depends on ARCH_MSM8X60 || ARCH_MSM8960 || ARCH_APQ8064 || ARCH_MSM8974 || ARCH_MPQ8092 || ARCH_MSM8910 || ARCH_MSM8226
 	select IOMMU_API
 	help
 	  Support for the IOMMUs found on certain Qualcomm SOCs.
diff --git a/drivers/iommu/msm_iommu-v2.c b/drivers/iommu/msm_iommu-v2.c
index e3aa30c..aab8d24 100644
--- a/drivers/iommu/msm_iommu-v2.c
+++ b/drivers/iommu/msm_iommu-v2.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012 The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -43,6 +43,29 @@
 	struct list_head list_attached;
 };
 
+static int __enable_regulators(struct msm_iommu_drvdata *drvdata)
+{
+	int ret = regulator_enable(drvdata->gdsc);
+	if (ret)
+		goto fail;
+
+	if (drvdata->alt_gdsc)
+		ret = regulator_enable(drvdata->alt_gdsc);
+
+	if (ret)
+		regulator_disable(drvdata->gdsc);
+fail:
+	return ret;
+}
+
+static void __disable_regulators(struct msm_iommu_drvdata *drvdata)
+{
+	if (drvdata->alt_gdsc)
+		regulator_disable(drvdata->alt_gdsc);
+
+	regulator_disable(drvdata->gdsc);
+}
+
 static int __enable_clocks(struct msm_iommu_drvdata *drvdata)
 {
 	int ret;
@@ -62,6 +85,14 @@
 			clk_disable_unprepare(drvdata->pclk);
 		}
 	}
+
+	if (drvdata->clk_reg_virt) {
+		unsigned int value;
+
+		value = readl_relaxed(drvdata->clk_reg_virt);
+		value &= ~0x1;
+		writel_relaxed(value, drvdata->clk_reg_virt);
+	}
 fail:
 	return ret;
 }
@@ -478,13 +509,13 @@
 
 	is_secure = iommu_drvdata->sec_id != -1;
 
-	ret = regulator_enable(iommu_drvdata->gdsc);
+	ret = __enable_regulators(iommu_drvdata);
 	if (ret)
 		goto fail;
 
 	ret = __enable_clocks(iommu_drvdata);
 	if (ret) {
-		regulator_disable(iommu_drvdata->gdsc);
+		__disable_regulators(iommu_drvdata);
 		goto fail;
 	}
 
@@ -496,7 +527,7 @@
 			ret = msm_iommu_sec_program_iommu(
 				iommu_drvdata->sec_id);
 			if (ret) {
-				regulator_disable(iommu_drvdata->gdsc);
+				__disable_regulators(iommu_drvdata);
 				__disable_clocks(iommu_drvdata);
 				goto fail;
 			}
@@ -550,7 +581,7 @@
 
 	__disable_clocks(iommu_drvdata);
 
-	regulator_disable(iommu_drvdata->gdsc);
+	__disable_regulators(iommu_drvdata);
 
 	list_del_init(&ctx_drvdata->attached_elm);
 	ctx_drvdata->attached_domain = NULL;
diff --git a/drivers/iommu/msm_iommu_dev-v2.c b/drivers/iommu/msm_iommu_dev-v2.c
index 7961280..9b6dc0e 100644
--- a/drivers/iommu/msm_iommu_dev-v2.c
+++ b/drivers/iommu/msm_iommu_dev-v2.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012 The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -93,6 +93,7 @@
 {
 	struct device_node *child;
 	int ret = 0;
+	struct resource *r;
 
 	drvdata->dev = &pdev->dev;
 	msm_iommu_add_drv(drvdata);
@@ -111,6 +112,19 @@
 	drvdata->sec_id = -1;
 	of_property_read_u32(pdev->dev.of_node, "qcom,iommu-secure-id",
 				&drvdata->sec_id);
+
+	r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "clk_base");
+	if (r) {
+		drvdata->clk_reg_virt = devm_ioremap(&pdev->dev, r->start,
+						     resource_size(r));
+		if (!drvdata->clk_reg_virt) {
+			pr_err("Failed to map 0x%x for iommu clk\n",
+				r->start);
+			ret = -ENOMEM;
+			goto fail;
+		}
+	}
+
 	return 0;
 fail:
 	return ret;
@@ -126,7 +140,7 @@
 	if (!drvdata)
 		return -ENOMEM;
 
-	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "iommu_base");
 	if (!r)
 		return -EINVAL;
 
@@ -140,6 +154,10 @@
 	if (IS_ERR(drvdata->gdsc))
 		return -EINVAL;
 
+	drvdata->alt_gdsc = devm_regulator_get(&pdev->dev, "qcom,alt-vdd");
+	if (IS_ERR(drvdata->alt_gdsc))
+		drvdata->alt_gdsc = NULL;
+
 	drvdata->pclk = devm_clk_get(&pdev->dev, "iface_clk");
 	if (IS_ERR(drvdata->pclk))
 		return PTR_ERR(drvdata->pclk);
diff --git a/drivers/media/dvb/dvb-core/dmxdev.c b/drivers/media/dvb/dvb-core/dmxdev.c
index 9b66b05..82b6aa0 100644
--- a/drivers/media/dvb/dvb-core/dmxdev.c
+++ b/drivers/media/dvb/dvb-core/dmxdev.c
@@ -4,7 +4,7 @@
  * Copyright (C) 2000 Ralph Metzler & Marcus Metzler
  *		      for convergence integrated media GmbH
  *
- * Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public License
@@ -2255,6 +2255,7 @@
 
 	spin_lock_irq(&dmxdevfilter->dev->lock);
 	dvb_dmxdev_flush_output(&dmxdevfilter->buffer, &dmxdevfilter->events);
+	dvb_ringbuffer_reset(&dmxdevfilter->buffer);
 	spin_unlock_irq(&dmxdevfilter->dev->lock);
 
 	wake_up_all(&dmxdevfilter->buffer.queue);
diff --git a/drivers/media/video/msm/msm_mctl_buf.c b/drivers/media/video/msm/msm_mctl_buf.c
index 2919d23..f4bb5b3 100644
--- a/drivers/media/video/msm/msm_mctl_buf.c
+++ b/drivers/media/video/msm/msm_mctl_buf.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2011-2013, 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
@@ -122,6 +122,11 @@
 	}
 	for (i = 0; i < vb->num_planes; i++) {
 		mem = vb2_plane_cookie(vb, i);
+		if (mem == NULL) {
+			pr_err("%s Inst %p Buffer %d Plane %d cookie is null",
+				__func__, pcam_inst, buf_idx, i);
+			return -EINVAL;
+		}
 		if (buf_type == VIDEOBUF2_MULTIPLE_PLANES)
 			offset.data_offset =
 				pcam_inst->plane_info.plane[i].offset;
@@ -266,8 +271,14 @@
 	}
 	for (i = 0; i < vb->num_planes; i++) {
 		mem = vb2_plane_cookie(vb, i);
-		videobuf2_pmem_contig_user_put(mem, pmctl->client,
-			pmctl->domain_num);
+		if (mem) {
+			videobuf2_pmem_contig_user_put(mem, pmctl->client,
+				pmctl->domain_num);
+		} else {
+			pr_err("%s Inst %p buffer plane cookie is null",
+				__func__, pcam_inst);
+			return;
+		}
 	}
 	buf->state = MSM_BUFFER_STATE_UNUSED;
 }
@@ -385,7 +396,13 @@
 			&pcam_inst->free_vq, list) {
 		buf_idx = buf->vidbuf.v4l2_buf.index;
 		mem = vb2_plane_cookie(&buf->vidbuf, 0);
-		if (mem->buffer_type ==	VIDEOBUF2_MULTIPLE_PLANES)
+		if (mem == NULL) {
+			pr_err("%s Inst %p plane cookie is null",
+				__func__, pcam_inst);
+			spin_unlock_irqrestore(&pcam_inst->vq_irqlock, flags);
+			return NULL;
+		}
+		if (mem->buffer_type == VIDEOBUF2_MULTIPLE_PLANES)
 			offset = mem->offset.data_offset +
 				pcam_inst->buf_offset[buf_idx][0].data_offset;
 		else
@@ -690,7 +707,19 @@
 		return rc;
 	}
 	spin_lock_irqsave(&pcam_inst->vq_irqlock, flags);
+	if (pcam_inst->free_vq.next == NULL) {
+		pr_err("%s Inst %p Free queue head is null",
+			__func__, pcam_inst);
+		spin_unlock_irqrestore(&pcam_inst->vq_irqlock, flags);
+		return rc;
+	}
 	list_for_each_entry(buf, &pcam_inst->free_vq, list) {
+		if (buf == NULL) {
+			pr_err("%s Inst %p Invalid buffer ptr",
+				__func__, pcam_inst);
+			spin_unlock_irqrestore(&pcam_inst->vq_irqlock, flags);
+			return rc;
+		}
 		if (buf->state != MSM_BUFFER_STATE_QUEUED)
 			continue;
 
@@ -701,6 +730,13 @@
 				pcam_inst->plane_info.num_planes;
 			for (i = 0; i < free_buf->num_planes; i++) {
 				mem = vb2_plane_cookie(&buf->vidbuf, i);
+				if (mem == NULL) {
+					pr_err("%s Inst %p %d invalid cookie",
+						__func__, pcam_inst, buf_idx);
+					spin_unlock_irqrestore(
+						&pcam_inst->vq_irqlock, flags);
+					return rc;
+				}
 				if (mem->buffer_type ==
 						VIDEOBUF2_MULTIPLE_PLANES)
 					plane_offset =
@@ -721,6 +757,13 @@
 			}
 		} else {
 			mem = vb2_plane_cookie(&buf->vidbuf, 0);
+			if (mem == NULL) {
+				pr_err("%s Inst %p %d invalid cookie",
+					__func__, pcam_inst, buf_idx);
+				spin_unlock_irqrestore(
+					&pcam_inst->vq_irqlock, flags);
+				return rc;
+			}
 			free_buf->ch_paddr[0] = (uint32_t)
 				videobuf2_to_pmem_contig(&buf->vidbuf, 0) +
 				mem->offset.sp_off.y_off;
diff --git a/drivers/media/video/msm/msm_mctl_pp.c b/drivers/media/video/msm/msm_mctl_pp.c
index 7155d4c..7f0fd94 100644
--- a/drivers/media/video/msm/msm_mctl_pp.c
+++ b/drivers/media/video/msm/msm_mctl_pp.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2011-2013, 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
@@ -138,6 +138,12 @@
 	&pcam_inst->free_vq, list) {
 		buf_idx = buf->vidbuf.v4l2_buf.index;
 		mem = vb2_plane_cookie(&buf->vidbuf, 0);
+		if (mem == NULL) {
+			pr_err("%s Inst %p Buffer %d invalid plane cookie",
+				__func__, pcam_inst, buf_idx);
+			spin_unlock_irqrestore(&pcam_inst->vq_irqlock, flags);
+			return 0;
+		}
 		if (mem->buffer_type ==	VIDEOBUF2_MULTIPLE_PLANES)
 			offset = mem->offset.data_offset +
 				pcam_inst->buf_offset[buf_idx][0].data_offset;
@@ -272,6 +278,11 @@
 	 * Also use this to check the number of planes in
 	 * this buffer.*/
 	mem = vb2_plane_cookie(&vb->vidbuf, 0);
+	if (mem == NULL) {
+		pr_err("%s Inst %p Buffer %d, invalid plane cookie ", __func__,
+			pcam_inst, buf_idx);
+		return -EINVAL;
+	}
 	div.frame.path = mem->path;
 	div.frame.node_type = node;
 	if (mem->buffer_type == VIDEOBUF2_SINGLE_PLANE) {
@@ -296,6 +307,11 @@
 		 * fill out the plane info. */
 		for (i = 0; i < div.frame.num_planes; i++) {
 			mem = vb2_plane_cookie(&vb->vidbuf, i);
+			if (mem == NULL) {
+				pr_err("%s Inst %p %d invalid plane cookie ",
+					__func__, pcam_inst, buf_idx);
+				return -EINVAL;
+			}
 			div.frame.mp[i].phy_addr =
 				videobuf2_to_pmem_contig(&vb->vidbuf, i);
 			if (!pcam_inst->buf_offset)
@@ -338,6 +354,11 @@
 	 * Also use this to check the number of planes in
 	 * this buffer.*/
 	mem = vb2_plane_cookie(&vb->vidbuf, 0);
+	if (mem == NULL) {
+		pr_err("%s Inst %p Buffer %d, invalid plane cookie ", __func__,
+			pcam_inst, buf_idx);
+		return -EINVAL;
+	}
 	pp_frame->image_type = (unsigned short)mem->path;
 	if (mem->buffer_type == VIDEOBUF2_SINGLE_PLANE) {
 		pp_frame->num_planes = 1;
diff --git a/drivers/media/video/msm_vidc/Makefile b/drivers/media/video/msm_vidc/Makefile
index c8e7076..da829cc 100644
--- a/drivers/media/video/msm_vidc/Makefile
+++ b/drivers/media/video/msm_vidc/Makefile
@@ -8,3 +8,4 @@
 				venus_hfi.o \
 				hfi_response_handler.o \
 				hfi_packetization.o \
+				vidc_hfi.o \
diff --git a/drivers/media/video/msm_vidc/hfi_packetization.c b/drivers/media/video/msm_vidc/hfi_packetization.c
index 509b013..4d3d07d 100644
--- a/drivers/media/video/msm_vidc/hfi_packetization.c
+++ b/drivers/media/video/msm_vidc/hfi_packetization.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -794,6 +794,7 @@
 			HFI_PROPERTY_CONFIG_VENC_TARGET_BITRATE;
 		hfi = (struct hfi_bitrate *) &pkt->rg_property_data[1];
 		hfi->bit_rate = ((struct hal_bitrate *)pdata)->bit_rate;
+		hfi->layer_id = ((struct hal_bitrate *)pdata)->layer_id;
 		pkt->size += sizeof(u32) * 2;
 		break;
 	}
@@ -943,11 +944,15 @@
 	case HAL_PARAM_VENC_SESSION_QP:
 	{
 		struct hfi_quantization *hfi;
+		struct hal_quantization *hal_quant =
+			(struct hal_quantization *) pdata;
 		pkt->rg_property_data[0] =
 			HFI_PROPERTY_PARAM_VENC_SESSION_QP;
 		hfi = (struct hfi_quantization *) &pkt->rg_property_data[1];
-		memcpy(hfi, (struct hfi_quantization *) pdata,
-				sizeof(struct hfi_quantization));
+		hfi->qp_i = hal_quant->qpi;
+		hfi->qp_p = hal_quant->qpp;
+		hfi->qp_b = hal_quant->qpb;
+		hfi->layer_id = hal_quant->layer_id;
 		pkt->size += sizeof(u32) + sizeof(struct hfi_quantization);
 		break;
 	}
diff --git a/drivers/media/video/msm_vidc/hfi_packetization.h b/drivers/media/video/msm_vidc/hfi_packetization.h
index 541654f..a3edc7c 100644
--- a/drivers/media/video/msm_vidc/hfi_packetization.h
+++ b/drivers/media/video/msm_vidc/hfi_packetization.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -15,8 +15,8 @@
 
 #include <linux/types.h>
 #include "vidc_hfi_helper.h"
+#include "vidc_hfi.h"
 #include "vidc_hfi_api.h"
-#include "venus_hfi.h"
 
 int create_pkt_cmd_sys_init(struct hfi_cmd_sys_init_packet *pkt,
 							   u32 arch_type);
diff --git a/drivers/media/video/msm_vidc/hfi_response_handler.c b/drivers/media/video/msm_vidc/hfi_response_handler.c
index 50970cb..23829e5 100644
--- a/drivers/media/video/msm_vidc/hfi_response_handler.c
+++ b/drivers/media/video/msm_vidc/hfi_response_handler.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -14,9 +14,10 @@
 #include <linux/slab.h>
 #include <linux/list.h>
 #include <linux/interrupt.h>
-#include "venus_hfi.h"
+#include "vidc_hfi_helper.h"
 #include "vidc_hfi_io.h"
 #include "msm_vidc_debug.h"
+#include "vidc_hfi.h"
 
 static enum vidc_status hfi_map_err_status(int hfi_err)
 {
@@ -75,8 +76,9 @@
 	return vidc_err;
 }
 
-static void hfi_process_sess_evt_seq_changed(struct venus_hfi_device *device,
-	struct hfi_msg_event_notify_packet *pkt)
+static void hfi_process_sess_evt_seq_changed(
+		msm_vidc_callback callback, u32 device_id,
+		struct hfi_msg_event_notify_packet *pkt)
 {
 	struct msm_vidc_cb_cmd_done cmd_done;
 	struct msm_vidc_cb_event event_notify;
@@ -95,7 +97,7 @@
 	memset(&event_notify, 0, sizeof(struct
 				msm_vidc_cb_event));
 
-	cmd_done.device_id = device->device_id;
+	cmd_done.device_id = device_id;
 	cmd_done.session_id = ((struct hal_session *) pkt->session_id)->
 		session_id;
 	cmd_done.status = VIDC_ERR_NONE;
@@ -136,39 +138,35 @@
 		} while (num_properties_changed > 0);
 	}
 	cmd_done.data = &event_notify;
-	device->callback(VIDC_EVENT_CHANGE, &cmd_done);
+	callback(VIDC_EVENT_CHANGE, &cmd_done);
 }
-static void hfi_process_sys_watchdog_timeout(struct venus_hfi_device *device)
-{
-	struct msm_vidc_cb_cmd_done cmd_done;
-	device->intr_status &= ~VIDC_WRAPPER_INTR_STATUS_A2HWD_BMSK;
-	memset(&cmd_done, 0, sizeof(struct msm_vidc_cb_cmd_done));
-	cmd_done.device_id = device->device_id;
-	device->callback(SYS_WATCHDOG_TIMEOUT, &cmd_done);
-}
-static void hfi_process_sys_error(struct venus_hfi_device *device)
+
+static void hfi_process_sys_error(
+		msm_vidc_callback callback, u32 device_id)
 {
 	struct msm_vidc_cb_cmd_done cmd_done;
 	memset(&cmd_done, 0, sizeof(struct msm_vidc_cb_cmd_done));
-	cmd_done.device_id = device->device_id;
-	device->callback(SYS_ERROR, &cmd_done);
+	cmd_done.device_id = device_id;
+	callback(SYS_ERROR, &cmd_done);
 }
-static void hfi_process_session_error(struct venus_hfi_device *device,
+static void hfi_process_session_error(
+		msm_vidc_callback callback, u32 device_id,
 		struct hfi_msg_event_notify_packet *pkt)
 {
 	struct msm_vidc_cb_cmd_done cmd_done;
 	memset(&cmd_done, 0, sizeof(struct msm_vidc_cb_cmd_done));
-	cmd_done.device_id = device->device_id;
+	cmd_done.device_id = device_id;
 	cmd_done.session_id = ((struct hal_session *) pkt->session_id)->
 		session_id;
-	device->callback(SESSION_ERROR, &cmd_done);
+	callback(SESSION_ERROR, &cmd_done);
 }
-static void hfi_process_event_notify(struct venus_hfi_device *device,
-	struct hfi_msg_event_notify_packet *pkt)
+static void hfi_process_event_notify(
+		msm_vidc_callback callback, u32 device_id,
+		struct hfi_msg_event_notify_packet *pkt)
 {
 	dprintk(VIDC_DBG, "RECVD:EVENT_NOTIFY");
 
-	if (!device || !pkt ||
+	if (!callback || !pkt ||
 		pkt->size < sizeof(struct hfi_msg_event_notify_packet)) {
 		dprintk(VIDC_ERR, "Invalid Params");
 		return;
@@ -178,15 +176,15 @@
 	case HFI_EVENT_SYS_ERROR:
 		dprintk(VIDC_ERR, "HFI_EVENT_SYS_ERROR: %d\n",
 			pkt->event_data1);
-		hfi_process_sys_error(device);
+		hfi_process_sys_error(callback, device_id);
 		break;
 	case HFI_EVENT_SESSION_ERROR:
 		dprintk(VIDC_ERR, "HFI_EVENT_SESSION_ERROR");
-		hfi_process_session_error(device, pkt);
+		hfi_process_session_error(callback, device_id, pkt);
 		break;
 	case HFI_EVENT_SESSION_SEQUENCE_CHANGED:
 		dprintk(VIDC_INFO, "HFI_EVENT_SESSION_SEQUENCE_CHANGED");
-		hfi_process_sess_evt_seq_changed(device, pkt);
+		hfi_process_sess_evt_seq_changed(callback, device_id, pkt);
 		break;
 	case HFI_EVENT_SESSION_PROPERTY_CHANGED:
 		dprintk(VIDC_INFO, "HFI_EVENT_SESSION_PROPERTY_CHANGED");
@@ -196,7 +194,8 @@
 		break;
 	}
 }
-static void hfi_process_sys_init_done(struct venus_hfi_device *device,
+static void hfi_process_sys_init_done(
+		msm_vidc_callback callback, u32 device_id,
 		struct hfi_msg_sys_init_done_packet *pkt)
 {
 	struct msm_vidc_cb_cmd_done cmd_done;
@@ -273,16 +272,17 @@
 		}
 	}
 err_no_prop:
-	cmd_done.device_id = device->device_id;
+	cmd_done.device_id = device_id;
 	cmd_done.session_id = 0;
 	cmd_done.status = (u32) status;
 	cmd_done.size = sizeof(struct vidc_hal_sys_init_done);
 	cmd_done.data = (void *) &sys_init_done;
-	device->callback(SYS_INIT_DONE, &cmd_done);
+	callback(SYS_INIT_DONE, &cmd_done);
 }
 
-static void hfi_process_sys_rel_resource_done(struct venus_hfi_device *device,
-	struct hfi_msg_sys_release_resource_done_packet *pkt)
+static void hfi_process_sys_rel_resource_done(
+		msm_vidc_callback callback, u32 device_id,
+		struct hfi_msg_sys_release_resource_done_packet *pkt)
 {
 	struct msm_vidc_cb_cmd_done cmd_done;
 	enum vidc_status status = VIDC_ERR_NONE;
@@ -297,12 +297,12 @@
 		return;
 	}
 	status = hfi_map_err_status((u32)pkt->error_type);
-	cmd_done.device_id = device->device_id;
+	cmd_done.device_id = device_id;
 	cmd_done.session_id = 0;
 	cmd_done.status = (u32) status;
 	cmd_done.size = 0;
 	cmd_done.data = NULL;
-	device->callback(RELEASE_RESOURCE_DONE, &cmd_done);
+	callback(RELEASE_RESOURCE_DONE, &cmd_done);
 }
 
 enum vidc_status hfi_process_sess_init_done_prop_read(
@@ -408,8 +408,9 @@
 	}
 }
 
-static void hfi_process_session_prop_info(struct venus_hfi_device *device,
-	struct hfi_msg_session_property_info_packet *pkt)
+static void hfi_process_session_prop_info(
+		msm_vidc_callback callback, u32 device_id,
+		struct hfi_msg_session_property_info_packet *pkt)
 {
 	struct msm_vidc_cb_cmd_done cmd_done;
 	struct buffer_requirements buff_req;
@@ -433,13 +434,13 @@
 	switch (pkt->rg_property_data[0]) {
 	case HFI_PROPERTY_CONFIG_BUFFER_REQUIREMENTS:
 		hfi_process_sess_get_prop_buf_req(pkt, &buff_req);
-		cmd_done.device_id = device->device_id;
+		cmd_done.device_id = device_id;
 		cmd_done.session_id =
 			((struct hal_session *) pkt->session_id)->session_id;
 		cmd_done.status = VIDC_ERR_NONE;
 		cmd_done.data = &buff_req;
 		cmd_done.size = sizeof(struct buffer_requirements);
-		device->callback(SESSION_PROPERTY_INFO, &cmd_done);
+		callback(SESSION_PROPERTY_INFO, &cmd_done);
 		break;
 	default:
 		dprintk(VIDC_ERR, "hal_process_session_prop_info:"
@@ -449,8 +450,9 @@
 	}
 }
 
-static void hfi_process_session_init_done(struct venus_hfi_device *device,
-	struct hfi_msg_sys_session_init_done_packet *pkt)
+static void hfi_process_session_init_done(
+		msm_vidc_callback callback, u32 device_id,
+		struct hfi_msg_sys_session_init_done_packet *pkt)
 {
 	struct msm_vidc_cb_cmd_done cmd_done;
 	struct vidc_hal_session_init_done session_init_done;
@@ -466,7 +468,7 @@
 	memset(&session_init_done, 0, sizeof(struct
 				vidc_hal_session_init_done));
 
-	cmd_done.device_id = device->device_id;
+	cmd_done.device_id = device_id;
 	cmd_done.session_id =
 		((struct hal_session *) pkt->session_id)->session_id;
 	cmd_done.status = hfi_map_err_status((u32)pkt->error_type);
@@ -476,11 +478,12 @@
 			pkt, &cmd_done);
 	}
 	cmd_done.size = sizeof(struct vidc_hal_session_init_done);
-	device->callback(SESSION_INIT_DONE, &cmd_done);
+	callback(SESSION_INIT_DONE, &cmd_done);
 }
 
-static void hfi_process_session_load_res_done(struct venus_hfi_device *device,
-	struct hfi_msg_session_load_resources_done_packet *pkt)
+static void hfi_process_session_load_res_done(
+		msm_vidc_callback callback, u32 device_id,
+		struct hfi_msg_session_load_resources_done_packet *pkt)
 {
 	struct msm_vidc_cb_cmd_done cmd_done;
 	dprintk(VIDC_DBG, "RECEIVED:SESSION_LOAD_RESOURCES_DONE");
@@ -494,17 +497,18 @@
 
 	memset(&cmd_done, 0, sizeof(struct msm_vidc_cb_cmd_done));
 
-	cmd_done.device_id = device->device_id;
+	cmd_done.device_id = device_id;
 	cmd_done.session_id =
 		((struct hal_session *) pkt->session_id)->session_id;
 	cmd_done.status = hfi_map_err_status((u32)pkt->error_type);
 	cmd_done.data = NULL;
 	cmd_done.size = 0;
-	device->callback(SESSION_LOAD_RESOURCE_DONE, &cmd_done);
+	callback(SESSION_LOAD_RESOURCE_DONE, &cmd_done);
 }
 
-static void hfi_process_session_flush_done(struct venus_hfi_device *device,
-	struct hfi_msg_session_flush_done_packet *pkt)
+static void hfi_process_session_flush_done(
+		msm_vidc_callback callback, u32 device_id,
+		struct hfi_msg_session_flush_done_packet *pkt)
 {
 	struct msm_vidc_cb_cmd_done cmd_done;
 
@@ -517,17 +521,18 @@
 	}
 
 	memset(&cmd_done, 0, sizeof(struct msm_vidc_cb_cmd_done));
-	cmd_done.device_id = device->device_id;
+	cmd_done.device_id = device_id;
 	cmd_done.session_id =
 		((struct hal_session *) pkt->session_id)->session_id;
 	cmd_done.status = hfi_map_err_status((u32)pkt->error_type);
 	cmd_done.data = (void *) pkt->flush_type;
 	cmd_done.size = sizeof(u32);
-	device->callback(SESSION_FLUSH_DONE, &cmd_done);
+	callback(SESSION_FLUSH_DONE, &cmd_done);
 }
 
-static void hfi_process_session_etb_done(struct venus_hfi_device *device,
-	struct hfi_msg_session_empty_buffer_done_packet *pkt)
+static void hfi_process_session_etb_done(
+		msm_vidc_callback callback, u32 device_id,
+		struct hfi_msg_session_empty_buffer_done_packet *pkt)
 {
 	struct msm_vidc_cb_data_done data_done;
 
@@ -541,7 +546,7 @@
 
 	memset(&data_done, 0, sizeof(struct msm_vidc_cb_data_done));
 
-	data_done.device_id = device->device_id;
+	data_done.device_id = device_id;
 	data_done.session_id =
 		((struct hal_session *) pkt->session_id)->session_id;
 	data_done.status = hfi_map_err_status((u32) pkt->error_type);
@@ -550,11 +555,12 @@
 	data_done.input_done.offset = pkt->offset;
 	data_done.input_done.filled_len = pkt->filled_len;
 	data_done.input_done.packet_buffer = pkt->packet_buffer;
-	device->callback(SESSION_ETB_DONE, &data_done);
+	callback(SESSION_ETB_DONE, &data_done);
 }
 
-static void hfi_process_session_ftb_done(struct venus_hfi_device *device,
-			void *msg_hdr)
+static void hfi_process_session_ftb_done(
+		msm_vidc_callback callback, u32 device_id,
+		void *msg_hdr)
 {
 	struct msm_vidc_cb_data_done data_done;
 	struct hfi_msg_session_fill_buffer_done_compressed_packet *pack =
@@ -590,7 +596,7 @@
 			/* Proceed with the FBD */
 		}
 
-		data_done.device_id = device->device_id;
+		data_done.device_id = device_id;
 		data_done.session_id = (u32) session;
 		data_done.status = hfi_map_err_status((u32)
 							pkt->error_type);
@@ -624,7 +630,7 @@
 			return;
 		}
 
-		data_done.device_id = device->device_id;
+		data_done.device_id = device_id;
 		data_done.session_id = (u32) session;
 		data_done.status = hfi_map_err_status((u32)
 			pkt->error_type);
@@ -657,11 +663,12 @@
 		else if (pkt->stream_id == 1)
 			data_done.output_done.buffer_type = HAL_BUFFER_OUTPUT2;
 		}
-	device->callback(SESSION_FTB_DONE, &data_done);
+	callback(SESSION_FTB_DONE, &data_done);
 }
 
-static void hfi_process_session_start_done(struct venus_hfi_device *device,
-	struct hfi_msg_session_start_done_packet *pkt)
+static void hfi_process_session_start_done(
+		msm_vidc_callback callback, u32 device_id,
+		struct hfi_msg_session_start_done_packet *pkt)
 {
 	struct msm_vidc_cb_cmd_done cmd_done;
 
@@ -675,17 +682,18 @@
 	}
 
 	memset(&cmd_done, 0, sizeof(struct msm_vidc_cb_cmd_done));
-	cmd_done.device_id = device->device_id;
+	cmd_done.device_id = device_id;
 	cmd_done.session_id =
 		((struct hal_session *) pkt->session_id)->session_id;
 	cmd_done.status = hfi_map_err_status((u32)pkt->error_type);
 	cmd_done.data = NULL;
 	cmd_done.size = 0;
-	device->callback(SESSION_START_DONE, &cmd_done);
+	callback(SESSION_START_DONE, &cmd_done);
 }
 
-static void hfi_process_session_stop_done(struct venus_hfi_device *device,
-	struct hfi_msg_session_stop_done_packet *pkt)
+static void hfi_process_session_stop_done(
+		msm_vidc_callback callback, u32 device_id,
+		struct hfi_msg_session_stop_done_packet *pkt)
 {
 	struct msm_vidc_cb_cmd_done cmd_done;
 
@@ -699,17 +707,18 @@
 	}
 
 	memset(&cmd_done, 0, sizeof(struct msm_vidc_cb_cmd_done));
-	cmd_done.device_id = device->device_id;
+	cmd_done.device_id = device_id;
 	cmd_done.session_id =
 		((struct hal_session *) pkt->session_id)->session_id;
 	cmd_done.status = hfi_map_err_status((u32)pkt->error_type);
 	cmd_done.data = NULL;
 	cmd_done.size = 0;
-	device->callback(SESSION_STOP_DONE, &cmd_done);
+	callback(SESSION_STOP_DONE, &cmd_done);
 }
 
-static void hfi_process_session_rel_res_done(struct venus_hfi_device *device,
-	struct hfi_msg_session_release_resources_done_packet *pkt)
+static void hfi_process_session_rel_res_done(
+		msm_vidc_callback callback, u32 device_id,
+		struct hfi_msg_session_release_resources_done_packet *pkt)
 {
 	struct msm_vidc_cb_cmd_done cmd_done;
 
@@ -723,17 +732,18 @@
 	}
 
 	memset(&cmd_done, 0, sizeof(struct msm_vidc_cb_cmd_done));
-	cmd_done.device_id = device->device_id;
+	cmd_done.device_id = device_id;
 	cmd_done.session_id =
 		((struct hal_session *) pkt->session_id)->session_id;
 	cmd_done.status = hfi_map_err_status((u32)pkt->error_type);
 	cmd_done.data = NULL;
 	cmd_done.size = 0;
-	device->callback(SESSION_RELEASE_RESOURCE_DONE, &cmd_done);
+	callback(SESSION_RELEASE_RESOURCE_DONE, &cmd_done);
 }
 
-static void hfi_process_session_rel_buf_done(struct venus_hfi_device *device,
-	struct hfi_msg_session_release_buffers_done_packet *pkt)
+static void hfi_process_session_rel_buf_done(
+		msm_vidc_callback callback, u32 device_id,
+		struct hfi_msg_session_release_buffers_done_packet *pkt)
 {
 	struct msm_vidc_cb_cmd_done cmd_done;
 	if (!pkt || pkt->size !=
@@ -743,7 +753,7 @@
 		return;
 	}
 	memset(&cmd_done, 0, sizeof(struct msm_vidc_cb_cmd_done));
-	cmd_done.device_id = device->device_id;
+	cmd_done.device_id = device_id;
 	cmd_done.size = sizeof(struct msm_vidc_cb_cmd_done);
 	cmd_done.session_id =
 		((struct hal_session *) pkt->session_id)->session_id;
@@ -754,11 +764,12 @@
 	} else {
 		dprintk(VIDC_ERR, "invalid payload in rel_buff_done\n");
 	}
-	device->callback(SESSION_RELEASE_BUFFER_DONE, &cmd_done);
+	callback(SESSION_RELEASE_BUFFER_DONE, &cmd_done);
 }
 
-static void hfi_process_session_end_done(struct venus_hfi_device *device,
-	struct hfi_msg_sys_session_end_done_packet *pkt)
+static void hfi_process_session_end_done(
+		msm_vidc_callback callback, u32 device_id,
+		struct hfi_msg_sys_session_end_done_packet *pkt)
 {
 	struct msm_vidc_cb_cmd_done cmd_done;
 	struct hal_session *sess_close;
@@ -779,17 +790,17 @@
 	kfree(sess_close);
 
 	memset(&cmd_done, 0, sizeof(struct msm_vidc_cb_cmd_done));
-	cmd_done.device_id = device->device_id;
+	cmd_done.device_id = device_id;
 	cmd_done.session_id =
 		((struct hal_session *) pkt->session_id)->session_id;
 	cmd_done.status = hfi_map_err_status((u32)pkt->error_type);
 	cmd_done.data = NULL;
 	cmd_done.size = 0;
-	device->callback(SESSION_END_DONE, &cmd_done);
+	callback(SESSION_END_DONE, &cmd_done);
 }
 
 static void hfi_process_session_get_seq_hdr_done(
-	struct venus_hfi_device *device,
+	msm_vidc_callback callback, u32 device_id,
 	struct hfi_msg_session_get_sequence_header_done_packet *pkt)
 {
 	struct msm_vidc_cb_data_done data_done;
@@ -800,7 +811,7 @@
 		return;
 	}
 	memset(&data_done, 0, sizeof(struct msm_vidc_cb_data_done));
-	data_done.device_id = device->device_id;
+	data_done.device_id = device_id;
 	data_done.size = sizeof(struct msm_vidc_cb_data_done);
 	data_done.session_id =
 		((struct hal_session *) pkt->session_id)->session_id;
@@ -809,121 +820,99 @@
 	data_done.output_done.filled_len1 = pkt->header_len;
 	dprintk(VIDC_INFO, "seq_hdr: %p, Length: %d",
 		   pkt->sequence_header, pkt->header_len);
-	device->callback(SESSION_GET_SEQ_HDR_DONE, &data_done);
+	callback(SESSION_GET_SEQ_HDR_DONE, &data_done);
 }
 
-static void hfi_process_msg_packet(struct venus_hfi_device *device,
-	struct vidc_hal_msg_pkt_hdr *msg_hdr)
+void hfi_process_msg_packet(
+		msm_vidc_callback callback, u32 device_id,
+		struct vidc_hal_msg_pkt_hdr *msg_hdr)
 {
-	if (!device || !msg_hdr || msg_hdr->size <
-		VIDC_IFACEQ_MIN_PKT_SIZE) {
+	if (!callback || !msg_hdr || msg_hdr->size <
+		HFI_MIN_PKT_SIZE) {
 		dprintk(VIDC_ERR, "hal_process_msg_packet:bad"
 			"packet/packet size: %d", msg_hdr->size);
 		return;
 	}
 
 	dprintk(VIDC_INFO, "Received: 0x%x in ", msg_hdr->packet);
-	if ((device->intr_status & VIDC_WRAPPER_INTR_CLEAR_A2HWD_BMSK)) {
-		dprintk(VIDC_ERR, "Received: Watchdog timeout %s", __func__);
-		hfi_process_sys_watchdog_timeout(device);
-		return;
-	}
 
 	switch (msg_hdr->packet) {
 	case HFI_MSG_EVENT_NOTIFY:
-		hfi_process_event_notify(device,
+		hfi_process_event_notify(callback, device_id,
 			(struct hfi_msg_event_notify_packet *) msg_hdr);
 		break;
 	case  HFI_MSG_SYS_INIT_DONE:
-		hfi_process_sys_init_done(device,
+		hfi_process_sys_init_done(callback, device_id,
 			(struct hfi_msg_sys_init_done_packet *)
 					msg_hdr);
 		break;
 	case HFI_MSG_SYS_SESSION_INIT_DONE:
-		hfi_process_session_init_done(device,
+		hfi_process_session_init_done(callback, device_id,
 			(struct hfi_msg_sys_session_init_done_packet *)
 					msg_hdr);
 		break;
 	case HFI_MSG_SYS_SESSION_END_DONE:
-		hfi_process_session_end_done(device,
+		hfi_process_session_end_done(callback, device_id,
 			(struct hfi_msg_sys_session_end_done_packet *)
 					msg_hdr);
 		break;
 	case HFI_MSG_SESSION_LOAD_RESOURCES_DONE:
-		hfi_process_session_load_res_done(device,
+		hfi_process_session_load_res_done(callback, device_id,
 			(struct hfi_msg_session_load_resources_done_packet *)
 					msg_hdr);
 		break;
 	case HFI_MSG_SESSION_START_DONE:
-		hfi_process_session_start_done(device,
+		hfi_process_session_start_done(callback, device_id,
 			(struct hfi_msg_session_start_done_packet *)
 					msg_hdr);
 		break;
 	case HFI_MSG_SESSION_STOP_DONE:
-		hfi_process_session_stop_done(device,
+		hfi_process_session_stop_done(callback, device_id,
 			(struct hfi_msg_session_stop_done_packet *)
 					msg_hdr);
 		break;
 	case HFI_MSG_SESSION_EMPTY_BUFFER_DONE:
-		hfi_process_session_etb_done(device,
+		hfi_process_session_etb_done(callback, device_id,
 			(struct hfi_msg_session_empty_buffer_done_packet *)
 					msg_hdr);
 		break;
 	case HFI_MSG_SESSION_FILL_BUFFER_DONE:
-		hfi_process_session_ftb_done(device, msg_hdr);
+		hfi_process_session_ftb_done(callback, device_id, msg_hdr);
 		break;
 	case HFI_MSG_SESSION_FLUSH_DONE:
-		hfi_process_session_flush_done(device,
+		hfi_process_session_flush_done(callback, device_id,
 			(struct hfi_msg_session_flush_done_packet *)
 					msg_hdr);
 		break;
 	case HFI_MSG_SESSION_PROPERTY_INFO:
-		hfi_process_session_prop_info(device,
+		hfi_process_session_prop_info(callback, device_id,
 			(struct hfi_msg_session_property_info_packet *)
 					msg_hdr);
 		break;
 	case HFI_MSG_SESSION_RELEASE_RESOURCES_DONE:
-		hfi_process_session_rel_res_done(device,
+		hfi_process_session_rel_res_done(callback, device_id,
 			(struct hfi_msg_session_release_resources_done_packet *)
 					msg_hdr);
 		break;
 	case HFI_MSG_SYS_RELEASE_RESOURCE:
-		hfi_process_sys_rel_resource_done(device,
+		hfi_process_sys_rel_resource_done(callback, device_id,
 			(struct hfi_msg_sys_release_resource_done_packet *)
 			msg_hdr);
 		break;
 	case HFI_MSG_SESSION_GET_SEQUENCE_HEADER_DONE:
-		hfi_process_session_get_seq_hdr_done(device, (struct
-			hfi_msg_session_get_sequence_header_done_packet
-			 *) msg_hdr);
+		hfi_process_session_get_seq_hdr_done(
+			callback, device_id, (struct
+			hfi_msg_session_get_sequence_header_done_packet*)
+			msg_hdr);
 		break;
 	case HFI_MSG_SESSION_RELEASE_BUFFERS_DONE:
-		hfi_process_session_rel_buf_done(device, (struct
-			hfi_msg_session_release_buffers_done_packet
-			*) msg_hdr);
+		hfi_process_session_rel_buf_done(
+			callback, device_id, (struct
+			hfi_msg_session_release_buffers_done_packet*)
+			msg_hdr);
 		break;
 	default:
 		dprintk(VIDC_ERR, "UNKNOWN_MSG_TYPE : %d", msg_hdr->packet);
 		break;
 	}
 }
-
-void hfi_response_handler(struct venus_hfi_device *device)
-{
-	u8 packet[VIDC_IFACEQ_MED_PKT_SIZE];
-
-	dprintk(VIDC_INFO, "#####vidc_hal_response_handler#####\n");
-	if (device) {
-		while (!venus_hfi_iface_msgq_read(device, packet)) {
-			hfi_process_msg_packet(device,
-				(struct vidc_hal_msg_pkt_hdr *) packet);
-		}
-		while (!venus_hfi_iface_dbgq_read(device, packet)) {
-			struct hfi_msg_sys_debug_packet *pkt =
-				(struct hfi_msg_sys_debug_packet *) packet;
-			dprintk(VIDC_FW, "FW-SAYS: %s", pkt->rg_msg_data);
-		}
-	} else {
-		dprintk(VIDC_ERR, "SPURIOUS_INTERRUPT");
-	}
-}
diff --git a/drivers/media/video/msm_vidc/msm_v4l2_vidc.c b/drivers/media/video/msm_vidc/msm_v4l2_vidc.c
index e51896c..4f39357 100644
--- a/drivers/media/video/msm_vidc/msm_v4l2_vidc.c
+++ b/drivers/media/video/msm_vidc/msm_v4l2_vidc.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -29,7 +29,7 @@
 #include "msm_vidc_debug.h"
 #include "vidc_hfi_api.h"
 #include "msm_smem.h"
-#include "venus_hfi.h"
+#include "vidc_hfi_api.h"
 
 #define BASE_DEVICE_NUMBER 32
 
@@ -355,7 +355,8 @@
 	int i, rc = 0;
 	int smem_flags = 0;
 	int domain;
-	struct venus_hfi_device *device;
+	struct hfi_device *hdev;
+
 	vidc_inst = get_vidc_inst(file, fh);
 	v4l2_inst = get_v4l2_inst(file, fh);
 	if (!v4l2_inst || !vidc_inst || !vidc_inst->core
@@ -364,7 +365,8 @@
 		goto exit;
 	}
 
-	device = vidc_inst->core->device;
+	hdev = vidc_inst->core->device;
+
 	if (!v4l2_inst->mem_client) {
 		dprintk(VIDC_ERR, "Failed to get memory client\n");
 		rc = -ENOMEM;
@@ -404,9 +406,11 @@
 				&& (!EXTRADATA_IDX(b->length)
 					|| (i != EXTRADATA_IDX(b->length)))) {
 			smem_flags |= SMEM_SECURE;
-			domain = venus_hfi_get_domain(device, CP_MAP);
+			domain = hdev->get_domain(hdev->hfi_device_data,
+						CP_MAP);
 		} else
-			domain = venus_hfi_get_domain(device, NS_MAP);
+			domain = hdev->get_domain(hdev->hfi_device_data,
+						NS_MAP);
 
 		if (b->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)
 			smem_flags |= SMEM_INPUT;
@@ -667,6 +671,30 @@
 {
 }
 
+static int msm_vidc_get_hfi(struct platform_device *pdev,
+			struct msm_vidc_core *core)
+{
+	struct device_node *np = pdev->dev.of_node;
+	int rc = 0;
+	const char *hfi_name = NULL;
+
+	rc = of_property_read_string(np, "hfi", &hfi_name);
+	if (rc) {
+		dprintk(VIDC_ERR, "Failed to read hfi from device tree\n");
+		goto err_hfi_read;
+	}
+
+	if (!strcmp(hfi_name, "venus"))
+		core->hfi_type = VIDC_HFI_VENUS;
+	else if (!strcmp(hfi_name, "q6"))
+		core->hfi_type = VIDC_HFI_Q6;
+
+	dprintk(VIDC_INFO, "hfi_type = %d\n", core->hfi_type);
+
+err_hfi_read:
+	return rc;
+}
+
 static int msm_vidc_initialize_core(struct platform_device *pdev,
 				struct msm_vidc_core *core)
 {
@@ -685,6 +713,11 @@
 		init_completion(&core->completions[i]);
 	}
 
+	rc = msm_vidc_get_hfi(pdev, core);
+	if (rc)
+		dprintk(VIDC_ERR,
+			"Failed to read Host-Firmware Interface rc: %d\n", rc);
+
 	return rc;
 }
 
@@ -736,8 +769,8 @@
 	}
 	video_set_drvdata(&core->vdev[MSM_VIDC_ENCODER].vdev, core);
 
-	core->device =
-		venus_hfi_get_device(core->id, pdev, &handle_cmd_response);
+	core->device = vidc_hfi_initialize(core->hfi_type, core->id,
+				pdev, &handle_cmd_response);
 	if (!core->device) {
 		dprintk(VIDC_ERR, "Failed to create HFI device\n");
 		goto err_cores_exceeded;
@@ -774,9 +807,20 @@
 static int __devexit msm_vidc_remove(struct platform_device *pdev)
 {
 	int rc = 0;
-	struct msm_vidc_core *core = pdev->dev.platform_data;
+	struct msm_vidc_core *core;
 
-	venus_hfi_delete_device(core->device);
+	if (!pdev) {
+		dprintk(VIDC_ERR, "%s invalid input %p", __func__, pdev);
+		return -EINVAL;
+	}
+	core = pdev->dev.platform_data;
+
+	if (!core) {
+		dprintk(VIDC_ERR, "%s invalid core", __func__);
+		return -EINVAL;
+	}
+
+	vidc_hfi_deinitialize(core->hfi_type, core->device);
 	video_unregister_device(&core->vdev[MSM_VIDC_ENCODER].vdev);
 	video_unregister_device(&core->vdev[MSM_VIDC_DECODER].vdev);
 	v4l2_device_unregister(&core->v4l2_dev);
diff --git a/drivers/media/video/msm_vidc/msm_vdec.c b/drivers/media/video/msm_vidc/msm_vdec.c
index 525bad8..24407dd 100644
--- a/drivers/media/video/msm_vidc/msm_vdec.c
+++ b/drivers/media/video/msm_vidc/msm_vdec.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -377,6 +377,14 @@
 	struct vidc_buffer_addr_info buffer_info;
 	int extra_idx = 0;
 	int i;
+	struct hfi_device *hdev;
+
+	if (!inst || !inst->core || !inst->core->device) {
+		dprintk(VIDC_ERR, "%s invalid parameters", __func__);
+		return -EINVAL;
+	}
+	hdev = inst->core->device;
+
 	switch (b->type) {
 	case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
 		break;
@@ -415,7 +423,7 @@
 				buffer_info.extradata_addr = 0;
 				buffer_info.extradata_size = 0;
 			}
-			rc = venus_hfi_session_set_buffers(
+			rc = hdev->session_set_buffers(
 				(void *)inst->session, &buffer_info);
 			if (rc)
 				dprintk(VIDC_ERR,
@@ -436,6 +444,15 @@
 	struct msm_vidc_core *core = inst->core;
 	int extra_idx = 0;
 	int i;
+	struct hfi_device *hdev;
+
+	if (!inst || !inst->core || !inst->core->device) {
+		dprintk(VIDC_ERR, "%s invalid parameters", __func__);
+		return -EINVAL;
+	}
+
+	hdev = inst->core->device;
+
 	if (inst->state == MSM_VIDC_CORE_INVALID ||
 			core->state == VIDC_CORE_INVALID) {
 		dprintk(VIDC_ERR,
@@ -484,7 +501,7 @@
 			else
 				buffer_info.extradata_addr = 0;
 			buffer_info.response_required = false;
-			rc = venus_hfi_session_release_buffers(
+			rc = hdev->session_release_buffers(
 					(void *)inst->session, &buffer_info);
 			if (rc)
 				dprintk(VIDC_ERR,
@@ -809,6 +826,7 @@
 	unsigned long flags;
 	struct hal_buffer_requirements *bufreq;
 	int extra_idx = 0;
+	struct hfi_device *hdev;
 	if (!q || !num_buffers || !num_planes
 		|| !sizes || !q->drv_priv) {
 		dprintk(VIDC_ERR, "Invalid input, q = %p, %p, %p\n",
@@ -816,6 +834,14 @@
 		return -EINVAL;
 	}
 	inst = q->drv_priv;
+
+	if (!inst || !inst->core || !inst->core->device) {
+		dprintk(VIDC_ERR, "%s invalid parameters", __func__);
+		return -EINVAL;
+	}
+
+	hdev = inst->core->device;
+
 	switch (q->type) {
 	case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
 		*num_planes = inst->fmts[OUTPUT_PORT]->num_planes;
@@ -851,7 +877,7 @@
 
 			new_buf_count.buffer_type = HAL_BUFFER_OUTPUT;
 			new_buf_count.buffer_count_actual = *num_buffers;
-			rc = venus_hfi_session_set_property(inst->session,
+			rc = hdev->session_set_property(inst->session,
 					property_id, &new_buf_count);
 
 		}
@@ -1088,6 +1114,13 @@
 	enum hal_property property_id = 0;
 	u32 property_val = 0;
 	void *pdata;
+	struct hfi_device *hdev;
+
+	if (!inst || !inst->core || !inst->core->device) {
+		dprintk(VIDC_ERR, "%s invalid parameters", __func__);
+		return -EINVAL;
+	}
+	hdev = inst->core->device;
 
 	switch (ctrl->id) {
 	case V4L2_CID_MPEG_VIDC_VIDEO_STREAM_FORMAT:
@@ -1166,7 +1199,7 @@
 			property_id,
 			msm_vdec_ctrls[control_idx].id,
 			control.value);
-			rc = venus_hfi_session_set_property((void *)
+			rc = hdev->session_set_property((void *)
 				inst->session, property_id,
 					pdata);
 	}
diff --git a/drivers/media/video/msm_vidc/msm_venc.c b/drivers/media/video/msm_vidc/msm_venc.c
index 341e06f..0326c79 100644
--- a/drivers/media/video/msm_vidc/msm_venc.c
+++ b/drivers/media/video/msm_vidc/msm_venc.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -611,11 +611,19 @@
 	struct hal_buffer_count_actual new_buf_count;
 	enum hal_property property_id;
 	unsigned long flags;
+	struct hfi_device *hdev;
 	if (!q || !q->drv_priv) {
 		dprintk(VIDC_ERR, "Invalid input, q = %p\n", q);
 		return -EINVAL;
 	}
 	inst = q->drv_priv;
+
+	if (!inst || !inst->core || !inst->core->device) {
+		dprintk(VIDC_ERR, "%s invalid parameters", __func__);
+		return -EINVAL;
+	}
+	hdev = inst->core->device;
+
 	switch (q->type) {
 	case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
 		*num_planes = 1;
@@ -648,7 +656,7 @@
 		property_id = HAL_PARAM_BUFFER_COUNT_ACTUAL;
 		new_buf_count.buffer_type = HAL_BUFFER_INPUT;
 		new_buf_count.buffer_count_actual = *num_buffers;
-		rc = venus_hfi_session_set_property(inst->session,
+		rc = hdev->session_set_property(inst->session,
 					property_id, &new_buf_count);
 		dprintk(VIDC_DBG, "size = %d, alignment = %d, count = %d\n",
 				inst->buff_req.buffer[0].buffer_size,
@@ -966,6 +974,13 @@
 	u32 property_id = 0, property_val = 0;
 	void *pdata;
 	struct v4l2_ctrl *temp_ctrl = NULL;
+	struct hfi_device *hdev;
+
+	if (!inst || !inst->core || !inst->core->device) {
+		dprintk(VIDC_ERR, "%s invalid parameters", __func__);
+		return -EINVAL;
+	}
+	hdev = inst->core->device;
 
 	/* Small helper macro for quickly getting a control and err checking */
 #define TRY_GET_CTRL(__ctrl_id) ({ \
@@ -1104,6 +1119,7 @@
 		property_id =
 			HAL_CONFIG_VENC_TARGET_BITRATE;
 		bitrate.bit_rate = ctrl->val;
+		bitrate.layer_id = 0;
 		pdata = &bitrate;
 		break;
 	case V4L2_CID_MPEG_VIDEO_H264_ENTROPY_MODE:
@@ -1218,6 +1234,7 @@
 		quantization.qpi = ctrl->val;
 		quantization.qpp = qpp->val;
 		quantization.qpb = qpb->val;
+		quantization.layer_id = 0;
 
 		pdata = &quantization;
 		break;
@@ -1233,6 +1250,7 @@
 		quantization.qpp = ctrl->val;
 		quantization.qpi = qpi->val;
 		quantization.qpb = qpb->val;
+		quantization.layer_id = 0;
 
 		pdata = &quantization;
 		break;
@@ -1248,6 +1266,7 @@
 		quantization.qpb = ctrl->val;
 		quantization.qpi = qpi->val;
 		quantization.qpp = qpp->val;
+		quantization.layer_id = 0;
 
 		pdata = &quantization;
 		break;
@@ -1405,7 +1424,7 @@
 		dprintk(VIDC_DBG, "Control: HAL property=%d,ctrl_value=%d\n",
 				property_id,
 				ctrl->val);
-		rc = venus_hfi_session_set_property((void *)inst->session,
+		rc = hdev->session_set_property((void *)inst->session,
 				property_id, pdata);
 	}
 
@@ -1570,6 +1589,14 @@
 	void *pdata;
 	int rc = 0;
 	struct hal_frame_rate frame_rate;
+	struct hfi_device *hdev;
+
+	if (!inst || !inst->core || !inst->core->device) {
+		dprintk(VIDC_ERR, "%s invalid parameters", __func__);
+		return -EINVAL;
+	}
+	hdev = inst->core->device;
+
 	property_id = HAL_CONFIG_FRAME_RATE;
 	if (a->parm.output.timeperframe.denominator) {
 		switch (a->type) {
@@ -1597,7 +1624,7 @@
 		frame_rate.frame_rate = inst->prop.fps * (0x1<<16);
 		frame_rate.buffer_type = HAL_BUFFER_OUTPUT;
 		pdata = &frame_rate;
-		rc = venus_hfi_session_set_property((void *)inst->session,
+		rc = hdev->session_set_property((void *)inst->session,
 				property_id, pdata);
 		if (rc) {
 			dprintk(VIDC_WARN,
@@ -1614,11 +1641,19 @@
 	struct hal_frame_size frame_sz;
 	int rc = 0;
 	int i;
+	struct hfi_device *hdev;
 	if (!inst || !f) {
 		dprintk(VIDC_ERR,
 			"Invalid input, inst = %p, format = %p\n", inst, f);
 		return -EINVAL;
 	}
+
+	if (!inst->core || !inst->core->device) {
+		dprintk(VIDC_ERR, "%s invalid parameters", __func__);
+		return -EINVAL;
+	}
+	hdev = inst->core->device;
+
 	if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
 		fmt = msm_comm_get_pixel_fmt_fourcc(venc_formats,
 			ARRAY_SIZE(venc_formats), f->fmt.pix_mp.pixelformat,
@@ -1638,7 +1673,7 @@
 		frame_sz.height = inst->prop.height;
 		dprintk(VIDC_DBG, "width = %d, height = %d\n",
 				frame_sz.width, frame_sz.height);
-		rc = venus_hfi_session_set_property((void *)inst->session,
+		rc = hdev->session_set_property((void *)inst->session,
 				HAL_PARAM_FRAME_SIZE, &frame_sz);
 		if (rc) {
 			dprintk(VIDC_ERR,
@@ -1646,7 +1681,7 @@
 			goto exit;
 		}
 		frame_sz.buffer_type = HAL_BUFFER_OUTPUT;
-		rc = venus_hfi_session_set_property((void *)inst->session,
+		rc = hdev->session_set_property((void *)inst->session,
 				HAL_PARAM_FRAME_SIZE, &frame_sz);
 		if (rc) {
 			dprintk(VIDC_ERR,
@@ -1752,6 +1787,14 @@
 	int rc = 0;
 	int i;
 	struct vidc_buffer_addr_info buffer_info;
+	struct hfi_device *hdev;
+
+	if (!inst || !inst->core || !inst->core->device) {
+		dprintk(VIDC_ERR, "%s invalid parameters", __func__);
+		return -EINVAL;
+	}
+
+	hdev = inst->core->device;
 
 	switch (b->type) {
 	case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
@@ -1769,7 +1812,7 @@
 				b->m.planes[i].m.userptr;
 			buffer_info.extradata_size = 0;
 			buffer_info.extradata_addr = 0;
-			rc = venus_hfi_session_set_buffers(
+			rc = hdev->session_set_buffers(
 				(void *)inst->session, &buffer_info);
 			if (rc)
 				dprintk(VIDC_ERR,
@@ -1790,6 +1833,15 @@
 	int rc = 0;
 	int i;
 	struct vidc_buffer_addr_info buffer_info;
+	struct hfi_device *hdev;
+
+	if (!inst || !inst->core || !inst->core->device) {
+		dprintk(VIDC_ERR, "%s invalid parameters", __func__);
+		return -EINVAL;
+	}
+
+	hdev = inst->core->device;
+
 	rc = msm_comm_try_state(inst, MSM_VIDC_RELEASE_RESOURCES_DONE);
 	if (rc) {
 		dprintk(VIDC_ERR,
@@ -1814,7 +1866,7 @@
 			buffer_info.extradata_size = 0;
 			buffer_info.extradata_addr = 0;
 			buffer_info.response_required = false;
-			rc = venus_hfi_session_release_buffers(
+			rc = hdev->session_release_buffers(
 				(void *)inst->session, &buffer_info);
 			if (rc)
 				dprintk(VIDC_ERR,
diff --git a/drivers/media/video/msm_vidc/msm_vidc.c b/drivers/media/video/msm_vidc/msm_vidc.c
index b9f1508..73c9860 100644
--- a/drivers/media/video/msm_vidc/msm_vidc.c
+++ b/drivers/media/video/msm_vidc/msm_vidc.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -21,7 +21,7 @@
 #include "msm_vidc_common.h"
 #include "msm_smem.h"
 #include <linux/delay.h>
-#include "venus_hfi.h"
+#include "vidc_hfi_api.h"
 
 #define MAX_EVENTS 30
 
@@ -86,11 +86,14 @@
 		struct msm_vidc_iommu_info maps[MAX_MAP])
 {
 	struct msm_vidc_inst *inst = instance;
+	struct hfi_device *hdev;
 
-	if (!inst || !maps || !inst->core)
+	if (!inst || !maps || !inst->core || !inst->core->device)
 		return -EINVAL;
 
-	return venus_hfi_iommu_get_map(inst->core->device, maps);
+	hdev = inst->core->device;
+
+	return hdev->iommu_get_map(hdev->hfi_device_data, maps);
 }
 
 int msm_vidc_querycap(void *instance, struct v4l2_capability *cap)
diff --git a/drivers/media/video/msm_vidc/msm_vidc_common.c b/drivers/media/video/msm_vidc/msm_vidc_common.c
index eac715f..955f4ca 100644
--- a/drivers/media/video/msm_vidc/msm_vidc_common.c
+++ b/drivers/media/video/msm_vidc/msm_vidc_common.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -20,7 +20,6 @@
 #include "vidc_hfi_api.h"
 #include "msm_smem.h"
 #include "msm_vidc_debug.h"
-#include "venus_hfi.h"
 
 #define HW_RESPONSE_TIMEOUT (5 * 60 * 1000)
 
@@ -77,14 +76,22 @@
 {
 	int load;
 	int rc = 0;
+	struct hfi_device *hdev;
 
 	if (!core || type >= MSM_VIDC_MAX_DEVICES) {
 		dprintk(VIDC_ERR, "Invalid args: %p, %d\n", core, type);
 		return -EINVAL;
 	}
+
+	hdev = core->device;
+	if (!hdev) {
+		dprintk(VIDC_ERR, "Invalid device handle %p\n", hdev);
+		return -EINVAL;
+	}
+
 	load = msm_comm_get_load(core, type);
 
-	rc = venus_hfi_scale_bus(core->device, load, type, mtype);
+	rc = hdev->scale_bus(hdev->hfi_device_data, load, type, mtype);
 	if (rc)
 		dprintk(VIDC_ERR, "Failed to scale bus: %d\n", rc);
 
@@ -95,14 +102,23 @@
 	enum mem_type mtype)
 {
 	int i;
+	struct hfi_device *hdev;
+
+	if (!core || !core->device) {
+		dprintk(VIDC_ERR, "%s invalid parameters", __func__);
+		return;
+	}
+	hdev = core->device;
+
 	for (i = 0; i < MSM_VIDC_MAX_DEVICES; i++) {
 		if ((mtype & DDR_MEM) &&
-			venus_hfi_scale_bus(core->device, 0, i, DDR_MEM)) {
+			hdev->scale_bus(hdev->hfi_device_data, 0, i, DDR_MEM)) {
 			dprintk(VIDC_WARN,
 				"Failed to unvote for DDR accesses\n");
 		}
 		if ((mtype & OCMEM_MEM) &&
-			venus_hfi_scale_bus(core->device, 0, i, OCMEM_MEM)) {
+			hdev->scale_bus(hdev->hfi_device_data, 0, i,
+					OCMEM_MEM)) {
 			dprintk(VIDC_WARN,
 				"Failed to unvote for OCMEM accesses\n");
 		}
@@ -876,15 +892,23 @@
 {
 	int num_mbs_per_sec;
 	int rc = 0;
+	struct hfi_device *hdev;
 	if (!core) {
-		dprintk(VIDC_ERR, "Invalid args: %p\n", core);
+		dprintk(VIDC_ERR, "%s Invalid args: %p\n", __func__, core);
+		return -EINVAL;
+	}
+
+	hdev = core->device;
+	if (!hdev) {
+		dprintk(VIDC_ERR, "%s Invalid device handle: %p\n",
+			__func__, hdev);
 		return -EINVAL;
 	}
 	num_mbs_per_sec = msm_comm_get_load(core, MSM_VIDC_ENCODER);
 	num_mbs_per_sec += msm_comm_get_load(core, MSM_VIDC_DECODER);
 
 	dprintk(VIDC_INFO, "num_mbs_per_sec = %d\n", num_mbs_per_sec);
-	rc = venus_hfi_scale_clocks(core->device, num_mbs_per_sec);
+	rc = hdev->scale_clocks(hdev->hfi_device_data, num_mbs_per_sec);
 	if (rc)
 		dprintk(VIDC_ERR, "Failed to set clock rate: %d\n", rc);
 	return rc;
@@ -892,12 +916,16 @@
 
 void msm_comm_scale_clocks_and_bus(struct msm_vidc_inst *inst)
 {
-	struct msm_vidc_core *core = inst->core;
+	struct msm_vidc_core *core;
+	struct hfi_device *hdev;
 
-	if (!inst) {
-		dprintk(VIDC_WARN, "Invalid params\n");
+	if (!inst || !inst->core || !inst->core->device) {
+		dprintk(VIDC_ERR, "%s Invalid params\n", __func__);
 		return;
 	}
+	core = inst->core;
+	hdev = core->device;
+
 	if (msm_comm_scale_clocks(core)) {
 		dprintk(VIDC_WARN,
 				"Failed to scale clocks. Performance might be impacted\n");
@@ -906,7 +934,7 @@
 		dprintk(VIDC_WARN,
 				"Failed to scale DDR bus. Performance might be impacted\n");
 	}
-	if (venus_hfi_is_ocmem_present(core->device)) {
+	if (hdev->is_ocmem_present(hdev->hfi_device_data)) {
 		if (msm_comm_scale_bus(core, inst->session_type,
 					OCMEM_MEM))
 			dprintk(VIDC_WARN,
@@ -926,6 +954,14 @@
 static int msm_comm_unset_ocmem(struct msm_vidc_core *core)
 {
 	int rc = 0;
+	struct hfi_device *hdev;
+
+	if (!core || !core->device) {
+		dprintk(VIDC_ERR, "%s invalid parameters", __func__);
+		return -EINVAL;
+	}
+	hdev = core->device;
+
 	if (core->state == VIDC_CORE_INVALID) {
 		dprintk(VIDC_ERR,
 				"Core is in bad state. Cannot unset ocmem\n");
@@ -935,7 +971,7 @@
 	init_completion(
 		&core->completions[SYS_MSG_INDEX(RELEASE_RESOURCE_DONE)]);
 
-	rc = venus_hfi_unset_ocmem(core->device);
+	rc = hdev->unset_ocmem(hdev->hfi_device_data);
 	if (rc) {
 		dprintk(VIDC_ERR, "Failed to set OCMEM on driver\n");
 		goto release_ocmem_failed;
@@ -951,39 +987,6 @@
 	return rc;
 }
 
-int msm_vidc_ocmem_notify_handler(struct notifier_block *this,
-		unsigned long event, void *data)
-{
-	struct ocmem_buf *buff = data;
-	struct msm_vidc_core *core;
-	struct venus_hfi_device *device;
-	struct venus_resources *resources;
-	struct on_chip_mem *ocmem;
-	int rc = NOTIFY_DONE;
-	if (event == OCMEM_ALLOC_GROW) {
-		ocmem = container_of(this, struct on_chip_mem, vidc_ocmem_nb);
-		if (!ocmem) {
-			dprintk(VIDC_ERR, "Wrong handler passed\n");
-			rc = NOTIFY_BAD;
-			goto bad_notfier;
-		}
-		resources = container_of(ocmem,
-			struct venus_resources, ocmem);
-		device = container_of(resources,
-			struct venus_hfi_device, resources);
-		core = container_of((void *)device,
-			struct msm_vidc_core, device);
-		if (venus_hfi_set_ocmem(core->device, buff)) {
-			dprintk(VIDC_ERR, "Failed to set ocmem: %d\n", rc);
-			goto ocmem_set_failed;
-		}
-		rc = NOTIFY_OK;
-	}
-ocmem_set_failed:
-bad_notfier:
-	return rc;
-}
-
 static int msm_comm_init_core_done(struct msm_vidc_inst *inst)
 {
 	struct msm_vidc_core *core = inst->core;
@@ -1022,11 +1025,11 @@
 	int rc = 0;
 	struct msm_vidc_core *core = inst->core;
 	unsigned long flags;
-	struct venus_hfi_device *device;
+	struct hfi_device *hdev;
 
 	if (!core || !core->device)
 		return -EINVAL;
-	device = core->device;
+	hdev = core->device;
 
 	mutex_lock(&core->sync_lock);
 	if (core->state >= VIDC_CORE_INIT) {
@@ -1041,7 +1044,7 @@
 		goto fail_scale_bus;
 	}
 
-	rc = venus_hfi_load_fw(core->device);
+	rc = hdev->load_fw(hdev->hfi_device_data);
 	if (rc) {
 		dprintk(VIDC_ERR, "Failed to load video firmware\n");
 		goto fail_load_fw;
@@ -1053,7 +1056,7 @@
 	}
 
 	init_completion(&core->completions[SYS_MSG_INDEX(SYS_INIT_DONE)]);
-	rc = venus_hfi_core_init(core->device);
+	rc = hdev->core_init(hdev->hfi_device_data);
 	if (rc) {
 		dprintk(VIDC_ERR, "Failed to init core, id = %d\n", core->id);
 		goto fail_core_init;
@@ -1066,7 +1069,7 @@
 	mutex_unlock(&core->sync_lock);
 	return rc;
 fail_core_init:
-	venus_hfi_unload_fw(core->device);
+	hdev->unload_fw(hdev->hfi_device_data);
 fail_load_fw:
 	msm_comm_unvote_buses(core, DDR_MEM);
 fail_scale_bus:
@@ -1077,8 +1080,18 @@
 static int msm_vidc_deinit_core(struct msm_vidc_inst *inst)
 {
 	int rc = 0;
-	struct msm_vidc_core *core = inst->core;
+	struct msm_vidc_core *core;
+	struct hfi_device *hdev;
 	unsigned long flags;
+
+	if (!inst || !inst->core || !inst->core->device) {
+		dprintk(VIDC_ERR, "%s invalid parameters", __func__);
+		return -EINVAL;
+	}
+
+	core = inst->core;
+	hdev = core->device;
+
 	mutex_lock(&core->sync_lock);
 	if (core->state == VIDC_CORE_UNINIT) {
 		dprintk(VIDC_INFO, "Video core: %d is already in state: %d\n",
@@ -1088,9 +1101,9 @@
 	msm_comm_scale_clocks_and_bus(inst);
 	if (list_empty(&core->instances)) {
 		msm_comm_unset_ocmem(core);
-		venus_hfi_free_ocmem(core->device);
+		hdev->free_ocmem(hdev->hfi_device_data);
 		dprintk(VIDC_DBG, "Calling vidc_hal_core_release\n");
-		rc = venus_hfi_core_release(core->device);
+		rc = hdev->core_release(hdev->hfi_device_data);
 		if (rc) {
 			dprintk(VIDC_ERR, "Failed to release core, id = %d\n",
 							core->id);
@@ -1099,7 +1112,7 @@
 		spin_lock_irqsave(&core->lock, flags);
 		core->state = VIDC_CORE_UNINIT;
 		spin_unlock_irqrestore(&core->lock, flags);
-		venus_hfi_unload_fw(core->device);
+		hdev->unload_fw(hdev->hfi_device_data);
 		msm_comm_unvote_buses(core, DDR_MEM|OCMEM_MEM);
 	}
 core_already_uninited:
@@ -1182,6 +1195,14 @@
 {
 	int rc = 0;
 	int fourcc = 0;
+	struct hfi_device *hdev;
+
+	if (!inst || !inst->core || !inst->core->device) {
+		dprintk(VIDC_ERR, "%s invalid parameters", __func__);
+		return -EINVAL;
+	}
+	hdev = inst->core->device;
+
 	if (IS_ALREADY_IN_STATE(flipped_state, MSM_VIDC_OPEN)) {
 		dprintk(VIDC_INFO, "inst: %p is already in state: %d\n",
 						inst, inst->state);
@@ -1197,7 +1218,7 @@
 	}
 	init_completion(
 		&inst->completions[SESSION_MSG_INDEX(SESSION_INIT_DONE)]);
-	inst->session = venus_hfi_session_init(inst->core->device, (u32) inst,
+	inst->session = hdev->session_init(hdev->hfi_device_data, (u32) inst,
 					get_hal_domain(inst->session_type),
 					get_hal_codec_type(fourcc));
 	if (!inst->session) {
@@ -1218,6 +1239,14 @@
 {
 	int rc = 0;
 	u32 ocmem_sz = 0;
+	struct hfi_device *hdev;
+
+	if (!inst || !inst->core || !inst->core->device) {
+		dprintk(VIDC_ERR, "%s invalid parameters", __func__);
+		return -EINVAL;
+	}
+	hdev = inst->core->device;
+
 	if (IS_ALREADY_IN_STATE(flipped_state, MSM_VIDC_LOAD_RESOURCES)) {
 		dprintk(VIDC_INFO, "inst: %p is already in state: %d\n",
 						inst, inst->state);
@@ -1227,7 +1256,7 @@
 	rc = msm_comm_scale_bus(inst->core, inst->session_type, OCMEM_MEM);
 	if (!rc) {
 		mutex_lock(&inst->core->sync_lock);
-		rc = venus_hfi_alloc_ocmem(inst->core->device, ocmem_sz);
+		rc = hdev->alloc_ocmem(hdev->hfi_device_data, ocmem_sz);
 		mutex_unlock(&inst->core->sync_lock);
 		if (rc) {
 			dprintk(VIDC_WARN,
@@ -1238,7 +1267,7 @@
 		dprintk(VIDC_WARN,
 		"Failed to vote for OCMEM BW. Performance will be impacted\n");
 	}
-	rc = venus_hfi_session_load_res((void *) inst->session);
+	rc = hdev->session_load_res((void *) inst->session);
 	if (rc) {
 		dprintk(VIDC_ERR,
 			"Failed to send load resources\n");
@@ -1252,6 +1281,15 @@
 static int msm_vidc_start(int flipped_state, struct msm_vidc_inst *inst)
 {
 	int rc = 0;
+	struct hfi_device *hdev;
+
+	if (!inst || !inst->core || !inst->core->device) {
+		dprintk(VIDC_ERR, "%s invalid parameters", __func__);
+		return -EINVAL;
+	}
+
+	hdev = inst->core->device;
+
 	if (IS_ALREADY_IN_STATE(flipped_state, MSM_VIDC_START)) {
 		dprintk(VIDC_INFO,
 			"inst: %p is already in state: %d\n",
@@ -1260,7 +1298,7 @@
 	}
 	init_completion(
 		&inst->completions[SESSION_MSG_INDEX(SESSION_START_DONE)]);
-	rc = venus_hfi_session_start((void *) inst->session);
+	rc = hdev->session_start((void *) inst->session);
 	if (rc) {
 		dprintk(VIDC_ERR,
 			"Failed to send start\n");
@@ -1274,6 +1312,14 @@
 static int msm_vidc_stop(int flipped_state, struct msm_vidc_inst *inst)
 {
 	int rc = 0;
+	struct hfi_device *hdev;
+
+	if (!inst || !inst->core || !inst->core->device) {
+		dprintk(VIDC_ERR, "%s invalid parameters", __func__);
+		return -EINVAL;
+	}
+	hdev = inst->core->device;
+
 	if (IS_ALREADY_IN_STATE(flipped_state, MSM_VIDC_STOP)) {
 		dprintk(VIDC_INFO,
 			"inst: %p is already in state: %d\n",
@@ -1283,7 +1329,7 @@
 	dprintk(VIDC_DBG, "Send Stop to hal\n");
 	init_completion(
 		&inst->completions[SESSION_MSG_INDEX(SESSION_STOP_DONE)]);
-	rc = venus_hfi_session_stop((void *) inst->session);
+	rc = hdev->session_stop((void *) inst->session);
 	if (rc) {
 		dprintk(VIDC_ERR, "Failed to send stop\n");
 		goto exit;
@@ -1296,6 +1342,14 @@
 static int msm_vidc_release_res(int flipped_state, struct msm_vidc_inst *inst)
 {
 	int rc = 0;
+	struct hfi_device *hdev;
+
+	if (!inst || !inst->core || !inst->core->device) {
+		dprintk(VIDC_ERR, "%s invalid parameters", __func__);
+		return -EINVAL;
+	}
+	hdev = inst->core->device;
+
 	if (IS_ALREADY_IN_STATE(flipped_state, MSM_VIDC_RELEASE_RESOURCES)) {
 		dprintk(VIDC_INFO,
 			"inst: %p is already in state: %d\n",
@@ -1306,7 +1360,7 @@
 		"Send release res to hal\n");
 	init_completion(
 	&inst->completions[SESSION_MSG_INDEX(SESSION_RELEASE_RESOURCE_DONE)]);
-	rc = venus_hfi_session_release_res((void *) inst->session);
+	rc = hdev->session_release_res((void *) inst->session);
 	if (rc) {
 		dprintk(VIDC_ERR,
 			"Failed to send release resources\n");
@@ -1317,9 +1371,17 @@
 	return rc;
 }
 
-static int msm_comm_session_close(int flipped_state, struct msm_vidc_inst *inst)
+static int msm_comm_session_close(int flipped_state,
+			struct msm_vidc_inst *inst)
 {
 	int rc = 0;
+	struct hfi_device *hdev;
+
+	if (!inst || !inst->core || !inst->core->device) {
+		dprintk(VIDC_ERR, "%s invalid params", __func__);
+		return -EINVAL;
+	}
+	hdev = inst->core->device;
 	if (IS_ALREADY_IN_STATE(flipped_state, MSM_VIDC_CLOSE)) {
 		dprintk(VIDC_INFO,
 			"inst: %p is already in state: %d\n",
@@ -1330,7 +1392,7 @@
 		"Send session close to hal\n");
 	init_completion(
 		&inst->completions[SESSION_MSG_INDEX(SESSION_END_DONE)]);
-	rc = venus_hfi_session_end((void *) inst->session);
+	rc = hdev->session_end((void *) inst->session);
 	if (rc) {
 		dprintk(VIDC_ERR,
 			"Failed to send close\n");
@@ -1479,6 +1541,7 @@
 	struct vb2_buf_entry *entry;
 	struct vidc_frame_data frame_data;
 	struct msm_vidc_core *core;
+	struct hfi_device *hdev;
 	q = vb->vb2_queue;
 	inst = q->drv_priv;
 	if (!inst || !vb) {
@@ -1491,6 +1554,11 @@
 			"Invalid input: %p, %p, %p\n", inst, core, vb);
 		return -EINVAL;
 	}
+	hdev = core->device;
+	if (!hdev) {
+		dprintk(VIDC_ERR, "Invalid input: %p", hdev);
+		return -EINVAL;
+	}
 
 	if (inst->state == MSM_VIDC_CORE_INVALID ||
 		core->state == VIDC_CORE_INVALID) {
@@ -1534,7 +1602,7 @@
 			dprintk(VIDC_DBG,
 				"Sending etb to hal: Alloc: %d :filled: %d\n",
 				frame_data.alloc_len, frame_data.filled_len);
-			rc = venus_hfi_session_etb((void *) inst->session,
+			rc = hdev->session_etb((void *) inst->session,
 					&frame_data);
 			if (!rc)
 				msm_vidc_debugfs_update(inst,
@@ -1564,7 +1632,7 @@
 				seq_hdr.seq_hdr = (u8 *) vb->v4l2_planes[0].
 					m.userptr;
 				seq_hdr.seq_hdr_len = vb->v4l2_planes[0].length;
-				rc = venus_hfi_session_get_seq_hdr((void *)
+				rc = hdev->session_get_seq_hdr((void *)
 						inst->session, &seq_hdr);
 				if (!rc) {
 					inst->vb2_seq_hdr = vb;
@@ -1572,7 +1640,7 @@
 						inst->vb2_seq_hdr);
 				}
 			} else {
-				rc = venus_hfi_session_ftb((void *)
+				rc = hdev->session_ftb((void *)
 					inst->session, &frame_data);
 			if (!rc)
 				msm_vidc_debugfs_update(inst,
@@ -1595,6 +1663,14 @@
 int msm_comm_try_get_bufreqs(struct msm_vidc_inst *inst)
 {
 	int rc = 0;
+	struct hfi_device *hdev;
+
+	if (!inst || !inst->core || !inst->core->device) {
+		dprintk(VIDC_ERR, "%s invalid parameters", __func__);
+		return -EINVAL;
+	}
+	hdev = inst->core->device;
+
 	mutex_lock(&inst->sync_lock);
 	if (inst->state < MSM_VIDC_OPEN_DONE || inst->state >= MSM_VIDC_CLOSE) {
 		dprintk(VIDC_ERR,
@@ -1604,7 +1680,7 @@
 	}
 	init_completion(
 		&inst->completions[SESSION_MSG_INDEX(SESSION_PROPERTY_INFO)]);
-	rc = venus_hfi_session_get_buf_req((void *) inst->session);
+	rc = hdev->session_get_buf_req((void *) inst->session);
 	if (rc) {
 		dprintk(VIDC_ERR, "Failed to get property\n");
 		goto exit;
@@ -1632,6 +1708,7 @@
 	int rc = 0;
 	unsigned long flags;
 	struct msm_vidc_core *core;
+	struct hfi_device *hdev;
 	if (!inst) {
 		dprintk(VIDC_ERR,
 				"Invalid instance pointer = %p\n", inst);
@@ -1643,6 +1720,11 @@
 				"Invalid core pointer = %p\n", core);
 		return -EINVAL;
 	}
+	hdev = core->device;
+	if (!hdev) {
+		dprintk(VIDC_ERR, "Invalid device pointer = %p\n", hdev);
+		return -EINVAL;
+	}
 	spin_lock_irqsave(&inst->lock, flags);
 	if (!list_empty(&inst->internalbufs)) {
 		list_for_each_safe(ptr, next, &inst->internalbufs) {
@@ -1659,7 +1741,7 @@
 				init_completion(
 				   &inst->completions[SESSION_MSG_INDEX
 				   (SESSION_RELEASE_BUFFER_DONE)]);
-				rc = venus_hfi_session_release_buffers(
+				rc = hdev->session_release_buffers(
 						(void *) inst->session,
 							&buffer_info);
 				if (rc)
@@ -1692,6 +1774,7 @@
 	int rc = 0;
 	unsigned long flags;
 	struct msm_vidc_core *core;
+	struct hfi_device *hdev;
 	if (!inst) {
 		dprintk(VIDC_ERR,
 				"Invalid instance pointer = %p\n", inst);
@@ -1703,6 +1786,11 @@
 				"Invalid core pointer = %p\n", core);
 		return -EINVAL;
 	}
+	hdev = core->device;
+	if (!hdev) {
+		dprintk(VIDC_ERR, "Invalid device pointer = %p\n", hdev);
+		return -EINVAL;
+	}
 	spin_lock_irqsave(&inst->lock, flags);
 	if (!list_empty(&inst->persistbufs)) {
 		list_for_each_safe(ptr, next, &inst->persistbufs) {
@@ -1719,7 +1807,7 @@
 				init_completion(
 				   &inst->completions[SESSION_MSG_INDEX
 				   (SESSION_RELEASE_BUFFER_DONE)]);
-				rc = venus_hfi_session_release_buffers(
+				rc = hdev->session_release_buffers(
 						(void *) inst->session,
 							&buffer_info);
 				if (rc)
@@ -1747,17 +1835,25 @@
 	enum hal_property ptype, void *pdata)
 {
 	int rc = 0;
+	struct hfi_device *hdev;
 	if (!inst) {
 		dprintk(VIDC_ERR, "Invalid input: %p\n", inst);
 		return -EINVAL;
 	}
+
+	if (!inst->core || !inst->core->device) {
+		dprintk(VIDC_ERR, "%s invalid parameters", __func__);
+		return -EINVAL;
+	}
+	hdev = inst->core->device;
+
 	mutex_lock(&inst->sync_lock);
 	if (inst->state < MSM_VIDC_OPEN_DONE || inst->state >= MSM_VIDC_CLOSE) {
 		dprintk(VIDC_ERR, "Not in proper state to set property\n");
 		rc = -EAGAIN;
 		goto exit;
 	}
-	rc = venus_hfi_session_set_property((void *)inst->session,
+	rc = hdev->session_set_property((void *)inst->session,
 			ptype, pdata);
 	if (rc)
 		dprintk(VIDC_ERR, "Failed to set hal property for framesize\n");
@@ -1777,12 +1873,15 @@
 	unsigned long smem_flags = 0;
 	struct hal_buffer_requirements *scratch_buf;
 	int i;
-	struct venus_hfi_device *device;
+	struct hfi_device *hdev;
 
-	if (!inst || !inst->core || !inst->core->device)
+	if (!inst || !inst->core || !inst->core->device) {
+		dprintk(VIDC_ERR, "%s invalid parameters", __func__);
 		return -EINVAL;
+	}
 
-	device = inst->core->device;
+	hdev = inst->core->device;
+
 	scratch_buf =
 		&inst->buff_req.buffer[HAL_BUFFER_INTERNAL_SCRATCH];
 	dprintk(VIDC_DBG,
@@ -1792,10 +1891,10 @@
 	if (msm_comm_release_scratch_buffers(inst))
 		dprintk(VIDC_WARN, "Failed to release scratch buffers\n");
 	if (inst->mode == VIDC_SECURE) {
-		domain = venus_hfi_get_domain(device, CP_MAP);
+		domain = hdev->get_domain(hdev->hfi_device_data, CP_MAP);
 		smem_flags |= SMEM_SECURE;
 	} else
-		domain = venus_hfi_get_domain(device, NS_MAP);
+		domain = hdev->get_domain(hdev->hfi_device_data, NS_MAP);
 
 	if (scratch_buf->buffer_size) {
 		for (i = 0; i < scratch_buf->buffer_count_actual;
@@ -1822,7 +1921,7 @@
 			buffer_info.align_device_addr = handle->device_addr;
 			dprintk(VIDC_DBG, "Scratch buffer address: %x",
 					buffer_info.align_device_addr);
-			rc = venus_hfi_session_set_buffers(
+			rc = hdev->session_set_buffers(
 					(void *) inst->session,	&buffer_info);
 			if (rc) {
 				dprintk(VIDC_ERR,
@@ -1854,12 +1953,14 @@
 	int domain;
 	struct hal_buffer_requirements *persist_buf;
 	int i;
-	struct venus_hfi_device *device;
+	struct hfi_device *hdev;
 
-	if (!inst || !inst->core || !inst->core->device)
+	if (!inst || !inst->core || !inst->core->device) {
+		dprintk(VIDC_ERR, "%s invalid parameters", __func__);
 		return -EINVAL;
+	}
 
-	device = inst->core->device;
+	hdev = inst->core->device;
 
 	persist_buf =
 		&inst->buff_req.buffer[HAL_BUFFER_INTERNAL_PERSIST];
@@ -1874,10 +1975,10 @@
 	}
 
 	if (inst->mode == VIDC_SECURE) {
-		domain = venus_hfi_get_domain(device, CP_MAP);
+		domain = hdev->get_domain(hdev->hfi_device_data, CP_MAP);
 		flags |= SMEM_SECURE;
 	} else
-		domain = venus_hfi_get_domain(device, NS_MAP);
+		domain = hdev->get_domain(hdev->hfi_device_data, NS_MAP);
 
 	if (persist_buf->buffer_size) {
 		for (i = 0;	i <	persist_buf->buffer_count_actual; i++) {
@@ -1903,7 +2004,7 @@
 			buffer_info.align_device_addr = handle->device_addr;
 			dprintk(VIDC_DBG, "Persist buffer address: %x",
 					buffer_info.align_device_addr);
-			rc = venus_hfi_session_set_buffers(
+			rc = hdev->session_set_buffers(
 				(void *) inst->session, &buffer_info);
 			if (rc) {
 				dprintk(VIDC_ERR,
@@ -1977,6 +2078,7 @@
 	struct vb2_buf_entry *temp;
 	struct mutex *lock;
 	struct msm_vidc_core *core;
+	struct hfi_device *hdev;
 	if (!inst) {
 		dprintk(VIDC_ERR,
 				"Invalid instance pointer = %p\n", inst);
@@ -1988,6 +2090,11 @@
 				"Invalid core pointer = %p\n", core);
 		return -EINVAL;
 	}
+	hdev = core->device;
+	if (!hdev) {
+		dprintk(VIDC_ERR, "Invalid device pointer = %p", hdev);
+		return -EINVAL;
+	}
 
 	ip_flush = flags & V4L2_QCOM_CMD_FLUSH_OUTPUT;
 	op_flush = flags & V4L2_QCOM_CMD_FLUSH_CAPTURE;
@@ -2014,7 +2121,7 @@
 			dprintk(VIDC_WARN,
 			"FLUSH BUG: Pending q not empty! It should be empty\n");
 		}
-		rc = venus_hfi_session_flush(inst->session,
+		rc = hdev->session_flush(inst->session,
 				HAL_FLUSH_OUTPUT);
 	} else {
 		if (!list_empty(&inst->pendingq)) {
@@ -2035,7 +2142,7 @@
 				kfree(temp);
 			}
 		}
-		rc = venus_hfi_session_flush(inst->session,
+		rc = hdev->session_flush(inst->session,
 				HAL_FLUSH_ALL);
 	}
 	mutex_unlock(&inst->sync_lock);
diff --git a/drivers/media/video/msm_vidc/msm_vidc_debug.c b/drivers/media/video/msm_vidc/msm_vidc_debug.c
index bdf146e..ff829d7 100644
--- a/drivers/media/video/msm_vidc/msm_vidc_debug.c
+++ b/drivers/media/video/msm_vidc/msm_vidc_debug.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -12,7 +12,7 @@
  */
 
 #include "msm_vidc_debug.h"
-#include "venus_hfi.h"
+#include "vidc_hfi_api.h"
 
 #define MAX_DBG_BUF_SIZE 4096
 int msm_vidc_debug = 0x3;
@@ -53,22 +53,26 @@
 		size_t count, loff_t *ppos)
 {
 	struct msm_vidc_core *core = file->private_data;
-	struct venus_hfi_device *device;
+	struct hfi_device *hdev;
 	int i = 0;
 	if (!core || !core->device) {
 		dprintk(VIDC_ERR, "Invalid params, core: %p\n", core);
 		return 0;
 	}
-	device = core->device;
+	hdev = core->device;
 	INIT_DBG_BUF(dbg_buf);
 	write_str(&dbg_buf, "===============================\n");
 	write_str(&dbg_buf, "CORE %d: 0x%p\n", core->id, core);
 	write_str(&dbg_buf, "===============================\n");
 	write_str(&dbg_buf, "state: %d\n", core->state);
-	write_str(&dbg_buf, "base addr: 0x%x\n", device->base_addr);
-	write_str(&dbg_buf, "register_base: 0x%x\n", device->register_base);
-	write_str(&dbg_buf, "register_size: %u\n", device->register_size);
-	write_str(&dbg_buf, "irq: %u\n", device->irq);
+	write_str(&dbg_buf, "base addr: 0x%x\n",
+		hdev->get_fw_info(hdev->hfi_device_data, FW_BASE_ADDRESS));
+	write_str(&dbg_buf, "register_base: 0x%x\n",
+		hdev->get_fw_info(hdev->hfi_device_data, FW_REGISTER_BASE));
+	write_str(&dbg_buf, "register_size: %u\n",
+		hdev->get_fw_info(hdev->hfi_device_data, FW_REGISTER_SIZE));
+	write_str(&dbg_buf, "irq: %u\n",
+		hdev->get_fw_info(hdev->hfi_device_data, FW_IRQ));
 	for (i = SYS_MSG_START; i < SYS_MSG_END; i++) {
 		write_str(&dbg_buf, "completions[%d]: %s\n", i,
 			completion_done(&core->completions[SYS_MSG_INDEX(i)]) ?
diff --git a/drivers/media/video/msm_vidc/msm_vidc_internal.h b/drivers/media/video/msm_vidc/msm_vidc_internal.h
index 14cef1e..52c1de8 100644
--- a/drivers/media/video/msm_vidc/msm_vidc_internal.h
+++ b/drivers/media/video/msm_vidc/msm_vidc_internal.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -32,6 +32,7 @@
 #include <media/msm_media_info.h>
 
 #include "vidc_hfi_api.h"
+#include "vidc_hfi_api.h"
 
 #define MSM_VIDC_DRV_NAME "msm_vidc_driver"
 #define MSM_VIDC_VERSION KERNEL_VERSION(0, 0, 1);
@@ -177,6 +178,7 @@
 	struct dentry *debugfs_root;
 	enum vidc_core_state state;
 	struct completion completions[SYS_MSG_END - SYS_MSG_START + 1];
+	enum msm_vidc_hfi_type hfi_type;
 };
 
 struct msm_vidc_inst {
@@ -235,6 +237,4 @@
 };
 
 void handle_cmd_response(enum command_response cmd, void *data);
-int msm_vidc_ocmem_notify_handler(struct notifier_block *this,
-		unsigned long event, void *data);
 #endif
diff --git a/drivers/media/video/msm_vidc/venus_hfi.c b/drivers/media/video/msm_vidc/venus_hfi.c
index 8f0902f..015ed11 100644
--- a/drivers/media/video/msm_vidc/venus_hfi.c
+++ b/drivers/media/video/msm_vidc/venus_hfi.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -37,8 +37,6 @@
 
 #define SHARED_QSIZE 0x1000000
 
-struct hal_device_data hal_ctxt;
-
 static struct msm_bus_vectors enc_ocmem_init_vectors[]  = {
 	{
 		.src = MSM_BUS_MASTER_VIDEO_P0_OCMEM,
@@ -840,7 +838,7 @@
 	return result;
 }
 
-int venus_hfi_iface_msgq_read(struct venus_hfi_device *device, void *pkt)
+static int venus_hfi_iface_msgq_read(struct venus_hfi_device *device, void *pkt)
 {
 	u32 tx_req_is_set = 0;
 	int rc = 0;
@@ -875,7 +873,7 @@
 	return rc;
 }
 
-int venus_hfi_iface_dbgq_read(struct venus_hfi_device *device, void *pkt)
+static int venus_hfi_iface_dbgq_read(struct venus_hfi_device *device, void *pkt)
 {
 	u32 tx_req_is_set = 0;
 	int rc = 0;
@@ -1146,7 +1144,7 @@
 	return 0;
 }
 
-int venus_hfi_core_init(void *device)
+static int venus_hfi_core_init(void *device)
 {
 	struct hfi_cmd_sys_init_packet pkt;
 	int rc = 0;
@@ -1214,7 +1212,7 @@
 	return rc;
 }
 
-int venus_hfi_core_release(void *device)
+static int venus_hfi_core_release(void *device)
 {
 	struct venus_hfi_device *dev;
 	if (device) {
@@ -1288,7 +1286,7 @@
 	dprintk(VIDC_DBG, "Cleared WRAPPER/A2H interrupt");
 }
 
-int venus_hfi_core_set_resource(void *device,
+static int venus_hfi_core_set_resource(void *device,
 		struct vidc_resource_hdr *resource_hdr, void *resource_value)
 {
 	struct hfi_cmd_sys_set_resource_packet *pkt;
@@ -1318,7 +1316,7 @@
 	return rc;
 }
 
-int venus_hfi_core_release_resource(void *device,
+static int venus_hfi_core_release_resource(void *device,
 			struct vidc_resource_hdr *resource_hdr)
 {
 	struct hfi_cmd_sys_release_resource_packet pkt;
@@ -1345,7 +1343,7 @@
 	return rc;
 }
 
-int venus_hfi_core_ping(void *device)
+static int venus_hfi_core_ping(void *device)
 {
 	struct hfi_cmd_sys_ping_packet pkt;
 	int rc = 0;
@@ -1371,8 +1369,8 @@
 	return rc;
 }
 
-int venus_hfi_session_set_property(void *sess,
-	enum hal_property ptype, void *pdata)
+static int venus_hfi_session_set_property(void *sess,
+					enum hal_property ptype, void *pdata)
 {
 	u8 packet[VIDC_IFACEQ_VAR_LARGE_PKT_SIZE];
 	struct hfi_cmd_session_set_property_packet *pkt =
@@ -1401,8 +1399,8 @@
 	return rc;
 }
 
-int venus_hfi_session_get_property(void *sess,
-	enum hal_property ptype, void *pdata)
+static int venus_hfi_session_get_property(void *sess,
+				enum hal_property ptype, void *pdata)
 {
 	struct hal_session *session;
 
@@ -1524,8 +1522,8 @@
 	return 0;
 }
 
-void *venus_hfi_session_init(void *device, u32 session_id,
-	enum hal_domain session_type, enum hal_video_codec codec_type)
+static void *venus_hfi_session_init(void *device, u32 session_id,
+		enum hal_domain session_type, enum hal_video_codec codec_type)
 {
 	struct hfi_cmd_sys_session_init_packet pkt;
 	struct hal_session *new_session;
@@ -1592,20 +1590,20 @@
 	return rc;
 }
 
-int venus_hfi_session_end(void *session)
+static int venus_hfi_session_end(void *session)
 {
 	return venus_hfi_send_session_cmd(session,
 		HFI_CMD_SYS_SESSION_END);
 }
 
-int venus_hfi_session_abort(void *session)
+static int venus_hfi_session_abort(void *session)
 {
 	return venus_hfi_send_session_cmd(session,
 		HFI_CMD_SYS_SESSION_ABORT);
 }
 
-int venus_hfi_session_set_buffers(void *sess,
-	struct vidc_buffer_addr_info *buffer_info)
+static int venus_hfi_session_set_buffers(void *sess,
+				struct vidc_buffer_addr_info *buffer_info)
 {
 	struct hfi_cmd_session_set_buffers_packet *pkt;
 	u8 packet[VIDC_IFACEQ_VAR_LARGE_PKT_SIZE];
@@ -1638,8 +1636,8 @@
 	return rc;
 }
 
-int venus_hfi_session_release_buffers(void *sess,
-	struct vidc_buffer_addr_info *buffer_info)
+static int venus_hfi_session_release_buffers(void *sess,
+				struct vidc_buffer_addr_info *buffer_info)
 {
 	struct hfi_cmd_session_release_buffer_packet *pkt;
 	u8 packet[VIDC_IFACEQ_VAR_LARGE_PKT_SIZE];
@@ -1672,43 +1670,44 @@
 	return rc;
 }
 
-int venus_hfi_session_load_res(void *sess)
+static int venus_hfi_session_load_res(void *sess)
 {
 	return venus_hfi_send_session_cmd(sess,
 		HFI_CMD_SESSION_LOAD_RESOURCES);
 }
 
-int venus_hfi_session_release_res(void *sess)
+static int venus_hfi_session_release_res(void *sess)
 {
 	return venus_hfi_send_session_cmd(sess,
 		HFI_CMD_SESSION_RELEASE_RESOURCES);
 }
 
-int venus_hfi_session_start(void *sess)
+static int venus_hfi_session_start(void *sess)
 {
 	return venus_hfi_send_session_cmd(sess,
 		HFI_CMD_SESSION_START);
 }
 
-int venus_hfi_session_stop(void *sess)
+static int venus_hfi_session_stop(void *sess)
 {
 	return venus_hfi_send_session_cmd(sess,
 		HFI_CMD_SESSION_STOP);
 }
 
-int venus_hfi_session_suspend(void *sess)
+static int venus_hfi_session_suspend(void *sess)
 {
 	return venus_hfi_send_session_cmd(sess,
 		HFI_CMD_SESSION_SUSPEND);
 }
 
-int venus_hfi_session_resume(void *sess)
+static int venus_hfi_session_resume(void *sess)
 {
 	return venus_hfi_send_session_cmd(sess,
 		HFI_CMD_SESSION_RESUME);
 }
 
-int venus_hfi_session_etb(void *sess, struct vidc_frame_data *input_frame)
+static int venus_hfi_session_etb(void *sess,
+				struct vidc_frame_data *input_frame)
 {
 	int rc = 0;
 	struct hal_session *session;
@@ -1752,8 +1751,8 @@
 	return rc;
 }
 
-int venus_hfi_session_ftb(void *sess,
-	struct vidc_frame_data *output_frame)
+static int venus_hfi_session_ftb(void *sess,
+				struct vidc_frame_data *output_frame)
 {
 	struct hfi_cmd_session_fill_buffer_packet pkt;
 	int rc = 0;
@@ -1778,8 +1777,8 @@
 	return rc;
 }
 
-int venus_hfi_session_parse_seq_hdr(void *sess,
-	struct vidc_seq_hdr *seq_hdr)
+static int venus_hfi_session_parse_seq_hdr(void *sess,
+					struct vidc_seq_hdr *seq_hdr)
 {
 	struct hfi_cmd_session_parse_sequence_header_packet *pkt;
 	int rc = 0;
@@ -1809,8 +1808,8 @@
 	return rc;
 }
 
-int venus_hfi_session_get_seq_hdr(void *sess,
-	struct vidc_seq_hdr *seq_hdr)
+static int venus_hfi_session_get_seq_hdr(void *sess,
+				struct vidc_seq_hdr *seq_hdr)
 {
 	struct hfi_cmd_session_get_sequence_header_packet *pkt;
 	int rc = 0;
@@ -1837,7 +1836,7 @@
 	return rc;
 }
 
-int venus_hfi_session_get_buf_req(void *sess)
+static int venus_hfi_session_get_buf_req(void *sess)
 {
 	struct hfi_cmd_session_get_property_packet pkt;
 	int rc = 0;
@@ -1862,7 +1861,7 @@
 	return rc;
 }
 
-int venus_hfi_session_flush(void *sess, enum hal_flush flush_mode)
+static int venus_hfi_session_flush(void *sess, enum hal_flush flush_mode)
 {
 	struct hfi_cmd_session_flush_packet pkt;
 	int rc = 0;
@@ -1937,6 +1936,44 @@
 	return -EINVAL;
 }
 
+static void venus_hfi_process_sys_watchdog_timeout(
+				struct venus_hfi_device *device)
+{
+	struct msm_vidc_cb_cmd_done cmd_done;
+	device->intr_status &= ~VIDC_WRAPPER_INTR_STATUS_A2HWD_BMSK;
+	memset(&cmd_done, 0, sizeof(struct msm_vidc_cb_cmd_done));
+	cmd_done.device_id = device->device_id;
+	device->callback(SYS_WATCHDOG_TIMEOUT, &cmd_done);
+}
+
+static void venus_hfi_response_handler(struct venus_hfi_device *device)
+{
+	u8 packet[VIDC_IFACEQ_MED_PKT_SIZE];
+
+	dprintk(VIDC_INFO, "#####venus_hfi_response_handler#####\n");
+	if (device) {
+		if ((device->intr_status &
+			VIDC_WRAPPER_INTR_CLEAR_A2HWD_BMSK)) {
+			dprintk(VIDC_ERR, "Received: Watchdog timeout %s",
+				__func__);
+			venus_hfi_process_sys_watchdog_timeout(device);
+		}
+
+		while (!venus_hfi_iface_msgq_read(device, packet)) {
+			hfi_process_msg_packet(device->callback,
+				device->device_id,
+				(struct vidc_hal_msg_pkt_hdr *) packet);
+		}
+		while (!venus_hfi_iface_dbgq_read(device, packet)) {
+			struct hfi_msg_sys_debug_packet *pkt =
+				(struct hfi_msg_sys_debug_packet *) packet;
+			dprintk(VIDC_FW, "FW-SAYS: %s", pkt->rg_msg_data);
+		}
+	} else {
+		dprintk(VIDC_ERR, "SPURIOUS_INTERRUPT");
+	}
+}
+
 static void venus_hfi_core_work_handler(struct work_struct *work)
 {
 	struct venus_hfi_device *device = list_first_entry(
@@ -1949,7 +1986,7 @@
 		return;
 	}
 	venus_hfi_core_clear_interrupt(device);
-	hfi_response_handler(device);
+	venus_hfi_response_handler(device);
 	enable_irq(device->hal_data->irq);
 }
 static DECLARE_WORK(venus_hfi_work, venus_hfi_core_work_handler);
@@ -2157,9 +2194,10 @@
 	return ret;
 }
 
-int venus_hfi_scale_clocks(struct venus_hfi_device *device, int load)
+static int venus_hfi_scale_clocks(void *dev, int load)
 {
 	int rc = 0;
+	struct venus_hfi_device *device = dev;
 	if (!device) {
 		dprintk(VIDC_ERR, "Invalid args: %p\n", device);
 		return -EINVAL;
@@ -2374,11 +2412,18 @@
 	return i;
 }
 
-int venus_hfi_scale_bus(struct venus_hfi_device *device, int load,
+static int venus_hfi_scale_bus(void *dev, int load,
 				enum session_type type, enum mem_type mtype)
 {
 	int rc = 0;
 	u32 handle = 0;
+	struct venus_hfi_device *device = dev;
+
+	if (!device) {
+		dprintk(VIDC_ERR, "%s invalid device handle %p",
+			__func__, device);
+		return -EINVAL;
+	}
 
 	if (mtype & DDR_MEM)
 		handle = device->resources.bus_info.ddr_handle[type];
@@ -2399,24 +2444,10 @@
 	return rc;
 }
 
-static void venus_hfi_ocmem_init(struct venus_hfi_device *device)
-{
-	struct on_chip_mem *ocmem;
-
-	ocmem = &device->resources.ocmem;
-	ocmem->vidc_ocmem_nb.notifier_call = msm_vidc_ocmem_notify_handler;
-	ocmem->handle =
-		ocmem_notifier_register(OCMEM_VIDEO, &ocmem->vidc_ocmem_nb);
-	if (!ocmem->handle) {
-		dprintk(VIDC_WARN, "Failed to register OCMEM notifier.");
-		dprintk(VIDC_INFO, " Performance will be impacted\n");
-	}
-}
-
-int venus_hfi_set_ocmem(struct venus_hfi_device *device,
-	struct ocmem_buf *ocmem)
+static int venus_hfi_set_ocmem(void *dev, struct ocmem_buf *ocmem)
 {
 	struct vidc_resource_hdr rhdr;
+	struct venus_hfi_device *device = dev;
 	int rc = 0;
 	if (!device || !ocmem) {
 		dprintk(VIDC_ERR, "Invalid params, core:%p, ocmem: %p\n",
@@ -2437,12 +2468,14 @@
 	return rc;
 }
 
-int venus_hfi_unset_ocmem(struct venus_hfi_device *device)
+static int venus_hfi_unset_ocmem(void *dev)
 {
 	struct vidc_resource_hdr rhdr;
+	struct venus_hfi_device *device = dev;
 	int rc = 0;
 	if (!device || !device->resources.ocmem.buf) {
-		dprintk(VIDC_ERR, "Invalid params, device:%p\n", device);
+		dprintk(VIDC_ERR, "%s Invalid params, device:%p\n",
+			__func__, device);
 		return -EINVAL;
 	}
 	rhdr.resource_id = VIDC_RESOURCE_OCMEM;
@@ -2454,15 +2487,59 @@
 	return rc;
 }
 
-int venus_hfi_alloc_ocmem(struct venus_hfi_device *device,
-		unsigned long size)
+static int venus_hfi_ocmem_notify_handler(struct notifier_block *this,
+		unsigned long event, void *data)
+{
+	struct ocmem_buf *buff = data;
+	struct venus_hfi_device *device;
+	struct venus_resources *resources;
+	struct on_chip_mem *ocmem;
+	int rc = NOTIFY_DONE;
+	if (event == OCMEM_ALLOC_GROW) {
+		ocmem = container_of(this, struct on_chip_mem, vidc_ocmem_nb);
+		if (!ocmem) {
+			dprintk(VIDC_ERR, "Wrong handler passed\n");
+			rc = NOTIFY_BAD;
+			goto err_ocmem_notify;
+		}
+		resources = container_of(ocmem,
+			struct venus_resources, ocmem);
+		device = container_of(resources,
+			struct venus_hfi_device, resources);
+		if (venus_hfi_set_ocmem(device, buff)) {
+			dprintk(VIDC_ERR, "Failed to set ocmem: %d\n", rc);
+			goto err_ocmem_notify;
+		}
+		rc = NOTIFY_OK;
+	}
+
+err_ocmem_notify:
+	return rc;
+}
+
+static void venus_hfi_ocmem_init(struct venus_hfi_device *device)
+{
+	struct on_chip_mem *ocmem;
+
+	ocmem = &device->resources.ocmem;
+	ocmem->vidc_ocmem_nb.notifier_call = venus_hfi_ocmem_notify_handler;
+	ocmem->handle =
+		ocmem_notifier_register(OCMEM_VIDEO, &ocmem->vidc_ocmem_nb);
+	if (!ocmem->handle) {
+		dprintk(VIDC_WARN, "Failed to register OCMEM notifier.");
+		dprintk(VIDC_INFO, " Performance will be impacted\n");
+	}
+}
+
+static int venus_hfi_alloc_ocmem(void *dev, unsigned long size)
 {
 	int rc = 0;
 	struct ocmem_buf *ocmem_buffer;
+	struct venus_hfi_device *device = dev;
 
 	if (!device || !size) {
-		dprintk(VIDC_ERR,
-			"Invalid param, core: %p, size: %lu\n", device, size);
+		dprintk(VIDC_ERR, "%s Invalid param, core: %p, size: %lu\n",
+			__func__, device, size);
 		return -EINVAL;
 	}
 	ocmem_buffer = device->resources.ocmem.buf;
@@ -2490,21 +2567,35 @@
 	return rc;
 }
 
-int venus_hfi_free_ocmem(struct venus_hfi_device *device)
+static int venus_hfi_free_ocmem(void *dev)
 {
+	struct venus_hfi_device *device = dev;
 	int rc = 0;
 
+	if (!device) {
+		dprintk(VIDC_ERR, "%s invalid device handle %p",
+			__func__, device);
+		return -EINVAL;
+	}
+
 	if (device->resources.ocmem.buf) {
 		rc = ocmem_free(OCMEM_VIDEO, device->resources.ocmem.buf);
 		if (rc)
 			dprintk(VIDC_ERR, "Failed to free ocmem\n");
+		device->resources.ocmem.buf = NULL;
 	}
-	device->resources.ocmem.buf = NULL;
 	return rc;
 }
 
-int venus_hfi_is_ocmem_present(struct venus_hfi_device *device)
+static int venus_hfi_is_ocmem_present(void *dev)
 {
+	struct venus_hfi_device *device = dev;
+	if (!device) {
+		dprintk(VIDC_ERR, "%s invalid device handle %p",
+			__func__, device);
+		return -EINVAL;
+	}
+
 	return device->resources.ocmem.buf ? 1 : 0;
 }
 
@@ -2515,6 +2606,7 @@
 				&device->resources.ocmem.vidc_ocmem_nb);
 }
 
+
 static int venus_hfi_init_resources(struct venus_hfi_device *device,
 				struct platform_device *pdev)
 {
@@ -2619,9 +2711,9 @@
 	}
 }
 
-int venus_hfi_get_domain(struct venus_hfi_device *device,
-						 enum msm_vidc_io_maps iomap)
+static int venus_hfi_get_domain(void *dev, enum msm_vidc_io_maps iomap)
 {
+	struct venus_hfi_device *device = dev;
 	if (!device || iomap < CP_MAP || iomap >= MAX_MAP) {
 		dprintk(VIDC_ERR, "%s: Invalid parameter: %p iomap: %d\n",
 				__func__, device, iomap);
@@ -2630,10 +2722,11 @@
 	return device->resources.io_map[iomap].domain;
 }
 
-int venus_hfi_iommu_get_map(struct venus_hfi_device *device,
+static int venus_hfi_iommu_get_map(void *dev,
 			struct msm_vidc_iommu_info maps[MAX_MAP])
 {
 	int i = 0;
+	struct venus_hfi_device *device = dev;
 
 	if (!device || !maps) {
 		dprintk(VIDC_ERR, "%s: Invalid param device: %p maps: %p\n",
@@ -2677,12 +2770,14 @@
 	return rc;
 }
 
-int venus_hfi_load_fw(struct venus_hfi_device *device)
+static int venus_hfi_load_fw(void *dev)
 {
 	int rc = 0;
+	struct venus_hfi_device *device = dev;
 
 	if (!device) {
-		dprintk(VIDC_ERR, "Invalid paramter: %p\n", device);
+		dprintk(VIDC_ERR, "%s Invalid paramter: %p\n",
+			__func__, device);
 		return -EINVAL;
 	}
 
@@ -2723,10 +2818,12 @@
 	return rc;
 }
 
-void venus_hfi_unload_fw(struct venus_hfi_device *device)
+static void venus_hfi_unload_fw(void *dev)
 {
+	struct venus_hfi_device *device = dev;
 	if (!device) {
-		dprintk(VIDC_ERR, "Invalid paramter: %p\n", device);
+		dprintk(VIDC_ERR, "%s Invalid paramter: %p\n",
+			__func__, device);
 		return;
 	}
 	if (device->resources.fw.cookie) {
@@ -2737,6 +2834,40 @@
 	}
 }
 
+static int venus_hfi_get_fw_info(void *dev, enum fw_info info)
+{
+	int rc = 0;
+	struct venus_hfi_device *device = dev;
+
+	if (!device) {
+		dprintk(VIDC_ERR, "%s Invalid paramter: %p\n",
+			__func__, device);
+		return -EINVAL;
+	}
+
+	switch (info) {
+	case FW_BASE_ADDRESS:
+		rc = device->base_addr;
+		break;
+
+	case FW_REGISTER_BASE:
+		rc = device->register_base;
+		break;
+
+	case FW_REGISTER_SIZE:
+		rc = device->register_size;
+		break;
+
+	case FW_IRQ:
+		rc = device->irq;
+		break;
+
+	default:
+		dprintk(VIDC_ERR, "Invalid fw info requested");
+	}
+	return rc;
+}
+
 static void *venus_hfi_add_device(u32 device_id, struct platform_device *pdev,
 		void (*callback) (enum command_response cmd, void *data))
 {
@@ -2786,9 +2917,9 @@
 	return NULL;
 }
 
-void *venus_hfi_get_device(u32 device_id,
-	struct platform_device *pdev,
-	void (*callback) (enum command_response cmd, void *data))
+static void *venus_hfi_get_device(u32 device_id,
+				struct platform_device *pdev,
+				hfi_cmd_response_callback callback)
 {
 	struct venus_hfi_device *device;
 	int rc = 0;
@@ -2837,3 +2968,60 @@
 
 	}
 }
+
+static void venus_init_hfi_callbacks(struct hfi_device *hdev)
+{
+	hdev->core_init = venus_hfi_core_init;
+	hdev->core_release = venus_hfi_core_release;
+	hdev->core_pc_prep = venus_hfi_core_pc_prep;
+	hdev->core_ping = venus_hfi_core_ping;
+	hdev->session_init = venus_hfi_session_init;
+	hdev->session_end = venus_hfi_session_end;
+	hdev->session_abort = venus_hfi_session_abort;
+	hdev->session_set_buffers = venus_hfi_session_set_buffers;
+	hdev->session_release_buffers = venus_hfi_session_release_buffers;
+	hdev->session_load_res = venus_hfi_session_load_res;
+	hdev->session_release_res = venus_hfi_session_release_res;
+	hdev->session_start = venus_hfi_session_start;
+	hdev->session_stop = venus_hfi_session_stop;
+	hdev->session_suspend = venus_hfi_session_suspend;
+	hdev->session_resume = venus_hfi_session_resume;
+	hdev->session_etb = venus_hfi_session_etb;
+	hdev->session_ftb = venus_hfi_session_ftb;
+	hdev->session_parse_seq_hdr = venus_hfi_session_parse_seq_hdr;
+	hdev->session_get_seq_hdr = venus_hfi_session_get_seq_hdr;
+	hdev->session_get_buf_req = venus_hfi_session_get_buf_req;
+	hdev->session_flush = venus_hfi_session_flush;
+	hdev->session_set_property = venus_hfi_session_set_property;
+	hdev->session_get_property = venus_hfi_session_get_property;
+	hdev->scale_clocks = venus_hfi_scale_clocks;
+	hdev->scale_bus = venus_hfi_scale_bus;
+	hdev->unset_ocmem = venus_hfi_unset_ocmem;
+	hdev->alloc_ocmem = venus_hfi_alloc_ocmem;
+	hdev->free_ocmem = venus_hfi_free_ocmem;
+	hdev->is_ocmem_present = venus_hfi_is_ocmem_present;
+	hdev->get_domain = venus_hfi_get_domain;
+	hdev->iommu_get_map = venus_hfi_iommu_get_map;
+	hdev->load_fw = venus_hfi_load_fw;
+	hdev->unload_fw = venus_hfi_unload_fw;
+	hdev->get_fw_info = venus_hfi_get_fw_info;
+}
+
+int venus_hfi_initialize(struct hfi_device *hdev, u32 device_id,
+	struct platform_device *pdev, hfi_cmd_response_callback callback)
+{
+	int rc = 0;
+
+	if (!hdev || !callback) {
+		dprintk(VIDC_ERR, "Invalid params: %p %p\n", pdev, callback);
+		rc = -EINVAL;
+		goto err_venus_hfi_init;
+	}
+	hdev->hfi_device_data = venus_hfi_get_device(device_id, pdev, callback);
+
+	venus_init_hfi_callbacks(hdev);
+
+err_venus_hfi_init:
+	return rc;
+}
+
diff --git a/drivers/media/video/msm_vidc/venus_hfi.h b/drivers/media/video/msm_vidc/venus_hfi.h
index 93b9ae3..f825c20 100644
--- a/drivers/media/video/msm_vidc/venus_hfi.h
+++ b/drivers/media/video/msm_vidc/venus_hfi.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -19,10 +19,12 @@
 #include <linux/platform_device.h>
 #include <linux/spinlock.h>
 #include <mach/ocmem.h>
-#include <media/msm_vidc.h>
+
 #include "vidc_hfi_api.h"
 #include "msm_smem.h"
 #include "vidc_hfi_helper.h"
+#include "vidc_hfi_api.h"
+#include "vidc_hfi.h"
 
 #define HFI_MASK_QHDR_TX_TYPE			0xFF000000
 #define HFI_MASK_QHDR_RX_TYPE			0x00FF0000
@@ -106,793 +108,6 @@
 	VIDC_HWREG_HVI_SOFTINTEN =  0xA,
 };
 
-#define HFI_EVENT_SESSION_SEQUENCE_CHANGED (HFI_OX_BASE + 0x3)
-#define HFI_EVENT_SESSION_PROPERTY_CHANGED (HFI_OX_BASE + 0x4)
-
-#define HFI_EVENT_DATA_SEQUENCE_CHANGED_SUFFICIENT_BUFFER_RESOURCES	\
-	(HFI_OX_BASE + 0x1)
-#define HFI_EVENT_DATA_SEQUENCE_CHANGED_INSUFFICIENT_BUFFER_RESOURCES	\
-	(HFI_OX_BASE + 0x2)
-
-#define HFI_BUFFERFLAG_EOS				0x00000001
-#define HFI_BUFFERFLAG_STARTTIME		0x00000002
-#define HFI_BUFFERFLAG_DECODEONLY		0x00000004
-#define HFI_BUFFERFLAG_DATACORRUPT		0x00000008
-#define HFI_BUFFERFLAG_ENDOFFRAME		0x00000010
-#define HFI_BUFFERFLAG_SYNCFRAME		0x00000020
-#define HFI_BUFFERFLAG_EXTRADATA		0x00000040
-#define HFI_BUFFERFLAG_CODECCONFIG		0x00000080
-#define HFI_BUFFERFLAG_TIMESTAMPINVALID	0x00000100
-#define HFI_BUFFERFLAG_READONLY			0x00000200
-#define HFI_BUFFERFLAG_ENDOFSUBFRAME	0x00000400
-#define HFI_BUFFERFLAG_EOSEQ			0x00200000
-#define HFI_BUFFERFLAG_DISCONTINUITY	0x80000000
-#define HFI_BUFFERFLAG_TEI				0x40000000
-
-#define HFI_ERR_SESSION_EMPTY_BUFFER_DONE_OUTPUT_PENDING	\
-	(HFI_OX_BASE + 0x1001)
-#define HFI_ERR_SESSION_SAME_STATE_OPERATION		\
-	(HFI_OX_BASE + 0x1002)
-#define HFI_ERR_SESSION_SYNC_FRAME_NOT_DETECTED		\
-	(HFI_OX_BASE + 0x1003)
-#define  HFI_ERR_SESSION_START_CODE_NOT_FOUND		\
-	(HFI_OX_BASE + 0x1004)
-
-#define HFI_BUFFER_INTERNAL_SCRATCH (HFI_OX_BASE + 0x1)
-#define HFI_BUFFER_EXTRADATA_INPUT (HFI_OX_BASE + 0x2)
-#define HFI_BUFFER_EXTRADATA_OUTPUT (HFI_OX_BASE + 0x3)
-#define HFI_BUFFER_EXTRADATA_OUTPUT2 (HFI_OX_BASE + 0x4)
-
-#define HFI_BUFFER_MODE_STATIC (HFI_OX_BASE + 0x1)
-#define HFI_BUFFER_MODE_RING (HFI_OX_BASE + 0x2)
-
-struct hfi_buffer_alloc_mode {
-	u32 buffer_type;
-	u32 buffer_mode;
-};
-
-#define HFI_FLUSH_INPUT (HFI_OX_BASE + 0x1)
-#define HFI_FLUSH_OUTPUT (HFI_OX_BASE + 0x2)
-#define HFI_FLUSH_OUTPUT2 (HFI_OX_BASE + 0x3)
-#define HFI_FLUSH_ALL (HFI_OX_BASE + 0x4)
-
-#define HFI_EXTRADATA_NONE					0x00000000
-#define HFI_EXTRADATA_MB_QUANTIZATION		0x00000001
-#define HFI_EXTRADATA_INTERLACE_VIDEO		0x00000002
-#define HFI_EXTRADATA_VC1_FRAMEDISP			0x00000003
-#define HFI_EXTRADATA_VC1_SEQDISP			0x00000004
-#define HFI_EXTRADATA_TIMESTAMP				0x00000005
-#define HFI_EXTRADATA_S3D_FRAME_PACKING		0x00000006
-#define HFI_EXTRADATA_FRAME_RATE			0x00000007
-#define HFI_EXTRADATA_PANSCAN_WINDOW		0x00000008
-#define HFI_EXTRADATA_RECOVERY_POINT_SEI	0x00000009
-#define HFI_EXTRADATA_CLOSED_CAPTION_UD		0x0000000A
-#define HFI_EXTRADATA_AFD_UD				0x0000000B
-#define HFI_EXTRADATA_MULTISLICE_INFO		0x7F100000
-#define HFI_EXTRADATA_NUM_CONCEALED_MB		0x7F100001
-#define HFI_EXTRADATA_INDEX					0x7F100002
-#define HFI_EXTRADATA_METADATA_FILLER		0x7FE00002
-
-#define HFI_INDEX_EXTRADATA_INPUT_CROP		0x0700000E
-#define HFI_INDEX_EXTRADATA_DIGITAL_ZOOM	0x07000010
-#define HFI_INDEX_EXTRADATA_ASPECT_RATIO	0x7F100003
-
-struct hfi_index_extradata_config {
-	int enable;
-	u32 index_extra_data_id;
-};
-
-struct hfi_extradata_header {
-	u32 size;
-	u32 version;
-	u32 port_index;
-	u32 type;
-	u32 data_size;
-	u8 rg_data[1];
-};
-
-#define HFI_INTERLACE_FRAME_PROGRESSIVE					0x01
-#define HFI_INTERLACE_INTERLEAVE_FRAME_TOPFIELDFIRST	0x02
-#define HFI_INTERLACE_INTERLEAVE_FRAME_BOTTOMFIELDFIRST	0x04
-#define HFI_INTERLACE_FRAME_TOPFIELDFIRST				0x08
-#define HFI_INTERLACE_FRAME_BOTTOMFIELDFIRST			0x10
-
-#define HFI_PROPERTY_SYS_OX_START			\
-	(HFI_DOMAIN_BASE_COMMON + HFI_ARCH_OX_OFFSET + 0x0000)
-#define HFI_PROPERTY_SYS_IDLE_INDICATOR		\
-	(HFI_PROPERTY_SYS_OX_START + 0x001)
-
-#define HFI_PROPERTY_PARAM_OX_START				\
-	(HFI_DOMAIN_BASE_COMMON + HFI_ARCH_OX_OFFSET + 0x1000)
-#define HFI_PROPERTY_PARAM_BUFFER_COUNT_ACTUAL			\
-	(HFI_PROPERTY_PARAM_OX_START + 0x001)
-#define HFI_PROPERTY_PARAM_UNCOMPRESSED_PLANE_ACTUAL_CONSTRAINTS_INFO	\
-	(HFI_PROPERTY_PARAM_OX_START + 0x002)
-#define HFI_PROPERTY_PARAM_INTERLACE_FORMAT_SUPPORTED	\
-	(HFI_PROPERTY_PARAM_OX_START + 0x003)
-#define HFI_PROPERTY_PARAM_CHROMA_SITE					\
-(HFI_PROPERTY_PARAM_OX_START + 0x004)
-#define HFI_PROPERTY_PARAM_EXTRA_DATA_HEADER_CONFIG		\
-	(HFI_PROPERTY_PARAM_OX_START + 0x005)
-#define HFI_PROPERTY_PARAM_INDEX_EXTRADATA             \
-	(HFI_PROPERTY_PARAM_OX_START + 0x006)
-#define HFI_PROPERTY_PARAM_DIVX_FORMAT					\
-	(HFI_PROPERTY_PARAM_OX_START + 0x007)
-#define HFI_PROPERTY_PARAM_BUFFER_ALLOC_MODE			\
-	(HFI_PROPERTY_PARAM_OX_START + 0x008)
-#define HFI_PROPERTY_PARAM_S3D_FRAME_PACKING_EXTRADATA	\
-	(HFI_PROPERTY_PARAM_OX_START + 0x009)
-
-#define HFI_PROPERTY_CONFIG_OX_START					\
-	(HFI_DOMAIN_BASE_COMMON + HFI_ARCH_OX_OFFSET + 0x02000)
-#define HFI_PROPERTY_CONFIG_BUFFER_REQUIREMENTS			\
-	(HFI_PROPERTY_CONFIG_OX_START + 0x001)
-#define HFI_PROPERTY_CONFIG_REALTIME					\
-	(HFI_PROPERTY_CONFIG_OX_START + 0x002)
-#define HFI_PROPERTY_CONFIG_PRIORITY					\
-	(HFI_PROPERTY_CONFIG_OX_START + 0x003)
-#define HFI_PROPERTY_CONFIG_BATCH_INFO					\
-	(HFI_PROPERTY_CONFIG_OX_START + 0x004)
-
-#define HFI_PROPERTY_PARAM_VDEC_OX_START				\
-	(HFI_DOMAIN_BASE_VDEC + HFI_ARCH_OX_OFFSET + 0x3000)
-#define HFI_PROPERTY_PARAM_VDEC_CONTINUE_DATA_TRANSFER	\
-	(HFI_PROPERTY_PARAM_VDEC_OX_START + 0x001)
-#define HFI_PROPERTY_PARAM_VDEC_DISPLAY_PICTURE_BUFFER_COUNT\
-	(HFI_PROPERTY_PARAM_VDEC_OX_START + 0x002)
-#define HFI_PROPERTY_PARAM_VDEC_MULTI_VIEW_SELECT		\
-	(HFI_PROPERTY_PARAM_VDEC_OX_START + 0x003)
-#define HFI_PROPERTY_PARAM_VDEC_PICTURE_TYPE_DECODE		\
-	(HFI_PROPERTY_PARAM_VDEC_OX_START + 0x004)
-#define HFI_PROPERTY_PARAM_VDEC_OUTPUT_ORDER			\
-	(HFI_PROPERTY_PARAM_VDEC_OX_START + 0x005)
-#define HFI_PROPERTY_PARAM_VDEC_MB_QUANTIZATION			\
-	(HFI_PROPERTY_PARAM_VDEC_OX_START + 0x006)
-#define HFI_PROPERTY_PARAM_VDEC_NUM_CONCEALED_MB		\
-	(HFI_PROPERTY_PARAM_VDEC_OX_START + 0x007)
-#define HFI_PROPERTY_PARAM_VDEC_H264_ENTROPY_SWITCHING	\
-	(HFI_PROPERTY_PARAM_VDEC_OX_START + 0x008)
-#define HFI_PROPERTY_PARAM_VDEC_OUTPUT2_KEEP_ASPECT_RATIO\
-	(HFI_PROPERTY_PARAM_VDEC_OX_START + 0x009)
-#define HFI_PROPERTY_PARAM_VDEC_FRAME_RATE_EXTRADATA  \
-	(HFI_PROPERTY_PARAM_VDEC_OX_START + 0x00A)
-#define HFI_PROPERTY_PARAM_VDEC_PANSCAN_WNDW_EXTRADATA \
-	(HFI_PROPERTY_PARAM_VDEC_OX_START + 0x00B)
-#define HFI_PROPERTY_PARAM_VDEC_RECOVERY_POINT_SEI_EXTRADATA \
-	(HFI_PROPERTY_PARAM_VDEC_OX_START + 0x00C)
-#define HFI_PROPERTY_PARAM_VDEC_THUMBNAIL_MODE   \
-	(HFI_PROPERTY_PARAM_VDEC_OX_START + 0x00D)
-
-#define HFI_PROPERTY_PARAM_VDEC_FRAME_ASSEMBLY		\
-	(HFI_PROPERTY_PARAM_VDEC_OX_START + 0x00E)
-#define HFI_PROPERTY_PARAM_VDEC_CLOSED_CAPTION_EXTRADATA	\
-	(HFI_PROPERTY_PARAM_VDEC_OX_START + 0x00F)
-#define HFI_PROPERTY_PARAM_VDEC_AFD_EXTRADATA		\
-	(HFI_PROPERTY_PARAM_VDEC_OX_START + 0x010)
-#define HFI_PROPERTY_PARAM_VDEC_VC1_FRAMEDISP_EXTRADATA		\
-	(HFI_PROPERTY_PARAM_VDEC_OX_START + 0x011)
-#define HFI_PROPERTY_PARAM_VDEC_VC1_SEQDISP_EXTRADATA		\
-	(HFI_PROPERTY_PARAM_VDEC_OX_START + 0x012)
-#define HFI_PROPERTY_PARAM_VDEC_TIMESTAMP_EXTRADATA			\
-	(HFI_PROPERTY_PARAM_VDEC_OX_START + 0x013)
-#define HFI_PROPERTY_PARAM_VDEC_INTERLACE_VIDEO_EXTRADATA	\
-	(HFI_PROPERTY_PARAM_VDEC_OX_START + 0x014)
-#define HFI_PROPERTY_PARAM_VDEC_AVC_SESSION_SELECT \
-	(HFI_PROPERTY_PARAM_VDEC_OX_START + 0x015)
-
-#define HFI_PROPERTY_CONFIG_VDEC_OX_START				\
-	(HFI_DOMAIN_BASE_VDEC + HFI_ARCH_OX_OFFSET + 0x0000)
-#define HFI_PROPERTY_CONFIG_VDEC_POST_LOOP_DEBLOCKER	\
-	(HFI_PROPERTY_CONFIG_VDEC_OX_START + 0x001)
-#define HFI_PROPERTY_CONFIG_VDEC_MB_ERROR_MAP_REPORTING	\
-	(HFI_PROPERTY_CONFIG_VDEC_OX_START + 0x002)
-#define HFI_PROPERTY_CONFIG_VDEC_MB_ERROR_MAP			\
-	(HFI_PROPERTY_CONFIG_VDEC_OX_START + 0x003)
-
-#define HFI_PROPERTY_PARAM_VENC_OX_START				\
-	(HFI_DOMAIN_BASE_VENC + HFI_ARCH_OX_OFFSET + 0x5000)
-#define  HFI_PROPERTY_PARAM_VENC_MULTI_SLICE_INFO       \
-	(HFI_PROPERTY_PARAM_VENC_OX_START + 0x001)
-#define  HFI_PROPERTY_PARAM_VENC_H264_IDR_S3D_FRAME_PACKING_NAL \
-	(HFI_PROPERTY_PARAM_VENC_OX_START + 0x002)
-
-#define HFI_PROPERTY_CONFIG_VENC_OX_START				\
-	(HFI_DOMAIN_BASE_VENC + HFI_ARCH_OX_OFFSET + 0x6000)
-#define  HFI_PROPERTY_CONFIG_VENC_FRAME_QP				\
-	(HFI_PROPERTY_CONFIG_VENC_OX_START + 0x001)
-
-#define HFI_PROPERTY_PARAM_VPE_OX_START					\
-	(HFI_DOMAIN_BASE_VPE + HFI_ARCH_OX_OFFSET + 0x7000)
-#define HFI_PROPERTY_CONFIG_VPE_OX_START				\
-	(HFI_DOMAIN_BASE_VPE + HFI_ARCH_OX_OFFSET + 0x8000)
-
-struct hfi_batch_info {
-	u32 input_batch_count;
-	u32 output_batch_count;
-};
-
-struct hfi_buffer_count_actual {
-	u32 buffer_type;
-	u32 buffer_count_actual;
-};
-
-struct hfi_buffer_requirements {
-	u32 buffer_type;
-	u32 buffer_size;
-	u32 buffer_region_size;
-	u32 buffer_hold_count;
-	u32 buffer_count_min;
-	u32 buffer_count_actual;
-	u32 contiguous;
-	u32 buffer_alignment;
-};
-
-#define HFI_CHROMA_SITE_0			(HFI_OX_BASE + 0x1)
-#define HFI_CHROMA_SITE_1			(HFI_OX_BASE + 0x2)
-#define HFI_CHROMA_SITE_2			(HFI_OX_BASE + 0x3)
-#define HFI_CHROMA_SITE_3			(HFI_OX_BASE + 0x4)
-#define HFI_CHROMA_SITE_4			(HFI_OX_BASE + 0x5)
-#define HFI_CHROMA_SITE_5			(HFI_OX_BASE + 0x6)
-
-struct hfi_data_payload {
-	u32 size;
-	u8 rg_data[1];
-};
-
-struct hfi_enable_picture {
-	u32 picture_type;
-};
-
-struct hfi_display_picture_buffer_count {
-	int enable;
-	u32 count;
-};
-
-struct hfi_extra_data_header_config {
-	u32 type;
-	u32 buffer_type;
-	u32 version;
-	u32 port_index;
-	u32 client_extra_data_id;
-};
-
-struct hfi_interlace_format_supported {
-	u32 buffer_type;
-	u32 format;
-};
-
-struct hfi_mb_error_map {
-	u32 error_map_size;
-	u8 rg_error_map[1];
-};
-
-struct hfi_metadata_pass_through {
-	int enable;
-	u32 size;
-};
-
-struct hfi_multi_view_select {
-	u32 view_index;
-};
-
-#define HFI_PRIORITY_LOW		10
-#define HFI_PRIOIRTY_MEDIUM		20
-#define HFI_PRIORITY_HIGH		30
-
-#define HFI_OUTPUT_ORDER_DISPLAY	(HFI_OX_BASE + 0x1)
-#define HFI_OUTPUT_ORDER_DECODE		(HFI_OX_BASE + 0x2)
-
-#define HFI_RATE_CONTROL_OFF		(HFI_OX_BASE + 0x1)
-#define HFI_RATE_CONTROL_VBR_VFR	(HFI_OX_BASE + 0x2)
-#define HFI_RATE_CONTROL_VBR_CFR	(HFI_OX_BASE + 0x3)
-#define HFI_RATE_CONTROL_CBR_VFR	(HFI_OX_BASE + 0x4)
-#define HFI_RATE_CONTROL_CBR_CFR	(HFI_OX_BASE + 0x5)
-
-struct hfi_uncompressed_plane_actual_constraints_info {
-	u32 buffer_type;
-	u32 num_planes;
-	struct hfi_uncompressed_plane_constraints rg_plane_format[1];
-};
-
-#define HFI_CMD_SYS_OX_START		\
-(HFI_DOMAIN_BASE_COMMON + HFI_ARCH_OX_OFFSET + HFI_CMD_START_OFFSET + 0x0000)
-#define HFI_CMD_SYS_SESSION_ABORT	(HFI_CMD_SYS_OX_START + 0x001)
-#define HFI_CMD_SYS_PING		(HFI_CMD_SYS_OX_START + 0x002)
-
-#define HFI_CMD_SESSION_OX_START	\
-(HFI_DOMAIN_BASE_COMMON + HFI_ARCH_OX_OFFSET + HFI_CMD_START_OFFSET + 0x1000)
-#define HFI_CMD_SESSION_LOAD_RESOURCES	(HFI_CMD_SESSION_OX_START + 0x001)
-#define HFI_CMD_SESSION_START		(HFI_CMD_SESSION_OX_START + 0x002)
-#define HFI_CMD_SESSION_STOP		(HFI_CMD_SESSION_OX_START + 0x003)
-#define HFI_CMD_SESSION_EMPTY_BUFFER	(HFI_CMD_SESSION_OX_START + 0x004)
-#define HFI_CMD_SESSION_FILL_BUFFER	(HFI_CMD_SESSION_OX_START + 0x005)
-#define HFI_CMD_SESSION_SUSPEND		(HFI_CMD_SESSION_OX_START + 0x006)
-#define HFI_CMD_SESSION_RESUME		(HFI_CMD_SESSION_OX_START + 0x007)
-#define HFI_CMD_SESSION_FLUSH		(HFI_CMD_SESSION_OX_START + 0x008)
-#define HFI_CMD_SESSION_GET_PROPERTY	(HFI_CMD_SESSION_OX_START + 0x009)
-#define HFI_CMD_SESSION_PARSE_SEQUENCE_HEADER	\
-	(HFI_CMD_SESSION_OX_START + 0x00A)
-#define HFI_CMD_SESSION_RELEASE_BUFFERS		\
-	(HFI_CMD_SESSION_OX_START + 0x00B)
-#define HFI_CMD_SESSION_RELEASE_RESOURCES	\
-	(HFI_CMD_SESSION_OX_START + 0x00C)
-
-#define HFI_MSG_SYS_OX_START			\
-(HFI_DOMAIN_BASE_COMMON + HFI_ARCH_OX_OFFSET + HFI_MSG_START_OFFSET + 0x0000)
-#define HFI_MSG_SYS_IDLE		(HFI_MSG_SYS_OX_START + 0x1)
-#define HFI_MSG_SYS_PING_ACK	(HFI_MSG_SYS_OX_START + 0x2)
-#define HFI_MSG_SYS_PROPERTY_INFO	(HFI_MSG_SYS_OX_START + 0x3)
-#define HFI_MSG_SYS_SESSION_ABORT_DONE	(HFI_MSG_SYS_OX_START + 0x4)
-
-#define HFI_MSG_SESSION_OX_START		\
-(HFI_DOMAIN_BASE_COMMON + HFI_ARCH_OX_OFFSET + HFI_MSG_START_OFFSET + 0x1000)
-#define HFI_MSG_SESSION_LOAD_RESOURCES_DONE	(HFI_MSG_SESSION_OX_START + 0x1)
-#define HFI_MSG_SESSION_START_DONE		(HFI_MSG_SESSION_OX_START + 0x2)
-#define HFI_MSG_SESSION_STOP_DONE		(HFI_MSG_SESSION_OX_START + 0x3)
-#define HFI_MSG_SESSION_SUSPEND_DONE	(HFI_MSG_SESSION_OX_START + 0x4)
-#define HFI_MSG_SESSION_RESUME_DONE		(HFI_MSG_SESSION_OX_START + 0x5)
-#define HFI_MSG_SESSION_FLUSH_DONE		(HFI_MSG_SESSION_OX_START + 0x6)
-#define HFI_MSG_SESSION_EMPTY_BUFFER_DONE	(HFI_MSG_SESSION_OX_START + 0x7)
-#define HFI_MSG_SESSION_FILL_BUFFER_DONE	(HFI_MSG_SESSION_OX_START + 0x8)
-#define HFI_MSG_SESSION_PROPERTY_INFO		(HFI_MSG_SESSION_OX_START + 0x9)
-#define HFI_MSG_SESSION_RELEASE_RESOURCES_DONE	\
-	(HFI_MSG_SESSION_OX_START + 0xA)
-#define HFI_MSG_SESSION_PARSE_SEQUENCE_HEADER_DONE		\
-	(HFI_MSG_SESSION_OX_START + 0xB)
-#define  HFI_MSG_SESSION_RELEASE_BUFFERS_DONE			\
-	(HFI_MSG_SESSION_OX_START + 0xC)
-
-struct hfi_cmd_sys_session_abort_packet {
-	u32 size;
-	u32 packet_type;
-	u32 session_id;
-};
-
-struct hfi_cmd_sys_ping_packet {
-	u32 size;
-	u32 packet_type;
-	u32 client_data;
-};
-
-struct hfi_cmd_session_load_resources_packet {
-	u32 size;
-	u32 packet_type;
-	u32 session_id;
-};
-
-struct hfi_cmd_session_start_packet {
-	u32 size;
-	u32 packet_type;
-	u32 session_id;
-};
-
-struct hfi_cmd_session_stop_packet {
-	u32 size;
-	u32 packet_type;
-	u32 session_id;
-};
-
-struct hfi_cmd_session_empty_buffer_compressed_packet {
-	u32 size;
-	u32 packet_type;
-	u32 session_id;
-	u32 time_stamp_hi;
-	u32 time_stamp_lo;
-	u32 flags;
-	u32 mark_target;
-	u32 mark_data;
-	u32 offset;
-	u32 alloc_len;
-	u32 filled_len;
-	u32 input_tag;
-	u8 *packet_buffer;
-	u8 *extra_data_buffer;
-	u32 rgData[0];
-};
-
-struct hfi_cmd_session_empty_buffer_uncompressed_plane0_packet {
-	u32 size;
-	u32 packet_type;
-	u32 session_id;
-	u32 view_id;
-	u32 time_stamp_hi;
-	u32 time_stamp_lo;
-	u32 flags;
-	u32 mark_target;
-	u32 mark_data;
-	u32 alloc_len;
-	u32 filled_len;
-	u32 offset;
-	u32 input_tag;
-	u8 *packet_buffer;
-	u8 *extra_data_buffer;
-	u32 rgData[0];
-};
-
-struct hfi_cmd_session_empty_buffer_uncompressed_plane1_packet {
-	u32 flags;
-	u32 alloc_len;
-	u32 filled_len;
-	u32 offset;
-	u8 *packet_buffer2;
-	u32 rgData[0];
-};
-
-struct hfi_cmd_session_empty_buffer_uncompressed_plane2_packet {
-	u32 flags;
-	u32 alloc_len;
-	u32 filled_len;
-	u32 offset;
-	u8 *packet_buffer3;
-	u32 rgData[0];
-};
-
-struct hfi_cmd_session_fill_buffer_packet {
-	u32 size;
-	u32 packet_type;
-	u32 session_id;
-	u32 stream_id;
-	u32 offset;
-	u32 alloc_len;
-	u32 filled_len;
-	u32 output_tag;
-	u8 *packet_buffer;
-	u8 *extra_data_buffer;
-	u32 rgData[0];
-};
-
-struct hfi_cmd_session_flush_packet {
-	u32 size;
-	u32 packet_type;
-	u32 session_id;
-	u32 flush_type;
-};
-
-struct hfi_cmd_session_suspend_packet {
-	u32 size;
-	u32 packet_type;
-	u32 session_id;
-};
-
-struct hfi_cmd_session_resume_packet {
-	u32 size;
-	u32 packet_type;
-	u32 session_id;
-};
-
-struct hfi_cmd_session_get_property_packet {
-	u32 size;
-	u32 packet_type;
-	u32 session_id;
-	u32 num_properties;
-	u32 rg_property_data[1];
-};
-
-struct hfi_cmd_session_release_buffer_packet {
-	u32 size;
-	u32 packet_type;
-	u32 session_id;
-	u32 buffer_type;
-	u32 buffer_size;
-	u32 extra_data_size;
-	int response_req;
-	u32 num_buffers;
-	u32 rg_buffer_info[1];
-};
-
-struct hfi_cmd_session_release_resources_packet {
-	u32 size;
-	u32 packet_type;
-	u32 session_id;
-};
-
-struct hfi_cmd_session_parse_sequence_header_packet {
-	u32 size;
-	u32 packet_type;
-	u32 session_id;
-	u32 header_len;
-	u8 *packet_buffer;
-};
-
-struct hfi_msg_sys_session_abort_done_packet {
-	u32 size;
-	u32 packet_type;
-	u32 session_id;
-	u32 error_type;
-};
-
-struct hfi_msg_sys_idle_packet {
-	u32 size;
-	u32 packet_type;
-};
-
-struct hfi_msg_sys_ping_ack_packet {
-	u32 size;
-	u32 packet_type;
-	u32 client_data;
-};
-
-struct hfi_msg_sys_property_info_packet {
-	u32 size;
-	u32 packet_type;
-	u32 num_properties;
-	u32 rg_property_data[1];
-};
-
-struct hfi_msg_session_load_resources_done_packet {
-	u32 size;
-	u32 packet_type;
-	u32 session_id;
-	u32 error_type;
-};
-
-struct hfi_msg_session_start_done_packet {
-	u32 size;
-	u32 packet_type;
-	u32 session_id;
-	u32 error_type;
-};
-
-struct hfi_msg_session_stop_done_packet {
-	u32 size;
-	u32 packet_type;
-	u32 session_id;
-	u32 error_type;
-};
-
-struct hfi_msg_session_suspend_done_packet {
-	u32 size;
-	u32 packet_type;
-	u32 session_id;
-	u32 error_type;
-};
-
-struct hfi_msg_session_resume_done_packet {
-	u32 size;
-	u32 packet_type;
-	u32 session_id;
-	u32 error_type;
-};
-
-struct hfi_msg_session_flush_done_packet {
-	u32 size;
-	u32 packet_type;
-	u32 session_id;
-	u32 error_type;
-	u32 flush_type;
-};
-
-struct hfi_msg_session_empty_buffer_done_packet {
-	u32 size;
-	u32 packet_type;
-	u32 session_id;
-	u32 error_type;
-	u32 offset;
-	u32 filled_len;
-	u32 input_tag;
-	u8 *packet_buffer;
-	u8 *extra_data_buffer;
-	u32 rgData[0];
-};
-
-struct hfi_msg_session_fill_buffer_done_compressed_packet {
-	u32 size;
-	u32 packet_type;
-	u32 session_id;
-	u32 time_stamp_hi;
-	u32 time_stamp_lo;
-	u32 error_type;
-	u32 flags;
-	u32 mark_target;
-	u32 mark_data;
-	u32 stats;
-	u32 offset;
-	u32 alloc_len;
-	u32 filled_len;
-	u32 input_tag;
-	u32 output_tag;
-	u32 picture_type;
-	u8 *packet_buffer;
-	u8 *extra_data_buffer;
-	u32 rgData[0];
-};
-
-struct hfi_msg_session_fbd_uncompressed_plane0_packet {
-	u32 size;
-	u32 packet_type;
-	u32 session_id;
-	u32 stream_id;
-	u32 view_id;
-	u32 error_type;
-	u32 time_stamp_hi;
-	u32 time_stamp_lo;
-	u32 flags;
-	u32 mark_target;
-	u32 mark_data;
-	u32 stats;
-	u32 alloc_len;
-	u32 filled_len;
-	u32 offset;
-	u32 frame_width;
-	u32 frame_height;
-	u32 start_x_coord;
-	u32 start_y_coord;
-	u32 input_tag;
-	u32 input_tag2;
-	u32 output_tag;
-	u32 picture_type;
-	u8 *packet_buffer;
-	u8 *extra_data_buffer;
-	u32 rgData[0];
-};
-
-struct hfi_msg_session_fill_buffer_done_uncompressed_plane1_packet {
-	u32 flags;
-	u32 alloc_len;
-	u32 filled_len;
-	u32 offset;
-	u8 *packet_buffer2;
-	u32 rgData[0];
-};
-
-struct hfi_msg_session_fill_buffer_done_uncompressed_plane2_packet {
-	u32 flags;
-	u32 alloc_len;
-	u32 filled_len;
-	u32 offset;
-	u8 *packet_buffer3;
-	u32 rgData[0];
-};
-
-struct hfi_msg_session_parse_sequence_header_done_packet {
-	u32 size;
-	u32 packet_type;
-	u32 session_id;
-	u32 error_type;
-	u32 num_properties;
-	u32 rg_property_data[1];
-};
-
-struct hfi_msg_session_property_info_packet {
-	u32 size;
-	u32 packet_type;
-	u32 session_id;
-	u32 num_properties;
-	u32 rg_property_data[1];
-};
-
-struct hfi_msg_session_release_resources_done_packet {
-	u32 size;
-	u32 packet_type;
-	u32 session_id;
-	u32 error_type;
-};
-
-struct hfi_msg_session_release_buffers_done_packet {
-	u32 size;
-	u32 packet_type;
-	u32 session_id;
-	u32 error_type;
-	u32 num_buffers;
-	u32 rg_buffer_info[1];
-};
-
-struct hfi_extradata_mb_quantization_payload {
-	u8 rg_mb_qp[1];
-};
-
-struct hfi_extradata_vc1_pswnd {
-	u32 ps_wnd_h_offset;
-	u32 ps_wnd_v_offset;
-	u32 ps_wnd_width;
-	u32 ps_wnd_height;
-};
-
-struct hfi_extradata_vc1_framedisp_payload {
-	u32 res_pic;
-	u32 ref;
-	u32 range_map_present;
-	u32 range_map_y;
-	u32 range_map_uv;
-	u32 num_pan_scan_wnds;
-	struct hfi_extradata_vc1_pswnd rg_ps_wnd[1];
-};
-
-struct hfi_extradata_vc1_seqdisp_payload {
-	u32 prog_seg_frm;
-	u32 uv_sampling_fmt;
-	u32 color_fmt_flag;
-	u32 color_primaries;
-	u32 transfer_char;
-	u32 mat_coeff;
-	u32 aspect_ratio;
-	u32 aspect_horiz;
-	u32 aspect_vert;
-};
-
-struct hfi_extradata_timestamp_payload {
-	u32 time_stamp_low;
-	u32 time_stamp_high;
-};
-
-
-struct hfi_extradata_s3d_frame_packing_payload {
-	u32 fpa_id;
-	int cancel_flag;
-	u32 fpa_type;
-	int quin_cunx_flag;
-	u32 content_interprtation_type;
-	int spatial_flipping_flag;
-	int frame0_flipped_flag;
-	int field_views_flag;
-	int current_frame_isFrame0_flag;
-	int frame0_self_contained_flag;
-	int frame1_self_contained_flag;
-	u32 frame0_graid_pos_x;
-	u32 frame0_graid_pos_y;
-	u32 frame1_graid_pos_x;
-	u32 frame1_graid_pos_y;
-	u32 fpa_reserved_byte;
-	u32 fpa_repetition_period;
-	int fpa_extension_flag;
-};
-
-struct hfi_extradata_interlace_video_payload {
-	u32 format;
-};
-
-struct hfi_extradata_num_concealed_mb_payload {
-	u32 num_mb_concealed;
-};
-
-struct hfi_extradata_sliceinfo {
-	u32 offset_in_stream;
-	u32 slice_length;
-};
-
-struct hfi_extradata_multislice_info_payload {
-	u32 num_slices;
-	struct hfi_extradata_sliceinfo rg_slice_info[1];
-};
-
-struct hfi_index_extradata_input_crop_payload {
-	u32 size;
-	u32 version;
-	u32 port_index;
-	u32 left;
-	u32 top;
-	u32 width;
-	u32 height;
-};
-
-struct hfi_index_extradata_digital_zoom_payload {
-	u32 size;
-	u32 version;
-	u32 port_index;
-	int width;
-	int height;
-};
-
-struct hfi_index_extradata_aspect_ratio_payload {
-	u32 size;
-	u32 version;
-	u32 port_index;
-	u32 aspect_width;
-	u32 aspect_height;
-};
-struct hfi_extradata_panscan_wndw_payload {
-	u32 num_window;
-	struct hfi_extradata_vc1_pswnd wnd[1];
-};
-
-struct hfi_extradata_frame_type_payload {
-	u32 frame_rate;
-};
-
-struct hfi_extradata_recovery_point_sei_payload {
-	u32 flag;
-};
-
 struct vidc_mem_addr {
 	u8 *align_device_addr;
 	u8 *align_virtual_addr;
@@ -921,11 +136,6 @@
 	VCODEC_MAX_CLKS
 };
 
-enum mem_type {
-	DDR_MEM = 0x1,
-	OCMEM_MEM = 0x2,
-};
-
 struct load_freq_table {
 	u32 load;
 	u32 freq;
@@ -968,7 +178,7 @@
 	u32 device_id;
 	spinlock_t read_lock;
 	spinlock_t write_lock;
-	void (*callback) (u32 response, void *callback);
+	msm_vidc_callback callback;
 	struct vidc_mem_addr iface_q_table;
 	struct vidc_mem_addr qdss;
 	struct vidc_mem_addr sfr;
@@ -986,49 +196,7 @@
 	struct venus_resources resources;
 };
 
-struct hal_session {
-	struct list_head list;
-	u32 session_id;
-	u32 is_decoder;
-	struct venus_hfi_device *device;
-};
-
-struct hal_device_data {
-	struct list_head dev_head;
-	int dev_count;
-};
-
-extern struct hal_device_data hal_ctxt;
-
-int venus_hfi_iface_msgq_read(struct venus_hfi_device *device, void *pkt);
-int venus_hfi_iface_dbgq_read(struct venus_hfi_device *device, void *pkt);
-
-/* Interrupt Processing:*/
-void hfi_response_handler(struct venus_hfi_device *device);
-
 void venus_hfi_delete_device(void *device);
-
-int venus_hfi_scale_clocks(struct venus_hfi_device *device, int load);
-
-void *venus_hfi_get_device(u32 device_id,
-	struct platform_device *pdev,
-	void (*callback) (enum command_response cmd, void *data));
-
-int venus_hfi_scale_bus(struct venus_hfi_device *device, int load,
-				enum session_type type, enum mem_type mtype);
-int venus_hfi_set_ocmem(struct venus_hfi_device *device,
-	struct ocmem_buf *ocmem);
-int venus_hfi_unset_ocmem(struct venus_hfi_device *device);
-int venus_hfi_alloc_ocmem(struct venus_hfi_device *device,
-		unsigned long size);
-int venus_hfi_free_ocmem(struct venus_hfi_device *device);
-int venus_hfi_is_ocmem_present(struct venus_hfi_device *device);
-
-int venus_hfi_get_domain(struct venus_hfi_device *device,
-						 enum msm_vidc_io_maps iomap);
-int venus_hfi_iommu_get_map(struct venus_hfi_device *device,
-			struct msm_vidc_iommu_info maps[MAX_MAP]);
-int venus_hfi_load_fw(struct venus_hfi_device *device);
-void venus_hfi_unload_fw(struct venus_hfi_device *device);
-
+int venus_hfi_initialize(struct hfi_device *hdev, u32 device_id,
+	struct platform_device *pdev, hfi_cmd_response_callback callback);
 #endif
diff --git a/drivers/media/video/msm_vidc/vidc_hfi.c b/drivers/media/video/msm_vidc/vidc_hfi.c
new file mode 100644
index 0000000..f09d3d5
--- /dev/null
+++ b/drivers/media/video/msm_vidc/vidc_hfi.c
@@ -0,0 +1,68 @@
+/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+#include <linux/slab.h>
+#include "msm_vidc_debug.h"
+#include "vidc_hfi_api.h"
+#include "venus_hfi.h"
+
+struct hal_device_data hal_ctxt;
+
+void *vidc_hfi_initialize(enum msm_vidc_hfi_type hfi_type, u32 device_id,
+			struct platform_device *pdev,
+			hfi_cmd_response_callback callback)
+{
+	struct hfi_device *hdev = NULL;
+	hdev = (struct hfi_device *)
+			kzalloc(sizeof(struct hfi_device), GFP_KERNEL);
+	if (!hdev) {
+		dprintk(VIDC_ERR, "%s: failed to allocate hdev\n", __func__);
+		return NULL;
+	}
+
+	switch (hfi_type) {
+	case VIDC_HFI_VENUS:
+		venus_hfi_initialize(hdev, device_id, pdev, callback);
+		break;
+
+	case VIDC_HFI_Q6:
+	default:
+		dprintk(VIDC_ERR, "Unsupported host-firmware interface\n");
+		goto err_hfi_init;
+	}
+	return hdev;
+
+err_hfi_init:
+	kfree(hdev);
+	return NULL;
+}
+
+void vidc_hfi_deinitialize(enum msm_vidc_hfi_type hfi_type,
+			struct hfi_device *hdev)
+{
+	if (!hdev) {
+		dprintk(VIDC_ERR, "%s invalid device %p", __func__, hdev);
+		return;
+	}
+
+	switch (hfi_type) {
+	case VIDC_HFI_VENUS:
+		venus_hfi_delete_device(hdev->hfi_device_data);
+		break;
+
+	case VIDC_HFI_Q6:
+	default:
+		dprintk(VIDC_ERR, "Unsupported host-firmware interface\n");
+	}
+	kfree(hdev);
+}
+
diff --git a/drivers/media/video/msm_vidc/vidc_hfi.h b/drivers/media/video/msm_vidc/vidc_hfi.h
new file mode 100644
index 0000000..6ff0921
--- /dev/null
+++ b/drivers/media/video/msm_vidc/vidc_hfi.h
@@ -0,0 +1,826 @@
+/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+#ifndef __H_VIDC_HFI_H__
+#define __H_VIDC_HFI_H__
+
+#include "vidc_hfi_helper.h"
+#include "vidc_hfi_api.h"
+
+#define HFI_EVENT_SESSION_SEQUENCE_CHANGED (HFI_OX_BASE + 0x3)
+#define HFI_EVENT_SESSION_PROPERTY_CHANGED (HFI_OX_BASE + 0x4)
+
+#define HFI_EVENT_DATA_SEQUENCE_CHANGED_SUFFICIENT_BUFFER_RESOURCES	\
+	(HFI_OX_BASE + 0x1)
+#define HFI_EVENT_DATA_SEQUENCE_CHANGED_INSUFFICIENT_BUFFER_RESOURCES	\
+	(HFI_OX_BASE + 0x2)
+
+#define HFI_BUFFERFLAG_EOS				0x00000001
+#define HFI_BUFFERFLAG_STARTTIME		0x00000002
+#define HFI_BUFFERFLAG_DECODEONLY		0x00000004
+#define HFI_BUFFERFLAG_DATACORRUPT		0x00000008
+#define HFI_BUFFERFLAG_ENDOFFRAME		0x00000010
+#define HFI_BUFFERFLAG_SYNCFRAME		0x00000020
+#define HFI_BUFFERFLAG_EXTRADATA		0x00000040
+#define HFI_BUFFERFLAG_CODECCONFIG		0x00000080
+#define HFI_BUFFERFLAG_TIMESTAMPINVALID	0x00000100
+#define HFI_BUFFERFLAG_READONLY			0x00000200
+#define HFI_BUFFERFLAG_ENDOFSUBFRAME	0x00000400
+#define HFI_BUFFERFLAG_EOSEQ			0x00200000
+#define HFI_BUFFERFLAG_DISCONTINUITY	0x80000000
+#define HFI_BUFFERFLAG_TEI				0x40000000
+
+#define HFI_ERR_SESSION_EMPTY_BUFFER_DONE_OUTPUT_PENDING	\
+	(HFI_OX_BASE + 0x1001)
+#define HFI_ERR_SESSION_SAME_STATE_OPERATION		\
+	(HFI_OX_BASE + 0x1002)
+#define HFI_ERR_SESSION_SYNC_FRAME_NOT_DETECTED		\
+	(HFI_OX_BASE + 0x1003)
+#define  HFI_ERR_SESSION_START_CODE_NOT_FOUND		\
+	(HFI_OX_BASE + 0x1004)
+
+#define HFI_BUFFER_INTERNAL_SCRATCH (HFI_OX_BASE + 0x1)
+#define HFI_BUFFER_EXTRADATA_INPUT (HFI_OX_BASE + 0x2)
+#define HFI_BUFFER_EXTRADATA_OUTPUT (HFI_OX_BASE + 0x3)
+#define HFI_BUFFER_EXTRADATA_OUTPUT2 (HFI_OX_BASE + 0x4)
+
+#define HFI_BUFFER_MODE_STATIC (HFI_OX_BASE + 0x1)
+#define HFI_BUFFER_MODE_RING (HFI_OX_BASE + 0x2)
+
+#define HFI_FLUSH_INPUT (HFI_OX_BASE + 0x1)
+#define HFI_FLUSH_OUTPUT (HFI_OX_BASE + 0x2)
+#define HFI_FLUSH_OUTPUT2 (HFI_OX_BASE + 0x3)
+#define HFI_FLUSH_ALL (HFI_OX_BASE + 0x4)
+
+#define HFI_EXTRADATA_NONE					0x00000000
+#define HFI_EXTRADATA_MB_QUANTIZATION		0x00000001
+#define HFI_EXTRADATA_INTERLACE_VIDEO		0x00000002
+#define HFI_EXTRADATA_VC1_FRAMEDISP			0x00000003
+#define HFI_EXTRADATA_VC1_SEQDISP			0x00000004
+#define HFI_EXTRADATA_TIMESTAMP				0x00000005
+#define HFI_EXTRADATA_S3D_FRAME_PACKING		0x00000006
+#define HFI_EXTRADATA_FRAME_RATE			0x00000007
+#define HFI_EXTRADATA_PANSCAN_WINDOW		0x00000008
+#define HFI_EXTRADATA_RECOVERY_POINT_SEI	0x00000009
+#define HFI_EXTRADATA_CLOSED_CAPTION_UD		0x0000000A
+#define HFI_EXTRADATA_AFD_UD				0x0000000B
+#define HFI_EXTRADATA_MULTISLICE_INFO		0x7F100000
+#define HFI_EXTRADATA_NUM_CONCEALED_MB		0x7F100001
+#define HFI_EXTRADATA_INDEX					0x7F100002
+#define HFI_EXTRADATA_METADATA_FILLER		0x7FE00002
+
+#define HFI_INDEX_EXTRADATA_INPUT_CROP		0x0700000E
+#define HFI_INDEX_EXTRADATA_DIGITAL_ZOOM	0x07000010
+#define HFI_INDEX_EXTRADATA_ASPECT_RATIO	0x7F100003
+
+struct hfi_buffer_alloc_mode {
+	u32 buffer_type;
+	u32 buffer_mode;
+};
+
+
+struct hfi_index_extradata_config {
+	int enable;
+	u32 index_extra_data_id;
+};
+
+struct hfi_extradata_header {
+	u32 size;
+	u32 version;
+	u32 port_index;
+	u32 type;
+	u32 data_size;
+	u8 rg_data[1];
+};
+
+#define HFI_INTERLACE_FRAME_PROGRESSIVE					0x01
+#define HFI_INTERLACE_INTERLEAVE_FRAME_TOPFIELDFIRST	0x02
+#define HFI_INTERLACE_INTERLEAVE_FRAME_BOTTOMFIELDFIRST	0x04
+#define HFI_INTERLACE_FRAME_TOPFIELDFIRST				0x08
+#define HFI_INTERLACE_FRAME_BOTTOMFIELDFIRST			0x10
+
+#define HFI_PROPERTY_SYS_OX_START			\
+	(HFI_DOMAIN_BASE_COMMON + HFI_ARCH_OX_OFFSET + 0x0000)
+#define HFI_PROPERTY_SYS_IDLE_INDICATOR		\
+	(HFI_PROPERTY_SYS_OX_START + 0x001)
+
+#define HFI_PROPERTY_PARAM_OX_START				\
+	(HFI_DOMAIN_BASE_COMMON + HFI_ARCH_OX_OFFSET + 0x1000)
+#define HFI_PROPERTY_PARAM_BUFFER_COUNT_ACTUAL			\
+	(HFI_PROPERTY_PARAM_OX_START + 0x001)
+#define HFI_PROPERTY_PARAM_UNCOMPRESSED_PLANE_ACTUAL_CONSTRAINTS_INFO	\
+	(HFI_PROPERTY_PARAM_OX_START + 0x002)
+#define HFI_PROPERTY_PARAM_INTERLACE_FORMAT_SUPPORTED	\
+	(HFI_PROPERTY_PARAM_OX_START + 0x003)
+#define HFI_PROPERTY_PARAM_CHROMA_SITE					\
+(HFI_PROPERTY_PARAM_OX_START + 0x004)
+#define HFI_PROPERTY_PARAM_EXTRA_DATA_HEADER_CONFIG		\
+	(HFI_PROPERTY_PARAM_OX_START + 0x005)
+#define HFI_PROPERTY_PARAM_INDEX_EXTRADATA             \
+	(HFI_PROPERTY_PARAM_OX_START + 0x006)
+#define HFI_PROPERTY_PARAM_DIVX_FORMAT					\
+	(HFI_PROPERTY_PARAM_OX_START + 0x007)
+#define HFI_PROPERTY_PARAM_BUFFER_ALLOC_MODE			\
+	(HFI_PROPERTY_PARAM_OX_START + 0x008)
+#define HFI_PROPERTY_PARAM_S3D_FRAME_PACKING_EXTRADATA	\
+	(HFI_PROPERTY_PARAM_OX_START + 0x009)
+
+#define HFI_PROPERTY_CONFIG_OX_START					\
+	(HFI_DOMAIN_BASE_COMMON + HFI_ARCH_OX_OFFSET + 0x02000)
+#define HFI_PROPERTY_CONFIG_BUFFER_REQUIREMENTS			\
+	(HFI_PROPERTY_CONFIG_OX_START + 0x001)
+#define HFI_PROPERTY_CONFIG_REALTIME					\
+	(HFI_PROPERTY_CONFIG_OX_START + 0x002)
+#define HFI_PROPERTY_CONFIG_PRIORITY					\
+	(HFI_PROPERTY_CONFIG_OX_START + 0x003)
+#define HFI_PROPERTY_CONFIG_BATCH_INFO					\
+	(HFI_PROPERTY_CONFIG_OX_START + 0x004)
+
+#define HFI_PROPERTY_PARAM_VDEC_OX_START				\
+	(HFI_DOMAIN_BASE_VDEC + HFI_ARCH_OX_OFFSET + 0x3000)
+#define HFI_PROPERTY_PARAM_VDEC_CONTINUE_DATA_TRANSFER	\
+	(HFI_PROPERTY_PARAM_VDEC_OX_START + 0x001)
+#define HFI_PROPERTY_PARAM_VDEC_DISPLAY_PICTURE_BUFFER_COUNT\
+	(HFI_PROPERTY_PARAM_VDEC_OX_START + 0x002)
+#define HFI_PROPERTY_PARAM_VDEC_MULTI_VIEW_SELECT		\
+	(HFI_PROPERTY_PARAM_VDEC_OX_START + 0x003)
+#define HFI_PROPERTY_PARAM_VDEC_PICTURE_TYPE_DECODE		\
+	(HFI_PROPERTY_PARAM_VDEC_OX_START + 0x004)
+#define HFI_PROPERTY_PARAM_VDEC_OUTPUT_ORDER			\
+	(HFI_PROPERTY_PARAM_VDEC_OX_START + 0x005)
+#define HFI_PROPERTY_PARAM_VDEC_MB_QUANTIZATION			\
+	(HFI_PROPERTY_PARAM_VDEC_OX_START + 0x006)
+#define HFI_PROPERTY_PARAM_VDEC_NUM_CONCEALED_MB		\
+	(HFI_PROPERTY_PARAM_VDEC_OX_START + 0x007)
+#define HFI_PROPERTY_PARAM_VDEC_H264_ENTROPY_SWITCHING	\
+	(HFI_PROPERTY_PARAM_VDEC_OX_START + 0x008)
+#define HFI_PROPERTY_PARAM_VDEC_OUTPUT2_KEEP_ASPECT_RATIO\
+	(HFI_PROPERTY_PARAM_VDEC_OX_START + 0x009)
+#define HFI_PROPERTY_PARAM_VDEC_FRAME_RATE_EXTRADATA  \
+	(HFI_PROPERTY_PARAM_VDEC_OX_START + 0x00A)
+#define HFI_PROPERTY_PARAM_VDEC_PANSCAN_WNDW_EXTRADATA \
+	(HFI_PROPERTY_PARAM_VDEC_OX_START + 0x00B)
+#define HFI_PROPERTY_PARAM_VDEC_RECOVERY_POINT_SEI_EXTRADATA \
+	(HFI_PROPERTY_PARAM_VDEC_OX_START + 0x00C)
+#define HFI_PROPERTY_PARAM_VDEC_THUMBNAIL_MODE   \
+	(HFI_PROPERTY_PARAM_VDEC_OX_START + 0x00D)
+
+#define HFI_PROPERTY_PARAM_VDEC_FRAME_ASSEMBLY		\
+	(HFI_PROPERTY_PARAM_VDEC_OX_START + 0x00E)
+#define HFI_PROPERTY_PARAM_VDEC_CLOSED_CAPTION_EXTRADATA	\
+	(HFI_PROPERTY_PARAM_VDEC_OX_START + 0x00F)
+#define HFI_PROPERTY_PARAM_VDEC_AFD_EXTRADATA		\
+	(HFI_PROPERTY_PARAM_VDEC_OX_START + 0x010)
+#define HFI_PROPERTY_PARAM_VDEC_VC1_FRAMEDISP_EXTRADATA		\
+	(HFI_PROPERTY_PARAM_VDEC_OX_START + 0x011)
+#define HFI_PROPERTY_PARAM_VDEC_VC1_SEQDISP_EXTRADATA		\
+	(HFI_PROPERTY_PARAM_VDEC_OX_START + 0x012)
+#define HFI_PROPERTY_PARAM_VDEC_TIMESTAMP_EXTRADATA			\
+	(HFI_PROPERTY_PARAM_VDEC_OX_START + 0x013)
+#define HFI_PROPERTY_PARAM_VDEC_INTERLACE_VIDEO_EXTRADATA	\
+	(HFI_PROPERTY_PARAM_VDEC_OX_START + 0x014)
+#define HFI_PROPERTY_PARAM_VDEC_AVC_SESSION_SELECT \
+	(HFI_PROPERTY_PARAM_VDEC_OX_START + 0x015)
+
+#define HFI_PROPERTY_CONFIG_VDEC_OX_START				\
+	(HFI_DOMAIN_BASE_VDEC + HFI_ARCH_OX_OFFSET + 0x0000)
+#define HFI_PROPERTY_CONFIG_VDEC_POST_LOOP_DEBLOCKER	\
+	(HFI_PROPERTY_CONFIG_VDEC_OX_START + 0x001)
+#define HFI_PROPERTY_CONFIG_VDEC_MB_ERROR_MAP_REPORTING	\
+	(HFI_PROPERTY_CONFIG_VDEC_OX_START + 0x002)
+#define HFI_PROPERTY_CONFIG_VDEC_MB_ERROR_MAP			\
+	(HFI_PROPERTY_CONFIG_VDEC_OX_START + 0x003)
+
+#define HFI_PROPERTY_PARAM_VENC_OX_START				\
+	(HFI_DOMAIN_BASE_VENC + HFI_ARCH_OX_OFFSET + 0x5000)
+#define  HFI_PROPERTY_PARAM_VENC_MULTI_SLICE_INFO       \
+	(HFI_PROPERTY_PARAM_VENC_OX_START + 0x001)
+#define  HFI_PROPERTY_PARAM_VENC_H264_IDR_S3D_FRAME_PACKING_NAL \
+	(HFI_PROPERTY_PARAM_VENC_OX_START + 0x002)
+
+#define HFI_PROPERTY_CONFIG_VENC_OX_START				\
+	(HFI_DOMAIN_BASE_VENC + HFI_ARCH_OX_OFFSET + 0x6000)
+#define  HFI_PROPERTY_CONFIG_VENC_FRAME_QP				\
+	(HFI_PROPERTY_CONFIG_VENC_OX_START + 0x001)
+
+#define HFI_PROPERTY_PARAM_VPE_OX_START					\
+	(HFI_DOMAIN_BASE_VPE + HFI_ARCH_OX_OFFSET + 0x7000)
+#define HFI_PROPERTY_CONFIG_VPE_OX_START				\
+	(HFI_DOMAIN_BASE_VPE + HFI_ARCH_OX_OFFSET + 0x8000)
+
+struct hfi_batch_info {
+	u32 input_batch_count;
+	u32 output_batch_count;
+};
+
+struct hfi_buffer_count_actual {
+	u32 buffer_type;
+	u32 buffer_count_actual;
+};
+
+struct hfi_buffer_requirements {
+	u32 buffer_type;
+	u32 buffer_size;
+	u32 buffer_region_size;
+	u32 buffer_hold_count;
+	u32 buffer_count_min;
+	u32 buffer_count_actual;
+	u32 contiguous;
+	u32 buffer_alignment;
+};
+
+#define HFI_CHROMA_SITE_0			(HFI_OX_BASE + 0x1)
+#define HFI_CHROMA_SITE_1			(HFI_OX_BASE + 0x2)
+#define HFI_CHROMA_SITE_2			(HFI_OX_BASE + 0x3)
+#define HFI_CHROMA_SITE_3			(HFI_OX_BASE + 0x4)
+#define HFI_CHROMA_SITE_4			(HFI_OX_BASE + 0x5)
+#define HFI_CHROMA_SITE_5			(HFI_OX_BASE + 0x6)
+
+struct hfi_data_payload {
+	u32 size;
+	u8 rg_data[1];
+};
+
+struct hfi_enable_picture {
+	u32 picture_type;
+};
+
+struct hfi_display_picture_buffer_count {
+	int enable;
+	u32 count;
+};
+
+struct hfi_extra_data_header_config {
+	u32 type;
+	u32 buffer_type;
+	u32 version;
+	u32 port_index;
+	u32 client_extra_data_id;
+};
+
+struct hfi_interlace_format_supported {
+	u32 buffer_type;
+	u32 format;
+};
+
+struct hfi_mb_error_map {
+	u32 error_map_size;
+	u8 rg_error_map[1];
+};
+
+struct hfi_metadata_pass_through {
+	int enable;
+	u32 size;
+};
+
+struct hfi_multi_view_select {
+	u32 view_index;
+};
+
+#define HFI_PRIORITY_LOW		10
+#define HFI_PRIOIRTY_MEDIUM		20
+#define HFI_PRIORITY_HIGH		30
+
+#define HFI_OUTPUT_ORDER_DISPLAY	(HFI_OX_BASE + 0x1)
+#define HFI_OUTPUT_ORDER_DECODE		(HFI_OX_BASE + 0x2)
+
+#define HFI_RATE_CONTROL_OFF		(HFI_OX_BASE + 0x1)
+#define HFI_RATE_CONTROL_VBR_VFR	(HFI_OX_BASE + 0x2)
+#define HFI_RATE_CONTROL_VBR_CFR	(HFI_OX_BASE + 0x3)
+#define HFI_RATE_CONTROL_CBR_VFR	(HFI_OX_BASE + 0x4)
+#define HFI_RATE_CONTROL_CBR_CFR	(HFI_OX_BASE + 0x5)
+
+struct hfi_uncompressed_plane_actual_constraints_info {
+	u32 buffer_type;
+	u32 num_planes;
+	struct hfi_uncompressed_plane_constraints rg_plane_format[1];
+};
+
+#define HFI_CMD_SYS_OX_START		\
+(HFI_DOMAIN_BASE_COMMON + HFI_ARCH_OX_OFFSET + HFI_CMD_START_OFFSET + 0x0000)
+#define HFI_CMD_SYS_SESSION_ABORT	(HFI_CMD_SYS_OX_START + 0x001)
+#define HFI_CMD_SYS_PING		(HFI_CMD_SYS_OX_START + 0x002)
+
+#define HFI_CMD_SESSION_OX_START	\
+(HFI_DOMAIN_BASE_COMMON + HFI_ARCH_OX_OFFSET + HFI_CMD_START_OFFSET + 0x1000)
+#define HFI_CMD_SESSION_LOAD_RESOURCES	(HFI_CMD_SESSION_OX_START + 0x001)
+#define HFI_CMD_SESSION_START		(HFI_CMD_SESSION_OX_START + 0x002)
+#define HFI_CMD_SESSION_STOP		(HFI_CMD_SESSION_OX_START + 0x003)
+#define HFI_CMD_SESSION_EMPTY_BUFFER	(HFI_CMD_SESSION_OX_START + 0x004)
+#define HFI_CMD_SESSION_FILL_BUFFER	(HFI_CMD_SESSION_OX_START + 0x005)
+#define HFI_CMD_SESSION_SUSPEND		(HFI_CMD_SESSION_OX_START + 0x006)
+#define HFI_CMD_SESSION_RESUME		(HFI_CMD_SESSION_OX_START + 0x007)
+#define HFI_CMD_SESSION_FLUSH		(HFI_CMD_SESSION_OX_START + 0x008)
+#define HFI_CMD_SESSION_GET_PROPERTY	(HFI_CMD_SESSION_OX_START + 0x009)
+#define HFI_CMD_SESSION_PARSE_SEQUENCE_HEADER	\
+	(HFI_CMD_SESSION_OX_START + 0x00A)
+#define HFI_CMD_SESSION_RELEASE_BUFFERS		\
+	(HFI_CMD_SESSION_OX_START + 0x00B)
+#define HFI_CMD_SESSION_RELEASE_RESOURCES	\
+	(HFI_CMD_SESSION_OX_START + 0x00C)
+
+#define HFI_MSG_SYS_OX_START			\
+(HFI_DOMAIN_BASE_COMMON + HFI_ARCH_OX_OFFSET + HFI_MSG_START_OFFSET + 0x0000)
+#define HFI_MSG_SYS_IDLE		(HFI_MSG_SYS_OX_START + 0x1)
+#define HFI_MSG_SYS_PING_ACK	(HFI_MSG_SYS_OX_START + 0x2)
+#define HFI_MSG_SYS_PROPERTY_INFO	(HFI_MSG_SYS_OX_START + 0x3)
+#define HFI_MSG_SYS_SESSION_ABORT_DONE	(HFI_MSG_SYS_OX_START + 0x4)
+
+#define HFI_MSG_SESSION_OX_START		\
+(HFI_DOMAIN_BASE_COMMON + HFI_ARCH_OX_OFFSET + HFI_MSG_START_OFFSET + 0x1000)
+#define HFI_MSG_SESSION_LOAD_RESOURCES_DONE	(HFI_MSG_SESSION_OX_START + 0x1)
+#define HFI_MSG_SESSION_START_DONE		(HFI_MSG_SESSION_OX_START + 0x2)
+#define HFI_MSG_SESSION_STOP_DONE		(HFI_MSG_SESSION_OX_START + 0x3)
+#define HFI_MSG_SESSION_SUSPEND_DONE	(HFI_MSG_SESSION_OX_START + 0x4)
+#define HFI_MSG_SESSION_RESUME_DONE		(HFI_MSG_SESSION_OX_START + 0x5)
+#define HFI_MSG_SESSION_FLUSH_DONE		(HFI_MSG_SESSION_OX_START + 0x6)
+#define HFI_MSG_SESSION_EMPTY_BUFFER_DONE	(HFI_MSG_SESSION_OX_START + 0x7)
+#define HFI_MSG_SESSION_FILL_BUFFER_DONE	(HFI_MSG_SESSION_OX_START + 0x8)
+#define HFI_MSG_SESSION_PROPERTY_INFO		(HFI_MSG_SESSION_OX_START + 0x9)
+#define HFI_MSG_SESSION_RELEASE_RESOURCES_DONE	\
+	(HFI_MSG_SESSION_OX_START + 0xA)
+#define HFI_MSG_SESSION_PARSE_SEQUENCE_HEADER_DONE		\
+	(HFI_MSG_SESSION_OX_START + 0xB)
+#define  HFI_MSG_SESSION_RELEASE_BUFFERS_DONE			\
+	(HFI_MSG_SESSION_OX_START + 0xC)
+
+#define HFI_MIN_PKT_SIZE			8
+
+struct hfi_cmd_sys_session_abort_packet {
+	u32 size;
+	u32 packet_type;
+	u32 session_id;
+};
+
+struct hfi_cmd_sys_ping_packet {
+	u32 size;
+	u32 packet_type;
+	u32 client_data;
+};
+
+struct hfi_cmd_session_load_resources_packet {
+	u32 size;
+	u32 packet_type;
+	u32 session_id;
+};
+
+struct hfi_cmd_session_start_packet {
+	u32 size;
+	u32 packet_type;
+	u32 session_id;
+};
+
+struct hfi_cmd_session_stop_packet {
+	u32 size;
+	u32 packet_type;
+	u32 session_id;
+};
+
+struct hfi_cmd_session_empty_buffer_compressed_packet {
+	u32 size;
+	u32 packet_type;
+	u32 session_id;
+	u32 time_stamp_hi;
+	u32 time_stamp_lo;
+	u32 flags;
+	u32 mark_target;
+	u32 mark_data;
+	u32 offset;
+	u32 alloc_len;
+	u32 filled_len;
+	u32 input_tag;
+	u8 *packet_buffer;
+	u8 *extra_data_buffer;
+	u32 rgData[0];
+};
+
+struct hfi_cmd_session_empty_buffer_uncompressed_plane0_packet {
+	u32 size;
+	u32 packet_type;
+	u32 session_id;
+	u32 view_id;
+	u32 time_stamp_hi;
+	u32 time_stamp_lo;
+	u32 flags;
+	u32 mark_target;
+	u32 mark_data;
+	u32 alloc_len;
+	u32 filled_len;
+	u32 offset;
+	u32 input_tag;
+	u8 *packet_buffer;
+	u8 *extra_data_buffer;
+	u32 rgData[0];
+};
+
+struct hfi_cmd_session_empty_buffer_uncompressed_plane1_packet {
+	u32 flags;
+	u32 alloc_len;
+	u32 filled_len;
+	u32 offset;
+	u8 *packet_buffer2;
+	u32 rgData[0];
+};
+
+struct hfi_cmd_session_empty_buffer_uncompressed_plane2_packet {
+	u32 flags;
+	u32 alloc_len;
+	u32 filled_len;
+	u32 offset;
+	u8 *packet_buffer3;
+	u32 rgData[0];
+};
+
+struct hfi_cmd_session_fill_buffer_packet {
+	u32 size;
+	u32 packet_type;
+	u32 session_id;
+	u32 stream_id;
+	u32 offset;
+	u32 alloc_len;
+	u32 filled_len;
+	u32 output_tag;
+	u8 *packet_buffer;
+	u8 *extra_data_buffer;
+	u32 rgData[0];
+};
+
+struct hfi_cmd_session_flush_packet {
+	u32 size;
+	u32 packet_type;
+	u32 session_id;
+	u32 flush_type;
+};
+
+struct hfi_cmd_session_suspend_packet {
+	u32 size;
+	u32 packet_type;
+	u32 session_id;
+};
+
+struct hfi_cmd_session_resume_packet {
+	u32 size;
+	u32 packet_type;
+	u32 session_id;
+};
+
+struct hfi_cmd_session_get_property_packet {
+	u32 size;
+	u32 packet_type;
+	u32 session_id;
+	u32 num_properties;
+	u32 rg_property_data[1];
+};
+
+struct hfi_cmd_session_release_buffer_packet {
+	u32 size;
+	u32 packet_type;
+	u32 session_id;
+	u32 buffer_type;
+	u32 buffer_size;
+	u32 extra_data_size;
+	int response_req;
+	u32 num_buffers;
+	u32 rg_buffer_info[1];
+};
+
+struct hfi_cmd_session_release_resources_packet {
+	u32 size;
+	u32 packet_type;
+	u32 session_id;
+};
+
+struct hfi_cmd_session_parse_sequence_header_packet {
+	u32 size;
+	u32 packet_type;
+	u32 session_id;
+	u32 header_len;
+	u8 *packet_buffer;
+};
+
+struct hfi_msg_sys_session_abort_done_packet {
+	u32 size;
+	u32 packet_type;
+	u32 session_id;
+	u32 error_type;
+};
+
+struct hfi_msg_sys_idle_packet {
+	u32 size;
+	u32 packet_type;
+};
+
+struct hfi_msg_sys_ping_ack_packet {
+	u32 size;
+	u32 packet_type;
+	u32 client_data;
+};
+
+struct hfi_msg_sys_property_info_packet {
+	u32 size;
+	u32 packet_type;
+	u32 num_properties;
+	u32 rg_property_data[1];
+};
+
+struct hfi_msg_session_load_resources_done_packet {
+	u32 size;
+	u32 packet_type;
+	u32 session_id;
+	u32 error_type;
+};
+
+struct hfi_msg_session_start_done_packet {
+	u32 size;
+	u32 packet_type;
+	u32 session_id;
+	u32 error_type;
+};
+
+struct hfi_msg_session_stop_done_packet {
+	u32 size;
+	u32 packet_type;
+	u32 session_id;
+	u32 error_type;
+};
+
+struct hfi_msg_session_suspend_done_packet {
+	u32 size;
+	u32 packet_type;
+	u32 session_id;
+	u32 error_type;
+};
+
+struct hfi_msg_session_resume_done_packet {
+	u32 size;
+	u32 packet_type;
+	u32 session_id;
+	u32 error_type;
+};
+
+struct hfi_msg_session_flush_done_packet {
+	u32 size;
+	u32 packet_type;
+	u32 session_id;
+	u32 error_type;
+	u32 flush_type;
+};
+
+struct hfi_msg_session_empty_buffer_done_packet {
+	u32 size;
+	u32 packet_type;
+	u32 session_id;
+	u32 error_type;
+	u32 offset;
+	u32 filled_len;
+	u32 input_tag;
+	u8 *packet_buffer;
+	u8 *extra_data_buffer;
+	u32 rgData[0];
+};
+
+struct hfi_msg_session_fill_buffer_done_compressed_packet {
+	u32 size;
+	u32 packet_type;
+	u32 session_id;
+	u32 time_stamp_hi;
+	u32 time_stamp_lo;
+	u32 error_type;
+	u32 flags;
+	u32 mark_target;
+	u32 mark_data;
+	u32 stats;
+	u32 offset;
+	u32 alloc_len;
+	u32 filled_len;
+	u32 input_tag;
+	u32 output_tag;
+	u32 picture_type;
+	u8 *packet_buffer;
+	u8 *extra_data_buffer;
+	u32 rgData[0];
+};
+
+struct hfi_msg_session_fbd_uncompressed_plane0_packet {
+	u32 size;
+	u32 packet_type;
+	u32 session_id;
+	u32 stream_id;
+	u32 view_id;
+	u32 error_type;
+	u32 time_stamp_hi;
+	u32 time_stamp_lo;
+	u32 flags;
+	u32 mark_target;
+	u32 mark_data;
+	u32 stats;
+	u32 alloc_len;
+	u32 filled_len;
+	u32 offset;
+	u32 frame_width;
+	u32 frame_height;
+	u32 start_x_coord;
+	u32 start_y_coord;
+	u32 input_tag;
+	u32 input_tag2;
+	u32 output_tag;
+	u32 picture_type;
+	u8 *packet_buffer;
+	u8 *extra_data_buffer;
+	u32 rgData[0];
+};
+
+struct hfi_msg_session_fill_buffer_done_uncompressed_plane1_packet {
+	u32 flags;
+	u32 alloc_len;
+	u32 filled_len;
+	u32 offset;
+	u8 *packet_buffer2;
+	u32 rgData[0];
+};
+
+struct hfi_msg_session_fill_buffer_done_uncompressed_plane2_packet {
+	u32 flags;
+	u32 alloc_len;
+	u32 filled_len;
+	u32 offset;
+	u8 *packet_buffer3;
+	u32 rgData[0];
+};
+
+struct hfi_msg_session_parse_sequence_header_done_packet {
+	u32 size;
+	u32 packet_type;
+	u32 session_id;
+	u32 error_type;
+	u32 num_properties;
+	u32 rg_property_data[1];
+};
+
+struct hfi_msg_session_property_info_packet {
+	u32 size;
+	u32 packet_type;
+	u32 session_id;
+	u32 num_properties;
+	u32 rg_property_data[1];
+};
+
+struct hfi_msg_session_release_resources_done_packet {
+	u32 size;
+	u32 packet_type;
+	u32 session_id;
+	u32 error_type;
+};
+
+struct hfi_msg_session_release_buffers_done_packet {
+	u32 size;
+	u32 packet_type;
+	u32 session_id;
+	u32 error_type;
+	u32 num_buffers;
+	u32 rg_buffer_info[1];
+};
+
+struct hfi_extradata_mb_quantization_payload {
+	u8 rg_mb_qp[1];
+};
+
+struct hfi_extradata_vc1_pswnd {
+	u32 ps_wnd_h_offset;
+	u32 ps_wnd_v_offset;
+	u32 ps_wnd_width;
+	u32 ps_wnd_height;
+};
+
+struct hfi_extradata_vc1_framedisp_payload {
+	u32 res_pic;
+	u32 ref;
+	u32 range_map_present;
+	u32 range_map_y;
+	u32 range_map_uv;
+	u32 num_pan_scan_wnds;
+	struct hfi_extradata_vc1_pswnd rg_ps_wnd[1];
+};
+
+struct hfi_extradata_vc1_seqdisp_payload {
+	u32 prog_seg_frm;
+	u32 uv_sampling_fmt;
+	u32 color_fmt_flag;
+	u32 color_primaries;
+	u32 transfer_char;
+	u32 mat_coeff;
+	u32 aspect_ratio;
+	u32 aspect_horiz;
+	u32 aspect_vert;
+};
+
+struct hfi_extradata_timestamp_payload {
+	u32 time_stamp_low;
+	u32 time_stamp_high;
+};
+
+
+struct hfi_extradata_s3d_frame_packing_payload {
+	u32 fpa_id;
+	int cancel_flag;
+	u32 fpa_type;
+	int quin_cunx_flag;
+	u32 content_interprtation_type;
+	int spatial_flipping_flag;
+	int frame0_flipped_flag;
+	int field_views_flag;
+	int current_frame_isFrame0_flag;
+	int frame0_self_contained_flag;
+	int frame1_self_contained_flag;
+	u32 frame0_graid_pos_x;
+	u32 frame0_graid_pos_y;
+	u32 frame1_graid_pos_x;
+	u32 frame1_graid_pos_y;
+	u32 fpa_reserved_byte;
+	u32 fpa_repetition_period;
+	int fpa_extension_flag;
+};
+
+struct hfi_extradata_interlace_video_payload {
+	u32 format;
+};
+
+struct hfi_extradata_num_concealed_mb_payload {
+	u32 num_mb_concealed;
+};
+
+struct hfi_extradata_sliceinfo {
+	u32 offset_in_stream;
+	u32 slice_length;
+};
+
+struct hfi_extradata_multislice_info_payload {
+	u32 num_slices;
+	struct hfi_extradata_sliceinfo rg_slice_info[1];
+};
+
+struct hfi_index_extradata_input_crop_payload {
+	u32 size;
+	u32 version;
+	u32 port_index;
+	u32 left;
+	u32 top;
+	u32 width;
+	u32 height;
+};
+
+struct hfi_index_extradata_digital_zoom_payload {
+	u32 size;
+	u32 version;
+	u32 port_index;
+	int width;
+	int height;
+};
+
+struct hfi_index_extradata_aspect_ratio_payload {
+	u32 size;
+	u32 version;
+	u32 port_index;
+	u32 aspect_width;
+	u32 aspect_height;
+};
+struct hfi_extradata_panscan_wndw_payload {
+	u32 num_window;
+	struct hfi_extradata_vc1_pswnd wnd[1];
+};
+
+struct hfi_extradata_frame_type_payload {
+	u32 frame_rate;
+};
+
+struct hfi_extradata_recovery_point_sei_payload {
+	u32 flag;
+};
+
+struct hal_session {
+	struct list_head list;
+	u32 session_id;
+	u32 is_decoder;
+	void *device;
+};
+
+struct hal_device_data {
+	struct list_head dev_head;
+	int dev_count;
+};
+
+extern struct hal_device_data hal_ctxt;
+
+void hfi_process_msg_packet(msm_vidc_callback callback,
+		u32 device_id, struct vidc_hal_msg_pkt_hdr *msg_hdr);
+#endif
+
diff --git a/drivers/media/video/msm_vidc/vidc_hfi_api.h b/drivers/media/video/msm_vidc/vidc_hfi_api.h
index 79fee90..370785c 100644
--- a/drivers/media/video/msm_vidc/vidc_hfi_api.h
+++ b/drivers/media/video/msm_vidc/vidc_hfi_api.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -14,7 +14,9 @@
 #ifndef __VIDC_HFI_API_H__
 #define __VIDC_HFI_API_H__
 
+#include <linux/platform_device.h>
 #include <linux/types.h>
+#include <media/msm_vidc.h>
 
 #define CONTAINS(__a, __sz, __t) ({\
 	int __rc = __t >= __a && \
@@ -513,6 +515,7 @@
 
 struct hal_bitrate {
 	u32 bit_rate;
+	u32 layer_id;
 };
 
 struct hal_profile_level {
@@ -587,6 +590,7 @@
 	u32 qpi;
 	u32 qpp;
 	u32 qpb;
+	u32 layer_id;
 };
 
 struct hal_intra_period {
@@ -979,44 +983,84 @@
 	struct hal_buffer_requirements buffer[HAL_BUFFER_MAX];
 };
 
-/* VIDC_HAL CORE API's */
-int venus_hfi_core_init(void *device);
-int venus_hfi_core_release(void *device);
-int venus_hfi_core_pc_prep(void *device);
-int venus_hfi_core_set_resource(void *device,
-	struct vidc_resource_hdr *resource_hdr, void *resource_value);
-int venus_hfi_core_release_resource(void *device,
-	struct vidc_resource_hdr *resource_hdr);
-int venus_hfi_core_ping(void *device);
+enum msm_vidc_hfi_type {
+	VIDC_HFI_VENUS,
+	VIDC_HFI_Q6,
+};
 
-/* VIDC_HAL SESSION API's */
-void *venus_hfi_session_init(void *device, u32 session_id,
-	enum hal_domain session_type, enum hal_video_codec codec_type);
-int venus_hfi_session_end(void *session);
-int venus_hfi_session_abort(void *session);
-int venus_hfi_session_set_buffers(void *sess,
-	struct vidc_buffer_addr_info *buffer_info);
-int venus_hfi_session_release_buffers(void *sess,
-	struct vidc_buffer_addr_info *buffer_info);
-int venus_hfi_session_load_res(void *sess);
-int venus_hfi_session_release_res(void *sess);
-int venus_hfi_session_start(void *sess);
-int venus_hfi_session_stop(void *sess);
-int venus_hfi_session_suspend(void *sess);
-int venus_hfi_session_resume(void *sess);
-int venus_hfi_session_etb(void *sess,
-	struct vidc_frame_data *input_frame);
-int venus_hfi_session_ftb(void *sess,
-	struct vidc_frame_data *output_frame);
-int venus_hfi_session_parse_seq_hdr(void *sess,
-	struct vidc_seq_hdr *seq_hdr);
-int venus_hfi_session_get_seq_hdr(void *sess,
-	struct vidc_seq_hdr *seq_hdr);
-int venus_hfi_session_get_buf_req(void *sess);
-int venus_hfi_session_flush(void *sess, enum hal_flush flush_mode);
-int venus_hfi_session_set_property(void *sess, enum hal_property ptype,
-								  void *pdata);
-int venus_hfi_session_get_property(void *sess, enum hal_property ptype,
-								  void *pdata);
+enum mem_type {
+	DDR_MEM = 0x1,
+	OCMEM_MEM = 0x2,
+};
+
+enum fw_info {
+	FW_BASE_ADDRESS,
+	FW_REGISTER_BASE,
+	FW_REGISTER_SIZE,
+	FW_IRQ,
+	FW_INFO_MAX,
+};
+
+struct hfi_device {
+	void *hfi_device_data;
+
+	/*Add function pointers for all the hfi functions below*/
+	int (*core_init)(void *device);
+	int (*core_release)(void *device);
+	int (*core_pc_prep)(void *device);
+	int (*core_ping)(void *device);
+	void *(*session_init)(void *device, u32 session_id,
+		enum hal_domain session_type, enum hal_video_codec codec_type);
+	int (*session_end)(void *session);
+	int (*session_abort)(void *session);
+	int (*session_set_buffers)(void *sess,
+				struct vidc_buffer_addr_info *buffer_info);
+	int (*session_release_buffers)(void *sess,
+				struct vidc_buffer_addr_info *buffer_info);
+	int (*session_load_res)(void *sess);
+	int (*session_release_res)(void *sess);
+	int (*session_start)(void *sess);
+	int (*session_stop)(void *sess);
+	int (*session_suspend)(void *sess);
+	int (*session_resume)(void *sess);
+	int (*session_etb)(void *sess,
+			struct vidc_frame_data *input_frame);
+	int (*session_ftb)(void *sess,
+			struct vidc_frame_data *output_frame);
+	int (*session_parse_seq_hdr)(void *sess,
+			struct vidc_seq_hdr *seq_hdr);
+	int (*session_get_seq_hdr)(void *sess,
+			struct vidc_seq_hdr *seq_hdr);
+	int (*session_get_buf_req)(void *sess);
+	int (*session_flush)(void *sess, enum hal_flush flush_mode);
+	int (*session_set_property)(void *sess, enum hal_property ptype,
+			void *pdata);
+	int (*session_get_property)(void *sess, enum hal_property ptype,
+			void *pdata);
+	int (*scale_clocks)(void *dev, int load);
+	int (*scale_bus)(void *dev, int load,
+			enum session_type type, enum mem_type mtype);
+	int (*unset_ocmem)(void *dev);
+	int (*alloc_ocmem)(void *dev, unsigned long size);
+	int (*free_ocmem)(void *dev);
+	int (*is_ocmem_present)(void *dev);
+	int (*get_domain)(void *dev, enum msm_vidc_io_maps iomap);
+	int (*iommu_get_map)(void *dev,
+			struct msm_vidc_iommu_info maps[MAX_MAP]);
+	int (*load_fw)(void *dev);
+	void (*unload_fw)(void *dev);
+	int (*get_fw_info)(void *dev, enum fw_info info);
+};
+
+typedef void (*hfi_cmd_response_callback) (enum command_response cmd,
+			void *data);
+typedef void (*msm_vidc_callback) (u32 response, void *callback);
+
+void *vidc_hfi_initialize(enum msm_vidc_hfi_type hfi_type, u32 device_id,
+			struct platform_device *pdev,
+			hfi_cmd_response_callback callback);
+void vidc_hfi_deinitialize(enum msm_vidc_hfi_type hfi_type,
+			struct hfi_device *hdev);
+
 
 #endif /*__VIDC_HFI_API_H__ */
diff --git a/drivers/media/video/msm_wfd/mdp-4-subdev.c b/drivers/media/video/msm_wfd/mdp-4-subdev.c
index c68d5d4..d2ecd22 100644
--- a/drivers/media/video/msm_wfd/mdp-4-subdev.c
+++ b/drivers/media/video/msm_wfd/mdp-4-subdev.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2011-2013, The Linux Foundation. All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 and
@@ -11,6 +11,7 @@
 *
 */
 #include <linux/msm_mdp.h>
+#include <linux/switch.h>
 #include <mach/iommu_domains.h>
 #include <media/videobuf2-core.h>
 #include "enc-subdev.h"
@@ -23,6 +24,7 @@
 	u32 width;
 	bool secure;
 	bool uses_iommu_split_domain;
+	struct switch_dev sdev;
 };
 
 int mdp_init(struct v4l2_subdev *sd, u32 val)
@@ -54,14 +56,13 @@
 		rc = -ENODEV;
 		goto mdp_open_fail;
 	}
-
-	/*Tell HDMI daemon to open fb2*/
-	rc = kobject_uevent(&fbi->dev->kobj, KOBJ_ADD);
+	inst->sdev.name = "wfd";
+	/* Register wfd node to switch driver */
+	rc = switch_dev_register(&inst->sdev);
 	if (rc) {
-		WFD_MSG_ERR("Failed add to kobj");
+		WFD_MSG_ERR("WFD switch registration failed\n");
 		goto mdp_open_fail;
 	}
-
 	msm_fb_writeback_init(fbi);
 	inst->mdp = fbi;
 	inst->secure = mops->secure;
@@ -91,9 +92,8 @@
 			rc = -ENODEV;
 			goto exit;
 		}
-		rc = kobject_uevent(&fbi->dev->kobj, KOBJ_ONLINE);
-		if (rc)
-			WFD_MSG_ERR("Failed to send ONLINE event\n");
+		switch_set_state(&inst->sdev, true);
+		WFD_MSG_DBG("wfd state switched to %d\n", inst->sdev.state);
 	}
 exit:
 	return rc;
@@ -110,11 +110,8 @@
 			return rc;
 		}
 		fbi = (struct fb_info *)inst->mdp;
-		rc = kobject_uevent(&fbi->dev->kobj, KOBJ_OFFLINE);
-		if (rc) {
-			WFD_MSG_ERR("Failed to send offline event\n");
-			return -EIO;
-		}
+		switch_set_state(&inst->sdev, false);
+		WFD_MSG_DBG("wfd state switched to %d\n", inst->sdev.state);
 	}
 	return 0;
 }
@@ -126,6 +123,8 @@
 		fbi = (struct fb_info *)inst->mdp;
 		msm_fb_writeback_terminate(fbi);
 		kfree(inst);
+		/* Unregister wfd node from switch driver */
+		switch_dev_unregister(&inst->sdev);
 	}
 	return 0;
 }
diff --git a/drivers/media/video/msm_wfd/mdp-5-subdev.c b/drivers/media/video/msm_wfd/mdp-5-subdev.c
index 4f29389..5b49498 100644
--- a/drivers/media/video/msm_wfd/mdp-5-subdev.c
+++ b/drivers/media/video/msm_wfd/mdp-5-subdev.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011-2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2011-2013, The Linux Foundation. All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 and
@@ -11,18 +11,19 @@
 *
 */
 #include <linux/msm_mdp.h>
+#include <linux/switch.h>
 #include <mach/iommu_domains.h>
 #include <media/videobuf2-core.h>
 #include "enc-subdev.h"
 #include "mdp-subdev.h"
 #include "wfd-util.h"
 
-
 struct mdp_instance {
 	struct fb_info *mdp;
 	u32 height;
 	u32 width;
 	bool secure;
+	struct switch_dev sdev;
 };
 
 int mdp_init(struct v4l2_subdev *sd, u32 val)
@@ -54,12 +55,13 @@
 		rc = -ENODEV;
 		goto mdp_open_fail;
 	}
-
-	/*Tell HDMI daemon to open fb2*/
-	rc = kobject_uevent(&fbi->dev->kobj, KOBJ_ADD);
-	if (rc)
-		WFD_MSG_ERR("Failed add to kobj");
-
+	inst->sdev.name = "wfd";
+	/* Register wfd node to switch driver */
+	rc = switch_dev_register(&inst->sdev);
+	if (rc) {
+		WFD_MSG_ERR("WFD switch registration failed\n");
+		goto mdp_open_fail;
+	}
 	msm_fb_writeback_init(fbi);
 	inst->mdp = fbi;
 	inst->secure = mops->secure;
@@ -88,9 +90,8 @@
 			rc = -ENODEV;
 			goto exit;
 		}
-		rc = kobject_uevent(&fbi->dev->kobj, KOBJ_ONLINE);
-		if (rc)
-			WFD_MSG_ERR("Failed to send ONLINE event\n");
+		switch_set_state(&inst->sdev, true);
+		WFD_MSG_DBG("wfd state switched to %d\n", inst->sdev.state);
 	}
 exit:
 	return rc;
@@ -108,11 +109,8 @@
 			return rc;
 		}
 		fbi = (struct fb_info *)inst->mdp;
-		rc = kobject_uevent(&fbi->dev->kobj, KOBJ_OFFLINE);
-		if (rc) {
-			WFD_MSG_ERR("Failed to send offline event\n");
-			return -EIO;
-		}
+		switch_set_state(&inst->sdev, false);
+		WFD_MSG_DBG("wfd state switched to %d\n", inst->sdev.state);
 	}
 	return 0;
 }
@@ -124,6 +122,8 @@
 		fbi = (struct fb_info *)inst->mdp;
 		msm_fb_writeback_terminate(fbi);
 		kfree(inst);
+		/* Unregister wfd node from switch driver */
+		switch_dev_unregister(&inst->sdev);
 	}
 	return 0;
 }
diff --git a/drivers/media/video/vcap_vc.c b/drivers/media/video/vcap_vc.c
index 642074f..5760fba 100644
--- a/drivers/media/video/vcap_vc.c
+++ b/drivers/media/video/vcap_vc.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2012-2013, 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
@@ -132,23 +132,25 @@
 inline void vc_isr_error_checking(struct vcap_dev *dev,
 		struct v4l2_event v4l2_evt, uint32_t irq)
 {
-	if (irq & 0x8000200) {
-		writel_iowmb(0x00000102, VCAP_VC_NPL_CTRL);
-		v4l2_evt.type = V4L2_EVENT_PRIVATE_START +
-			VCAP_VC_PIX_ERR_EVENT;
-		v4l2_event_queue(dev->vfd, &v4l2_evt);
-	}
-	if (irq & 0x40000200) {
-		writel_iowmb(0x00000102, VCAP_VC_NPL_CTRL);
-		v4l2_evt.type = V4L2_EVENT_PRIVATE_START +
-			VCAP_VC_LINE_ERR_EVENT;
-		v4l2_event_queue(dev->vfd, &v4l2_evt);
-	}
-	if (irq & 0x20000200) {
-		writel_iowmb(0x00000102, VCAP_VC_NPL_CTRL);
-		v4l2_evt.type = V4L2_EVENT_PRIVATE_START +
-			VCAP_VC_VSYNC_ERR_EVENT;
-		v4l2_event_queue(dev->vfd, &v4l2_evt);
+	if (irq & 0x200) {
+		if (irq & 0x80000000) {
+			writel_iowmb(0x00000102, VCAP_VC_NPL_CTRL);
+			v4l2_evt.type = V4L2_EVENT_PRIVATE_START +
+				VCAP_VC_PIX_ERR_EVENT;
+			v4l2_event_queue(dev->vfd, &v4l2_evt);
+		}
+		if (irq & 0x40000000) {
+			writel_iowmb(0x00000102, VCAP_VC_NPL_CTRL);
+			v4l2_evt.type = V4L2_EVENT_PRIVATE_START +
+				VCAP_VC_LINE_ERR_EVENT;
+			v4l2_event_queue(dev->vfd, &v4l2_evt);
+		}
+		if (irq & 0x20000000) {
+			writel_iowmb(0x00000102, VCAP_VC_NPL_CTRL);
+			v4l2_evt.type = V4L2_EVENT_PRIVATE_START +
+				VCAP_VC_VSYNC_ERR_EVENT;
+			v4l2_event_queue(dev->vfd, &v4l2_evt);
+		}
 	}
 	if (irq & 0x00001000) {
 		writel_iowmb(0x00000102, VCAP_VC_NPL_CTRL);
diff --git a/drivers/misc/qseecom.c b/drivers/misc/qseecom.c
index c415952..f4fc7b6 100644
--- a/drivers/misc/qseecom.c
+++ b/drivers/misc/qseecom.c
@@ -2,7 +2,7 @@
 
 /*Qualcomm Secure Execution Environment Communicator (QSEECOM) driver
  *
- * Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -1463,7 +1463,7 @@
 	struct qseecom_command_scm_resp resp;
 	u8 *img_data = NULL;
 
-	if (__qseecom_get_fw_size("commonlib", &fw_size))
+	if (__qseecom_get_fw_size("cmnlib", &fw_size))
 		return -EIO;
 
 	img_data = kzalloc(fw_size, GFP_KERNEL);
@@ -1471,7 +1471,7 @@
 		pr_err("Mem allocation for lib image data failed\n");
 		return -ENOMEM;
 	}
-	ret = __qseecom_get_fw_data("commonlib", img_data, &load_req);
+	ret = __qseecom_get_fw_data("cmnlib", img_data, &load_req);
 	if (ret) {
 		kzfree(img_data);
 		return -EIO;
diff --git a/drivers/misc/tspp.c b/drivers/misc/tspp.c
index d4ff38b..563a013 100644
--- a/drivers/misc/tspp.c
+++ b/drivers/misc/tspp.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2011-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -25,6 +25,7 @@
 #include <linux/slab.h>          /* kfree, kzalloc */
 #include <linux/ioport.h>        /* XXX_ mem_region */
 #include <linux/dma-mapping.h>   /* dma_XXX */
+#include <linux/dmapool.h>       /* DMA pools */
 #include <linux/delay.h>         /* msleep */
 #include <linux/platform_device.h>
 #include <linux/clk.h>
@@ -65,6 +66,14 @@
 #define TSPP_MAX_BUFFER_SIZE           (32 * 1024 - 1)
 
 /*
+ * Returns whether to use DMA pool for TSPP output buffers.
+ * For buffers smaller than page size, using DMA pool
+ * provides better memory utilization as dma_alloc_coherent
+ * allocates minimum of page size.
+ */
+#define TSPP_USE_DMA_POOL(buff_size)   ((buff_size) < PAGE_SIZE)
+
+/*
  * Max allowed TSPP buffers/descriptors.
  * If SPS desc FIFO holds X descriptors, we can queue up to X-1 descriptors.
  */
@@ -398,6 +407,7 @@
 	void *notify_data;       /* data to be passed with the notifier */
 	u32 expiration_period_ms; /* notification on partially filled buffers */
 	struct timer_list expiration_timer;
+	struct dma_pool *dma_pool;
 	tspp_memfree *memfree;   /* user defined memory free function */
 	void *user_info; /* user cookie passed to memory alloc/free function */
 };
@@ -898,7 +908,7 @@
 }
 
 static int tspp_alloc_buffer(u32 channel_id, struct tspp_data_descriptor *desc,
-	u32 size, tspp_allocator *alloc, void *user)
+	u32 size, struct dma_pool *dma_pool, tspp_allocator *alloc, void *user)
 {
 	if (size < TSPP_MIN_BUFFER_SIZE ||
 		size > TSPP_MAX_BUFFER_SIZE) {
@@ -911,10 +921,15 @@
 		desc->virt_base = alloc(channel_id, size,
 			&desc->phys_base, user);
 	} else {
-		desc->virt_base = dma_alloc_coherent(NULL, size,
-			&desc->phys_base, GFP_KERNEL);
+		if (!dma_pool)
+			desc->virt_base = dma_alloc_coherent(NULL, size,
+				&desc->phys_base, GFP_KERNEL);
+		else
+			desc->virt_base = dma_pool_alloc(dma_pool, GFP_KERNEL,
+				&desc->phys_base);
+
 		if (desc->virt_base == 0) {
-			pr_err("tspp dma alloc coherent failed %i", size);
+			pr_err("tspp: dma buffer allocation failed %i\n", size);
 			return -ENOMEM;
 		}
 	}
@@ -1225,10 +1240,15 @@
 					pbuf->desc.phys_base,
 					channel->user_info);
 			} else {
-				dma_free_coherent(NULL,
-					pbuf->desc.size,
-					pbuf->desc.virt_base,
-					pbuf->desc.phys_base);
+				if (!channel->dma_pool)
+					dma_free_coherent(NULL,
+						pbuf->desc.size,
+						pbuf->desc.virt_base,
+						pbuf->desc.phys_base);
+				else
+					dma_pool_free(channel->dma_pool,
+						pbuf->desc.virt_base,
+						pbuf->desc.phys_base);
 			}
 			pbuf->desc.phys_base = 0;
 		}
@@ -1568,6 +1588,10 @@
 		config->desc.phys_base);
 
 	tspp_destroy_buffers(channel_id, channel);
+	if (channel->dma_pool) {
+		dma_pool_destroy(channel->dma_pool);
+		channel->dma_pool = NULL;
+	}
 
 	channel->src = TSPP_SOURCE_NONE;
 	channel->mode = TSPP_MODE_DISABLED;
@@ -1704,7 +1728,7 @@
 	 */
 	if (channel->buffer_count == 0) {
 		channel->buffer_size =
-			tspp_align_buffer_size_by_mode(channel->buffer_size,
+		tspp_align_buffer_size_by_mode(channel->buffer_size,
 							channel->mode);
 		rc = tspp_allocate_buffers(dev, channel->id,
 					channel->max_buffers,
@@ -2072,6 +2096,7 @@
 	}
 
 	channel = &pdev->channels[channel_id];
+
 	/* allow buffer allocation only if there was no previous buffer
 	 * allocation for this channel.
 	 */
@@ -2101,6 +2126,22 @@
 	channel->memfree = memfree;
 	channel->user_info = user;
 
+	/*
+	 * For small buffers, create a DMA pool so that memory
+	 * is not wasted through dma_alloc_coherent.
+	 */
+	if (TSPP_USE_DMA_POOL(channel->buffer_size)) {
+		channel->dma_pool = dma_pool_create("tspp",
+			NULL, channel->buffer_size, 0, 0);
+		if (!channel->dma_pool) {
+			pr_err("%s: Can't allocate memory pool\n", __func__);
+			return -ENOMEM;
+		}
+	} else {
+		channel->dma_pool = NULL;
+	}
+
+
 	for (channel->buffer_count = 0;
 		channel->buffer_count < channel->max_buffers;
 		channel->buffer_count++) {
@@ -2117,7 +2158,8 @@
 		desc->desc.id = channel->buffer_count;
 		/* allocate the buffer */
 		if (tspp_alloc_buffer(channel_id, &desc->desc,
-			channel->buffer_size, alloc, user) != 0) {
+			channel->buffer_size, channel->dma_pool,
+			alloc, user) != 0) {
 			kfree(desc);
 			pr_warn("%s: Can't allocate buffer %i",
 				__func__, channel->buffer_count);
@@ -2154,6 +2196,11 @@
 		 */
 		tspp_destroy_buffers(channel_id, channel);
 		channel->buffer_count = 0;
+
+		if (channel->dma_pool) {
+			dma_pool_destroy(channel->dma_pool);
+			channel->dma_pool = NULL;
+		}
 		return -ENOMEM;
 	}
 
@@ -2292,8 +2339,10 @@
 		 */
 		if (buffer->read_index == buffer->filled) {
 			buffer->state = TSPP_BUF_STATE_WAITING;
+
 			if (tspp_queue_buffer(channel, buffer))
 				pr_err("tspp: can't submit transfer");
+
 			channel->locked = channel->read;
 			channel->read = channel->read->next;
 		}
diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c
index 0f4cc6d..776b832 100644
--- a/drivers/mmc/card/block.c
+++ b/drivers/mmc/card/block.c
@@ -57,6 +57,7 @@
 #define INAND_CMD38_ARG_SECERASE 0x80
 #define INAND_CMD38_ARG_SECTRIM1 0x81
 #define INAND_CMD38_ARG_SECTRIM2 0x88
+#define MMC_BLK_TIMEOUT_MS  (30 * 1000)        /* 30 sec timeout */
 
 #define MMC_SANITIZE_REQ_TIMEOUT 240000 /* msec */
 
@@ -121,7 +122,8 @@
 	struct device_attribute force_ro;
 	struct device_attribute power_ro_lock;
 	struct device_attribute num_wr_reqs_to_start_packing;
-	struct device_attribute min_sectors_to_check_bkops_status;
+	struct device_attribute bkops_check_threshold;
+	struct device_attribute no_pack_for_random;
 	int	area_type;
 };
 
@@ -331,6 +333,114 @@
 	return ret;
 }
 
+static ssize_t
+bkops_check_threshold_show(struct device *dev,
+				  struct device_attribute *attr, char *buf)
+{
+	struct mmc_blk_data *md = mmc_blk_get(dev_to_disk(dev));
+	struct mmc_card *card = md->queue.card;
+	int ret;
+
+	if (!card)
+		ret = -EINVAL;
+	else
+	    ret = snprintf(buf, PAGE_SIZE, "%d\n",
+		card->bkops_info.size_percentage_to_queue_delayed_work);
+
+	mmc_blk_put(md);
+	return ret;
+}
+
+static ssize_t
+bkops_check_threshold_store(struct device *dev,
+				 struct device_attribute *attr,
+				 const char *buf, size_t count)
+{
+	int value;
+	struct mmc_blk_data *md = mmc_blk_get(dev_to_disk(dev));
+	struct mmc_card *card = md->queue.card;
+	unsigned int card_size;
+	int ret = count;
+
+	if (!card) {
+		ret = -EINVAL;
+		goto exit;
+	}
+
+	sscanf(buf, "%d", &value);
+	if ((value <= 0) || (value >= 100)) {
+		ret = -EINVAL;
+		goto exit;
+	}
+
+	card_size = (unsigned int)get_capacity(md->disk);
+	if (card_size <= 0) {
+		ret = -EINVAL;
+		goto exit;
+	}
+	card->bkops_info.size_percentage_to_queue_delayed_work = value;
+	card->bkops_info.min_sectors_to_queue_delayed_work =
+		(card_size * value) / 100;
+
+	pr_debug("%s: size_percentage = %d, min_sectors = %d",
+			mmc_hostname(card->host),
+			card->bkops_info.size_percentage_to_queue_delayed_work,
+			card->bkops_info.min_sectors_to_queue_delayed_work);
+
+exit:
+	mmc_blk_put(md);
+	return count;
+}
+
+static ssize_t
+no_pack_for_random_show(struct device *dev,
+				  struct device_attribute *attr, char *buf)
+{
+	struct mmc_blk_data *md = mmc_blk_get(dev_to_disk(dev));
+	int ret;
+
+	ret = snprintf(buf, PAGE_SIZE, "%d\n", md->queue.no_pack_for_random);
+
+	mmc_blk_put(md);
+	return ret;
+}
+
+static ssize_t
+no_pack_for_random_store(struct device *dev,
+				 struct device_attribute *attr,
+				 const char *buf, size_t count)
+{
+	int value;
+	struct mmc_blk_data *md = mmc_blk_get(dev_to_disk(dev));
+	struct mmc_card *card = md->queue.card;
+	int ret = count;
+
+	if (!card) {
+		ret = -EINVAL;
+		goto exit;
+	}
+
+	sscanf(buf, "%d", &value);
+
+	if (value < 0) {
+		pr_err("%s: value %d is not valid. old value remains = %d",
+			mmc_hostname(card->host), value,
+			md->queue.no_pack_for_random);
+		ret = -EINVAL;
+		goto exit;
+	}
+
+	md->queue.no_pack_for_random = (value > 0) ?  true : false;
+
+	pr_debug("%s: no_pack_for_random: new value = %d",
+		mmc_hostname(card->host),
+		md->queue.no_pack_for_random);
+
+exit:
+	mmc_blk_put(md);
+	return ret;
+}
+
 static int mmc_blk_open(struct block_device *bdev, fmode_t mode)
 {
 	struct mmc_blk_data *md = mmc_blk_get(bdev->bd_disk);
@@ -958,6 +1068,9 @@
 	from = blk_rq_pos(req);
 	nr = blk_rq_sectors(req);
 
+	if (card->ext_csd.bkops_en)
+		card->bkops_info.sectors_changed += blk_rq_sectors(req);
+
 	if (mmc_can_discard(card))
 		arg = MMC_DISCARD_ARG;
 	else if (mmc_can_trim(card))
@@ -1188,6 +1301,9 @@
 	 */
 	if (!mmc_host_is_spi(card->host) && rq_data_dir(req) != READ) {
 		u32 status;
+		unsigned long timeout;
+
+		timeout = jiffies + msecs_to_jiffies(MMC_BLK_TIMEOUT_MS);
 		do {
 			int err = get_card_status(card, &status, 5);
 			if (err) {
@@ -1195,6 +1311,17 @@
 				       req->rq_disk->disk_name, err);
 				return MMC_BLK_CMD_ERR;
 			}
+
+			/* Timeout if the device never becomes ready for data
+			 * and never leaves the program state.
+			 */
+			if (time_after(jiffies, timeout)) {
+				pr_err("%s: Card stuck in programming state!"\
+					" %s %s\n", mmc_hostname(card->host),
+					req->rq_disk->disk_name, __func__);
+
+				return MMC_BLK_CMD_ERR;
+			}
 			/*
 			 * Some cards mishandle the status bits,
 			 * so make sure to check both the busy
@@ -1512,39 +1639,6 @@
 }
 EXPORT_SYMBOL(mmc_blk_init_packed_statistics);
 
-/**
- * mmc_blk_init_async_event_statistics() - Init async event
- * statistics data
- * @card:	The mmc_card in which the async_event_stats
- *		struct is a member
- *
- * Initiate counters for the new request feature, and mark the
- * statistics as enabled.
- */
-void mmc_blk_init_async_event_statistics(struct mmc_card *card)
-{
-	if (!card)
-		return;
-
-	/* init async events tests stats */
-	memset(&card->async_event_stats,
-	       sizeof(struct mmc_async_event_stats), 0);
-	card->async_event_stats.null_fetched = 0;
-	card->async_event_stats.wakeup_new = 0;
-	card->async_event_stats.new_request_flag = 0;
-	card->async_event_stats.q_no_waiting = 0;
-	card->async_event_stats.enabled = true;
-	card->async_event_stats.no_mmc_request_action = 0;
-	card->async_event_stats.wakeup_mq_thread = 0;
-	card->async_event_stats.fetch_due_to_new_req = 0;
-	card->async_event_stats.returned_new_req = 0;
-	card->async_event_stats.done_flag = 0;
-	card->async_event_stats.cmd_retry = 0;
-	card->async_event_stats.done_when_new_req_event_on = 0;
-	card->async_event_stats.new_req_when_new_marked = 0;
-}
-EXPORT_SYMBOL(mmc_blk_init_async_event_statistics);
-
 static u8 mmc_blk_prep_packed_list(struct mmc_queue *mq, struct request *req)
 {
 	struct request_queue *q = mq->queue;
@@ -1557,12 +1651,7 @@
 	u8 put_back = 0;
 	u8 max_packed_rw = 0;
 	u8 reqs = 0;
-	struct mmc_wr_pack_stats *stats;
-
-	if (!card)
-		goto no_packed;
-
-	stats = &card->wr_pack_stats;
+	struct mmc_wr_pack_stats *stats = &card->wr_pack_stats;
 
 	mmc_blk_clear_packed(mq->mqrq_cur);
 
@@ -1657,8 +1746,21 @@
 			break;
 		}
 
-		if (rq_data_dir(next) == WRITE)
+		if (mq->no_pack_for_random) {
+			if ((blk_rq_pos(cur) + blk_rq_sectors(cur)) !=
+			    blk_rq_pos(next)) {
+				MMC_BLK_UPDATE_STOP_REASON(stats, RANDOM);
+				put_back = 1;
+				break;
+			}
+		}
+
+		if (rq_data_dir(next) == WRITE) {
 			mq->num_of_potential_packed_wr_reqs++;
+			if (card->ext_csd.bkops_en)
+				card->bkops_info.sectors_changed +=
+					blk_rq_sectors(next);
+		}
 		list_add_tail(&next->queuelist, &mq->mqrq_cur->packed_list);
 		cur = next;
 		reqs++;
@@ -1885,12 +1987,13 @@
 	struct mmc_async_req *areq;
 	const u8 packed_num = 2;
 	u8 reqs = 0;
-	struct mmc_async_event_stats *stats = &card->async_event_stats;
 
 	if (!rqc && !mq->mqrq_prev->req)
 		return 0;
 
 	if (rqc) {
+		if ((card->ext_csd.bkops_en) && (rq_data_dir(rqc) == WRITE))
+			card->bkops_info.sectors_changed += blk_rq_sectors(rqc);
 		reqs = mmc_blk_prep_packed_list(mq, rqc);
 	}
 
@@ -1906,12 +2009,8 @@
 			areq = NULL;
 		areq = mmc_start_req(card->host, areq, (int *) &status);
 		if (!areq) {
-			if (status == MMC_BLK_NEW_REQUEST && stats) {
-				if (stats->enabled)
-					stats->returned_new_req++;
-
+			if (status == MMC_BLK_NEW_REQUEST)
 				mq->flags |= MMC_QUEUE_NEW_REQUEST;
-			}
 			return 0;
 		}
 
@@ -1922,8 +2021,6 @@
 		mmc_queue_bounce_post(mq_rq);
 
 		switch (status) {
-		case MMC_BLK_NEW_REQUEST:
-			BUG(); /* should never get here */
 		case MMC_BLK_SUCCESS:
 		case MMC_BLK_PARTIAL:
 			/*
@@ -1996,6 +2093,11 @@
 			break;
 		case MMC_BLK_NOMEDIUM:
 			goto cmd_abort;
+		default:
+			pr_err("%s:%s: Unhandled return value (%d)",
+					req->rq_disk->disk_name,
+					__func__, status);
+			goto cmd_abort;
 		}
 
 		if (ret) {
@@ -2051,6 +2153,8 @@
 	int ret;
 	struct mmc_blk_data *md = mq->data;
 	struct mmc_card *card = md->queue.card;
+	struct mmc_host *host = card->host;
+	unsigned long flags;
 
 #ifdef CONFIG_MMC_BLOCK_DEFERRED_RESUME
 	if (mmc_bus_needs_resume(card->host)) {
@@ -2062,11 +2166,8 @@
 	if (req && !mq->mqrq_prev->req) {
 		/* claim host only for the first request */
 		mmc_claim_host(card->host);
-		if (card->ext_csd.bkops_en &&
-		    card->bkops_info.started_delayed_bkops) {
-			card->bkops_info.started_delayed_bkops = false;
+		if (card->ext_csd.bkops_en)
 			mmc_stop_bkops(card);
-		}
 	}
 
 	ret = mmc_blk_part_switch(card, md);
@@ -2101,13 +2202,21 @@
 			mmc_blk_issue_rw_rq(mq, NULL);
 		ret = mmc_blk_issue_flush(mq, req);
 	} else {
+		if (!req && host->areq) {
+			spin_lock_irqsave(&host->context_info.lock, flags);
+			host->context_info.is_waiting_last_req = true;
+			spin_unlock_irqrestore(&host->context_info.lock, flags);
+		}
 		ret = mmc_blk_issue_rw_rq(mq, req);
 	}
 
 out:
-	if (!req && !(mq->flags & MMC_QUEUE_NEW_REQUEST))
+	if (!req && !(mq->flags & MMC_QUEUE_NEW_REQUEST)) {
+		if (mmc_card_need_bkops(card))
+			mmc_start_bkops(card, false);
 		/* release host only when there are no more requests */
 		mmc_release_host(card->host);
+	}
 	return ret;
 }
 
@@ -2126,6 +2235,8 @@
 {
 	struct mmc_blk_data *md;
 	int devidx, ret;
+	unsigned int percentage =
+		BKOPS_SIZE_PERCENTAGE_TO_QUEUE_DELAYED_WORK;
 
 	devidx = find_first_zero_bit(dev_use, max_devices);
 	if (devidx >= max_devices)
@@ -2205,6 +2316,10 @@
 	blk_queue_logical_block_size(md->queue.queue, 512);
 	set_capacity(md->disk, size);
 
+	card->bkops_info.size_percentage_to_queue_delayed_work = percentage;
+	card->bkops_info.min_sectors_to_queue_delayed_work =
+		((unsigned int)size * percentage) / 100;
+
 	if (mmc_host_cmd23(card->host)) {
 		if (mmc_card_mmc(card) ||
 		    (mmc_card_sd(card) &&
@@ -2397,8 +2512,34 @@
 	if (ret)
 		goto num_wr_reqs_to_start_packing_fail;
 
+	md->bkops_check_threshold.show = bkops_check_threshold_show;
+	md->bkops_check_threshold.store = bkops_check_threshold_store;
+	sysfs_attr_init(&md->bkops_check_threshold.attr);
+	md->bkops_check_threshold.attr.name = "bkops_check_threshold";
+	md->bkops_check_threshold.attr.mode = S_IRUGO | S_IWUSR;
+	ret = device_create_file(disk_to_dev(md->disk),
+				 &md->bkops_check_threshold);
+	if (ret)
+		goto bkops_check_threshold_fails;
+
+	md->no_pack_for_random.show = no_pack_for_random_show;
+	md->no_pack_for_random.store = no_pack_for_random_store;
+	sysfs_attr_init(&md->no_pack_for_random.attr);
+	md->no_pack_for_random.attr.name = "no_pack_for_random";
+	md->no_pack_for_random.attr.mode = S_IRUGO | S_IWUSR;
+	ret = device_create_file(disk_to_dev(md->disk),
+				 &md->no_pack_for_random);
+	if (ret)
+		goto no_pack_for_random_fails;
+
 	return ret;
 
+no_pack_for_random_fails:
+	device_remove_file(disk_to_dev(md->disk),
+			   &md->bkops_check_threshold);
+bkops_check_threshold_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:
diff --git a/drivers/mmc/card/mmc_block_test.c b/drivers/mmc/card/mmc_block_test.c
index 5d571a5..2cda66c 100644
--- a/drivers/mmc/card/mmc_block_test.c
+++ b/drivers/mmc/card/mmc_block_test.c
@@ -285,50 +285,6 @@
 	spin_unlock(&card->wr_pack_stats.lock);
 }
 
-/**
- * mmc_print_async_event_stats() - Print async event statistics
- * @card:	The mmc_card in which the async_event_stats
- *		struct is a member
- */
-void mmc_print_async_event_stats(struct mmc_card *card)
-{
-	struct mmc_async_event_stats *s;
-
-	if (!card)
-		return;
-
-	s = &card->async_event_stats;
-	if (!s)
-		return;
-
-	pr_info("%s: new notification & req statistics:\n",
-		mmc_hostname(card->host));
-	pr_info("%s: done_flag:%d", mmc_hostname(card->host),
-		s->done_flag);
-	pr_info("%s: cmd_retry:%d", mmc_hostname(card->host),
-		s->cmd_retry);
-	pr_info("%s: NULL fetched:%d", mmc_hostname(card->host),
-		s->null_fetched);
-	pr_info("%s: wake up new:%d", mmc_hostname(card->host),
-		s->wakeup_new);
-	pr_info("%s: new_request_flag:%d", mmc_hostname(card->host),
-		s->new_request_flag);
-	pr_info("%s: no waiting:%d\n", mmc_hostname(card->host),
-		s->q_no_waiting);
-	pr_info("%s: no_mmc_request_action:%d", mmc_hostname(card->host),
-		s->no_mmc_request_action);
-	pr_info("%s: wakeup_mq_thread:%d", mmc_hostname(card->host),
-		s->wakeup_mq_thread);
-	pr_info("%s: fetch_due_to_new_req:%d", mmc_hostname(card->host),
-		s->fetch_due_to_new_req);
-	pr_info("%s: returned_new_req:%d", mmc_hostname(card->host),
-		s->returned_new_req);
-	pr_info("%s: done_when_new_req_event_on:%d", mmc_hostname(card->host),
-		s->done_when_new_req_event_on);
-	pr_info("%s: new_req_when_new_marked:%d", mmc_hostname(card->host),
-		s->new_req_when_new_marked);
-}
-
 /*
  * A callback assigned to the packed_test_fn field.
  * Called from block layer in mmc_blk_packed_hdr_wrq_prep.
@@ -1893,6 +1849,8 @@
 	case BKOPS_DELAYED_WORK_LEVEL_1:
 		bkops_stat->ignore_card_bkops_status = true;
 		card->ext_csd.raw_bkops_status = 1;
+		card->bkops_info.sectors_changed =
+			card->bkops_info.min_sectors_to_queue_delayed_work + 1;
 		mbtd->bkops_stage = BKOPS_STAGE_1;
 
 		__blk_run_queue(q);
@@ -1909,6 +1867,8 @@
 	case BKOPS_DELAYED_WORK_LEVEL_1_HPI:
 		bkops_stat->ignore_card_bkops_status = true;
 		card->ext_csd.raw_bkops_status = 1;
+		card->bkops_info.sectors_changed =
+			card->bkops_info.min_sectors_to_queue_delayed_work + 1;
 		mbtd->bkops_stage = BKOPS_STAGE_1;
 
 		__blk_run_queue(q);
@@ -1937,6 +1897,8 @@
 	case BKOPS_CANCEL_DELAYED_WORK:
 		bkops_stat->ignore_card_bkops_status = true;
 		card->ext_csd.raw_bkops_status = 1;
+		card->bkops_info.sectors_changed =
+			card->bkops_info.min_sectors_to_queue_delayed_work + 1;
 		mbtd->bkops_stage = BKOPS_STAGE_1;
 
 		__blk_run_queue(q);
@@ -2091,9 +2053,6 @@
 	if (!mq || !mq->card)
 		goto exit;
 
-	/* disable async_event test stats */
-	mq->card->async_event_stats.enabled = false;
-	mmc_print_async_event_stats(mq->card);
 	test_pr_info("Completed %d requests",
 			mbtd->completed_req_count);
 
@@ -2147,14 +2106,12 @@
 	struct mmc_queue *mq = (struct mmc_queue *)q->queuedata;
 
 	mmc_blk_init_packed_statistics(mq->card);
-	mmc_blk_init_async_event_statistics(mq->card);
-
 	mbtd->completed_req_count = 0;
 
 	return 0;
 }
 
-static int test_new_req_notification(struct test_data *ptd)
+static int run_new_req(struct test_data *ptd)
 {
 	int ret = 0;
 	int i;
@@ -2224,18 +2181,6 @@
 	return ret;
 }
 
-static int run_new_req(struct test_data *td)
-{
-	int ret = 0;
-	struct request_queue *q = td->req_q;
-	struct mmc_queue *mq = (struct mmc_queue *)q->queuedata;
-
-	mmc_blk_init_async_event_statistics(mq->card);
-	ret = test_new_req_notification(td);
-
-	return ret;
-}
-
 static bool message_repeat;
 static int test_open(struct inode *inode, struct file *file)
 {
diff --git a/drivers/mmc/card/queue.c b/drivers/mmc/card/queue.c
index dc27db6..c4b2d16 100644
--- a/drivers/mmc/card/queue.c
+++ b/drivers/mmc/card/queue.c
@@ -59,33 +59,18 @@
 	struct request_queue *q = mq->queue;
 	struct request *req;
 	struct mmc_card *card = mq->card;
-	struct mmc_async_event_stats *stats;
-	struct mmc_queue_req *tmp;
-
-	if (!card)
-		return 0;
-
-	stats = &mq->card->async_event_stats;
 
 	current->flags |= PF_MEMALLOC;
 
 	down(&mq->thread_sem);
 	do {
-
+		struct mmc_queue_req *tmp;
 		req = NULL;	/* Must be set to NULL at each iteration */
 
 		spin_lock_irq(q->queue_lock);
 		set_current_state(TASK_INTERRUPTIBLE);
 		req = blk_fetch_request(q);
 		mq->mqrq_cur->req = req;
-		if (!req && mq->mqrq_prev->req &&
-			!(mq->mqrq_prev->req->cmd_flags & REQ_SANITIZE) &&
-			!(mq->mqrq_prev->req->cmd_flags & REQ_FLUSH) &&
-			!(mq->mqrq_prev->req->cmd_flags & REQ_DISCARD)) {
-			card->host->context_info.is_waiting_last_req = true;
-			if (stats && stats->enabled)
-				stats->null_fetched++;
-		}
 		spin_unlock_irq(q->queue_lock);
 
 		if (req || mq->mqrq_prev->req) {
@@ -93,10 +78,18 @@
 			mq->issue_fn(mq, req);
 			if (mq->flags & MMC_QUEUE_NEW_REQUEST) {
 				mq->flags &= ~MMC_QUEUE_NEW_REQUEST;
-				if (stats && stats->enabled)
-					stats->fetch_due_to_new_req++;
 				continue; /* fetch again */
 			}
+
+			/*
+			 * Current request becomes previous request
+			 * and vice versa.
+			 */
+			mq->mqrq_prev->brq.mrq.data = NULL;
+			mq->mqrq_prev->req = NULL;
+			tmp = mq->mqrq_prev;
+			mq->mqrq_prev = mq->mqrq_cur;
+			mq->mqrq_cur = tmp;
 		} else {
 			if (kthread_should_stop()) {
 				set_current_state(TASK_RUNNING);
@@ -107,13 +100,6 @@
 			schedule();
 			down(&mq->thread_sem);
 		}
-
-		/* Current request becomes previous request and vice versa. */
-		mq->mqrq_prev->brq.mrq.data = NULL;
-		mq->mqrq_prev->req = NULL;
-		tmp = mq->mqrq_prev;
-		mq->mqrq_prev = mq->mqrq_cur;
-		mq->mqrq_cur = tmp;
 	} while (1);
 	up(&mq->thread_sem);
 
@@ -129,7 +115,6 @@
 static void mmc_request(struct request_queue *q)
 {
 	struct mmc_queue *mq = q->queuedata;
-	struct mmc_async_event_stats *stats;
 	struct request *req;
 	unsigned long flags;
 	struct mmc_context_info *cntx;
@@ -141,39 +126,22 @@
 		}
 		return;
 	}
-	if (mq->card) {
-		cntx = &mq->card->host->context_info;
-		stats = &mq->card->async_event_stats;
-	} else
-		return;
 
 	cntx = &mq->card->host->context_info;
-	stats = &mq->card->async_event_stats;
 	if (!mq->mqrq_cur->req && mq->mqrq_prev->req) {
 		/*
 		 * New MMC request arrived when MMC thread may be
 		 * blocked on the previous request to be complete
 		 * with no current request fetched
 		 */
-
 		spin_lock_irqsave(&cntx->lock, flags);
 		if (cntx->is_waiting_last_req) {
-			if (stats && stats->enabled)
-				stats->wakeup_new++;
-			if (cntx->is_new_req)
-				if (stats->enabled)
-					stats->new_req_when_new_marked++;
 			cntx->is_new_req = true;
 			wake_up_interruptible(&cntx->wait);
-		} else if (stats->enabled)
-			stats->q_no_waiting++;
+		}
 		spin_unlock_irqrestore(&cntx->lock, flags);
-	} else if (!mq->mqrq_cur->req && !mq->mqrq_prev->req) {
+	} else if (!mq->mqrq_cur->req && !mq->mqrq_prev->req)
 		wake_up_process(mq->thread);
-		if (stats->enabled)
-			stats->wakeup_mq_thread++;
-	} else if (stats->enabled)
-			stats->no_mmc_request_action++;
 }
 
 static struct scatterlist *mmc_alloc_sg(int sg_len, int *err)
diff --git a/drivers/mmc/card/queue.h b/drivers/mmc/card/queue.h
index 0a72372..119b0c7 100644
--- a/drivers/mmc/card/queue.h
+++ b/drivers/mmc/card/queue.h
@@ -51,6 +51,7 @@
 	bool			wr_packing_enabled;
 	int			num_of_potential_packed_wr_reqs;
 	int			num_wr_reqs_to_start_packing;
+	bool			no_pack_for_random;
 	int (*err_check_fn) (struct mmc_card *, struct mmc_async_req *);
 	void (*packed_test_fn) (struct request_queue *, struct mmc_queue_req *);
 };
diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
index f598e63..afa0197 100644
--- a/drivers/mmc/core/core.c
+++ b/drivers/mmc/core/core.c
@@ -47,6 +47,9 @@
 
 static void mmc_clk_scaling(struct mmc_host *host, bool from_wq);
 
+/* If the device is not responding */
+#define MMC_CORE_TIMEOUT_MS	(10 * 60 * 1000) /* 10 minute timeout */
+
 /*
  * Background operations can take a long time, depending on the housekeeping
  * operations the card has to perform.
@@ -357,6 +360,10 @@
 	if (!card || !card->ext_csd.bkops_en || mmc_card_doing_bkops(card))
 		return;
 
+	if (card->bkops_info.sectors_changed <
+	    card->bkops_info.min_sectors_to_queue_delayed_work)
+		return;
+
 	pr_debug("%s: %s: queueing delayed_bkops_work\n",
 		 mmc_hostname(card->host), __func__);
 
@@ -366,7 +373,6 @@
 	 * it was removed from the queue work but not started yet
 	 */
 	card->bkops_info.cancel_delayed_work = false;
-	card->bkops_info.started_delayed_bkops = true;
 	queue_delayed_work(system_nrt_wq, &card->bkops_info.dw,
 			   msecs_to_jiffies(
 				   card->bkops_info.delay_ms));
@@ -386,8 +392,6 @@
 void mmc_start_bkops(struct mmc_card *card, bool from_exception)
 {
 	int err;
-	int timeout;
-	bool use_busy_signal;
 
 	BUG_ON(!card);
 	if (!card->ext_csd.bkops_en)
@@ -408,43 +412,45 @@
 		goto out;
 	}
 
-	err = mmc_read_bkops_status(card);
-	if (err) {
-		pr_err("%s: %s: Failed to read bkops status: %d\n",
-		       mmc_hostname(card->host), __func__, err);
+	if (from_exception && mmc_card_need_bkops(card))
 		goto out;
-	}
-
-	if (!card->ext_csd.raw_bkops_status)
-		goto out;
-
-	pr_info("%s: %s: card->ext_csd.raw_bkops_status = 0x%x\n",
-		mmc_hostname(card->host), __func__,
-		card->ext_csd.raw_bkops_status);
 
 	/*
-	 * If the function was called due to exception but there is no need
-	 * for urgent BKOPS, BKOPs will be performed by the delayed BKOPs
-	 * work, before going to suspend
+	 * If the need BKOPS flag is set, there is no need to check if BKOPS
+	 * is needed since we already know that it does
 	 */
-	if (card->ext_csd.raw_bkops_status < EXT_CSD_BKOPS_LEVEL_2 &&
-	    from_exception) {
-		pr_debug("%s: %s: Level 1 from exception, exit",
-			 mmc_hostname(card->host), __func__);
+	if (!mmc_card_need_bkops(card)) {
+		err = mmc_read_bkops_status(card);
+		if (err) {
+			pr_err("%s: %s: Failed to read bkops status: %d\n",
+			       mmc_hostname(card->host), __func__, err);
+			goto out;
+		}
+
+		if (!card->ext_csd.raw_bkops_status)
+			goto out;
+
+		pr_info("%s: %s: raw_bkops_status=0x%x, from_exception=%d\n",
+			mmc_hostname(card->host), __func__,
+			card->ext_csd.raw_bkops_status,
+			from_exception);
+	}
+
+	/*
+	 * If the function was called due to exception, BKOPS will be performed
+	 * after handling the last pending request
+	 */
+	if (from_exception) {
+		pr_debug("%s: %s: Level %d from exception, exit",
+			 mmc_hostname(card->host), __func__,
+			 card->ext_csd.raw_bkops_status);
+		mmc_card_set_need_bkops(card);
 		goto out;
 	}
-
-	if (card->ext_csd.raw_bkops_status >= EXT_CSD_BKOPS_LEVEL_2) {
-		timeout = MMC_BKOPS_MAX_TIMEOUT;
-		use_busy_signal = true;
-	} else {
-		timeout = 0;
-		use_busy_signal = false;
-	}
+	pr_info("%s: %s: Starting bkops\n", mmc_hostname(card->host), __func__);
 
 	err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
-			   EXT_CSD_BKOPS_START, 1, timeout,
-			   use_busy_signal, use_busy_signal);
+			EXT_CSD_BKOPS_START, 1, 0, false, false);
 	if (err) {
 		pr_warn("%s: %s: Error %d when starting bkops\n",
 			mmc_hostname(card->host), __func__, err);
@@ -452,19 +458,13 @@
 	}
 	MMC_UPDATE_STATS_BKOPS_SEVERITY_LEVEL(card->bkops_info.bkops_stats,
 					card->ext_csd.raw_bkops_status);
+	mmc_card_clr_need_bkops(card);
 
-	/*
-	 * For urgent bkops status (LEVEL_2 and more)
-	 * bkops executed synchronously, otherwise
-	 * the operation is in progress
-	 */
-	if (!use_busy_signal) {
-		mmc_card_set_doing_bkops(card);
-		pr_debug("%s: %s: starting the polling thread\n",
-			 mmc_hostname(card->host), __func__);
-		queue_work(system_nrt_wq,
-			   &card->bkops_info.poll_for_completion);
-	}
+	mmc_card_set_doing_bkops(card);
+	pr_debug("%s: %s: starting the polling thread\n",
+		 mmc_hostname(card->host), __func__);
+	queue_work(system_nrt_wq,
+		   &card->bkops_info.poll_for_completion);
 
 out:
 	mmc_release_host(card->host);
@@ -518,7 +518,7 @@
 			pr_debug("%s: %s: completed BKOPs, exit polling\n",
 				 mmc_hostname(card->host), __func__);
 			mmc_card_clr_doing_bkops(card);
-			card->bkops_info.started_delayed_bkops = false;
+			card->bkops_info.sectors_changed = 0;
 			goto out;
 		}
 
@@ -531,8 +531,12 @@
 		msleep(BKOPS_COMPLETION_POLLING_INTERVAL_MS);
 	} while (time_before(jiffies, timeout_jiffies));
 
-	pr_err("%s: %s: exit polling due to timeout\n",
+	pr_err("%s: %s: exit polling due to timeout, stop bkops\n",
 	       mmc_hostname(card->host), __func__);
+	err = mmc_stop_bkops(card);
+	if (err)
+		pr_err("%s: %s: mmc_stop_bkops failed, err=%d\n",
+			       mmc_hostname(card->host), __func__, err);
 
 	return;
 out:
@@ -559,6 +563,7 @@
 	mmc_start_bkops(card, false);
 }
 EXPORT_SYMBOL(mmc_start_idle_time_bkops);
+
 /*
  * mmc_wait_data_done() - done callback for data request
  * @mrq: done data request
@@ -622,13 +627,13 @@
  * Returns enum mmc_blk_status after checking errors.
  */
 static int mmc_wait_for_data_req_done(struct mmc_host *host,
-				      struct mmc_request *mrq)
+				      struct mmc_request *mrq,
+				      struct mmc_async_req *next_req)
 {
 	struct mmc_command *cmd;
 	struct mmc_context_info *context_info = &host->context_info;
 	int err;
 	unsigned long flags;
-	struct mmc_async_event_stats *stats = &host->card->async_event_stats;
 
 	while (1) {
 		wait_io_event_interruptible(context_info->wait,
@@ -641,18 +646,13 @@
 			context_info->is_done_rcv = false;
 			context_info->is_new_req = false;
 			cmd = mrq->cmd;
-			if (stats->enabled) {
-				stats->done_flag++;
-				if (context_info->is_new_req)
-					stats->done_when_new_req_event_on++;
-			}
 			if (!cmd->error || !cmd->retries ||
 					mmc_card_removed(host->card)) {
 				err = host->areq->err_check(host->card,
 						host->areq);
 				break; /* return err */
 			} else {
-				pr_info("%s: req failed (CMD%u):%d, retrying\n",
+				pr_info("%s: req failed (CMD%u): %d, retrying...\n",
 						mmc_hostname(host),
 						cmd->opcode, cmd->error);
 				cmd->retries--;
@@ -662,8 +662,6 @@
 			}
 		} else if (context_info->is_new_req) {
 			context_info->is_new_req = false;
-			if (stats->enabled)
-				stats->new_request_flag++;
 			err = MMC_BLK_NEW_REQUEST;
 			break; /* return err */
 		}
@@ -778,13 +776,9 @@
 		mmc_pre_req(host, areq->mrq, !host->areq);
 
 	if (host->areq) {
-		err = mmc_wait_for_data_req_done(host, host->areq->mrq);
+		err = mmc_wait_for_data_req_done(host, host->areq->mrq,
+				areq);
 		if (err == MMC_BLK_NEW_REQUEST) {
-			if (areq) {
-				pr_err("%s: new request while areq = %p",
-						mmc_hostname(host), areq);
-				BUG_ON(1);
-			}
 			if (error)
 				*error = err;
 			/*
@@ -854,6 +848,7 @@
 {
 	int err;
 	u32 status;
+	unsigned long prg_wait;
 
 	BUG_ON(!card);
 
@@ -869,30 +864,39 @@
 		goto out;
 	}
 
-	/*
-	 * If the card status is in PRG-state, we can send the HPI command.
-	 */
-	if (R1_CURRENT_STATE(status) == R1_STATE_PRG) {
-		do {
-			/*
-			 * We don't know when the HPI command will finish
-			 * processing, so we need to resend HPI until out
-			 * of prg-state, and keep checking the card status
-			 * with SEND_STATUS.  If a timeout error occurs when
-			 * sending the HPI command, we are already out of
-			 * prg-state.
-			 */
-			err = mmc_send_hpi_cmd(card, &status);
-			if (err)
-				pr_debug("%s: abort HPI (%d error)\n",
-					 mmc_hostname(card->host), err);
+	switch (R1_CURRENT_STATE(status)) {
+	case R1_STATE_IDLE:
+	case R1_STATE_READY:
+	case R1_STATE_STBY:
+	case R1_STATE_TRAN:
+		/*
+		 * In idle and transfer states, HPI is not needed and the caller
+		 * can issue the next intended command immediately
+		 */
+		goto out;
+	case R1_STATE_PRG:
+		break;
+	default:
+		/* In all other states, it's illegal to issue HPI */
+		pr_debug("%s: HPI cannot be sent. Card state=%d\n",
+			mmc_hostname(card->host), R1_CURRENT_STATE(status));
+		err = -EINVAL;
+		goto out;
+	}
 
-			err = mmc_send_status(card, &status);
-			if (err)
-				break;
-		} while (R1_CURRENT_STATE(status) == R1_STATE_PRG);
-	} else
-		pr_debug("%s: Left prg-state\n", mmc_hostname(card->host));
+	err = mmc_send_hpi_cmd(card, &status);
+	if (err)
+		goto out;
+
+	prg_wait = jiffies + msecs_to_jiffies(card->ext_csd.out_of_int_time);
+	do {
+		err = mmc_send_status(card, &status);
+
+		if (!err && R1_CURRENT_STATE(status) == R1_STATE_TRAN)
+			break;
+		if (time_after(jiffies, prg_wait))
+			err = -ETIMEDOUT;
+	} while (!err);
 
 out:
 	mmc_release_host(card->host);
@@ -936,7 +940,9 @@
  *	Send HPI command to stop ongoing background operations to
  *	allow rapid servicing of foreground operations, e.g. read/
  *	writes. Wait until the card comes out of the programming state
- *	to avoid errors in servicing read/write requests.
+ *      to avoid errors in servicing read/write requests.
+ *
+ *      The function should be called with host claimed.
  */
 int mmc_stop_bkops(struct mmc_card *card)
 {
@@ -2019,6 +2025,7 @@
 {
 	struct mmc_command cmd = {0};
 	unsigned int qty = 0;
+	unsigned long timeout;
 	int err;
 
 	/*
@@ -2096,6 +2103,7 @@
 	if (mmc_host_is_spi(card->host))
 		goto out;
 
+	timeout = jiffies + msecs_to_jiffies(MMC_CORE_TIMEOUT_MS);
 	do {
 		memset(&cmd, 0, sizeof(struct mmc_command));
 		cmd.opcode = MMC_SEND_STATUS;
@@ -2109,8 +2117,19 @@
 			err = -EIO;
 			goto out;
 		}
+
+		/* Timeout if the device never becomes ready for data and
+		 * never leaves the program state.
+		 */
+		if (time_after(jiffies, timeout)) {
+			pr_err("%s: Card stuck in programming state! %s\n",
+				mmc_hostname(card->host), __func__);
+			err =  -EIO;
+			goto out;
+		}
+
 	} while (!(cmd.resp[0] & R1_READY_FOR_DATA) ||
-		 R1_CURRENT_STATE(cmd.resp[0]) == R1_STATE_PRG);
+		 (R1_CURRENT_STATE(cmd.resp[0]) == R1_STATE_PRG));
 out:
 	return err;
 }
@@ -3061,6 +3080,7 @@
  * Turn the cache ON/OFF.
  * Turning the cache OFF shall trigger flushing of the data
  * to the non-volatile storage.
+ * This function should be called with host claimed
  */
 int mmc_cache_ctrl(struct mmc_host *host, u8 enable)
 {
@@ -3072,9 +3092,6 @@
 			mmc_card_is_removable(host))
 		return err;
 
-	if (!mmc_try_claim_host(host))
-		return -EBUSY;
-
 	if (card && mmc_card_mmc(card) &&
 			(card->ext_csd.cache_size > 0)) {
 		enable = !!enable;
@@ -3092,7 +3109,6 @@
 				card->ext_csd.cache_ctrl = enable;
 		}
 	}
-	mmc_release_host(host);
 
 	return err;
 }
@@ -3114,9 +3130,6 @@
 	if (cancel_delayed_work(&host->detect))
 		wake_unlock(&host->detect_wake_lock);
 	mmc_flush_scheduled_work();
-	err = mmc_cache_ctrl(host, 0);
-	if (err)
-		goto out;
 
 	mmc_bus_get(host);
 	if (host->bus_ops && !host->bus_dead) {
@@ -3174,7 +3187,6 @@
 	if (!err && !mmc_card_keep_power(host))
 		mmc_power_off(host);
 
-out:
 	return err;
 stop_bkops_err:
 	if (!(host->card && mmc_card_sdio(host->card)))
@@ -3317,6 +3329,14 @@
 EXPORT_SYMBOL(mmc_set_embedded_sdio_data);
 #endif
 
+/**
+ * mmc_init_context_info() - init synchronization context
+ * @host: mmc host
+ *
+ * Init struct context_info needed to implement asynchronous
+ * request mechanism, used by mmc core, host driver and mmc requests
+ * supplier.
+ */
 void mmc_init_context_info(struct mmc_host *host)
 {
 	spin_lock_init(&host->context_info.lock);
diff --git a/drivers/mmc/core/debugfs.c b/drivers/mmc/core/debugfs.c
index ae8a619..931ddb0 100644
--- a/drivers/mmc/core/debugfs.c
+++ b/drivers/mmc/core/debugfs.c
@@ -484,6 +484,13 @@
 			pack_stats->pack_stop_reason[LARGE_SEC_ALIGN]);
 		strlcat(ubuf, temp_buf, cnt);
 	}
+	if (pack_stats->pack_stop_reason[RANDOM]) {
+		snprintf(temp_buf, TEMP_BUF_SIZE,
+			 "%s: %d times: random request\n",
+			mmc_hostname(card->host),
+			pack_stats->pack_stop_reason[RANDOM]);
+		strlcat(ubuf, temp_buf, cnt);
+	}
 
 	spin_unlock(&pack_stats->lock);
 
@@ -528,141 +535,6 @@
 	.write		= mmc_wr_pack_stats_write,
 };
 
-static int mmc_new_req_stats_open(struct inode *inode, struct file *filp)
-{
-	struct mmc_card *card = inode->i_private;
-
-	filp->private_data = card;
-	card->async_event_stats.print_in_read = 1;
-	return 0;
-}
-
-static ssize_t mmc_new_req_stats_read(struct file *filp, char __user *ubuf,
-				size_t cnt, loff_t *ppos)
-{
-	struct mmc_card *card = filp->private_data;
-	struct mmc_async_event_stats *s;
-	char *temp_buf;
-
-	if (!card)
-		return cnt;
-
-	s = &card->async_event_stats;
-
-	if (!card->async_event_stats.enabled) {
-		pr_info("%s: New Request statistics are disabled\n",
-			 mmc_hostname(card->host));
-		goto exit;
-	}
-
-	temp_buf = kmalloc(2 * TEMP_BUF_SIZE, GFP_KERNEL);
-	if (!temp_buf)
-		goto exit;
-
-	memset(ubuf, 0, cnt);
-	memset(temp_buf, 0, 2 * TEMP_BUF_SIZE);
-
-	snprintf(temp_buf, TEMP_BUF_SIZE,
-		 "%s: new notification & req statistics:\n",
-		mmc_hostname(card->host));
-	strlcat(ubuf, temp_buf, cnt);
-
-	snprintf(temp_buf, TEMP_BUF_SIZE,
-		 "%s: done_flag:%d\n", mmc_hostname(card->host), s->done_flag);
-	strlcat(ubuf, temp_buf, cnt);
-
-	snprintf(temp_buf, TEMP_BUF_SIZE,
-		 "%s: cmd_retry:%d\n", mmc_hostname(card->host), s->cmd_retry);
-	strlcat(ubuf, temp_buf, cnt);
-
-	snprintf(temp_buf, TEMP_BUF_SIZE,
-		 "%s: NULL fetched:%d\n", mmc_hostname(card->host),
-		 s->null_fetched);
-	strlcat(ubuf, temp_buf, cnt);
-
-	snprintf(temp_buf, TEMP_BUF_SIZE,
-		 "%s: wake up new:%d\n",
-			mmc_hostname(card->host), s->wakeup_new);
-	strlcat(ubuf, temp_buf, cnt);
-
-	snprintf(temp_buf, TEMP_BUF_SIZE,
-		 "%s: new_request_flag:%d\n", mmc_hostname(card->host),
-		 s->new_request_flag);
-	strlcat(ubuf, temp_buf, cnt);
-
-	snprintf(temp_buf, TEMP_BUF_SIZE,
-		 "%s: no waiting:%d\n", mmc_hostname(card->host),
-		 s->q_no_waiting);
-	strlcat(ubuf, temp_buf, cnt);
-
-	snprintf(temp_buf, TEMP_BUF_SIZE,
-		 "%s: no_mmc_request_action:%d\n", mmc_hostname(card->host),
-		 s->no_mmc_request_action);
-	strlcat(ubuf, temp_buf, cnt);
-
-	snprintf(temp_buf, TEMP_BUF_SIZE,
-		 "%s: wakeup_mq_thread:%d\n", mmc_hostname(card->host),
-		 s->wakeup_mq_thread);
-	strlcat(ubuf, temp_buf, cnt);
-
-	snprintf(temp_buf, TEMP_BUF_SIZE,
-		 "%s: fetch_due_to_new_req:%d\n", mmc_hostname(card->host),
-		 s->fetch_due_to_new_req);
-	strlcat(ubuf, temp_buf, cnt);
-
-	snprintf(temp_buf, TEMP_BUF_SIZE,
-		 "%s: returned_new_req:%d\n", mmc_hostname(card->host),
-		 s->returned_new_req);
-	strlcat(ubuf, temp_buf, cnt);
-
-	snprintf(temp_buf, TEMP_BUF_SIZE,
-		 "%s: done_when_new_req_event_on:%d\n",
-		 mmc_hostname(card->host), s->done_when_new_req_event_on);
-	strlcat(ubuf, temp_buf, cnt);
-
-	kfree(temp_buf);
-
-	pr_info("%s", ubuf);
-
-exit:
-	if (card->async_event_stats.print_in_read == 1) {
-		card->async_event_stats.print_in_read = 0;
-		return strnlen(ubuf, cnt);
-	}
-
-	return 0;
-}
-
-static ssize_t mmc_new_req_stats_write(struct file *filp,
-				       const char __user *ubuf, size_t cnt,
-				       loff_t *ppos)
-{
-	struct mmc_card *card = filp->private_data;
-	int value;
-
-	if (!card)
-		return cnt;
-
-	sscanf(ubuf, "%d", &value);
-	if (value) {
-		mmc_blk_init_async_event_statistics(card);
-		pr_info("%s: %s: New request statistics are enabled",
-			mmc_hostname(card->host), __func__);
-	} else {
-		card->async_event_stats.enabled = false;
-		pr_info("%s: %s: New request statistics are disabled",
-			mmc_hostname(card->host), __func__);
-	}
-
-	return cnt;
-}
-
-static const struct file_operations mmc_dbg_new_req_stats_fops = {
-	.open		= mmc_new_req_stats_open,
-	.read		= mmc_new_req_stats_read,
-	.write		= mmc_new_req_stats_write,
-};
-
 static int mmc_bkops_stats_open(struct inode *inode, struct file *filp)
 {
 	struct mmc_card *card = inode->i_private;
@@ -808,10 +680,6 @@
 					 &mmc_dbg_wr_pack_stats_fops))
 			goto err;
 
-	if (!debugfs_create_file("new_req_stats", S_IRUSR, root, card,
-				&mmc_dbg_new_req_stats_fops))
-		goto err;
-
 	if (mmc_card_mmc(card) && (card->ext_csd.rev >= 5) &&
 	    card->ext_csd.bkops_en)
 		if (!debugfs_create_file("bkops_stats", S_IRUSR, root, card,
diff --git a/drivers/mmc/core/host.c b/drivers/mmc/core/host.c
index 751ba75..0cfddc4 100644
--- a/drivers/mmc/core/host.c
+++ b/drivers/mmc/core/host.c
@@ -33,6 +33,7 @@
 static void mmc_host_classdev_release(struct device *dev)
 {
 	struct mmc_host *host = cls_dev_to_mmc_host(dev);
+	kfree(host->wlock_name);
 	kfree(host);
 }
 
@@ -337,8 +338,10 @@
 
 	spin_lock_init(&host->lock);
 	init_waitqueue_head(&host->wq);
+	host->wlock_name = kasprintf(GFP_KERNEL,
+			"%s_detect", mmc_hostname(host));
 	wake_lock_init(&host->detect_wake_lock, WAKE_LOCK_SUSPEND,
-		kasprintf(GFP_KERNEL, "%s_detect", mmc_hostname(host)));
+			host->wlock_name);
 	INIT_DELAYED_WORK(&host->detect, mmc_rescan);
 #ifdef CONFIG_PM
 	host->pm_notify.notifier_call = mmc_pm_notify;
diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c
index f3653b8..ec30cad 100644
--- a/drivers/mmc/core/mmc.c
+++ b/drivers/mmc/core/mmc.c
@@ -1402,17 +1402,16 @@
 
 			/*
 			 * Calculate the time to start the BKOPs checking.
-			 * The idle time of the host controller should be taken
-			 * into account in order to prevent a race condition
-			 * before starting BKOPs and going into suspend.
-			 * If the host controller didn't set its idle time,
+			 * The host controller can set this time in order to
+			 * prevent a race condition before starting BKOPs
+			 * and going into suspend.
+			 * If the host controller didn't set this time,
 			 * a default value is used.
 			 */
 			card->bkops_info.delay_ms = MMC_IDLE_BKOPS_TIME_MS;
-			if (card->bkops_info.host_suspend_tout_ms)
-				card->bkops_info.delay_ms = min(
-					card->bkops_info.delay_ms,
-				      card->bkops_info.host_suspend_tout_ms/2);
+			if (card->bkops_info.host_delay_ms)
+				card->bkops_info.delay_ms =
+					card->bkops_info.host_delay_ms;
 		}
 	}
 
@@ -1530,6 +1529,11 @@
 	mmc_disable_clk_scaling(host);
 
 	mmc_claim_host(host);
+
+	err = mmc_cache_ctrl(host, 0);
+	if (err)
+		goto out;
+
 	if (mmc_can_poweroff_notify(host->card))
 		err = mmc_poweroff_notify(host->card, EXT_CSD_POWER_OFF_SHORT);
 	else if (mmc_card_can_sleep(host))
@@ -1537,8 +1541,9 @@
 	else if (!mmc_host_is_spi(host))
 		mmc_deselect_cards(host);
 	host->card->state &= ~(MMC_STATE_HIGHSPEED | MMC_STATE_HIGHSPEED_200);
-	mmc_release_host(host);
 
+out:
+	mmc_release_host(host);
 	return err;
 }
 
diff --git a/drivers/mmc/core/mmc_ops.c b/drivers/mmc/core/mmc_ops.c
index f8c9720..8087ea6 100644
--- a/drivers/mmc/core/mmc_ops.c
+++ b/drivers/mmc/core/mmc_ops.c
@@ -21,6 +21,8 @@
 #include "core.h"
 #include "mmc_ops.h"
 
+#define MMC_OPS_TIMEOUT_MS	(10 * 60 * 1000) /* 10 minute timeout */
+
 static int _mmc_select_card(struct mmc_host *host, struct mmc_card *card)
 {
 	int err;
@@ -386,6 +388,7 @@
 {
 	int err;
 	struct mmc_command cmd = {0};
+	unsigned long timeout;
 	u32 status;
 
 	BUG_ON(!card);
@@ -415,6 +418,7 @@
 		return 0;
 
 	/* Must check status to be sure of no errors */
+	timeout = jiffies + msecs_to_jiffies(MMC_OPS_TIMEOUT_MS);
 	do {
 		err = mmc_send_status(card, &status);
 		if (err)
@@ -423,6 +427,13 @@
 			break;
 		if (mmc_host_is_spi(card->host))
 			break;
+
+		/* Timeout if the device never leaves the program state. */
+		if (time_after(jiffies, timeout)) {
+			pr_err("%s: Card stuck in programming state! %s\n",
+				mmc_hostname(card->host), __func__);
+			return -ETIMEDOUT;
+		}
 	} while (R1_CURRENT_STATE(status) == R1_STATE_PRG);
 
 	if (mmc_host_is_spi(card->host)) {
@@ -594,7 +605,6 @@
 
 	cmd.opcode = opcode;
 	cmd.arg = card->rca << 16 | 1;
-	cmd.cmd_timeout_ms = card->ext_csd.out_of_int_time;
 
 	err = mmc_wait_for_cmd(card->host, &cmd, 0);
 	if (err) {
diff --git a/drivers/mmc/host/msm_sdcc.c b/drivers/mmc/host/msm_sdcc.c
index f1ba8ad..fb6b656 100644
--- a/drivers/mmc/host/msm_sdcc.c
+++ b/drivers/mmc/host/msm_sdcc.c
@@ -236,14 +236,6 @@
 {
 	int rc;
 
-	/* Reset and init DML */
-	rc = msmsdcc_dml_init(host);
-	if (rc) {
-		pr_err("%s: msmsdcc_dml_init error=%d\n",
-				mmc_hostname(host->mmc), rc);
-		goto out;
-	}
-
 	/* Reset all SDCC BAM pipes */
 	rc = msmsdcc_sps_reset_ep(host, &host->sps.prod);
 	if (rc) {
@@ -276,13 +268,21 @@
 	}
 
 	rc = msmsdcc_sps_restore_ep(host, &host->sps.cons);
-	if (rc)
+	if (rc) {
 		pr_err("%s: msmsdcc_sps_restore_ep(cons) error=%d\n",
 				mmc_hostname(host->mmc), rc);
-	else
-		host->sps.reset_bam = false;
+		goto out;
+	}
+
+	/* Reset and init DML */
+	rc = msmsdcc_dml_init(host);
+	if (rc)
+		pr_err("%s: msmsdcc_dml_init error=%d\n",
+				mmc_hostname(host->mmc), rc);
 
 out:
+	if (!rc)
+		host->sps.reset_bam = false;
 	return rc;
 }
 
@@ -6764,9 +6764,21 @@
 		msmsdcc_disable_status_gpio(host);
 	}
 
-	if (!pm_runtime_suspended(dev))
+	/*
+	 * If system comes out of suspend, msmsdcc_pm_resume() sets the
+	 * host->pending_resume flag if the SDCC wasn't runtime suspended.
+	 * Now if the system again goes to suspend without any SDCC activity
+	 * then host->pending_resume flag will remain set which may cause
+	 * the SDCC resume to happen first and then suspend.
+	 * To avoid this unnecessary resume/suspend, make sure that
+	 * pending_resume flag is cleared before calling the
+	 * msmsdcc_runtime_suspend().
+	 */
+	if (!pm_runtime_suspended(dev) && !host->pending_resume)
 		rc = msmsdcc_runtime_suspend(dev);
  out:
+	/* This flag must not be set if system is entering into suspend */
+	host->pending_resume = false;
 	msmsdcc_print_pm_stats(host, start, __func__, rc);
 	return rc;
 }
diff --git a/drivers/platform/msm/sps/bam.c b/drivers/platform/msm/sps/bam.c
index bcb4cdb..2e858ec 100644
--- a/drivers/platform/msm/sps/bam.c
+++ b/drivers/platform/msm/sps/bam.c
@@ -644,7 +644,7 @@
 int bam_init(void *base, u32 ee,
 		u16 summing_threshold,
 		u32 irq_mask, u32 *version,
-		u32 *num_pipes, u32 p_rst)
+		u32 *num_pipes, u32 options)
 {
 	u32 cfg_bits;
 	u32 ver = 0;
@@ -667,7 +667,7 @@
 				"use default 4.\n", (u32) base);
 	}
 
-	if (p_rst)
+	if (options & SPS_BAM_NO_EXT_P_RST)
 		cfg_bits = 0xffffffff & ~(3 << 11);
 	else
 		cfg_bits = 0xffffffff & ~(1 << 11);
@@ -681,7 +681,10 @@
 #ifdef CONFIG_SPS_SUPPORT_NDP_BAM
 	bam_write_reg_field(base, CTRL, CACHE_MISS_ERR_RESP_EN, 0);
 
-	bam_write_reg_field(base, CTRL, LOCAL_CLK_GATING, 1);
+	if (options & SPS_BAM_NO_LOCAL_CLK_GATING)
+		bam_write_reg_field(base, CTRL, LOCAL_CLK_GATING, 0);
+	else
+		bam_write_reg_field(base, CTRL, LOCAL_CLK_GATING, 1);
 #endif
 
 	bam_write_reg(base, DESC_CNT_TRSHLD, summing_threshold);
@@ -842,21 +845,9 @@
 static void bam_output_register_content(void *base)
 {
 	u32 num_pipes;
-	u32 test_bus_selection[] = {0x1, 0x2, 0x3, 0x4, 0xD, 0x10,
-			0x41, 0x42, 0x43, 0x44, 0x45, 0x46};
 	u32 i;
-	u32 size = sizeof(test_bus_selection) / sizeof(u32);
 
-	for (i = 0; i < size; i++) {
-		bam_write_reg_field(base, TEST_BUS_SEL, BAM_TESTBUS_SEL,
-					test_bus_selection[i]);
-
-		SPS_INFO("sps:bam 0x%x(va);BAM_TEST_BUS_REG is"
-			"0x%x when BAM_TEST_BUS_SEL is 0x%x.",
-			(u32) base, bam_read_reg(base, TEST_BUS_REG),
-			bam_read_reg_field(base, TEST_BUS_SEL,
-					BAM_TESTBUS_SEL));
-	}
+	print_bam_test_bus_reg(base, 0);
 
 	print_bam_reg(base);
 
@@ -1359,7 +1350,7 @@
 }
 
 /* output descriptor FIFO of a pipe */
-void print_bam_pipe_desc_fifo(void *virt_addr, u32 pipe_index)
+void print_bam_pipe_desc_fifo(void *virt_addr, u32 pipe_index, u32 option)
 {
 	void *base = virt_addr;
 	u32 pipe = pipe_index;
@@ -1393,33 +1384,93 @@
 
 	desc_fifo = (u32 *) phys_to_virt(desc_fifo_addr);
 
-	SPS_INFO("-------------------- begin of FIFO --------------------\n");
+	if (option == 100) {
+		SPS_INFO("----- start of data blocks -----\n");
+		for (i = 0; i < desc_fifo_size; i += 8) {
+			u32 *data_block_vir;
+			u32 data_block_phy = desc_fifo[i / 4];
 
-	for (i = 0; i < desc_fifo_size; i += 0x10)
-		SPS_INFO("addr 0x%x: 0x%x, 0x%x, 0x%x, 0x%x.\n",
-			desc_fifo_addr + i,
-			desc_fifo[i / 4], desc_fifo[(i / 4) + 1],
-			desc_fifo[(i / 4) + 2], desc_fifo[(i / 4) + 3]);
+			if (data_block_phy) {
+				data_block_vir =
+					(u32 *) phys_to_virt(data_block_phy);
 
-	SPS_INFO("--------------------  end of FIFO  --------------------\n");
+				SPS_INFO("desc addr:0x%x; data addr:0x%x:\n",
+					desc_fifo_addr + i, data_block_phy);
+				SPS_INFO("0x%x, 0x%x, 0x%x, 0x%x\n",
+					data_block_vir[0], data_block_vir[1],
+					data_block_vir[2], data_block_vir[3]);
+				SPS_INFO("0x%x, 0x%x, 0x%x, 0x%x\n",
+					data_block_vir[4], data_block_vir[5],
+					data_block_vir[6], data_block_vir[7]);
+				SPS_INFO("0x%x, 0x%x, 0x%x, 0x%x\n",
+					data_block_vir[8], data_block_vir[9],
+					data_block_vir[10], data_block_vir[11]);
+				SPS_INFO("0x%x, 0x%x, 0x%x, 0x%x\n\n",
+					data_block_vir[12], data_block_vir[13],
+					data_block_vir[14], data_block_vir[15]);
+			}
+		}
+		SPS_INFO("----- end of data blocks -----\n");
+	} else if (option) {
+		u32 size = option * 128;
+		u32 current_desc = bam_pipe_get_desc_read_offset(base,
+								pipe_index);
+		u32 begin = 0;
+		u32 end = desc_fifo_size;
+
+		if (current_desc > size / 2)
+			begin = current_desc - size / 2;
+
+		if (desc_fifo_size > current_desc + size / 2)
+			end = current_desc + size / 2;
+
+		SPS_INFO("------------- begin of partial FIFO -------------\n");
+
+		for (i = begin; i < end; i += 0x10)
+			SPS_INFO("addr 0x%x: 0x%x, 0x%x, 0x%x, 0x%x.\n",
+				desc_fifo_addr + i,
+				desc_fifo[i / 4], desc_fifo[(i / 4) + 1],
+				desc_fifo[(i / 4) + 2], desc_fifo[(i / 4) + 3]);
+
+		SPS_INFO("-------------  end of partial FIFO  -------------\n");
+	} else {
+		SPS_INFO("----------------- begin of FIFO -----------------\n");
+
+		for (i = 0; i < desc_fifo_size; i += 0x10)
+			SPS_INFO("addr 0x%x: 0x%x, 0x%x, 0x%x, 0x%x.\n",
+				desc_fifo_addr + i,
+				desc_fifo[i / 4], desc_fifo[(i / 4) + 1],
+				desc_fifo[(i / 4) + 2], desc_fifo[(i / 4) + 3]);
+
+		SPS_INFO("-----------------  end of FIFO  -----------------\n");
+	}
 }
 
 /* output BAM_TEST_BUS_REG with specified TEST_BUS_SEL */
 void print_bam_test_bus_reg(void *base, u32 tb_sel)
 {
 	u32 i;
-	u32 test_bus_selection[] = {0x1, 0x2, 0x3, 0x4, 0xD, 0x10,
+	u32 test_bus_selection[] = {0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7,
+			0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf,
+			0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+			0x20, 0x21, 0x22, 0x23,
 			0x41, 0x42, 0x43, 0x44, 0x45, 0x46};
 	u32 size = sizeof(test_bus_selection) / sizeof(u32);
 
-	if ((base == NULL) || (tb_sel == 0))
+	if (base == NULL) {
+		SPS_ERR("sps:%s:BAM is NULL.\n", __func__);
 		return;
+	}
 
-	SPS_INFO("\nsps:Specified TEST_BUS_SEL value: 0x%x\n", tb_sel);
-	bam_write_reg_field(base, TEST_BUS_SEL, BAM_TESTBUS_SEL, tb_sel);
-	SPS_INFO("sps:BAM_TEST_BUS_REG: 0x%x when TEST_BUS_SEL: 0x%x\n\n",
-		bam_read_reg(base, TEST_BUS_REG),
-		bam_read_reg_field(base, TEST_BUS_SEL, BAM_TESTBUS_SEL));
+	if (tb_sel) {
+		SPS_INFO("\nsps:Specified TEST_BUS_SEL value: 0x%x\n", tb_sel);
+		bam_write_reg_field(base, TEST_BUS_SEL, BAM_TESTBUS_SEL,
+					tb_sel);
+		SPS_INFO("sps:BAM_TEST_BUS_REG:0x%x for TEST_BUS_SEL:0x%x\n\n",
+			bam_read_reg(base, TEST_BUS_REG),
+			bam_read_reg_field(base, TEST_BUS_SEL,
+						BAM_TESTBUS_SEL));
+	}
 
 	/* output other selections */
 	for (i = 0; i < size; i++) {
diff --git a/drivers/platform/msm/sps/bam.h b/drivers/platform/msm/sps/bam.h
index c183fcd..86808d9 100644
--- a/drivers/platform/msm/sps/bam.h
+++ b/drivers/platform/msm/sps/bam.h
@@ -102,7 +102,7 @@
  *
  * @num_pipes - return number of pipes
  *
- * @p_rst - ignore external block pipe reset
+ * @options - BAM configuration options
  *
  * @return 0 on success, negative value on error
  *
@@ -111,7 +111,7 @@
 		u32 ee,
 		u16 summing_threshold,
 		u32 irq_mask, u32 *version,
-		u32 *num_pipes, u32 p_rst);
+		u32 *num_pipes, u32 options);
 
 /**
  * Initialize BAM device security execution environment
diff --git a/drivers/platform/msm/sps/sps.c b/drivers/platform/msm/sps/sps.c
index e9c3371..ae61f1b 100644
--- a/drivers/platform/msm/sps/sps.c
+++ b/drivers/platform/msm/sps/sps.c
@@ -91,7 +91,7 @@
 u8 reg_dump_option;
 u32 testbus_sel;
 u32 bam_pipe_sel;
-
+u32 desc_option;
 
 static char *debugfs_buf;
 static u32 debugfs_buf_size;
@@ -106,6 +106,7 @@
 struct dentry *dfile_reg_dump_option;
 struct dentry *dfile_testbus_sel;
 struct dentry *dfile_bam_pipe_sel;
+struct dentry *dfile_desc_option;
 struct dentry *dfile_bam_addr;
 
 static struct sps_bam *phy2bam(u32 phys_addr);
@@ -341,41 +342,187 @@
 		break;
 	case 7: /* output desc FIFO of all pipes */
 		for (i = 0; i < num_pipes; i++)
-			print_bam_pipe_desc_fifo(vir_addr, i);
+			print_bam_pipe_desc_fifo(vir_addr, i, 0);
 		break;
 	case 8: /* output desc FIFO of selected pipes */
 		for (i = 0; i < num_pipes; i++)
 			if (bam_pipe_sel & (1UL << i))
-				print_bam_pipe_desc_fifo(vir_addr, i);
+				print_bam_pipe_desc_fifo(vir_addr, i, 0);
 		break;
 	case 9: /* output desc FIFO of typical pipes */
-		print_bam_pipe_desc_fifo(vir_addr, 4);
-		print_bam_pipe_desc_fifo(vir_addr, 5);
+		print_bam_pipe_desc_fifo(vir_addr, 4, 0);
+		print_bam_pipe_desc_fifo(vir_addr, 5, 0);
 		break;
 	case 10: /* output selected registers and desc FIFO of all pipes */
 		for (i = 0; i < num_pipes; i++) {
 			print_bam_pipe_selected_reg(vir_addr, i);
-			print_bam_pipe_desc_fifo(vir_addr, i);
+			print_bam_pipe_desc_fifo(vir_addr, i, 0);
 		}
 		break;
 	case 11: /* output selected registers and desc FIFO of selected pipes */
 		for (i = 0; i < num_pipes; i++)
 			if (bam_pipe_sel & (1UL << i)) {
 				print_bam_pipe_selected_reg(vir_addr, i);
-				print_bam_pipe_desc_fifo(vir_addr, i);
+				print_bam_pipe_desc_fifo(vir_addr, i, 0);
 			}
 		break;
 	case 12: /* output selected registers and desc FIFO of typical pipes */
 		print_bam_pipe_selected_reg(vir_addr, 4);
-		print_bam_pipe_desc_fifo(vir_addr, 4);
+		print_bam_pipe_desc_fifo(vir_addr, 4, 0);
 		print_bam_pipe_selected_reg(vir_addr, 5);
-		print_bam_pipe_desc_fifo(vir_addr, 5);
+		print_bam_pipe_desc_fifo(vir_addr, 5, 0);
 		break;
 	case 13: /* output BAM_TEST_BUS_REG */
 		if (testbus_sel)
 			print_bam_test_bus_reg(vir_addr, testbus_sel);
-		else
-			pr_info("sps:TEST_BUS_SEL should NOT be zero.");
+		else {
+			pr_info("sps:output TEST_BUS_REG for all TEST_BUS_SEL");
+			print_bam_test_bus_reg(vir_addr, testbus_sel);
+		}
+		break;
+	case 14: /* output partial desc FIFO of selected pipes */
+		if (desc_option == 0)
+			desc_option = 1;
+		for (i = 0; i < num_pipes; i++)
+			if (bam_pipe_sel & (1UL << i))
+				print_bam_pipe_desc_fifo(vir_addr, i,
+							desc_option);
+		break;
+	case 15: /* output partial data blocks of descriptors */
+		for (i = 0; i < num_pipes; i++)
+			if (bam_pipe_sel & (1UL << i))
+				print_bam_pipe_desc_fifo(vir_addr, i, 100);
+		break;
+	case 16: /* output all registers of selected pipes */
+		for (i = 0; i < num_pipes; i++)
+			if (bam_pipe_sel & (1UL << i))
+				print_bam_pipe_reg(vir_addr, i);
+		break;
+	case 91: /* output testbus register, BAM global regisers
+			and registers of all pipes */
+		print_bam_test_bus_reg(vir_addr, testbus_sel);
+		print_bam_reg(vir_addr);
+		for (i = 0; i < num_pipes; i++)
+			print_bam_pipe_reg(vir_addr, i);
+		print_bam_selected_reg(vir_addr);
+		for (i = 0; i < num_pipes; i++)
+			print_bam_pipe_selected_reg(vir_addr, i);
+		break;
+	case 92: /* output testbus register, BAM global regisers
+			and registers of selected pipes */
+		print_bam_test_bus_reg(vir_addr, testbus_sel);
+		print_bam_reg(vir_addr);
+		for (i = 0; i < num_pipes; i++)
+			if (bam_pipe_sel & (1UL << i))
+				print_bam_pipe_reg(vir_addr, i);
+		print_bam_selected_reg(vir_addr);
+		for (i = 0; i < num_pipes; i++)
+			if (bam_pipe_sel & (1UL << i))
+				print_bam_pipe_selected_reg(vir_addr, i);
+		break;
+	case 93: /* output registers and partial desc FIFOs
+			of selected pipes: format 1 */
+		if (desc_option == 0)
+			desc_option = 1;
+		print_bam_test_bus_reg(vir_addr, testbus_sel);
+		print_bam_reg(vir_addr);
+		for (i = 0; i < num_pipes; i++)
+			if (bam_pipe_sel & (1UL << i))
+				print_bam_pipe_reg(vir_addr, i);
+		print_bam_selected_reg(vir_addr);
+		for (i = 0; i < num_pipes; i++)
+			if (bam_pipe_sel & (1UL << i))
+				print_bam_pipe_selected_reg(vir_addr, i);
+		for (i = 0; i < num_pipes; i++)
+			if (bam_pipe_sel & (1UL << i))
+				print_bam_pipe_desc_fifo(vir_addr, i,
+							desc_option);
+		break;
+	case 94: /* output registers and partial desc FIFOs
+			of selected pipes: format 2 */
+		if (desc_option == 0)
+			desc_option = 1;
+		print_bam_test_bus_reg(vir_addr, testbus_sel);
+		print_bam_reg(vir_addr);
+		print_bam_selected_reg(vir_addr);
+		for (i = 0; i < num_pipes; i++)
+			if (bam_pipe_sel & (1UL << i)) {
+				print_bam_pipe_reg(vir_addr, i);
+				print_bam_pipe_selected_reg(vir_addr, i);
+				print_bam_pipe_desc_fifo(vir_addr, i,
+							desc_option);
+			}
+		break;
+	case 95: /* output registers and desc FIFOs
+			of selected pipes: format 1 */
+		print_bam_test_bus_reg(vir_addr, testbus_sel);
+		print_bam_reg(vir_addr);
+		for (i = 0; i < num_pipes; i++)
+			if (bam_pipe_sel & (1UL << i))
+				print_bam_pipe_reg(vir_addr, i);
+		print_bam_selected_reg(vir_addr);
+		for (i = 0; i < num_pipes; i++)
+			if (bam_pipe_sel & (1UL << i))
+				print_bam_pipe_selected_reg(vir_addr, i);
+		for (i = 0; i < num_pipes; i++)
+			if (bam_pipe_sel & (1UL << i))
+				print_bam_pipe_desc_fifo(vir_addr, i, 0);
+		break;
+	case 96: /* output registers and desc FIFOs
+			of selected pipes: format 2 */
+		print_bam_test_bus_reg(vir_addr, testbus_sel);
+		print_bam_reg(vir_addr);
+		print_bam_selected_reg(vir_addr);
+		for (i = 0; i < num_pipes; i++)
+			if (bam_pipe_sel & (1UL << i)) {
+				print_bam_pipe_reg(vir_addr, i);
+				print_bam_pipe_selected_reg(vir_addr, i);
+				print_bam_pipe_desc_fifo(vir_addr, i, 0);
+			}
+		break;
+	case 97: /* output registers, desc FIFOs and partial data blocks
+			of selected pipes: format 1 */
+		print_bam_test_bus_reg(vir_addr, testbus_sel);
+		print_bam_reg(vir_addr);
+		for (i = 0; i < num_pipes; i++)
+			if (bam_pipe_sel & (1UL << i))
+				print_bam_pipe_reg(vir_addr, i);
+		print_bam_selected_reg(vir_addr);
+		for (i = 0; i < num_pipes; i++)
+			if (bam_pipe_sel & (1UL << i))
+				print_bam_pipe_selected_reg(vir_addr, i);
+		for (i = 0; i < num_pipes; i++)
+			if (bam_pipe_sel & (1UL << i))
+				print_bam_pipe_desc_fifo(vir_addr, i, 0);
+		for (i = 0; i < num_pipes; i++)
+			if (bam_pipe_sel & (1UL << i))
+				print_bam_pipe_desc_fifo(vir_addr, i, 100);
+		break;
+	case 98: /* output registers, desc FIFOs and partial data blocks
+			of selected pipes: format 2 */
+		print_bam_test_bus_reg(vir_addr, testbus_sel);
+		print_bam_reg(vir_addr);
+		print_bam_selected_reg(vir_addr);
+		for (i = 0; i < num_pipes; i++)
+			if (bam_pipe_sel & (1UL << i)) {
+				print_bam_pipe_reg(vir_addr, i);
+				print_bam_pipe_selected_reg(vir_addr, i);
+				print_bam_pipe_desc_fifo(vir_addr, i, 0);
+				print_bam_pipe_desc_fifo(vir_addr, i, 100);
+			}
+		break;
+	case 99: /* output all registers, desc FIFOs and partial data blocks */
+		print_bam_test_bus_reg(vir_addr, testbus_sel);
+		print_bam_reg(vir_addr);
+		for (i = 0; i < num_pipes; i++)
+			print_bam_pipe_reg(vir_addr, i);
+		print_bam_selected_reg(vir_addr);
+		for (i = 0; i < num_pipes; i++)
+			print_bam_pipe_selected_reg(vir_addr, i);
+		for (i = 0; i < num_pipes; i++)
+			print_bam_pipe_desc_fifo(vir_addr, i, 0);
+		for (i = 0; i < num_pipes; i++)
+			print_bam_pipe_desc_fifo(vir_addr, i, 100);
 		break;
 	default:
 		pr_info("sps:no dump option is chosen yet.");
@@ -397,6 +544,7 @@
 	reg_dump_option = 0;
 	testbus_sel = 0;
 	bam_pipe_sel = 0;
+	desc_option = 0;
 	debugfs_buf_size = 0;
 	debugfs_buf_used = 0;
 	wraparound = false;
@@ -460,6 +608,13 @@
 		goto bam_pipe_sel_err;
 	}
 
+	dfile_desc_option = debugfs_create_u32("desc_option", 0666,
+						dent, &desc_option);
+	if (!dfile_desc_option || IS_ERR(dfile_desc_option)) {
+		pr_err("sps:fail to create debug_fs file for desc_option.\n");
+		goto desc_option_err;
+	}
+
 	dfile_bam_addr = debugfs_create_file("bam_addr", 0666,
 			dent, 0, &sps_bam_addr_ops);
 	if (!dfile_bam_addr || IS_ERR(dfile_bam_addr)) {
@@ -471,6 +626,8 @@
 	return;
 
 bam_addr_err:
+	debugfs_remove(dfile_desc_option);
+desc_option_err:
 	debugfs_remove(dfile_bam_pipe_sel);
 bam_pipe_sel_err:
 	debugfs_remove(dfile_testbus_sel);
@@ -504,6 +661,8 @@
 		debugfs_remove(dfile_testbus_sel);
 	if (dfile_bam_pipe_sel)
 		debugfs_remove(dfile_bam_pipe_sel);
+	if (dfile_desc_option)
+		debugfs_remove(dfile_desc_option);
 	if (dfile_bam_addr)
 		debugfs_remove(dfile_bam_addr);
 	if (dent)
@@ -515,7 +674,7 @@
 
 /* Get the debug info of BAM registers and descriptor FIFOs */
 int sps_get_bam_debug_info(u32 dev, u32 option, u32 para,
-		u32 tb_sel, u8 pre_level)
+		u32 tb_sel, u8 desc_sel)
 {
 	int res = 0;
 	struct sps_bam *bam;
@@ -568,35 +727,35 @@
 		break;
 	case 7: /* output desc FIFO of all pipes */
 		for (i = 0; i < num_pipes; i++)
-			print_bam_pipe_desc_fifo(vir_addr, i);
+			print_bam_pipe_desc_fifo(vir_addr, i, 0);
 		break;
 	case 8: /* output desc FIFO of selected pipes */
 		for (i = 0; i < num_pipes; i++)
 			if (para & (1UL << i))
-				print_bam_pipe_desc_fifo(vir_addr, i);
+				print_bam_pipe_desc_fifo(vir_addr, i, 0);
 		break;
 	case 9: /* output desc FIFO of typical pipes */
-		print_bam_pipe_desc_fifo(vir_addr, 4);
-		print_bam_pipe_desc_fifo(vir_addr, 5);
+		print_bam_pipe_desc_fifo(vir_addr, 4, 0);
+		print_bam_pipe_desc_fifo(vir_addr, 5, 0);
 		break;
 	case 10: /* output selected registers and desc FIFO of all pipes */
 		for (i = 0; i < num_pipes; i++) {
 			print_bam_pipe_selected_reg(vir_addr, i);
-			print_bam_pipe_desc_fifo(vir_addr, i);
+			print_bam_pipe_desc_fifo(vir_addr, i, 0);
 		}
 		break;
 	case 11: /* output selected registers and desc FIFO of selected pipes */
 		for (i = 0; i < num_pipes; i++)
 			if (para & (1UL << i)) {
 				print_bam_pipe_selected_reg(vir_addr, i);
-				print_bam_pipe_desc_fifo(vir_addr, i);
+				print_bam_pipe_desc_fifo(vir_addr, i, 0);
 			}
 		break;
 	case 12: /* output selected registers and desc FIFO of typical pipes */
 		print_bam_pipe_selected_reg(vir_addr, 4);
-		print_bam_pipe_desc_fifo(vir_addr, 4);
+		print_bam_pipe_desc_fifo(vir_addr, 4, 0);
 		print_bam_pipe_selected_reg(vir_addr, 5);
-		print_bam_pipe_desc_fifo(vir_addr, 5);
+		print_bam_pipe_desc_fifo(vir_addr, 5, 0);
 		break;
 	case 13: /* output BAM_TEST_BUS_REG */
 		if (tb_sel)
@@ -604,6 +763,150 @@
 		else
 			pr_info("sps:TEST_BUS_SEL should NOT be zero.");
 		break;
+	case 14: /* output partial desc FIFO of selected pipes */
+		if (desc_sel == 0)
+			desc_sel = 1;
+		for (i = 0; i < num_pipes; i++)
+			if (para & (1UL << i))
+				print_bam_pipe_desc_fifo(vir_addr, i,
+							desc_sel);
+		break;
+	case 15: /* output partial data blocks of descriptors */
+		for (i = 0; i < num_pipes; i++)
+			if (para & (1UL << i))
+				print_bam_pipe_desc_fifo(vir_addr, i, 100);
+		break;
+	case 16: /* output all registers of selected pipes */
+		for (i = 0; i < num_pipes; i++)
+			if (para & (1UL << i))
+				print_bam_pipe_reg(vir_addr, i);
+		break;
+	case 91: /* output testbus register, BAM global regisers
+			and registers of all pipes */
+		print_bam_test_bus_reg(vir_addr, tb_sel);
+		print_bam_reg(vir_addr);
+		for (i = 0; i < num_pipes; i++)
+			print_bam_pipe_reg(vir_addr, i);
+		print_bam_selected_reg(vir_addr);
+		for (i = 0; i < num_pipes; i++)
+			print_bam_pipe_selected_reg(vir_addr, i);
+		break;
+	case 92: /* output testbus register, BAM global regisers
+			and registers of selected pipes */
+		print_bam_test_bus_reg(vir_addr, tb_sel);
+		print_bam_reg(vir_addr);
+		for (i = 0; i < num_pipes; i++)
+			if (para & (1UL << i))
+				print_bam_pipe_reg(vir_addr, i);
+		print_bam_selected_reg(vir_addr);
+		for (i = 0; i < num_pipes; i++)
+			if (para & (1UL << i))
+				print_bam_pipe_selected_reg(vir_addr, i);
+		break;
+	case 93: /* output registers and partial desc FIFOs
+			of selected pipes: format 1 */
+		if (desc_sel == 0)
+			desc_sel = 1;
+		print_bam_test_bus_reg(vir_addr, tb_sel);
+		print_bam_reg(vir_addr);
+		for (i = 0; i < num_pipes; i++)
+			if (para & (1UL << i))
+				print_bam_pipe_reg(vir_addr, i);
+		print_bam_selected_reg(vir_addr);
+		for (i = 0; i < num_pipes; i++)
+			if (para & (1UL << i))
+				print_bam_pipe_selected_reg(vir_addr, i);
+		for (i = 0; i < num_pipes; i++)
+			if (para & (1UL << i))
+				print_bam_pipe_desc_fifo(vir_addr, i,
+							desc_sel);
+		break;
+	case 94: /* output registers and partial desc FIFOs
+			of selected pipes: format 2 */
+		if (desc_sel == 0)
+			desc_sel = 1;
+		print_bam_test_bus_reg(vir_addr, tb_sel);
+		print_bam_reg(vir_addr);
+		print_bam_selected_reg(vir_addr);
+		for (i = 0; i < num_pipes; i++)
+			if (para & (1UL << i)) {
+				print_bam_pipe_reg(vir_addr, i);
+				print_bam_pipe_selected_reg(vir_addr, i);
+				print_bam_pipe_desc_fifo(vir_addr, i,
+							desc_sel);
+			}
+		break;
+	case 95: /* output registers and desc FIFOs
+			of selected pipes: format 1 */
+		print_bam_test_bus_reg(vir_addr, tb_sel);
+		print_bam_reg(vir_addr);
+		for (i = 0; i < num_pipes; i++)
+			if (para & (1UL << i))
+				print_bam_pipe_reg(vir_addr, i);
+		print_bam_selected_reg(vir_addr);
+		for (i = 0; i < num_pipes; i++)
+			if (para & (1UL << i))
+				print_bam_pipe_selected_reg(vir_addr, i);
+		for (i = 0; i < num_pipes; i++)
+			if (para & (1UL << i))
+				print_bam_pipe_desc_fifo(vir_addr, i, 0);
+		break;
+	case 96: /* output registers and desc FIFOs
+			of selected pipes: format 2 */
+		print_bam_test_bus_reg(vir_addr, tb_sel);
+		print_bam_reg(vir_addr);
+		print_bam_selected_reg(vir_addr);
+		for (i = 0; i < num_pipes; i++)
+			if (para & (1UL << i)) {
+				print_bam_pipe_reg(vir_addr, i);
+				print_bam_pipe_selected_reg(vir_addr, i);
+				print_bam_pipe_desc_fifo(vir_addr, i, 0);
+			}
+		break;
+	case 97: /* output registers, desc FIFOs and partial data blocks
+			of selected pipes: format 1 */
+		print_bam_test_bus_reg(vir_addr, tb_sel);
+		print_bam_reg(vir_addr);
+		for (i = 0; i < num_pipes; i++)
+			if (para & (1UL << i))
+				print_bam_pipe_reg(vir_addr, i);
+		print_bam_selected_reg(vir_addr);
+		for (i = 0; i < num_pipes; i++)
+			if (para & (1UL << i))
+				print_bam_pipe_selected_reg(vir_addr, i);
+		for (i = 0; i < num_pipes; i++)
+			if (para & (1UL << i))
+				print_bam_pipe_desc_fifo(vir_addr, i, 0);
+		for (i = 0; i < num_pipes; i++)
+			if (para & (1UL << i))
+				print_bam_pipe_desc_fifo(vir_addr, i, 100);
+		break;
+	case 98: /* output registers, desc FIFOs and partial data blocks
+			of selected pipes: format 2 */
+		print_bam_test_bus_reg(vir_addr, tb_sel);
+		print_bam_reg(vir_addr);
+		print_bam_selected_reg(vir_addr);
+		for (i = 0; i < num_pipes; i++)
+			if (para & (1UL << i)) {
+				print_bam_pipe_reg(vir_addr, i);
+				print_bam_pipe_selected_reg(vir_addr, i);
+				print_bam_pipe_desc_fifo(vir_addr, i, 0);
+				print_bam_pipe_desc_fifo(vir_addr, i, 100);
+			}
+		break;
+	case 99: /* output all registers, desc FIFOs and partial data blocks */
+		print_bam_test_bus_reg(vir_addr, tb_sel);
+		print_bam_reg(vir_addr);
+		for (i = 0; i < num_pipes; i++)
+			print_bam_pipe_reg(vir_addr, i);
+		print_bam_selected_reg(vir_addr);
+		for (i = 0; i < num_pipes; i++)
+			print_bam_pipe_selected_reg(vir_addr, i);
+		for (i = 0; i < num_pipes; i++)
+			print_bam_pipe_desc_fifo(vir_addr, i, 0);
+		for (i = 0; i < num_pipes; i++)
+			print_bam_pipe_desc_fifo(vir_addr, i, 100);
+		break;
 	default:
 		pr_info("sps:no option is chosen yet.");
 	}
diff --git a/drivers/platform/msm/sps/sps_bam.c b/drivers/platform/msm/sps/sps_bam.c
index af421ac..a1ff7cb 100644
--- a/drivers/platform/msm/sps/sps_bam.c
+++ b/drivers/platform/msm/sps/sps_bam.c
@@ -255,7 +255,7 @@
 				  (u16) dev->props.summing_threshold,
 				  irq_mask,
 				  &dev->version, &num_pipes,
-				  dev->props.options & SPS_BAM_NO_EXT_P_RST);
+				  dev->props.options);
 	else
 		/* No, so just verify that it is enabled */
 		rc = bam_check(dev->base, &dev->version, &num_pipes);
diff --git a/drivers/platform/msm/sps/spsi.h b/drivers/platform/msm/sps/spsi.h
index 8a5deff..eba9b7d 100644
--- a/drivers/platform/msm/sps/spsi.h
+++ b/drivers/platform/msm/sps/spsi.h
@@ -198,7 +198,7 @@
 void print_bam_pipe_selected_reg(void *, u32);
 
 /* output descriptor FIFO of a pipe */
-void print_bam_pipe_desc_fifo(void *, u32);
+void print_bam_pipe_desc_fifo(void *, u32, u32);
 
 /* output BAM_TEST_BUS_REG */
 void print_bam_test_bus_reg(void *, u32);
diff --git a/drivers/platform/msm/usb_bam.c b/drivers/platform/msm/usb_bam.c
index 52bdae1..a808e0b 100644
--- a/drivers/platform/msm/usb_bam.c
+++ b/drivers/platform/msm/usb_bam.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2011-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -387,6 +387,9 @@
 int usb_bam_connect(u8 idx, u32 *src_pipe_idx, u32 *dst_pipe_idx)
 {
 	struct usb_bam_connect_info *connection = &usb_bam_connections[idx];
+	struct msm_usb_bam_platform_data *pdata =
+				usb_bam_pdev->dev.platform_data;
+	int usb_active_bam = pdata->usb_active_bam;
 	int ret;
 
 	if (!usb_bam_pdev) {
@@ -409,6 +412,10 @@
 	connection->dst_pipe = dst_pipe_idx;
 	connection->idx = idx;
 
+	/* Check if BAM requires RESET before connect */
+	if (pdata->reset_on_connect[usb_active_bam] == true)
+		sps_device_reset(h_bam);
+
 	if (src_pipe_idx) {
 		/* open USB -> Peripheral pipe */
 		ret = connect_pipe(connection->idx, USB_TO_PEER_PERIPHERAL,
@@ -899,6 +906,7 @@
 	u32 pipe_entry = 0;
 	char *key = NULL;
 	enum usb_pipe_mem_type mem_type;
+	bool reset_bam;
 
 	pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
 	if (!pdata) {
@@ -985,6 +993,10 @@
 			pr_err("Cannot read string\n");
 			goto err;
 		}
+		reset_bam = of_property_read_bool(node,
+					"qcom,reset-bam-on-connect");
+		if (reset_bam)
+			pdata->reset_on_connect[bam] = true;
 
 		if (strnstr(str, "usb-to", 30))
 			dir = USB_TO_PEER_PERIPHERAL;
diff --git a/drivers/power/pm8921-bms.c b/drivers/power/pm8921-bms.c
index f6591c3d..ed57f2c 100644
--- a/drivers/power/pm8921-bms.c
+++ b/drivers/power/pm8921-bms.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011-2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2011-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -160,6 +160,8 @@
 	int			soc_calc_period;
 	int			normal_voltage_calc_ms;
 	int			low_voltage_calc_ms;
+	int			imax_ua;
+	struct wake_lock	soc_wake_lock;
 };
 
 /*
@@ -728,8 +730,9 @@
  * CC_RESOLUTION_N, CC_RESOLUTION_D, CC_READING_TICKS
  * and rsense
  */
-#define CC_RAW_5MAH	0x00110000
-#define MIN_OCV_UV	2000000
+#define CC_RAW_5MAH		0x00110000
+#define MIN_OCV_UV		2000000
+#define OCV_RAW_UNINITIALIZED	0xFFFF
 static int read_soc_params_raw(struct pm8921_bms_chip *chip,
 				struct pm8921_soc_params *raw,
 				int batt_temp_decidegc)
@@ -749,7 +752,7 @@
 
 	usb_chg =  usb_chg_plugged_in(chip);
 
-	if (chip->prev_last_good_ocv_raw == 0) {
+	if (chip->prev_last_good_ocv_raw == OCV_RAW_UNINITIALIZED) {
 		chip->prev_last_good_ocv_raw = raw->last_good_ocv_raw;
 
 		convert_vbatt_raw_to_uv(chip, usb_chg,
@@ -801,7 +804,7 @@
 
 	/* fake a high OCV if we are just done charging */
 	if (chip->ocv_reading_at_100 != raw->last_good_ocv_raw) {
-		chip->ocv_reading_at_100 = 0;
+		chip->ocv_reading_at_100 = OCV_RAW_UNINITIALIZED;
 		chip->cc_reading_at_100 = 0;
 	} else {
 		/*
@@ -1025,28 +1028,34 @@
 	return uuc;
 }
 
+#define TIME_PER_PERCENT_UUC			60
 static int adjust_uuc(struct pm8921_bms_chip *chip, int fcc_uah,
 			int new_pc_unusable,
 			int new_uuc,
 			int batt_temp,
 			int rbatt,
-			int *iavg_ma)
+			int *iavg_ma,
+			int delta_time_s)
 {
 	int new_unusable_mv;
 	int batt_temp_degc = batt_temp / 10;
+	int max_percent_change;
+
+	max_percent_change = max(delta_time_s / TIME_PER_PERCENT_UUC, 1);
 
 	if (chip->prev_pc_unusable == -EINVAL
-		|| abs(chip->prev_pc_unusable - new_pc_unusable) <= 1) {
+		|| abs(chip->prev_pc_unusable - new_pc_unusable)
+			<= max_percent_change) {
 		chip->prev_pc_unusable = new_pc_unusable;
 		return new_uuc;
 	}
 
 	/* the uuc is trying to change more than 1% restrict it */
 	if (new_pc_unusable > chip->prev_pc_unusable)
-		chip->prev_pc_unusable++;
+		chip->prev_pc_unusable += max_percent_change;
 	else
-		chip->prev_pc_unusable--;
-
+		chip->prev_pc_unusable -= max_percent_change;
+	chip->prev_pc_unusable = clamp(chip->prev_pc_unusable, 0, 100);
 	new_uuc = (fcc_uah * chip->prev_pc_unusable) / 100;
 
 	/* also find update the iavg_ma accordingly */
@@ -1096,57 +1105,58 @@
 	return 0;
 }
 
-static void calculate_iavg_ua(struct pm8921_bms_chip *chip, int cc_uah,
-				int *iavg_ua, int *delta_time_s)
+static int calculate_delta_time(struct pm8921_bms_chip *chip, int *delta_time_s)
 {
-	int delta_cc_uah;
 	unsigned long now_tm_sec = 0;
-	int rc = 0;
+
+	/* default to delta time = 0 if anything fails */
+	*delta_time_s = 0;
+
+	get_current_time(&now_tm_sec);
+
+	*delta_time_s = (now_tm_sec - chip->tm_sec);
+	pr_debug("tm_sec = %ld, now_tm_sec = %ld delta_s = %d\n",
+		chip->tm_sec, now_tm_sec, *delta_time_s);
+
+	/* remember this time */
+	chip->tm_sec = now_tm_sec;
+	return 0;
+}
+
+static void calculate_iavg_ua(struct pm8921_bms_chip *chip, int cc_uah,
+				int *iavg_ua, int delta_time_s)
+{
+	int delta_cc_uah = 0;
 
 	/* if anything fails report the previous iavg_ua */
 	*iavg_ua = chip->prev_iavg_ua;
 
-	rc = get_current_time(&now_tm_sec);
-	if (rc) {
-		pr_err("Could not get current time: %d\n", rc);
-		goto out;
-	}
-
-	if (chip->tm_sec == 0) {
-		*delta_time_s = 0;
+	if (chip->last_cc_uah == INT_MIN) {
 		pm8921_bms_get_battery_current(iavg_ua);
 		goto out;
 	}
 
-	*delta_time_s = (now_tm_sec - chip->tm_sec);
-
 	/* use the previous iavg if called within 15 seconds */
-	if (*delta_time_s < 15) {
+	if (delta_time_s < 15) {
 		*iavg_ua = chip->prev_iavg_ua;
 		goto out;
 	}
 
 	delta_cc_uah = cc_uah - chip->last_cc_uah;
 
-	*iavg_ua = div_s64((s64)delta_cc_uah * 3600, *delta_time_s);
-
-	pr_debug("tm_sec = %ld, now_tm_sec = %ld delta_s = %d delta_cc = %d iavg_ua = %d\n",
-				chip->tm_sec, now_tm_sec,
-				*delta_time_s, delta_cc_uah, (int)*iavg_ua);
+	*iavg_ua = div_s64((s64)delta_cc_uah * 3600, delta_time_s);
 
 out:
+	pr_debug("delta_cc = %d iavg_ua = %d\n", delta_cc_uah, (int)*iavg_ua);
 	/* remember the iavg */
 	chip->prev_iavg_ua = *iavg_ua;
 
 	/* remember cc_uah */
 	chip->last_cc_uah = cc_uah;
-
-	/* remember this time */
-	chip->tm_sec = now_tm_sec;
 }
 
 #define IAVG_SAMPLES 16
-#define CHARGING_IAVG_MA 250
+#define MIN_IAVG_MA 250
 #define MIN_SECONDS_FOR_VALID_SAMPLE	20
 static int calculate_unusable_charge_uah(struct pm8921_bms_chip *chip,
 				int rbatt, int fcc_uah, int cc_uah,
@@ -1180,8 +1190,8 @@
 	 * if we are charging use a nominal avg current so that we keep
 	 * a reasonable UUC while charging
 	 */
-	if (iavg_ma < 0)
-		iavg_ma = CHARGING_IAVG_MA;
+	if (iavg_ma < MIN_IAVG_MA)
+		iavg_ma = MIN_IAVG_MA;
 	iavg_samples[iavg_index] = iavg_ma;
 	iavg_index = (iavg_index + 1) % IAVG_SAMPLES;
 	iavg_num_samples++;
@@ -1205,9 +1215,9 @@
 					&pc_unusable);
 	pr_debug("iavg = %d uuc_iavg = %d\n", iavg_ma, uuc_uah_iavg);
 
-	/* restrict the uuc such that it can increase only by one percent */
+	/* restrict the uuc change to one percent per 60 seconds */
 	uuc_uah_iavg = adjust_uuc(chip, fcc_uah, pc_unusable, uuc_uah_iavg,
-					batt_temp, rbatt, &iavg_ma);
+				batt_temp, rbatt, &iavg_ma, delta_time_s);
 
 	/* find out what the avg current should be for this uuc */
 	chip->prev_uuc_iavg_ma = iavg_ma;
@@ -1239,11 +1249,17 @@
 						int *remaining_charge_uah,
 						int *cc_uah,
 						int *rbatt,
-						int *iavg_ua,
-						int *delta_time_s)
+						int *iavg_ua)
 {
 	int soc_rbatt;
+	int delta_time_s;
+	int rc;
 
+	rc = calculate_delta_time(chip, &delta_time_s);
+	if (rc) {
+		pr_err("Failed to get delta time from RTC: %d\n", rc);
+		delta_time_s = 0;
+	}
 	*fcc_uah = calculate_fcc_uah(chip, batt_temp, chargecycles);
 	pr_debug("FCC = %uuAh batt_temp = %d, cycles = %d\n",
 					*fcc_uah, batt_temp, chargecycles);
@@ -1271,7 +1287,7 @@
 	*unusable_charge_uah = calculate_unusable_charge_uah(chip, *rbatt,
 					*fcc_uah, *cc_uah, soc_rbatt,
 					batt_temp, chargecycles, *iavg_ua,
-					*delta_time_s);
+					delta_time_s);
 	pr_debug("UUC = %uuAh\n", *unusable_charge_uah);
 }
 
@@ -1286,7 +1302,6 @@
 	int real_fcc_uah;
 	int rbatt;
 	int iavg_ua;
-	int delta_time_s;
 
 	calculate_soc_params(chip, raw, batt_temp, chargecycles,
 						&fcc_uah,
@@ -1294,8 +1309,7 @@
 						&remaining_charge_uah,
 						&cc_uah,
 						&rbatt,
-						&iavg_ua,
-						&delta_time_s);
+						&iavg_ua);
 
 	real_fcc_uah = remaining_charge_uah - cc_uah;
 	*ret_fcc_uah = fcc_uah;
@@ -1406,6 +1420,13 @@
 	*ret_rc = rc_uah;
 	*ret_uuc = uuc_uah;
 }
+
+static void calc_current_max(struct pm8921_bms_chip *chip, int ocv_uv,
+		int rbatt_mohm)
+{
+	chip->imax_ua = 1000 * (ocv_uv - chip->v_cutoff * 1000) / rbatt_mohm;
+}
+
 static int bound_soc(int soc)
 {
 	soc = max(0, soc);
@@ -1533,6 +1554,7 @@
 	delta_ocv_uv_limit = DIV_ROUND_CLOSEST(ibat_ua, 1000);
 
 	ocv_est_uv = vbat_uv + (ibat_ua * rbatt)/1000;
+	calc_current_max(chip, ocv_est_uv, rbatt);
 	pc_est = calculate_pc(chip, ocv_est_uv, batt_temp, last_chargecycles);
 	soc_est = div_s64((s64)fcc_uah * pc_est - uuc_uah*100,
 						(s64)fcc_uah - uuc_uah);
@@ -1903,7 +1925,6 @@
 	int cc_uah;
 	int rbatt;
 	int iavg_ua;
-	int delta_time_s;
 	int new_ocv;
 	int new_rc_uah;
 	int new_ucc_uah;
@@ -1919,8 +1940,7 @@
 						&remaining_charge_uah,
 						&cc_uah,
 						&rbatt,
-						&iavg_ua,
-						&delta_time_s);
+						&iavg_ua);
 
 	/* calculate remaining usable charge */
 	remaining_usable_charge_uah = remaining_charge_uah
@@ -2047,6 +2067,7 @@
 	struct pm8921_soc_params raw;
 	int soc;
 
+	wake_lock(&the_chip->soc_wake_lock);
 	get_batt_temp(chip, &batt_temp);
 
 	mutex_lock(&chip->last_ocv_uv_mutex);
@@ -2055,6 +2076,7 @@
 	soc = calculate_state_of_charge(chip, &raw,
 					batt_temp, last_chargecycles);
 	mutex_unlock(&chip->last_ocv_uv_mutex);
+	wake_unlock(&the_chip->soc_wake_lock);
 	return soc;
 }
 
@@ -2241,42 +2263,15 @@
 }
 EXPORT_SYMBOL_GPL(pm8921_bms_get_percent_charge);
 
-int pm8921_bms_get_rbatt(void)
+int pm8921_bms_get_current_max(void)
 {
-	int batt_temp;
-	struct pm8921_soc_params raw;
-	int fcc_uah;
-	int unusable_charge_uah;
-	int remaining_charge_uah;
-	int cc_uah;
-	int rbatt;
-	int iavg_ua;
-	int delta_time_s;
-
 	if (!the_chip) {
 		pr_err("called before initialization\n");
 		return -EINVAL;
 	}
-
-	get_batt_temp(the_chip, &batt_temp);
-
-	mutex_lock(&the_chip->last_ocv_uv_mutex);
-
-	read_soc_params_raw(the_chip, &raw, batt_temp);
-
-	calculate_soc_params(the_chip, &raw, batt_temp, last_chargecycles,
-						&fcc_uah,
-						&unusable_charge_uah,
-						&remaining_charge_uah,
-						&cc_uah,
-						&rbatt,
-						&iavg_ua,
-						&delta_time_s);
-	mutex_unlock(&the_chip->last_ocv_uv_mutex);
-
-	return rbatt;
+	return the_chip->imax_ua;
 }
-EXPORT_SYMBOL_GPL(pm8921_bms_get_rbatt);
+EXPORT_SYMBOL_GPL(pm8921_bms_get_current_max);
 
 int pm8921_bms_get_fcc(void)
 {
@@ -3018,6 +3013,9 @@
 	chip->rconn_mohm = pdata->rconn_mohm;
 	chip->start_percent = -EINVAL;
 	chip->end_percent = -EINVAL;
+	chip->last_cc_uah = INT_MIN;
+	chip->ocv_reading_at_100 = OCV_RAW_UNINITIALIZED;
+	chip->prev_last_good_ocv_raw = OCV_RAW_UNINITIALIZED;
 	chip->shutdown_soc_valid_limit = pdata->shutdown_soc_valid_limit;
 	chip->adjust_soc_low_threshold = pdata->adjust_soc_low_threshold;
 
@@ -3031,6 +3029,7 @@
 
 	chip->prev_pc_unusable = -EINVAL;
 	chip->soc_at_cv = -EINVAL;
+	chip->imax_ua = -EINVAL;
 
 	chip->ignore_shutdown_soc = pdata->ignore_shutdown_soc;
 	rc = set_battery_data(chip);
@@ -3063,10 +3062,12 @@
 	INIT_DELAYED_WORK(&chip->calculate_soc_delayed_work,
 			calculate_soc_work);
 
+	wake_lock_init(&chip->soc_wake_lock,
+			WAKE_LOCK_SUSPEND, "pm8921_soc_lock");
 	rc = request_irqs(chip, pdev);
 	if (rc) {
 		pr_err("couldn't register interrupts rc = %d\n", rc);
-		goto free_chip;
+		goto destroy_soc_wl;
 	}
 
 	wake_lock_init(&chip->low_voltage_wake_lock,
@@ -3108,7 +3109,10 @@
 	return 0;
 
 free_irqs:
+	wake_lock_destroy(&chip->low_voltage_wake_lock);
 	free_irqs(chip);
+destroy_soc_wl:
+	wake_lock_destroy(&chip->soc_wake_lock);
 free_chip:
 	kfree(chip);
 	return rc;
diff --git a/drivers/power/pm8921-charger.c b/drivers/power/pm8921-charger.c
index c86ba9e..a09e5ee 100644
--- a/drivers/power/pm8921-charger.c
+++ b/drivers/power/pm8921-charger.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011-2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2011-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -1663,32 +1663,7 @@
 
 static int get_prop_batt_current_max(struct pm8921_chg_chip *chip)
 {
-	int rbatt, ibatt_ua, vbatt_uv, ocv_uv;
-	int imax_ma;
-	int rc;
-
-	rbatt = pm8921_bms_get_rbatt();
-
-	if (rbatt < 0) {
-		rc = -ENXIO;
-		return rc;
-	}
-
-	rc =  pm8921_bms_get_simultaneous_battery_voltage_and_current
-			(&ibatt_ua, &vbatt_uv);
-
-	if (rc)
-		return rc;
-
-	ocv_uv = vbatt_uv + ibatt_ua*rbatt/1000;
-
-	imax_ma = (ocv_uv - chip->min_voltage_mv*1000)/rbatt;
-
-	if (imax_ma < 0)
-		imax_ma = 0;
-
-	return imax_ma*1000;
-
+	return pm8921_bms_get_current_max();
 }
 
 static int get_prop_batt_current(struct pm8921_chg_chip *chip)
diff --git a/drivers/power/qpnp-charger.c b/drivers/power/qpnp-charger.c
index 510071a..32359e5 100644
--- a/drivers/power/qpnp-charger.c
+++ b/drivers/power/qpnp-charger.c
@@ -81,6 +81,7 @@
 #define CHGR_MISC_BOOT_DONE			0x42
 #define CHGR_BUCK_COMPARATOR_OVRIDE_3		0xED
 #define MISC_REVISION2				0x01
+#define USB_OVP_CTL				0x42
 #define SEC_ACCESS				0xD0
 
 /* SMBB peripheral subtype values */
@@ -99,6 +100,7 @@
 #define CHGR_BOOT_DONE			BIT(7)
 #define CHGR_CHG_EN			BIT(7)
 #define CHGR_ON_BAT_FORCE_BIT		BIT(0)
+#define USB_VALID_DEB_20MS		0x03
 
 /* Interrupt definitions */
 /* smbb_chg_interrupts */
@@ -481,6 +483,10 @@
 static int
 qpnp_chg_force_run_on_batt(struct qpnp_chg_chip *chip, int disable)
 {
+	/* Don't run on battery for batteryless hardware */
+	if (chip->use_default_batt_values)
+		return 0;
+
 	/* This bit forces the charger to run off of the battery rather
 	 * than a connected charger */
 	return qpnp_chg_masked_write(chip, chip->chgr_base + CHGR_CHG_CTRL,
@@ -1189,6 +1195,11 @@
 		}
 
 		rc = qpnp_chg_masked_write(chip,
+			chip->usb_chgpth_base + USB_OVP_CTL,
+			USB_VALID_DEB_20MS,
+			USB_VALID_DEB_20MS, 1);
+
+		rc = qpnp_chg_masked_write(chip,
 			chip->usb_chgpth_base + CHGR_USB_ENUM_T_STOP,
 			ENUM_T_STOP_BIT,
 			ENUM_T_STOP_BIT, 1);
diff --git a/drivers/slimbus/slim-msm.c b/drivers/slimbus/slim-msm.c
index c62ac27..137f85e 100644
--- a/drivers/slimbus/slim-msm.c
+++ b/drivers/slimbus/slim-msm.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2011-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -589,6 +589,11 @@
 #define SLIMBUS_QMI_POWER_REQ_V01 0x0021
 #define SLIMBUS_QMI_POWER_RESP_V01 0x0021
 
+#define SLIMBUS_QMI_POWER_REQ_MAX_MSG_LEN 7
+#define SLIMBUS_QMI_POWER_RESP_MAX_MSG_LEN 7
+#define SLIMBUS_QMI_SELECT_INSTANCE_REQ_MAX_MSG_LEN 14
+#define SLIMBUS_QMI_SELECT_INSTANCE_RESP_MAX_MSG_LEN 7
+
 enum slimbus_mode_enum_type_v01 {
 	/* To force a 32 bit signed enum. Do not change or use*/
 	SLIMBUS_MODE_ENUM_TYPE_MIN_ENUM_VAL_V01 = INT_MIN,
@@ -791,11 +796,11 @@
 	int rc;
 
 	req_desc.msg_id = SLIMBUS_QMI_SELECT_INSTANCE_REQ_V01;
-	req_desc.max_msg_len = sizeof(*req);
+	req_desc.max_msg_len = SLIMBUS_QMI_SELECT_INSTANCE_REQ_MAX_MSG_LEN;
 	req_desc.ei_array = slimbus_select_inst_req_msg_v01_ei;
 
 	resp_desc.msg_id = SLIMBUS_QMI_SELECT_INSTANCE_RESP_V01;
-	resp_desc.max_msg_len = sizeof(resp);
+	resp_desc.max_msg_len = SLIMBUS_QMI_SELECT_INSTANCE_RESP_MAX_MSG_LEN;
 	resp_desc.ei_array = slimbus_select_inst_resp_msg_v01_ei;
 
 	rc = qmi_send_req_wait(dev->qmi.handle, &req_desc, req, sizeof(*req),
@@ -823,11 +828,11 @@
 	int rc;
 
 	req_desc.msg_id = SLIMBUS_QMI_POWER_REQ_V01;
-	req_desc.max_msg_len = sizeof(*req);
+	req_desc.max_msg_len = SLIMBUS_QMI_POWER_REQ_MAX_MSG_LEN;
 	req_desc.ei_array = slimbus_power_req_msg_v01_ei;
 
 	resp_desc.msg_id = SLIMBUS_QMI_POWER_RESP_V01;
-	resp_desc.max_msg_len = sizeof(resp);
+	resp_desc.max_msg_len = SLIMBUS_QMI_POWER_RESP_MAX_MSG_LEN;
 	resp_desc.ei_array = slimbus_power_resp_msg_v01_ei;
 
 	rc = qmi_send_req_wait(dev->qmi.handle, &req_desc, req, sizeof(*req),
diff --git a/drivers/tty/serial/msm_serial_hs.c b/drivers/tty/serial/msm_serial_hs.c
index 4ffe0d8..2d73af6 100644
--- a/drivers/tty/serial/msm_serial_hs.c
+++ b/drivers/tty/serial/msm_serial_hs.c
@@ -3,7 +3,7 @@
  * MSM 7k High speed uart driver
  *
  * Copyright (c) 2008 Google Inc.
- * Copyright (c) 2007-2012, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2007-2013, The Linux Foundation. All rights reserved.
  * Modified: Nick Pelly <npelly@google.com>
  *
  * All source code in this file is licensed under the following license
@@ -754,7 +754,7 @@
 
 	uport->ignore_status_mask = termios->c_iflag & INPCK;
 	uport->ignore_status_mask |= termios->c_iflag & IGNPAR;
-	uport->ignore_status_mask = termios->c_iflag & IGNBRK;
+	uport->ignore_status_mask |= termios->c_iflag & IGNBRK;
 
 	uport->read_status_mask = (termios->c_cflag & CREAD);
 
diff --git a/drivers/tty/serial/msm_serial_hs_hwreg.h b/drivers/tty/serial/msm_serial_hs_hwreg.h
index 8debc36..20d6781 100644
--- a/drivers/tty/serial/msm_serial_hs_hwreg.h
+++ b/drivers/tty/serial/msm_serial_hs_hwreg.h
@@ -1,6 +1,6 @@
 /* drivers/serial/msm_serial_hs_hwreg.h
  *
- * Copyright (c) 2007-2009, 2012, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2007-2009, 2012-2013,The Linux Foundation. All rights reserved.
  * 
  * All source code in this file is licensed under the following license
  * except where indicated.
@@ -59,8 +59,16 @@
 #define UARTDM_MR1_ADDR 0x0
 #define UARTDM_MR2_ADDR 0x4
 
+/* Backward Compatability Register for UARTDM Core v1.4 */
+#define UARTDM_BCR_ADDR	0xc8
+
+/*
+ * UARTDM Core v1.4 STALE_IRQ_EMPTY bit defination
+ * Stale interrupt will fire if bit is set when RX-FIFO is empty
+ */
+#define UARTDM_BCR_STALE_IRQ_EMPTY	0x2
+
 /* write only register */
-#define UARTDM_CSR_ADDR    0x8
 #define UARTDM_CSR_115200 0xFF
 #define UARTDM_CSR_57600  0xEE
 #define UARTDM_CSR_38400  0xDD
@@ -79,22 +87,11 @@
 #define UARTDM_CSR_75     0x00
 
 /* write only register */
-#define UARTDM_TF_ADDR 0x70
-#define UARTDM_TF2_ADDR 0x74
-#define UARTDM_TF3_ADDR 0x78
-#define UARTDM_TF4_ADDR 0x7C
-
-/* write only register */
-#define UARTDM_CR_ADDR 0x10
-/* write only register */
-#define UARTDM_IMR_ADDR 0x14
-
 #define UARTDM_IPR_ADDR 0x18
 #define UARTDM_TFWR_ADDR 0x1c
 #define UARTDM_RFWR_ADDR 0x20
 #define UARTDM_HCR_ADDR 0x24
 #define UARTDM_DMRX_ADDR 0x34
-#define UARTDM_IRDA_ADDR 0x38
 #define UARTDM_DMEN_ADDR 0x3c
 
 /* UART_DM_NO_CHARS_FOR_TX */
@@ -105,21 +102,6 @@
 #define UARTDM_SIM_CFG_ADDR 0x80
 
 /* Read Only register */
-#define UARTDM_SR_ADDR 0x8
-
-/* Read Only register */
-#define UARTDM_RF_ADDR  0x70
-#define UARTDM_RF2_ADDR 0x74
-#define UARTDM_RF3_ADDR 0x78
-#define UARTDM_RF4_ADDR 0x7C
-
-/* Read Only register */
-#define UARTDM_MISR_ADDR 0x10
-
-/* Read Only register */
-#define UARTDM_ISR_ADDR 0x14
-#define UARTDM_RX_TOTAL_SNAP_ADDR 0x38
-
 #define UARTDM_TXFS_ADDR 0x4C
 #define UARTDM_RXFS_ADDR 0x50
 
@@ -155,11 +137,25 @@
 #define RESET_TX_ERROR		0x800
 #define RESET_TX_DONE		0x810
 
+/*
+ * UARTDM_CR BAM IFC comman bit value
+ * for UARTDM Core v1.4
+ */
+#define START_RX_BAM_IFC	0x850
+#define START_TX_BAM_IFC	0x860
+
 #define UARTDM_MR1_AUTO_RFR_LEVEL1_BMSK 0xffffff00
 #define UARTDM_MR1_AUTO_RFR_LEVEL0_BMSK 0x3f
 #define UARTDM_MR1_CTS_CTL_BMSK 0x40
 #define UARTDM_MR1_RX_RDY_CTL_BMSK 0x80
 
+/*
+ * UARTDM Core v1.4 MR2_RFR_CTS_LOOP bitmask
+ * Enables internal loopback between RFR_N of
+ * RX channel and CTS_N of TX channel.
+ */
+#define UARTDM_MR2_RFR_CTS_LOOP_MODE_BMSK	0x400
+
 #define UARTDM_MR2_LOOP_MODE_BMSK		0x80
 #define UARTDM_MR2_ERROR_MODE_BMSK		0x40
 #define UARTDM_MR2_BITS_PER_CHAR_BMSK		0x30
@@ -204,4 +200,110 @@
 #define UARTDM_TX_DM_EN_BMSK 0x1
 #define UARTDM_RX_DM_EN_BMSK 0x2
 
+/*
+ * UARTDM Core v1.4 bitmask
+ * Bitmasks for enabling Rx and Tx BAM Interface
+ */
+#define UARTDM_TX_BAM_ENABLE_BMSK 0x4
+#define UARTDM_RX_BAM_ENABLE_BMSK 0x8
+
+/*
+ * Some of the BLSP Based UART Core(v14) existing register offsets
+ * are different compare to GSBI based UART Core(v13)
+ * Hence add the changed register offsets for UART Core v14
+ */
+#ifdef CONFIG_MSM_UARTDM_Core_v14
+
+/* write only register */
+#define UARTDM_CSR_ADDR    0x0a
+
+/* write only register */
+#define UARTDM_TF_ADDR   0x100
+#define UARTDM_TF2_ADDR  0x104
+#define UARTDM_TF3_ADDR  0x108
+#define UARTDM_TF4_ADDR  0x10c
+#define UARTDM_TF5_ADDR  0x110
+#define UARTDM_TF6_ADDR  0x114
+#define UARTDM_TF7_ADDR  0x118
+#define UARTDM_TF8_ADDR  0x11c
+#define UARTDM_TF9_ADDR  0x120
+#define UARTDM_TF10_ADDR 0x124
+#define UARTDM_TF11_ADDR 0x128
+#define UARTDM_TF12_ADDR 0x12c
+#define UARTDM_TF13_ADDR 0x130
+#define UARTDM_TF14_ADDR 0x134
+#define UARTDM_TF15_ADDR 0x138
+#define UARTDM_TF16_ADDR 0x13c
+
+/* write only register */
+#define UARTDM_CR_ADDR 0xa8
+/* write only register */
+#define UARTDM_IMR_ADDR 0xb0
+#define UARTDM_IRDA_ADDR 0xb8
+
+/* Read Only register */
+#define UARTDM_SR_ADDR 0xa4
+
+/* Read Only register */
+#define UARTDM_RF_ADDR   0x140
+#define UARTDM_RF2_ADDR  0x144
+#define UARTDM_RF3_ADDR  0x148
+#define UARTDM_RF4_ADDR  0x14c
+#define UARTDM_RF5_ADDR  0x150
+#define UARTDM_RF6_ADDR  0x154
+#define UARTDM_RF7_ADDR  0x158
+#define UARTDM_RF8_ADDR  0x15c
+#define UARTDM_RF9_ADDR  0x160
+#define UARTDM_RF10_ADDR 0x164
+#define UARTDM_RF11_ADDR 0x168
+#define UARTDM_RF12_ADDR 0x16c
+#define UARTDM_RF13_ADDR 0x170
+#define UARTDM_RF14_ADDR 0x174
+#define UARTDM_RF15_ADDR 0x178
+#define UARTDM_RF16_ADDR 0x17c
+
+/* Read Only register */
+#define UARTDM_MISR_ADDR 0xac
+
+/* Read Only register */
+#define UARTDM_ISR_ADDR 0xb4
+#define UARTDM_RX_TOTAL_SNAP_ADDR 0xbc
+
+#else
+
+/* Register offsets for UART Core v13 */
+
+/* write only register */
+#define UARTDM_CSR_ADDR    0x8
+
+/* write only register */
+#define UARTDM_TF_ADDR   0x70
+#define UARTDM_TF2_ADDR  0x74
+#define UARTDM_TF3_ADDR  0x78
+#define UARTDM_TF4_ADDR  0x7c
+
+/* write only register */
+#define UARTDM_CR_ADDR 0x10
+/* write only register */
+#define UARTDM_IMR_ADDR 0x14
+#define UARTDM_IRDA_ADDR 0x38
+
+/* Read Only register */
+#define UARTDM_SR_ADDR 0x8
+
+/* Read Only register */
+#define UARTDM_RF_ADDR   0x70
+#define UARTDM_RF2_ADDR  0x74
+#define UARTDM_RF3_ADDR  0x78
+#define UARTDM_RF4_ADDR  0x7c
+
+/* Read Only register */
+#define UARTDM_MISR_ADDR 0x10
+
+/* Read Only register */
+#define UARTDM_ISR_ADDR 0x14
+#define UARTDM_RX_TOTAL_SNAP_ADDR 0x38
+
+#endif
+
 #endif /* MSM_SERIAL_HS_HWREG_H */
diff --git a/drivers/usb/dwc3/dwc3-msm.c b/drivers/usb/dwc3/dwc3-msm.c
index ccb9aa3..1ee0828 100644
--- a/drivers/usb/dwc3/dwc3-msm.c
+++ b/drivers/usb/dwc3/dwc3-msm.c
@@ -189,6 +189,7 @@
 	u32			bus_perf_client;
 	struct msm_bus_scale_pdata	*bus_scale_table;
 	struct power_supply	usb_psy;
+	struct power_supply	*ext_vbus_psy;
 	unsigned int		online;
 	unsigned int		host_mode;
 	unsigned int		current_max;
@@ -197,6 +198,7 @@
 	unsigned int		vdd_high_vol_level;
 	bool			vbus_active;
 	bool			ext_inuse;
+	enum dwc3_id_state	id_state;
 };
 
 #define USB_HSPHY_3P3_VOL_MIN		3050000 /* uV */
@@ -1441,6 +1443,7 @@
 	struct dwc3_msm *mdwc = context;
 
 	if (start == false) {
+		dev_dbg(mdwc->dev, "canceling charging detection work\n");
 		cancel_delayed_work_sync(&mdwc->chg_work);
 		mdwc->chg_state = USB_CHG_STATE_UNDEFINED;
 		charger->chg_type = DWC3_INVALID_CHARGER;
@@ -1797,8 +1800,8 @@
 	/* Process PMIC notification in PRESENT prop */
 	case POWER_SUPPLY_PROP_PRESENT:
 		dev_dbg(mdwc->dev, "%s: notify xceiv event\n", __func__);
-		if (mdwc->otg_xceiv && (mdwc->ext_xceiv.otg_capability ||
-							!init)) {
+		if (mdwc->otg_xceiv && !mdwc->ext_inuse &&
+		    (mdwc->ext_xceiv.otg_capability || !init)) {
 			mdwc->ext_xceiv.bsv = val->intval;
 			if (atomic_read(&mdwc->in_lpm)) {
 				dev_dbg(mdwc->dev,
@@ -1810,9 +1813,10 @@
 							mdwc->otg_xceiv->otg,
 							DWC3_EVENT_XCEIV_STATE);
 			}
+
+			if (!init)
+				init = true;
 		}
-		if (!init)
-			init = true;
 		mdwc->vbus_active = val->intval;
 		break;
 	case POWER_SUPPLY_PROP_ONLINE:
@@ -1829,6 +1833,33 @@
 	return 0;
 }
 
+static void dwc3_msm_external_power_changed(struct power_supply *psy)
+{
+	struct dwc3_msm *mdwc = container_of(psy, struct dwc3_msm, usb_psy);
+	union power_supply_propval ret = {0,};
+
+	if (!mdwc->ext_vbus_psy)
+		mdwc->ext_vbus_psy = power_supply_get_by_name("ext-vbus");
+
+	if (!mdwc->ext_vbus_psy) {
+		pr_err("%s: Unable to get ext_vbus power_supply\n", __func__);
+		return;
+	}
+
+	mdwc->ext_vbus_psy->get_property(mdwc->ext_vbus_psy,
+					POWER_SUPPLY_PROP_ONLINE, &ret);
+	if (ret.intval) {
+		dwc3_start_chg_det(&mdwc->charger, false);
+		mdwc->ext_vbus_psy->get_property(mdwc->ext_vbus_psy,
+					POWER_SUPPLY_PROP_CURRENT_MAX, &ret);
+		power_supply_set_current_limit(&mdwc->usb_psy, ret.intval);
+	}
+
+	power_supply_set_online(&mdwc->usb_psy, ret.intval);
+	power_supply_changed(&mdwc->usb_psy);
+}
+
+
 static char *dwc3_msm_pm_power_supplied_to[] = {
 	"battery",
 };
@@ -1845,6 +1876,7 @@
 static void dwc3_ext_notify_online(int on)
 {
 	struct dwc3_msm *mdwc = context;
+	bool notify_otg = false;
 
 	if (!mdwc) {
 		pr_err("%s: DWC3 driver already removed\n", __func__);
@@ -1853,11 +1885,31 @@
 
 	dev_dbg(mdwc->dev, "notify %s%s\n", on ? "" : "dis", "connected");
 
-	if (!on) {
-		/* external client offline; revert back to USB */
-		mdwc->ext_inuse = false;
-		queue_delayed_work(system_nrt_wq, &mdwc->resume_work, 0);
+	if (!mdwc->ext_vbus_psy)
+		mdwc->ext_vbus_psy = power_supply_get_by_name("ext-vbus");
+
+	mdwc->ext_inuse = on;
+	if (on) {
+		/* force OTG to exit B-peripheral state */
+		mdwc->ext_xceiv.bsv = false;
+		notify_otg = true;
+		dwc3_start_chg_det(&mdwc->charger, false);
+	} else {
+		/* external client offline; tell OTG about cached ID/BSV */
+		if (mdwc->ext_xceiv.id != mdwc->id_state) {
+			mdwc->ext_xceiv.id = mdwc->id_state;
+			notify_otg = true;
+		}
+
+		mdwc->ext_xceiv.bsv = mdwc->vbus_active;
+		notify_otg |= mdwc->vbus_active;
 	}
+
+	if (mdwc->ext_vbus_psy)
+		power_supply_set_present(mdwc->ext_vbus_psy, on);
+
+	if (notify_otg)
+		queue_delayed_work(system_nrt_wq, &mdwc->resume_work, 0);
 }
 
 static bool dwc3_ext_trigger_handled(struct dwc3_msm *mdwc,
@@ -1887,21 +1939,26 @@
 	dev_dbg(mdwc->dev, "%s: state = %s\n", __func__,
 			state == ADC_TM_HIGH_STATE ? "high" : "low");
 
+	/* Give external client a chance to handle */
+	if (!mdwc->ext_inuse)
+		dwc3_ext_trigger_handled(mdwc, (state == ADC_TM_HIGH_STATE));
+
+	/* save ID state, but don't necessarily notify OTG */
 	if (state == ADC_TM_HIGH_STATE) {
-		mdwc->ext_xceiv.id = DWC3_ID_FLOAT;
+		mdwc->id_state = DWC3_ID_FLOAT;
 		mdwc->adc_param.state_request = ADC_TM_LOW_THR_ENABLE;
 	} else {
-		mdwc->ext_xceiv.id = DWC3_ID_GROUND;
+		mdwc->id_state = DWC3_ID_GROUND;
 		mdwc->adc_param.state_request = ADC_TM_HIGH_THR_ENABLE;
 	}
 
-	/* Give external client a chance to handle, otherwise notify OTG */
-	if (!mdwc->ext_inuse &&
-			!dwc3_ext_trigger_handled(mdwc, mdwc->ext_xceiv.id))
-		queue_delayed_work(system_nrt_wq, &mdwc->resume_work, 0);
-
 	/* re-arm ADC interrupt */
 	qpnp_adc_tm_usbid_configure(&mdwc->adc_param);
+
+	if (!mdwc->ext_inuse) { /* notify OTG */
+		mdwc->ext_xceiv.id = mdwc->id_state;
+		queue_delayed_work(system_nrt_wq, &mdwc->resume_work, 0);
+	}
 }
 
 static void dwc3_init_adc_work(struct work_struct *w)
@@ -2234,6 +2291,8 @@
 	msm->usb_psy.num_properties = ARRAY_SIZE(dwc3_msm_pm_power_props_usb);
 	msm->usb_psy.get_property = dwc3_msm_power_get_property_usb;
 	msm->usb_psy.set_property = dwc3_msm_power_set_property_usb;
+	msm->usb_psy.external_power_changed =
+				dwc3_msm_external_power_changed;
 
 	ret = power_supply_register(&pdev->dev, &msm->usb_psy);
 	if (ret < 0) {
diff --git a/drivers/usb/gadget/android.c b/drivers/usb/gadget/android.c
index 0a9f500..6df0c96 100644
--- a/drivers/usb/gadget/android.c
+++ b/drivers/usb/gadget/android.c
@@ -2043,6 +2043,7 @@
 	struct android_usb_function_holder *f_holder;
 	struct android_configuration *conf;
 	int enabled = 0;
+	bool audio_enabled = false;
 
 	if (!cdev)
 		return -ENODEV;
@@ -2061,12 +2062,22 @@
 		cdev->desc.bDeviceClass = device_desc.bDeviceClass;
 		cdev->desc.bDeviceSubClass = device_desc.bDeviceSubClass;
 		cdev->desc.bDeviceProtocol = device_desc.bDeviceProtocol;
+
+		/* Audio dock accessory is unable to enumerate device if
+		 * pull-up is enabled immediately. The enumeration is
+		 * reliable with 100 msec delay.
+		 */
 		list_for_each_entry(conf, &dev->configs, list_item)
 			list_for_each_entry(f_holder, &conf->enabled_functions,
 						enabled_list) {
 				if (f_holder->f->enable)
 					f_holder->f->enable(f_holder->f);
+				if (!strncmp(f_holder->f->name,
+						"audio_source", 12))
+					audio_enabled = true;
 			}
+		if (audio_enabled)
+			msleep(100);
 		android_enable(dev);
 		dev->enabled = true;
 	} else if (!enabled && dev->enabled) {
diff --git a/drivers/usb/gadget/ci13xxx_udc.c b/drivers/usb/gadget/ci13xxx_udc.c
index 9c7b1ec..9d231d6 100644
--- a/drivers/usb/gadget/ci13xxx_udc.c
+++ b/drivers/usb/gadget/ci13xxx_udc.c
@@ -2115,7 +2115,6 @@
  */
 static int _gadget_stop_activity(struct usb_gadget *gadget)
 {
-	struct usb_ep *ep;
 	struct ci13xxx    *udc = container_of(gadget, struct ci13xxx, gadget);
 	unsigned long flags;
 
@@ -2136,20 +2135,10 @@
 	gadget->host_request = 0;
 	gadget->otg_srp_reqd = 0;
 
-	/* flush all endpoints */
-	gadget_for_each_ep(ep, gadget) {
-		usb_ep_fifo_flush(ep);
-	}
+	udc->driver->disconnect(gadget);
 	usb_ep_fifo_flush(&udc->ep0out.ep);
 	usb_ep_fifo_flush(&udc->ep0in.ep);
 
-	udc->driver->disconnect(gadget);
-
-	/* make sure to disable all endpoints */
-	gadget_for_each_ep(ep, gadget) {
-		usb_ep_disable(ep);
-	}
-
 	if (udc->status != NULL) {
 		usb_ep_free_request(&udc->ep0in.ep, udc->status);
 		udc->status = NULL;
diff --git a/drivers/usb/gadget/f_diag.c b/drivers/usb/gadget/f_diag.c
index aca2af3..a95bf24 100644
--- a/drivers/usb/gadget/f_diag.c
+++ b/drivers/usb/gadget/f_diag.c
@@ -2,7 +2,7 @@
  * Diag Function Device - Route ARM9 and ARM11 DIAG messages
  * between HOST and DEVICE.
  * Copyright (C) 2007 Google, Inc.
- * Copyright (c) 2008-2012, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2008-2013, Linux Foundation. All rights reserved.
  * Author: Brian Swetland <swetland@google.com>
  * This software is licensed under the terms of the GNU General Public
  * License version 2, as published by the Free Software Foundation, and
@@ -334,22 +334,10 @@
 }
 EXPORT_SYMBOL(usb_diag_close);
 
-/**
- * usb_diag_free_req() - Free USB requests
- * @ch: Channel handler
- *
- * This function free read and write USB requests for the interface
- * associated with this channel.
- *
- */
-void usb_diag_free_req(struct usb_diag_ch *ch)
+static void free_reqs(struct diag_context *ctxt)
 {
-	struct diag_context *ctxt = ch->priv_usb;
-	struct usb_request *req;
 	struct list_head *act, *tmp;
-
-	if (!ctxt)
-		return;
+	struct usb_request *req;
 
 	list_for_each_safe(act, tmp, &ctxt->write_pool) {
 		req = list_entry(act, struct usb_request, list);
@@ -363,6 +351,27 @@
 		usb_ep_free_request(ctxt->out, req);
 	}
 }
+
+/**
+ * usb_diag_free_req() - Free USB requests
+ * @ch: Channel handler
+ *
+ * This function free read and write USB requests for the interface
+ * associated with this channel.
+ *
+ */
+void usb_diag_free_req(struct usb_diag_ch *ch)
+{
+	struct diag_context *ctxt = ch->priv_usb;
+	unsigned long flags;
+
+	if (ctxt) {
+		spin_lock_irqsave(&ctxt->lock, flags);
+		free_reqs(ctxt);
+		spin_unlock_irqrestore(&ctxt->lock, flags);
+	}
+
+}
 EXPORT_SYMBOL(usb_diag_free_req);
 
 /**
@@ -381,10 +390,14 @@
 	struct diag_context *ctxt = ch->priv_usb;
 	struct usb_request *req;
 	int i;
+	unsigned long flags;
 
 	if (!ctxt)
 		return -ENODEV;
 
+	spin_lock_irqsave(&ctxt->lock, flags);
+	/* Free previous session's stale requests */
+	free_reqs(ctxt);
 	for (i = 0; i < n_write; i++) {
 		req = usb_ep_alloc_request(ctxt->in, GFP_ATOMIC);
 		if (!req)
@@ -400,11 +413,11 @@
 		req->complete = diag_read_complete;
 		list_add_tail(&req->list, &ctxt->read_pool);
 	}
-
+	spin_unlock_irqrestore(&ctxt->lock, flags);
 	return 0;
-
 fail:
-	usb_diag_free_req(ch);
+	free_reqs(ctxt);
+	spin_unlock_irqrestore(&ctxt->lock, flags);
 	return -ENOMEM;
 
 }
diff --git a/drivers/usb/gadget/msm72k_udc.c b/drivers/usb/gadget/msm72k_udc.c
index b408bfd..887a10c 100644
--- a/drivers/usb/gadget/msm72k_udc.c
+++ b/drivers/usb/gadget/msm72k_udc.c
@@ -2,7 +2,7 @@
  * Driver for HighSpeed USB Client Controller in MSM7K
  *
  * Copyright (C) 2008 Google, Inc.
- * Copyright (c) 2009-2012, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2009-2013, The Linux Foundation. All rights reserved.
  * Author: Mike Lockwood <lockwood@android.com>
  *         Brian Swetland <swetland@google.com>
  *
@@ -1649,6 +1649,20 @@
 				usb_phy_set_power(ui->xceiv, 0);
 
 				if (ui->irq) {
+					/* Disable and acknowledge all
+					 * USB interrupts before freeing
+					 * irq, so that no USB spurious
+					 * interrupt occurs during USB cable
+					 * disconnect which may lead to
+					 * IRQ nobody cared error.
+					 */
+					writel_relaxed(0, USB_USBINTR);
+					writel_relaxed(readl_relaxed(USB_USBSTS)
+								, USB_USBSTS);
+					/* Ensure that above STOREs are
+					 * completed before enabling
+					 * interrupts */
+					wmb();
 					free_irq(ui->irq, ui);
 					ui->irq = 0;
 				}
diff --git a/drivers/usb/gadget/u_bam.c b/drivers/usb/gadget/u_bam.c
index 4947f15..00744fb 100644
--- a/drivers/usb/gadget/u_bam.c
+++ b/drivers/usb/gadget/u_bam.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2011-2013, Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -220,7 +220,7 @@
 		ret = usb_ep_queue(ep, req, GFP_ATOMIC);
 		spin_lock(&port->port_lock_dl);
 		if (ret) {
-			pr_err("%s: usb epIn failed\n", __func__);
+			pr_err("%s: usb epIn failed with %d\n", __func__, ret);
 			list_add(&req->list, &d->tx_idle);
 			dev_kfree_skb_any(skb);
 			break;
@@ -517,7 +517,8 @@
 			dev_kfree_skb_any(skb);
 
 			if (printk_ratelimit())
-				pr_err("%s: rx queue failed\n", __func__);
+				pr_err("%s: rx queue failed %d\n",
+							__func__, ret);
 
 			if (port->port_usb)
 				list_add(&req->list, &d->rx_idle);
diff --git a/drivers/usb/host/ehci-msm-hsic.c b/drivers/usb/host/ehci-msm-hsic.c
index 1141a24..8ab4a6a 100644
--- a/drivers/usb/host/ehci-msm-hsic.c
+++ b/drivers/usb/host/ehci-msm-hsic.c
@@ -1625,19 +1625,23 @@
 {
 	struct device_node *node = pdev->dev.of_node;
 	struct msm_hsic_host_platform_data *pdata;
+	int res_gpio;
 
 	pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
 	if (!pdata) {
 		dev_err(&pdev->dev, "unable to allocate platform data\n");
 		return NULL;
 	}
-	pdata->strobe = of_get_named_gpio(node, "hsic,strobe-gpio", 0);
-	if (pdata->strobe < 0)
-		pdata->strobe = 0;
 
-	pdata->data = of_get_named_gpio(node, "hsic,data-gpio", 0);
-	if (pdata->data < 0)
-		pdata->data = 0;
+	res_gpio = of_get_named_gpio(node, "hsic,strobe-gpio", 0);
+	if (res_gpio < 0)
+		res_gpio = 0;
+	pdata->strobe = res_gpio;
+
+	res_gpio = of_get_named_gpio(node, "hsic,data-gpio", 0);
+	if (res_gpio < 0)
+		res_gpio = 0;
+	pdata->data = res_gpio;
 
 	pdata->ignore_cal_pad_config = of_property_read_bool(node,
 					"hsic,ignore-cal-pad-config");
diff --git a/drivers/usb/misc/ks_bridge.c b/drivers/usb/misc/ks_bridge.c
index dab6e7f..e76a9a8 100644
--- a/drivers/usb/misc/ks_bridge.c
+++ b/drivers/usb/misc/ks_bridge.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2012-2013, Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -297,6 +297,9 @@
 	if (!test_bit(USB_DEV_CONNECTED, &ksb->flags))
 		return -ENODEV;
 
+	if (count > MAX_DATA_PKT_SIZE)
+		count = MAX_DATA_PKT_SIZE;
+
 	pkt = ksb_alloc_data_pkt(count, GFP_KERNEL, ksb);
 	if (IS_ERR(pkt)) {
 		pr_err("unable to allocate data packet");
diff --git a/drivers/usb/otg/msm_otg.c b/drivers/usb/otg/msm_otg.c
index 3ad05b06..a4bb7b2 100644
--- a/drivers/usb/otg/msm_otg.c
+++ b/drivers/usb/otg/msm_otg.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2009-2012, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2009-2013, Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -2167,8 +2167,8 @@
 	}
 }
 
-#define MSM_CHG_DCD_POLL_TIME		(100 * HZ/1000) /* 100 msec */
-#define MSM_CHG_DCD_MAX_RETRIES		6 /* Tdcd_tmout = 6 * 100 msec */
+#define MSM_CHG_DCD_TIMEOUT		(750 * HZ/1000) /* 750 msec */
+#define MSM_CHG_DCD_POLL_TIME		(50 * HZ/1000) /* 50 msec */
 #define MSM_CHG_PRIMARY_DET_TIME	(50 * HZ/1000) /* TVDPSRC_ON */
 #define MSM_CHG_SECONDARY_DET_TIME	(50 * HZ/1000) /* TVDMSRC_ON */
 static void msm_chg_detect_work(struct work_struct *w)
@@ -2192,7 +2192,7 @@
 		msm_chg_enable_dcd(motg);
 		msm_chg_enable_aca_det(motg);
 		motg->chg_state = USB_CHG_STATE_WAIT_FOR_DCD;
-		motg->dcd_retries = 0;
+		motg->dcd_time = 0;
 		delay = MSM_CHG_DCD_POLL_TIME;
 		break;
 	case USB_CHG_STATE_WAIT_FOR_DCD:
@@ -2217,7 +2217,8 @@
 			}
 		}
 		is_dcd = msm_chg_check_dcd(motg);
-		tmout = ++motg->dcd_retries == MSM_CHG_DCD_MAX_RETRIES;
+		motg->dcd_time += MSM_CHG_DCD_POLL_TIME;
+		tmout = motg->dcd_time >= MSM_CHG_DCD_TIMEOUT;
 		if (is_dcd || tmout) {
 			msm_chg_disable_dcd(motg);
 			msm_chg_enable_primary_det(motg);
diff --git a/drivers/video/msm/mdp.h b/drivers/video/msm/mdp.h
index 7396013..20b20bc 100644
--- a/drivers/video/msm/mdp.h
+++ b/drivers/video/msm/mdp.h
@@ -73,6 +73,7 @@
 #define MDPOP_SHARPENING	BIT(11) /* enable sharpening */
 #define MDPOP_BLUR		BIT(12) /* enable blur */
 #define MDPOP_FG_PM_ALPHA       BIT(13)
+#define MDPOP_LAYER_IS_FG       BIT(14)
 #define MDP_ALLOC(x)  kmalloc(x, GFP_KERNEL)
 
 struct mdp_buf_type {
diff --git a/drivers/video/msm/mdp_ppp.c b/drivers/video/msm/mdp_ppp.c
index 8631d6d..c8367c3 100644
--- a/drivers/video/msm/mdp_ppp.c
+++ b/drivers/video/msm/mdp_ppp.c
@@ -1401,6 +1401,9 @@
 
 	iBuf.mdpImg.mdpOp = MDPOP_NOP;
 
+	if (req->flags & MDP_IS_FG)
+		iBuf.mdpImg.mdpOp |= MDPOP_LAYER_IS_FG;
+
 	/* blending check */
 	if (req->transp_mask != MDP_TRANSP_NOP) {
 		iBuf.mdpImg.mdpOp |= MDPOP_TRANSP;
diff --git a/drivers/video/msm/mdp_ppp_v20.c b/drivers/video/msm/mdp_ppp_v20.c
index 418528e..5da6b4f5 100644
--- a/drivers/video/msm/mdp_ppp_v20.c
+++ b/drivers/video/msm/mdp_ppp_v20.c
@@ -2467,7 +2467,8 @@
 			bg_alpha = PPP_BLEND_BG_USE_ALPHA_SEL |
 				PPP_BLEND_BG_ALPHA_REVERSE;
 
-			if (perPixelAlpha) {
+			if ((perPixelAlpha) && !(iBuf->mdpImg.mdpOp &
+							MDPOP_LAYER_IS_FG)) {
 				bg_alpha |= PPP_BLEND_BG_SRCPIXEL_ALPHA;
 			} else {
 				bg_alpha |= PPP_BLEND_BG_CONSTANT_ALPHA;
@@ -2478,7 +2479,12 @@
 			if (iBuf->mdpImg.mdpOp & MDPOP_TRANSP)
 				*pppop_reg_ptr |= PPP_BLEND_CALPHA_TRNASP;
 		} else if (perPixelAlpha) {
-				*pppop_reg_ptr |= PPP_OP_ROT_ON |
+				if (iBuf->mdpImg.mdpOp & MDPOP_LAYER_IS_FG)
+					*pppop_reg_ptr |= PPP_OP_ROT_ON |
+						  PPP_OP_BLEND_ON |
+						  PPP_OP_BLEND_CONSTANT_ALPHA;
+				else
+					*pppop_reg_ptr |= PPP_OP_ROT_ON |
 						  PPP_OP_BLEND_ON |
 						  PPP_OP_BLEND_SRCPIXEL_ALPHA;
 				outpdw(MDP_BASE + 0x70010, 0);
diff --git a/drivers/video/msm/mdss/Kconfig b/drivers/video/msm/mdss/Kconfig
index 56eb90c..7682a49 100644
--- a/drivers/video/msm/mdss/Kconfig
+++ b/drivers/video/msm/mdss/Kconfig
@@ -12,7 +12,7 @@
 	The MDSS HDMI Panel provides support for transmitting TMDS signals of
 	MDSS frame buffer data to connected hdmi compliant TVs, monitors etc.
 
-config FB_MSM_MDSS_HDMI_MHL_8334
+config FB_MSM_MDSS_HDMI_MHL_SII8334
 	depends on FB_MSM_MDSS_HDMI_PANEL
 	bool 'MHL SII8334 support '
 	default n
diff --git a/drivers/video/msm/mdss/Makefile b/drivers/video/msm/mdss/Makefile
index 4deaa8c..17987d4 100644
--- a/drivers/video/msm/mdss/Makefile
+++ b/drivers/video/msm/mdss/Makefile
@@ -19,7 +19,7 @@
 obj-$(CONFIG_FB_MSM_MDSS_HDMI_PANEL) += mdss_hdmi_tx.o
 obj-$(CONFIG_FB_MSM_MDSS_HDMI_PANEL) += mdss_hdmi_util.o
 obj-$(CONFIG_FB_MSM_MDSS_HDMI_PANEL) += mdss_hdmi_edid.o
-obj-$(CONFIG_FB_MSM_MDSS_HDMI_MHL_8334) += mhl_sii8334.o
+obj-$(CONFIG_FB_MSM_MDSS_HDMI_MHL_SII8334) += mhl_sii8334.o mhl_msc.o
 obj-$(CONFIG_FB_MSM_MDSS_HDMI_PANEL) += mdss_hdmi_hdcp.o
 
 obj-$(CONFIG_FB_MSM_MDSS_WRITEBACK) += mdss_wb.o
diff --git a/drivers/video/msm/mdss/mdss_mdp.h b/drivers/video/msm/mdss/mdss_mdp.h
index 9503489..e9427da 100644
--- a/drivers/video/msm/mdss/mdss_mdp.h
+++ b/drivers/video/msm/mdss/mdss_mdp.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -235,7 +235,6 @@
 
 	struct msm_fb_data_type *mfd;
 	struct mdss_mdp_mixer *mixer;
-	struct mutex lock;
 
 	struct mdp_overlay req_data;
 	u32 params_changed;
@@ -326,10 +325,10 @@
 
 
 struct mdss_mdp_pipe *mdss_mdp_pipe_alloc_pnum(u32 pnum);
-struct mdss_mdp_pipe *mdss_mdp_pipe_alloc_locked(u32 type);
-struct mdss_mdp_pipe *mdss_mdp_pipe_get_locked(u32 ndx);
-int mdss_mdp_pipe_lock(struct mdss_mdp_pipe *pipe);
-void mdss_mdp_pipe_unlock(struct mdss_mdp_pipe *pipe);
+struct mdss_mdp_pipe *mdss_mdp_pipe_alloc(u32 type);
+struct mdss_mdp_pipe *mdss_mdp_pipe_get(u32 ndx);
+int mdss_mdp_pipe_map(struct mdss_mdp_pipe *pipe);
+void mdss_mdp_pipe_unmap(struct mdss_mdp_pipe *pipe);
 
 int mdss_mdp_pipe_destroy(struct mdss_mdp_pipe *pipe);
 int mdss_mdp_pipe_queue_data(struct mdss_mdp_pipe *pipe,
diff --git a/drivers/video/msm/mdss/mdss_mdp_ctl.c b/drivers/video/msm/mdss/mdss_mdp_ctl.c
index f62dd24..2f4c2ed 100644
--- a/drivers/video/msm/mdss/mdss_mdp_ctl.c
+++ b/drivers/video/msm/mdss/mdss_mdp_ctl.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -784,6 +784,14 @@
 					stage);
 		}
 
+		if (mixercfg == MDSS_MDP_LM_BORDER_COLOR &&
+				pipe->src_fmt->alpha_enable &&
+				pipe->dst.w == mixer->width &&
+				pipe->dst.h == mixer->height) {
+			pr_debug("setting pipe=%d as BG_PIPE\n", pipe->num);
+			bgalpha = 1;
+		}
+
 		mixercfg |= stage << (3 * pipe->num);
 
 		MDSS_MDP_REG_WRITE(off + MDSS_MDP_REG_LM_OP_MODE, blend_op);
diff --git a/drivers/video/msm/mdss/mdss_mdp_overlay.c b/drivers/video/msm/mdss/mdss_mdp_overlay.c
index d278554..338cf87 100644
--- a/drivers/video/msm/mdss/mdss_mdp_overlay.c
+++ b/drivers/video/msm/mdss/mdss_mdp_overlay.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -39,14 +39,14 @@
 {
 	struct mdss_mdp_pipe *pipe;
 
-	pipe = mdss_mdp_pipe_get_locked(req->id);
-	if (pipe == NULL) {
+	pipe = mdss_mdp_pipe_get(req->id);
+	if (IS_ERR_OR_NULL(pipe)) {
 		pr_err("invalid pipe ndx=%x\n", req->id);
-		return -ENODEV;
+		return pipe ? PTR_ERR(pipe) : -ENODEV;
 	}
 
 	*req = pipe->req_data;
-	mdss_mdp_pipe_unlock(pipe);
+	mdss_mdp_pipe_unmap(pipe);
 
 	return 0;
 }
@@ -280,12 +280,12 @@
 		else
 			pipe_type = MDSS_MDP_PIPE_TYPE_RGB;
 
-		pipe = mdss_mdp_pipe_alloc_locked(pipe_type);
+		pipe = mdss_mdp_pipe_alloc(pipe_type);
 
 		/* VIG pipes can also support RGB format */
 		if (!pipe && pipe_type == MDSS_MDP_PIPE_TYPE_RGB) {
 			pipe_type = MDSS_MDP_PIPE_TYPE_VIG;
-			pipe = mdss_mdp_pipe_alloc_locked(pipe_type);
+			pipe = mdss_mdp_pipe_alloc(pipe_type);
 		}
 
 		if (pipe == NULL) {
@@ -293,16 +293,23 @@
 			return -ENOMEM;
 		}
 
+		ret = mdss_mdp_pipe_map(pipe);
+		if (ret) {
+			pr_err("unable to map pipe=%d\n", pipe->num);
+			return ret;
+		}
+
 		mutex_lock(&mfd->lock);
 		list_add(&pipe->used_list, &mfd->pipes_used);
 		mutex_unlock(&mfd->lock);
 		pipe->mixer = mixer;
 		pipe->mfd = mfd;
+		pipe->play_cnt = 0;
 	} else {
-		pipe = mdss_mdp_pipe_get_locked(req->id);
-		if (pipe == NULL) {
+		pipe = mdss_mdp_pipe_get(req->id);
+		if (IS_ERR_OR_NULL(pipe)) {
 			pr_err("invalid pipe ndx=%x\n", req->id);
-			return -ENODEV;
+			return pipe ? PTR_ERR(pipe) : -ENODEV;
 		}
 	}
 
@@ -353,7 +360,7 @@
 
 	*ppipe = pipe;
 
-	mdss_mdp_pipe_unlock(pipe);
+	mdss_mdp_pipe_unmap(pipe);
 
 	return ret;
 }
@@ -498,8 +505,8 @@
 		pipe_ndx = BIT(i);
 		if (pipe_ndx & ndx) {
 			unset_ndx |= pipe_ndx;
-			pipe = mdss_mdp_pipe_get_locked(pipe_ndx);
-			if (!pipe) {
+			pipe = mdss_mdp_pipe_get(pipe_ndx);
+			if (IS_ERR_OR_NULL(pipe)) {
 				pr_warn("unknown pipe ndx=%x\n", pipe_ndx);
 				continue;
 			}
@@ -508,6 +515,7 @@
 			list_add(&pipe->cleanup_list, &mfd->pipes_cleanup);
 			mutex_unlock(&mfd->lock);
 			mdss_mdp_mixer_pipe_unstage(pipe);
+			mdss_mdp_pipe_unmap(pipe);
 		}
 	}
 	return 0;
@@ -638,10 +646,10 @@
 	int ret;
 	u32 flags;
 
-	pipe = mdss_mdp_pipe_get_locked(req->id);
-	if (pipe == NULL) {
+	pipe = mdss_mdp_pipe_get(req->id);
+	if (IS_ERR_OR_NULL(pipe)) {
 		pr_err("pipe ndx=%x doesn't exist\n", req->id);
-		return -ENODEV;
+		return pipe ? PTR_ERR(pipe) : -ENODEV;
 	}
 
 	pr_debug("ov queue pnum=%d\n", pipe->num);
@@ -664,7 +672,7 @@
 			mdss_mdp_overlay_free_buf(src_data);
 	}
 	ctl = pipe->mixer->ctl;
-	mdss_mdp_pipe_unlock(pipe);
+	mdss_mdp_pipe_unmap(pipe);
 
 	return ret;
 }
@@ -844,9 +852,12 @@
 		return;
 	}
 
-	mdss_mdp_pipe_lock(pipe);
+	if (mdss_mdp_pipe_map(pipe)) {
+		pr_err("unable to map base pipe\n");
+		return;
+	}
 	ret = mdss_mdp_pipe_queue_data(pipe, &data);
-	mdss_mdp_pipe_unlock(pipe);
+	mdss_mdp_pipe_unmap(pipe);
 	if (ret) {
 		pr_err("unable to queue data\n");
 		return;
@@ -859,9 +870,12 @@
 			pr_err("unable to allocate right base pipe\n");
 			return;
 		}
-		mdss_mdp_pipe_lock(pipe);
+		if (mdss_mdp_pipe_map(pipe)) {
+			pr_err("unable to map right base pipe\n");
+			return;
+		}
 		ret = mdss_mdp_pipe_queue_data(pipe, &data);
-		mdss_mdp_pipe_unlock(pipe);
+		mdss_mdp_pipe_unmap(pipe);
 		if (ret) {
 			pr_err("unable to queue right data\n");
 			return;
@@ -901,10 +915,15 @@
 	if (!ctl->set_vsync_handler)
 		return -ENOTSUPP;
 
+	rc = mutex_lock_interruptible(&ctl->lock);
+	if (rc)
+		return rc;
+
 	if (!ctl->power_on) {
 		pr_debug("fb%d vsync pending first update en=%d\n",
 				mfd->index, en);
 		mfd->vsync_pending = en;
+		mutex_unlock(&ctl->lock);
 		return 0;
 	}
 
@@ -925,6 +944,8 @@
 		rc = ctl->set_vsync_handler(ctl, NULL);
 	mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_OFF, false);
 
+	mutex_unlock(&ctl->lock);
+
 	return rc;
 }
 
@@ -935,13 +956,20 @@
 	struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)fbi->par;
 	unsigned long flags;
 	u64 vsync_ticks;
+	unsigned long timeout;
 	int ret;
 
 	if (!mfd->ctl || !mfd->ctl->power_on)
 		return 0;
 
+	timeout = msecs_to_jiffies(VSYNC_PERIOD * 5);
+	if (mfd->ctl->play_cnt == 0) {
+		pr_debug("timegen enable still pending on fb%d\n", mfd->index);
+		timeout <<= 5;
+	}
+
 	ret = wait_for_completion_interruptible_timeout(&mfd->vsync_comp,
-			msecs_to_jiffies(VSYNC_PERIOD * 5));
+			timeout);
 	if (ret <= 0) {
 		pr_warn("vsync wait on fb%d interrupted (%d)\n",
 			mfd->index, ret);
diff --git a/drivers/video/msm/mdss/mdss_mdp_pipe.c b/drivers/video/msm/mdss/mdss_mdp_pipe.c
index ade7cb4..89f3405 100644
--- a/drivers/video/msm/mdss/mdss_mdp_pipe.c
+++ b/drivers/video/msm/mdss/mdss_mdp_pipe.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -27,6 +27,8 @@
 
 static struct mdss_mdp_pipe mdss_mdp_pipe_list[MDSS_MDP_MAX_SSPP];
 
+static int mdss_mdp_pipe_free(struct mdss_mdp_pipe *pipe);
+
 static u32 mdss_mdp_smp_mmb_reserve(unsigned long *smp, size_t n)
 {
 	u32 i, mmb;
@@ -157,47 +159,43 @@
 	return 0;
 }
 
-void mdss_mdp_pipe_unlock(struct mdss_mdp_pipe *pipe)
+void mdss_mdp_pipe_unmap(struct mdss_mdp_pipe *pipe)
 {
-	atomic_dec(&pipe->ref_cnt);
-	mutex_unlock(&pipe->lock);
+	int tmp;
+
+	tmp = atomic_dec_return(&pipe->ref_cnt);
+
+	WARN(tmp < 0, "Invalid unmap with ref_cnt=%d", tmp);
+	if (tmp == 0)
+		mdss_mdp_pipe_free(pipe);
 }
 
-int mdss_mdp_pipe_lock(struct mdss_mdp_pipe *pipe)
+int mdss_mdp_pipe_map(struct mdss_mdp_pipe *pipe)
 {
-	if (atomic_inc_not_zero(&pipe->ref_cnt)) {
-		if (mutex_lock_interruptible(&pipe->lock)) {
-			atomic_dec(&pipe->ref_cnt);
-			return -EINTR;
-		}
-		return 0;
+	if (!atomic_inc_not_zero(&pipe->ref_cnt)) {
+		pr_err("attempting to map unallocated pipe (%d)", pipe->num);
+		return -EINVAL;
 	}
-	return -EINVAL;
+	return 0;
 }
 
 static struct mdss_mdp_pipe *mdss_mdp_pipe_init(u32 pnum)
 {
-	struct mdss_mdp_pipe *pipe = NULL;
+	struct mdss_mdp_pipe *pipe;
 
-	if (atomic_read(&mdss_mdp_pipe_list[pnum].ref_cnt) == 0) {
-		pipe = &mdss_mdp_pipe_list[pnum];
-		memset(pipe, 0, sizeof(*pipe));
+	pipe = &mdss_mdp_pipe_list[pnum];
 
-		mutex_init(&pipe->lock);
-		atomic_set(&pipe->ref_cnt, 1);
+	if (atomic_cmpxchg(&pipe->ref_cnt, 0, 1) == 0) {
+		pipe->num = pnum;
+		pipe->type = mdss_res->pipe_type_map[pnum];
+		pipe->ndx = BIT(pnum);
 
-		if (mdss_mdp_pipe_lock(pipe) == 0) {
-			pipe->num = pnum;
-			pipe->type = mdss_res->pipe_type_map[pnum];
-			pipe->ndx = BIT(pnum);
+		pr_debug("ndx=%x pnum=%d\n", pipe->ndx, pipe->num);
 
-			pr_debug("ndx=%x pnum=%d\n", pipe->ndx, pipe->num);
-		} else {
-			atomic_set(&pipe->ref_cnt, 0);
-			pipe = NULL;
-		}
+		return pipe;
 	}
-	return pipe;
+
+	return NULL;
 }
 
 struct mdss_mdp_pipe *mdss_mdp_pipe_alloc_pnum(u32 pnum)
@@ -210,7 +208,7 @@
 	return pipe;
 }
 
-struct mdss_mdp_pipe *mdss_mdp_pipe_alloc_locked(u32 type)
+struct mdss_mdp_pipe *mdss_mdp_pipe_alloc(u32 type)
 {
 	struct mdss_mdp_pipe *pipe = NULL;
 	int pnum;
@@ -228,57 +226,60 @@
 	return pipe;
 }
 
-struct mdss_mdp_pipe *mdss_mdp_pipe_get_locked(u32 ndx)
+struct mdss_mdp_pipe *mdss_mdp_pipe_get(u32 ndx)
 {
 	struct mdss_mdp_pipe *pipe = NULL;
 	int i;
 
 	if (!ndx)
-		return NULL;
+		return ERR_PTR(-EINVAL);
 
 	mutex_lock(&mdss_mdp_sspp_lock);
 	for (i = 0; i < MDSS_MDP_MAX_SSPP; i++) {
 		pipe = &mdss_mdp_pipe_list[i];
-		if (ndx == pipe->ndx)
+		if (ndx == pipe->ndx) {
+			if (mdss_mdp_pipe_map(pipe))
+				pipe = ERR_PTR(-EACCES);
 			break;
+		}
 	}
 	mutex_unlock(&mdss_mdp_sspp_lock);
 
 	if (i == MDSS_MDP_MAX_SSPP)
-		return NULL;
-
-	if (mdss_mdp_pipe_lock(pipe))
-		return NULL;
-
-	if (pipe->ndx != ndx) {
-		mdss_mdp_pipe_unlock(pipe);
-		pipe = NULL;
-	}
+		return ERR_PTR(-ENODEV);
 
 	return pipe;
 }
 
-
-static void mdss_mdp_pipe_free(struct mdss_mdp_pipe *pipe)
-{
-	mdss_mdp_smp_free(pipe);
-	pipe->ndx = 0;
-	atomic_dec(&pipe->ref_cnt);
-	mdss_mdp_pipe_unlock(pipe);
-}
-
-int mdss_mdp_pipe_destroy(struct mdss_mdp_pipe *pipe)
+static int mdss_mdp_pipe_free(struct mdss_mdp_pipe *pipe)
 {
 	pr_debug("ndx=%x pnum=%d ref_cnt=%d\n", pipe->ndx, pipe->num,
 			atomic_read(&pipe->ref_cnt));
 
 	mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_ON, false);
-	mdss_mdp_pipe_free(pipe);
+	mdss_mdp_smp_free(pipe);
 	mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_OFF, false);
 
 	return 0;
 }
 
+int mdss_mdp_pipe_destroy(struct mdss_mdp_pipe *pipe)
+{
+	int tmp;
+
+	tmp = atomic_dec_return(&pipe->ref_cnt);
+
+	if (tmp != 0) {
+		pr_err("unable to free pipe %d while still in use (%d)\n",
+				pipe->num, tmp);
+		return -EBUSY;
+	}
+	mdss_mdp_pipe_free(pipe);
+
+	return 0;
+
+}
+
 static inline void mdss_mdp_pipe_write(struct mdss_mdp_pipe *pipe,
 				       u32 reg, u32 val)
 {
diff --git a/drivers/video/msm/mdss/mdss_mdp_rotator.c b/drivers/video/msm/mdss/mdss_mdp_rotator.c
index 1e58269..a151b38 100644
--- a/drivers/video/msm/mdss/mdss_mdp_rotator.c
+++ b/drivers/video/msm/mdss/mdss_mdp_rotator.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -89,7 +89,7 @@
 
 	pipe = mdss_mdp_pipe_alloc_pnum(pnum);
 
-	if (pipe)
+	if (!IS_ERR_OR_NULL(pipe))
 		pipe->mixer = mixer;
 done:
 	if (!pipe)
diff --git a/drivers/video/msm/mdss/mhl_msc.c b/drivers/video/msm/mdss/mhl_msc.c
new file mode 100644
index 0000000..94f6d2b
--- /dev/null
+++ b/drivers/video/msm/mdss/mhl_msc.c
@@ -0,0 +1,489 @@
+/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/types.h>
+#include <linux/mhl_8334.h>
+#include <linux/vmalloc.h>
+#include <linux/input.h>
+#include "mhl_msc.h"
+
+static struct mhl_tx_ctrl *mhl_ctrl;
+static DEFINE_MUTEX(msc_send_workqueue_mutex);
+
+const char *devcap_reg_name[] = {
+	"DEV_STATE       ",
+	"MHL_VERSION     ",
+	"DEV_CAT         ",
+	"ADOPTER_ID_H    ",
+	"ADOPTER_ID_L    ",
+	"VID_LINK_MODE   ",
+	"AUD_LINK_MODE   ",
+	"VIDEO_TYPE      ",
+	"LOG_DEV_MAP     ",
+	"BANDWIDTH       ",
+	"FEATURE_FLAG    ",
+	"DEVICE_ID_H     ",
+	"DEVICE_ID_L     ",
+	"SCRATCHPAD_SIZE ",
+	"INT_STAT_SIZE   ",
+	"Reserved        ",
+};
+
+static void mhl_print_devcap(u8 offset, u8 devcap)
+{
+	switch (offset) {
+	case DEVCAP_OFFSET_DEV_CAT:
+		pr_debug("DCAP: %02X %s: %02X DEV_TYPE=%X POW=%s\n",
+			offset, devcap_reg_name[offset], devcap,
+			devcap & 0x0F, (devcap & 0x10) ? "y" : "n");
+		break;
+	case DEVCAP_OFFSET_FEATURE_FLAG:
+		pr_debug("DCAP: %02X %s: %02X RCP=%s RAP=%s SP=%s\n",
+			offset, devcap_reg_name[offset], devcap,
+			(devcap & 0x01) ? "y" : "n",
+			(devcap & 0x02) ? "y" : "n",
+			(devcap & 0x04) ? "y" : "n");
+		break;
+	default:
+		pr_debug("DCAP: %02X %s: %02X\n",
+			offset, devcap_reg_name[offset], devcap);
+		break;
+	}
+}
+
+void mhl_register_msc(struct mhl_tx_ctrl *ctrl)
+{
+	if (ctrl)
+		mhl_ctrl = ctrl;
+}
+
+void mhl_msc_send_work(struct work_struct *work)
+{
+	struct mhl_tx_ctrl *mhl_ctrl =
+		container_of(work, struct mhl_tx_ctrl, mhl_msc_send_work);
+	struct msc_cmd_envelope *cmd_env;
+	int ret;
+	/*
+	 * Remove item from the queue
+	 * and schedule it
+	 */
+	mutex_lock(&msc_send_workqueue_mutex);
+	while (!list_empty(&mhl_ctrl->list_cmd)) {
+		cmd_env = list_first_entry(&mhl_ctrl->list_cmd,
+					   struct msc_cmd_envelope,
+					   msc_queue_envelope);
+		list_del(&cmd_env->msc_queue_envelope);
+		mutex_unlock(&msc_send_workqueue_mutex);
+
+		ret = mhl_send_msc_command(mhl_ctrl, &cmd_env->msc_cmd_msg);
+		if (ret == -EAGAIN) {
+			int retry = 2;
+			while (retry--) {
+				ret = mhl_send_msc_command(
+					mhl_ctrl,
+					&cmd_env->msc_cmd_msg);
+				if (ret != -EAGAIN)
+					break;
+			}
+		}
+		if (ret == -EAGAIN)
+			pr_err("%s: send_msc_command retry out!\n", __func__);
+
+		vfree(cmd_env);
+		mutex_lock(&msc_send_workqueue_mutex);
+	}
+	mutex_unlock(&msc_send_workqueue_mutex);
+}
+
+int mhl_queue_msc_command(struct mhl_tx_ctrl *mhl_ctrl,
+			  struct msc_command_struct *req,
+			  int priority_send)
+{
+	struct msc_cmd_envelope *cmd_env;
+
+	mutex_lock(&msc_send_workqueue_mutex);
+	cmd_env = vmalloc(sizeof(struct msc_cmd_envelope));
+	if (!cmd_env) {
+		pr_err("%s: out of memory!\n", __func__);
+		return -ENOMEM;
+	}
+
+	memcpy(&cmd_env->msc_cmd_msg, req,
+	       sizeof(struct msc_command_struct));
+
+	if (priority_send)
+		list_add(&cmd_env->msc_queue_envelope,
+			 &mhl_ctrl->list_cmd);
+	else
+		list_add_tail(&cmd_env->msc_queue_envelope,
+			      &mhl_ctrl->list_cmd);
+	mutex_unlock(&msc_send_workqueue_mutex);
+	queue_work(mhl_ctrl->msc_send_workqueue, &mhl_ctrl->mhl_msc_send_work);
+
+	return 0;
+}
+
+static int mhl_update_devcap(struct mhl_tx_ctrl *mhl_ctrl,
+	int offset, u8 devcap)
+{
+	if (!mhl_ctrl)
+		return -EFAULT;
+	if (offset < 0 || offset > 15)
+		return -EFAULT;
+	mhl_ctrl->devcap[offset] = devcap;
+	mhl_print_devcap(offset, mhl_ctrl->devcap[offset]);
+
+	return 0;
+}
+
+
+int mhl_msc_command_done(struct mhl_tx_ctrl *mhl_ctrl,
+			 struct msc_command_struct *req)
+{
+	switch (req->command) {
+	case MHL_WRITE_STAT:
+		if (req->offset == MHL_STATUS_REG_LINK_MODE) {
+			if (req->payload.data[0]
+			    & MHL_STATUS_PATH_ENABLED)
+				/* Enable TMDS output */
+				mhl_tmds_ctrl(mhl_ctrl, TMDS_ENABLE);
+			else
+				/* Disable TMDS output */
+				mhl_tmds_ctrl(mhl_ctrl, TMDS_DISABLE);
+		}
+		break;
+	case MHL_READ_DEVCAP:
+		mhl_update_devcap(mhl_ctrl,
+			req->offset, req->retval);
+		mhl_ctrl->devcap_state |= BIT(req->offset);
+		switch (req->offset) {
+		case MHL_DEV_CATEGORY_OFFSET:
+			if (req->retval & MHL_DEV_CATEGORY_POW_BIT)
+				pr_debug("%s: devcap pow bit set\n",
+					 __func__);
+			else
+				pr_debug("%s: devcap pow bit unset\n",
+					 __func__);
+			break;
+		case DEVCAP_OFFSET_MHL_VERSION:
+		case DEVCAP_OFFSET_INT_STAT_SIZE:
+			break;
+		}
+
+		break;
+	}
+	return 0;
+}
+
+int mhl_msc_send_set_int(struct mhl_tx_ctrl *mhl_ctrl,
+			 u8 offset, u8 mask)
+{
+	struct msc_command_struct req;
+	req.command = MHL_SET_INT;
+	req.offset = offset;
+	req.payload.data[0] = mask;
+	return mhl_queue_msc_command(mhl_ctrl, &req, MSC_NORMAL_SEND);
+}
+
+int mhl_msc_send_write_stat(struct mhl_tx_ctrl *mhl_ctrl,
+			    u8 offset, u8 value)
+{
+	struct msc_command_struct req;
+	req.command = MHL_WRITE_STAT;
+	req.offset = offset;
+	req.payload.data[0] = value;
+	return mhl_queue_msc_command(mhl_ctrl, &req, MSC_NORMAL_SEND);
+}
+
+int mhl_msc_send_msc_msg(struct mhl_tx_ctrl *mhl_ctrl,
+			 u8 sub_cmd, u8 cmd_data)
+{
+	struct msc_command_struct req;
+	req.command = MHL_MSC_MSG;
+	req.payload.data[0] = sub_cmd;
+	req.payload.data[1] = cmd_data;
+	return mhl_queue_msc_command(mhl_ctrl, &req, MSC_NORMAL_SEND);
+}
+
+/*
+ * Certain MSC msgs such as RCPK, RCPE and RAPK
+ * should be transmitted as a high priority
+ * because these msgs should be sent within
+ * 1000ms of a receipt of RCP/RAP. So such msgs can
+ * be added to the head of msc cmd queue.
+ */
+static int mhl_msc_send_prior_msc_msg(struct mhl_tx_ctrl *mhl_ctrl,
+				      u8 sub_cmd, u8 cmd_data)
+{
+	struct msc_command_struct req;
+	req.command = MHL_MSC_MSG;
+	req.payload.data[0] = sub_cmd;
+	req.payload.data[1] = cmd_data;
+	return mhl_queue_msc_command(mhl_ctrl, &req, MSC_PRIORITY_SEND);
+}
+
+
+int mhl_msc_read_devcap(struct mhl_tx_ctrl *mhl_ctrl, u8 offset)
+{
+	struct msc_command_struct req;
+	if (offset < 0 || offset > 15)
+		return -EFAULT;
+	req.command = MHL_READ_DEVCAP;
+	req.offset = offset;
+	req.payload.data[0] = 0;
+	return mhl_queue_msc_command(mhl_ctrl, &req, MSC_NORMAL_SEND);
+}
+
+int mhl_msc_read_devcap_all(struct mhl_tx_ctrl *mhl_ctrl)
+{
+	int offset;
+	int ret;
+
+	for (offset = 0; offset < DEVCAP_SIZE; offset++) {
+		ret = mhl_msc_read_devcap(mhl_ctrl, offset);
+		if (ret == -EBUSY)
+			pr_err("%s: queue busy!\n", __func__);
+	}
+	return ret;
+}
+
+
+static void mhl_handle_input(struct mhl_tx_ctrl *mhl_ctrl,
+			     u8 key_code, u16 input_key_code)
+{
+	int key_press = (key_code & 0x80) == 0;
+
+	pr_debug("%s: send key events[%x][%d]\n",
+		 __func__, key_code, key_press);
+	input_report_key(mhl_ctrl->input, input_key_code, key_press);
+	input_sync(mhl_ctrl->input);
+}
+
+
+
+int mhl_rcp_recv(struct mhl_tx_ctrl *mhl_ctrl, u8 key_code)
+{
+	u8 index = key_code & 0x7f;
+	u16 input_key_code;
+
+	if (!mhl_ctrl->rcp_key_code_tbl) {
+		pr_err("%s: RCP Key Code Table not initialized\n", __func__);
+		return -EINVAL;
+	}
+
+	input_key_code = mhl_ctrl->rcp_key_code_tbl[index];
+
+	if ((index < mhl_ctrl->rcp_key_code_tbl_len) &&
+	    (input_key_code > 0)) {
+		/* prior send rcpk */
+		mhl_msc_send_prior_msc_msg(
+			mhl_ctrl,
+			MHL_MSC_MSG_RCPK,
+			key_code);
+
+		if (mhl_ctrl->input)
+			mhl_handle_input(mhl_ctrl, key_code, input_key_code);
+	} else {
+		/* prior send rcpe */
+		mhl_msc_send_prior_msc_msg(
+			mhl_ctrl,
+			MHL_MSC_MSG_RCPE,
+			MHL_RCPE_INEFFECTIVE_KEY_CODE);
+
+		/* send rcpk after rcpe send */
+		mhl_msc_send_prior_msc_msg(
+			mhl_ctrl,
+			MHL_MSC_MSG_RCPK,
+			key_code);
+	}
+	return 0;
+}
+
+
+static int mhl_rap_action(struct mhl_tx_ctrl *mhl_ctrl, u8 action_code)
+{
+	switch (action_code) {
+	case MHL_RAP_CONTENT_ON:
+		mhl_tmds_ctrl(mhl_ctrl, TMDS_ENABLE);
+		break;
+	case MHL_RAP_CONTENT_OFF:
+		mhl_tmds_ctrl(mhl_ctrl, TMDS_DISABLE);
+		break;
+	default:
+		break;
+	}
+	return 0;
+}
+
+static int mhl_rap_recv(struct mhl_tx_ctrl *mhl_ctrl, u8 action_code)
+{
+	u8 error_code;
+
+	switch (action_code) {
+	case MHL_RAP_POLL:
+		if (mhl_ctrl->tmds_enabled())
+			error_code = MHL_RAPK_NO_ERROR;
+		else
+			error_code = MHL_RAPK_UNSUPPORTED_ACTION_CODE;
+		break;
+	case MHL_RAP_CONTENT_ON:
+	case MHL_RAP_CONTENT_OFF:
+		mhl_rap_action(mhl_ctrl, action_code);
+		error_code = MHL_RAPK_NO_ERROR;
+		break;
+	default:
+		error_code = MHL_RAPK_UNRECOGNIZED_ACTION_CODE;
+		break;
+	}
+	/* prior send rapk */
+	return mhl_msc_send_prior_msc_msg(
+		mhl_ctrl,
+		MHL_MSC_MSG_RAPK,
+		error_code);
+}
+
+
+int mhl_msc_recv_msc_msg(struct mhl_tx_ctrl *mhl_ctrl,
+			 u8 sub_cmd, u8 cmd_data)
+{
+	int rc = 0;
+	switch (sub_cmd) {
+	case MHL_MSC_MSG_RCP:
+		pr_debug("MHL: receive RCP(0x%02x)\n", cmd_data);
+		rc = mhl_rcp_recv(mhl_ctrl, cmd_data);
+		break;
+	case MHL_MSC_MSG_RCPK:
+		pr_debug("MHL: receive RCPK(0x%02x)\n", cmd_data);
+		break;
+	case MHL_MSC_MSG_RCPE:
+		pr_debug("MHL: receive RCPE(0x%02x)\n", cmd_data);
+		break;
+	case MHL_MSC_MSG_RAP:
+		pr_debug("MHL: receive RAP(0x%02x)\n", cmd_data);
+		rc = mhl_rap_recv(mhl_ctrl, cmd_data);
+		break;
+	case MHL_MSC_MSG_RAPK:
+		pr_debug("MHL: receive RAPK(0x%02x)\n", cmd_data);
+		break;
+	default:
+		break;
+	}
+	return rc;
+}
+
+int mhl_msc_recv_set_int(struct mhl_tx_ctrl *mhl_ctrl,
+			 u8 offset, u8 set_int)
+{
+	if (offset >= 2)
+		return -EFAULT;
+
+	switch (offset) {
+	case 0:
+		if (set_int & MHL_INT_DCAP_CHG) {
+			/* peer dcap has changed */
+			mhl_ctrl->devcap_state = 0;
+			mhl_msc_read_devcap_all(mhl_ctrl);
+		}
+		if (set_int & MHL_INT_DSCR_CHG)
+			pr_debug("%s: dscr chg\n", __func__);
+		if (set_int & MHL_INT_REQ_WRT) {
+			/* SET_INT: GRT_WRT */
+			mhl_msc_send_set_int(
+				mhl_ctrl,
+				MHL_RCHANGE_INT,
+				MHL_INT_GRT_WRT);
+		}
+		if (set_int & MHL_INT_GRT_WRT)
+			pr_debug("%s: recvd req to permit/grant write",
+				 __func__);
+		break;
+	case 1:
+		if (set_int & MHL_INT_EDID_CHG) {
+			/* peer EDID has changed
+			 * toggle HPD to read EDID
+			 */
+			pr_debug("%s: EDID CHG\n", __func__);
+			mhl_drive_hpd(mhl_ctrl, HPD_DOWN);
+			msleep(110);
+			mhl_drive_hpd(mhl_ctrl, HPD_UP);
+		}
+	}
+	return 0;
+}
+
+int mhl_msc_recv_write_stat(struct mhl_tx_ctrl *mhl_ctrl,
+			    u8 offset, u8 value)
+{
+	if (offset >= 2)
+		return -EFAULT;
+
+	switch (offset) {
+	case 0:
+		/*
+		 * connected device bits
+		 * changed and DEVCAP READY
+		 */
+		if (((value ^ mhl_ctrl->devcap_state) &
+		     MHL_STATUS_DCAP_RDY)) {
+			if (value & MHL_STATUS_DCAP_RDY) {
+				mhl_ctrl->devcap_state = 0;
+				mhl_msc_read_devcap_all(mhl_ctrl);
+			} else {
+				/*
+				 * peer dcap turned not ready
+				 * use old devap state
+				 */
+				pr_debug("%s: DCAP RDY bit cleared\n",
+					 __func__);
+			}
+		}
+		break;
+	case 1:
+		/*
+		 * connected device bits
+		 * changed and PATH ENABLED
+		 * bit set
+		 */
+		if ((value ^ mhl_ctrl->path_en_state)
+		    & MHL_STATUS_PATH_ENABLED) {
+			if (value & MHL_STATUS_PATH_ENABLED) {
+				if (mhl_ctrl->tmds_enabled() &&
+				    (mhl_ctrl->devcap[offset] &
+				     MHL_FEATURE_RAP_SUPPORT)) {
+					mhl_msc_send_msc_msg(
+						mhl_ctrl,
+						MHL_MSC_MSG_RAP,
+						MHL_RAP_CONTENT_ON);
+				}
+				mhl_ctrl->path_en_state
+					|= (MHL_STATUS_PATH_ENABLED |
+					    MHL_STATUS_CLK_MODE_NORMAL);
+				mhl_msc_send_write_stat(
+					mhl_ctrl,
+					MHL_STATUS_REG_LINK_MODE,
+					mhl_ctrl->path_en_state);
+			} else {
+				mhl_ctrl->path_en_state
+					&= ~(MHL_STATUS_PATH_ENABLED |
+					     MHL_STATUS_CLK_MODE_NORMAL);
+				mhl_msc_send_write_stat(
+					mhl_ctrl,
+					MHL_STATUS_REG_LINK_MODE,
+					mhl_ctrl->path_en_state);
+			}
+		}
+		break;
+	}
+	mhl_ctrl->path_en_state = value;
+	return 0;
+}
diff --git a/drivers/video/msm/mdss/mhl_msc.h b/drivers/video/msm/mdss/mhl_msc.h
new file mode 100644
index 0000000..9a7b3d6
--- /dev/null
+++ b/drivers/video/msm/mdss/mhl_msc.h
@@ -0,0 +1,57 @@
+/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#ifndef __MHL_MSC_H__
+#define __MHL_MSC_H__
+#include <linux/mhl_8334.h>
+
+#define MAX_RCP_KEYS_SUPPORTED 256
+
+#define MSC_NORMAL_SEND 0
+#define MSC_PRIORITY_SEND 1
+
+#define TMDS_ENABLE 1
+#define TMDS_DISABLE 0
+
+/******************************************************************/
+/* the below APIs are implemented by the MSC functionality */
+int mhl_msc_command_done(struct mhl_tx_ctrl *mhl_ctrl,
+			 struct msc_command_struct *req);
+
+int mhl_msc_send_set_int(struct mhl_tx_ctrl *mhl_ctrl,
+			 u8 offset, u8 mask);
+
+int mhl_msc_send_write_stat(struct mhl_tx_ctrl *mhl_ctrl,
+			    u8 offset, u8 value);
+int mhl_msc_send_msc_msg(struct mhl_tx_ctrl *mhl_ctrl,
+			 u8 sub_cmd, u8 cmd_data);
+
+int mhl_msc_recv_set_int(struct mhl_tx_ctrl *mhl_ctrl, u8 offset, u8 set_int);
+
+int mhl_msc_recv_write_stat(struct mhl_tx_ctrl *mhl_ctrl,
+			    u8 offset, u8 value);
+int mhl_msc_recv_msc_msg(struct mhl_tx_ctrl *mhl_ctrl,
+			 u8 sub_cmd, u8 cmd_data);
+void mhl_msc_send_work(struct work_struct *work);
+
+/******************************************************************/
+/* Tx should implement these APIs */
+int mhl_send_msc_command(struct mhl_tx_ctrl *mhl_ctrl,
+			 struct msc_command_struct *req);
+void mhl_drive_hpd(struct mhl_tx_ctrl *mhl_ctrl, uint8_t to_state);
+void mhl_tmds_ctrl(struct mhl_tx_ctrl *ctrl, uint8_t on);
+/******************************************************************/
+/* MHL driver registers ctrl with MSC */
+void mhl_register_msc(struct mhl_tx_ctrl *ctrl);
+
+#endif /* __MHL_MSC_H__ */
diff --git a/drivers/video/msm/mdss/mhl_sii8334.c b/drivers/video/msm/mdss/mhl_sii8334.c
index 0227e70..7baeef5 100644
--- a/drivers/video/msm/mdss/mhl_sii8334.c
+++ b/drivers/video/msm/mdss/mhl_sii8334.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -18,6 +18,8 @@
 #include <linux/of_address.h>
 #include <linux/of_gpio.h>
 #include <linux/types.h>
+#include <linux/vmalloc.h>
+#include <linux/input.h>
 #include <linux/usb/msm_hsusb.h>
 #include <linux/mhl_8334.h>
 
@@ -27,42 +29,150 @@
 #include "mdss.h"
 #include "mdss_panel.h"
 #include "mdss_io_util.h"
+#include "mhl_msc.h"
 
 #define MHL_DRIVER_NAME "sii8334"
 #define COMPATIBLE_NAME "qcom,mhl-sii8334"
+#define MAX_CURRENT 700000
 
 #define pr_debug_intr(...) pr_debug("\n")
 
-enum mhl_gpio_type {
-	MHL_TX_RESET_GPIO,
-	MHL_TX_INTR_GPIO,
-	MHL_TX_PMIC_PWR_GPIO,
-	MHL_TX_MAX_GPIO,
-};
+#define MSC_START_BIT_MSC_CMD        (0x01 << 0)
+#define MSC_START_BIT_VS_CMD        (0x01 << 1)
+#define MSC_START_BIT_READ_REG        (0x01 << 2)
+#define MSC_START_BIT_WRITE_REG        (0x01 << 3)
+#define MSC_START_BIT_WRITE_BURST        (0x01 << 4)
 
-enum mhl_vreg_type {
-	MHL_TX_3V_VREG,
-	MHL_TX_MAX_VREG,
-};
-
-struct mhl_tx_platform_data {
-	/* Data filled from device tree nodes */
-	struct dss_gpio *gpios[MHL_TX_MAX_GPIO];
-	struct dss_vreg *vregs[MHL_TX_MAX_VREG];
-	int irq;
-};
-
-struct mhl_tx_ctrl {
-	struct platform_device *pdev;
-	struct mhl_tx_platform_data *pdata;
-	struct i2c_client *i2c_handle;
-	uint8_t cur_state;
-	uint8_t chip_rev_id;
-	int mhl_mode;
-	struct completion rgnd_done;
-	void (*notify_usb_online)(int online);
-	struct usb_ext_notification *mhl_info;
-	bool disc_enabled;
+/* supported RCP key code */
+u16 support_rcp_key_code_tbl[] = {
+	KEY_ENTER,		/* 0x00 Select */
+	KEY_UP,			/* 0x01 Up */
+	KEY_DOWN,		/* 0x02 Down */
+	KEY_LEFT,		/* 0x03 Left */
+	KEY_RIGHT,		/* 0x04 Right */
+	KEY_UNKNOWN,		/* 0x05 Right-up */
+	KEY_UNKNOWN,		/* 0x06 Right-down */
+	KEY_UNKNOWN,		/* 0x07 Left-up */
+	KEY_UNKNOWN,		/* 0x08 Left-down */
+	KEY_MENU,		/* 0x09 Root Menu */
+	KEY_OPTION,		/* 0x0A Setup Menu */
+	KEY_UNKNOWN,		/* 0x0B Contents Menu */
+	KEY_UNKNOWN,		/* 0x0C Favorite Menu */
+	KEY_EXIT,		/* 0x0D Exit */
+	KEY_RESERVED,		/* 0x0E */
+	KEY_RESERVED,
+	KEY_RESERVED,
+	KEY_RESERVED,
+	KEY_RESERVED,
+	KEY_RESERVED,
+	KEY_RESERVED,
+	KEY_RESERVED,
+	KEY_RESERVED,
+	KEY_RESERVED,
+	KEY_RESERVED,
+	KEY_RESERVED,
+	KEY_RESERVED,
+	KEY_RESERVED,
+	KEY_RESERVED,
+	KEY_RESERVED,
+	KEY_RESERVED,
+	KEY_RESERVED,		/* 0x1F */
+	KEY_NUMERIC_0,		/* 0x20 NUMERIC_0 */
+	KEY_NUMERIC_1,		/* 0x21 NUMERIC_1 */
+	KEY_NUMERIC_2,		/* 0x22 NUMERIC_2 */
+	KEY_NUMERIC_3,		/* 0x23 NUMERIC_3 */
+	KEY_NUMERIC_4,		/* 0x24 NUMERIC_4 */
+	KEY_NUMERIC_5,		/* 0x25 NUMERIC_5 */
+	KEY_NUMERIC_6,		/* 0x26 NUMERIC_6 */
+	KEY_NUMERIC_7,		/* 0x27 NUMERIC_7 */
+	KEY_NUMERIC_8,		/* 0x28 NUMERIC_8 */
+	KEY_NUMERIC_9,		/* 0x29 NUMERIC_9 */
+	KEY_DOT,		/* 0x2A Dot */
+	KEY_ENTER,		/* 0x2B Enter */
+	KEY_ESC,		/* 0x2C Clear */
+	KEY_RESERVED,		/* 0x2D */
+	KEY_RESERVED,		/* 0x2E */
+	KEY_RESERVED,		/* 0x2F */
+	KEY_UNKNOWN,		/* 0x30 Channel Up */
+	KEY_UNKNOWN,		/* 0x31 Channel Down */
+	KEY_UNKNOWN,		/* 0x32 Previous Channel */
+	KEY_UNKNOWN,		/* 0x33 Sound Select */
+	KEY_UNKNOWN,		/* 0x34 Input Select */
+	KEY_UNKNOWN,		/* 0x35 Show Information */
+	KEY_UNKNOWN,		/* 0x36 Help */
+	KEY_UNKNOWN,		/* 0x37 Page Up */
+	KEY_UNKNOWN,		/* 0x38 Page Down */
+	KEY_RESERVED,		/* 0x39 */
+	KEY_RESERVED,
+	KEY_RESERVED,
+	KEY_RESERVED,
+	KEY_RESERVED,
+	KEY_RESERVED,
+	KEY_RESERVED,		/* 0x3F */
+	KEY_RESERVED,		/* 0x40 */
+	KEY_VOLUMEUP,		/* 0x41 Volume Up */
+	KEY_VOLUMEDOWN,		/* 0x42 Volume Down */
+	KEY_MUTE,		/* 0x43 Mute */
+	KEY_PLAY,		/* 0x44 Play */
+	KEY_STOP,		/* 0x45 Stop */
+	KEY_PAUSE,		/* 0x46 Pause */
+	KEY_UNKNOWN,		/* 0x47 Record */
+	KEY_REWIND,		/* 0x48 Rewind */
+	KEY_FASTFORWARD,	/* 0x49 Fast Forward */
+	KEY_UNKNOWN,		/* 0x4A Eject */
+	KEY_FORWARD,		/* 0x4B Forward */
+	KEY_BACK,		/* 0x4C Backward */
+	KEY_RESERVED,		/* 0x4D */
+	KEY_RESERVED,
+	KEY_RESERVED,		/* 0x4F */
+	KEY_UNKNOWN,		/* 0x50 Angle */
+	KEY_UNKNOWN,		/* 0x51 Subtitle */
+	KEY_RESERVED,		/* 0x52 */
+	KEY_RESERVED,
+	KEY_RESERVED,
+	KEY_RESERVED,
+	KEY_RESERVED,
+	KEY_RESERVED,
+	KEY_RESERVED,
+	KEY_RESERVED,
+	KEY_RESERVED,
+	KEY_RESERVED,
+	KEY_RESERVED,
+	KEY_RESERVED,
+	KEY_RESERVED,
+	KEY_RESERVED,		/* 0x5F */
+	KEY_PLAYPAUSE,		/* 0x60 Play Function */
+	KEY_PLAYPAUSE,		/* 0x61 Pause_Play Function */
+	KEY_UNKNOWN,		/* 0x62 Record Function */
+	KEY_PAUSE,		/* 0x63 Pause Record Function */
+	KEY_STOP,		/* 0x64 Stop Function  */
+	KEY_MUTE,		/* 0x65 Mute Function */
+	KEY_UNKNOWN,		/* 0x66 Restore Volume Function */
+	KEY_UNKNOWN,		/* 0x67 Tune Function */
+	KEY_UNKNOWN,		/* 0x68 Select Media Function */
+	KEY_RESERVED,		/* 0x69 */
+	KEY_RESERVED,
+	KEY_RESERVED,
+	KEY_RESERVED,
+	KEY_RESERVED,
+	KEY_RESERVED,
+	KEY_RESERVED,
+	KEY_RESERVED,		/* 0x70 */
+	KEY_BLUE,			/* 0x71 F1 */
+	KEY_RED,			/* 0x72 F2 */
+	KEY_GREEN,			/* 0x73 F3 */
+	KEY_YELLOW,			/* 0x74 F4 */
+	KEY_UNKNOWN,		/* 0x75 F5 */
+	KEY_RESERVED,		/* 0x76 */
+	KEY_RESERVED,
+	KEY_RESERVED,
+	KEY_RESERVED,
+	KEY_RESERVED,
+	KEY_RESERVED,
+	KEY_RESERVED,
+	KEY_RESERVED,		/* 0x7D */
+	KEY_VENDOR,		/* Vendor Specific */
+	KEY_RESERVED,		/* 0x7F */
 };
 
 
@@ -80,13 +190,12 @@
 static irqreturn_t mhl_tx_isr(int irq, void *dev_id);
 static void switch_mode(struct mhl_tx_ctrl *mhl_ctrl,
 			enum mhl_st_type to_mode);
-static void mhl_drive_hpd(struct mhl_tx_ctrl *mhl_ctrl,
-			  uint8_t to_state);
-
 static void mhl_init_reg_settings(struct mhl_tx_ctrl *mhl_ctrl,
-	bool mhl_disc_en);
+				  bool mhl_disc_en);
 
-static int mhl_i2c_reg_read(struct i2c_client *client,
+static uint8_t store_tmds_state;
+
+int mhl_i2c_reg_read(struct i2c_client *client,
 			    uint8_t slave_addr_index, uint8_t reg_offset)
 {
 	int rc = -1;
@@ -103,7 +212,7 @@
 }
 
 
-static int mhl_i2c_reg_write(struct i2c_client *client,
+int mhl_i2c_reg_write(struct i2c_client *client,
 			     uint8_t slave_addr_index, uint8_t reg_offset,
 			     uint8_t value)
 {
@@ -111,7 +220,7 @@
 				 reg_offset, &value);
 }
 
-static void mhl_i2c_reg_modify(struct i2c_client *client,
+void mhl_i2c_reg_modify(struct i2c_client *client,
 			       uint8_t slave_addr_index, uint8_t reg_offset,
 			       uint8_t mask, uint8_t val)
 {
@@ -267,6 +376,65 @@
 	return rc;
 }
 
+static int mhl_power_get_property(struct power_supply *psy,
+				  enum power_supply_property psp,
+				  union power_supply_propval *val)
+{
+	struct mhl_tx_ctrl *mhl_ctrl =
+		container_of(psy, struct mhl_tx_ctrl, mhl_psy);
+
+	switch (psp) {
+	case POWER_SUPPLY_PROP_CURRENT_MAX:
+		val->intval = mhl_ctrl->current_val;
+		break;
+	case POWER_SUPPLY_PROP_PRESENT:
+		val->intval = mhl_ctrl->vbus_active;
+		break;
+	case POWER_SUPPLY_PROP_ONLINE:
+		val->intval = mhl_ctrl->vbus_active && mhl_ctrl->mhl_mode;
+		break;
+	default:
+		return -EINVAL;
+	}
+	return 0;
+}
+
+static int mhl_power_set_property(struct power_supply *psy,
+				  enum power_supply_property psp,
+				  const union power_supply_propval *val)
+{
+	struct mhl_tx_ctrl *mhl_ctrl =
+		container_of(psy, struct mhl_tx_ctrl, mhl_psy);
+
+	switch (psp) {
+	case POWER_SUPPLY_PROP_PRESENT:
+		mhl_ctrl->vbus_active = val->intval;
+		if (mhl_ctrl->vbus_active)
+			mhl_ctrl->current_val = MAX_CURRENT;
+		else
+			mhl_ctrl->current_val = 0;
+		power_supply_changed(psy);
+		break;
+	case POWER_SUPPLY_PROP_ONLINE:
+	case POWER_SUPPLY_PROP_CURRENT_MAX:
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static char *mhl_pm_power_supplied_to[] = {
+	"usb",
+};
+
+static enum power_supply_property mhl_pm_power_props[] = {
+	POWER_SUPPLY_PROP_PRESENT,
+	POWER_SUPPLY_PROP_ONLINE,
+	POWER_SUPPLY_PROP_CURRENT_MAX,
+};
+
 static void cbus_reset(struct i2c_client *client)
 {
 	uint8_t i;
@@ -287,11 +455,11 @@
 	MHL_SII_REG_NAME_WR(REG_INTR5_MASK, 0x00);
 
 	/* Unmask CBUS1 Intrs */
-	MHL_SII_CBUS_WR(0x0009,
+	MHL_SII_REG_NAME_WR(REG_CBUS_INTR_ENABLE,
 		BIT2 | BIT3 | BIT4 | BIT5 | BIT6);
 
 	/* Unmask CBUS2 Intrs */
-	MHL_SII_CBUS_WR(0x001F, BIT2 | BIT3);
+	MHL_SII_REG_NAME_WR(REG_CBUS_MSC_INT2_ENABLE, BIT2 | BIT3);
 
 	for (i = 0; i < 4; i++) {
 		/*
@@ -306,7 +474,6 @@
 		 */
 		MHL_SII_CBUS_WR((0xF0 + i), 0xFF);
 	}
-	return;
 }
 
 static void init_cbus_regs(struct i2c_client *client)
@@ -513,6 +680,7 @@
 
 		/* Force HPD to 0 when not in MHL mode.  */
 		mhl_drive_hpd(mhl_ctrl, HPD_DOWN);
+		mhl_tmds_ctrl(mhl_ctrl, TMDS_DISABLE);
 		/*
 		 * Change TMDS termination to high impedance
 		 * on disconnection.
@@ -529,7 +697,31 @@
 	}
 }
 
-static void mhl_drive_hpd(struct mhl_tx_ctrl *mhl_ctrl, uint8_t to_state)
+uint8_t check_tmds_enabled(void)
+{
+	return store_tmds_state;
+}
+
+void mhl_tmds_ctrl(struct mhl_tx_ctrl *mhl_ctrl, uint8_t on)
+{
+	struct i2c_client *client = mhl_ctrl->i2c_handle;
+	if (on) {
+		MHL_SII_REG_NAME_MOD(REG_TMDS_CCTRL, BIT4, BIT4);
+		mhl_drive_hpd(mhl_ctrl, HPD_UP);
+		/*
+		 * store the state to be used
+		 * before responding to RAP msgs
+		 * this needs to be obtained from
+		 * hdmi driver
+		 */
+		store_tmds_state = 1;
+	} else {
+		MHL_SII_REG_NAME_MOD(REG_TMDS_CCTRL, BIT4, 0x00);
+		store_tmds_state = 0;
+	}
+}
+
+void mhl_drive_hpd(struct mhl_tx_ctrl *mhl_ctrl, uint8_t to_state)
 {
 	struct i2c_client *client = mhl_ctrl->i2c_handle;
 
@@ -537,15 +729,6 @@
 	if (to_state == HPD_UP) {
 		/*
 		 * Drive HPD to UP state
-		 *
-		 * The below two reg configs combined
-		 * enable TMDS output.
-		 */
-
-		/* Enable TMDS on TMDS_CCTRL */
-		MHL_SII_REG_NAME_MOD(REG_TMDS_CCTRL, BIT4, BIT4);
-
-		/*
 		 * Set HPD_OUT_OVR_EN = HPD State
 		 * EDID read and Un-force HPD (from low)
 		 * propogate to src let HPD float by clearing
@@ -553,15 +736,9 @@
 		 */
 		MHL_SII_REG_NAME_MOD(REG_INT_CTRL, BIT4, 0x00);
 	} else {
-		/*
-		 * Drive HPD to DOWN state
-		 * Disable TMDS Output on REG_TMDS_CCTRL
-		 * Enable/Disable TMDS output (MHL TMDS output only)
-		 */
+		/* Drive HPD to DOWN state */
 		MHL_SII_REG_NAME_MOD(REG_INT_CTRL, BIT4, BIT4);
-		MHL_SII_REG_NAME_MOD(REG_TMDS_CCTRL, BIT4, 0x00);
 	}
-	return;
 }
 
 static void mhl_msm_connection(struct mhl_tx_ctrl *mhl_ctrl)
@@ -592,7 +769,19 @@
 	val = MHL_SII_PAGE3_RD(0x10);
 	MHL_SII_PAGE3_WR(0x10, val | BIT0);
 
-	return;
+	/*
+	 * indicate DCAP_RDY and DCAP_CHG
+	 * to the peer only after
+	 * msm conn has been established
+	 */
+	mhl_msc_send_write_stat(mhl_ctrl,
+				MHL_STATUS_REG_CONNECTED_RDY,
+				MHL_STATUS_DCAP_RDY);
+
+	mhl_msc_send_set_int(mhl_ctrl,
+			     MHL_RCHANGE_INT,
+			     MHL_INT_DCAP_CHG);
+
 }
 
 static void mhl_msm_disconnection(struct mhl_tx_ctrl *mhl_ctrl)
@@ -605,7 +794,6 @@
 	MHL_SII_PAGE3_WR(0x30, 0xD0);
 
 	switch_mode(mhl_ctrl, POWER_STATE_D3);
-	return;
 }
 
 static int  mhl_msm_read_rgnd_int(struct mhl_tx_ctrl *mhl_ctrl)
@@ -613,13 +801,14 @@
 	uint8_t rgnd_imp;
 	struct i2c_client *client = mhl_ctrl->i2c_handle;
 	/* DISC STATUS REG 2 */
-	rgnd_imp = (mhl_i2c_reg_read(client,
-				     TX_PAGE_3, 0x001C) & (BIT1 | BIT0));
+	rgnd_imp = (mhl_i2c_reg_read(client, TX_PAGE_3, 0x001C) &
+		    (BIT1 | BIT0));
 	pr_debug("imp range read=%02X\n", (int)rgnd_imp);
 
 	if (0x02 == rgnd_imp) {
 		pr_debug("%s: mhl sink\n", __func__);
 		mhl_ctrl->mhl_mode = 1;
+		power_supply_changed(&mhl_ctrl->mhl_psy);
 		if (mhl_ctrl->notify_usb_online)
 			mhl_ctrl->notify_usb_online(1);
 	} else {
@@ -718,9 +907,9 @@
 		/* Short RGND */
 		MHL_SII_REG_NAME_MOD(REG_DISC_STAT2, BIT0 | BIT1, 0x00);
 		mhl_msm_disconnection(mhl_ctrl);
+		power_supply_changed(&mhl_ctrl->mhl_psy);
 		if (mhl_ctrl->notify_usb_online)
 			mhl_ctrl->notify_usb_online(0);
-
 	}
 
 	if (status & BIT5) {
@@ -730,6 +919,7 @@
 		reg = MHL_SII_REG_NAME_RD(REG_INTR4);
 		MHL_SII_REG_NAME_WR(REG_INTR4, reg);
 		mhl_msm_disconnection(mhl_ctrl);
+		power_supply_changed(&mhl_ctrl->mhl_psy);
 		if (mhl_ctrl->notify_usb_online)
 			mhl_ctrl->notify_usb_online(0);
 	}
@@ -755,8 +945,6 @@
 		release_usb_switch_open(mhl_ctrl);
 	}
 	MHL_SII_REG_NAME_WR(REG_INTR4, status);
-
-	return;
 }
 
 static void mhl_misc_isr(struct mhl_tx_ctrl *mhl_ctrl)
@@ -796,9 +984,225 @@
 		 */
 		cbus_stat = MHL_SII_CBUS_RD(0x0D);
 		if (BIT6 & cbus_stat)
-			mhl_drive_hpd(mhl_ctrl, HPD_UP);
+			mhl_tmds_ctrl(mhl_ctrl, TMDS_ENABLE);
 	}
-	return;
+}
+
+static void mhl_sii_cbus_process_errors(struct i2c_client *client,
+					u8 int_status)
+{
+	u8 abort_reason = 0;
+
+	if (int_status & BIT2) {
+		abort_reason = MHL_SII_REG_NAME_RD(REG_DDC_ABORT_REASON);
+		pr_debug("%s: CBUS DDC Abort Reason(0x%02x)\n",
+			 __func__, abort_reason);
+	}
+	if (int_status & BIT5) {
+		abort_reason = MHL_SII_REG_NAME_RD(REG_PRI_XFR_ABORT_REASON);
+		pr_debug("%s: CBUS MSC Requestor Abort Reason(0x%02x)\n",
+			 __func__, abort_reason);
+		MHL_SII_REG_NAME_WR(REG_PRI_XFR_ABORT_REASON, 0xFF);
+	}
+	if (int_status & BIT6) {
+		abort_reason = MHL_SII_REG_NAME_RD(
+			REG_CBUS_PRI_FWR_ABORT_REASON);
+		pr_debug("%s: CBUS MSC Responder Abort Reason(0x%02x)\n",
+			 __func__, abort_reason);
+		MHL_SII_REG_NAME_WR(REG_CBUS_PRI_FWR_ABORT_REASON, 0xFF);
+	}
+}
+
+int mhl_send_msc_command(struct mhl_tx_ctrl *mhl_ctrl,
+			 struct msc_command_struct *req)
+{
+	int timeout;
+	u8 start_bit = 0x00;
+	u8 *burst_data;
+	int i;
+	struct i2c_client *client = mhl_ctrl->i2c_handle;
+
+	if (mhl_ctrl->cur_state != POWER_STATE_D0_MHL) {
+		pr_debug("%s: power_state:%02x CBUS(0x0A):%02x\n",
+			 __func__,
+			 mhl_ctrl->cur_state,
+			 MHL_SII_REG_NAME_RD(REG_CBUS_BUS_STATUS));
+		return -EFAULT;
+	}
+
+	if (!req)
+		return -EFAULT;
+
+	pr_debug("%s: command=0x%02x offset=0x%02x %02x %02x",
+		 __func__,
+		 req->command,
+		 req->offset,
+		 req->payload.data[0],
+		 req->payload.data[1]);
+
+	/* REG_CBUS_PRI_ADDR_CMD = REQ CBUS CMD or OFFSET */
+	MHL_SII_REG_NAME_WR(REG_CBUS_PRI_ADDR_CMD, req->offset);
+	MHL_SII_REG_NAME_WR(REG_CBUS_PRI_WR_DATA_1ST,
+			    req->payload.data[0]);
+
+	switch (req->command) {
+	case MHL_SET_INT:
+	case MHL_WRITE_STAT:
+		start_bit = MSC_START_BIT_WRITE_REG;
+		break;
+	case MHL_READ_DEVCAP:
+		start_bit = MSC_START_BIT_READ_REG;
+		break;
+	case MHL_GET_STATE:
+	case MHL_GET_VENDOR_ID:
+	case MHL_SET_HPD:
+	case MHL_CLR_HPD:
+	case MHL_GET_SC1_ERRORCODE:
+	case MHL_GET_DDC_ERRORCODE:
+	case MHL_GET_MSC_ERRORCODE:
+	case MHL_GET_SC3_ERRORCODE:
+		start_bit = MSC_START_BIT_MSC_CMD;
+		MHL_SII_REG_NAME_WR(REG_CBUS_PRI_ADDR_CMD, req->command);
+		break;
+	case MHL_MSC_MSG:
+		start_bit = MSC_START_BIT_VS_CMD;
+		MHL_SII_REG_NAME_WR(REG_CBUS_PRI_WR_DATA_2ND,
+				    req->payload.data[1]);
+		MHL_SII_REG_NAME_WR(REG_CBUS_PRI_ADDR_CMD, req->command);
+		break;
+	case MHL_WRITE_BURST:
+		start_bit = MSC_START_BIT_WRITE_BURST;
+		MHL_SII_REG_NAME_WR(REG_MSC_WRITE_BURST_LEN, req->length - 1);
+		if (!(req->payload.burst_data)) {
+			pr_err("%s: burst data is null!\n", __func__);
+			goto cbus_send_fail;
+		}
+		burst_data = req->payload.burst_data;
+		for (i = 0; i < req->length; i++, burst_data++)
+			MHL_SII_CBUS_WR(0xC0 + i, *burst_data);
+		break;
+	default:
+		pr_err("%s: unknown command! (%02x)\n",
+		       __func__, req->command);
+		goto cbus_send_fail;
+	}
+
+	INIT_COMPLETION(mhl_ctrl->msc_cmd_done);
+	MHL_SII_REG_NAME_WR(REG_CBUS_PRI_START, start_bit);
+	timeout = wait_for_completion_interruptible_timeout
+		(&mhl_ctrl->msc_cmd_done, msecs_to_jiffies(T_ABORT_NEXT));
+	if (!timeout) {
+		pr_err("%s: cbus_command_send timed out!\n", __func__);
+		goto cbus_send_fail;
+	}
+
+	switch (req->command) {
+	case MHL_READ_DEVCAP:
+		req->retval = MHL_SII_REG_NAME_RD(REG_CBUS_PRI_RD_DATA_1ST);
+		break;
+	case MHL_MSC_MSG:
+		/* check if MSC_MSG NACKed */
+		if (MHL_SII_REG_NAME_RD(REG_MSC_WRITE_BURST_LEN) & BIT6)
+			return -EAGAIN;
+	default:
+		req->retval = 0;
+		break;
+	}
+	mhl_msc_command_done(mhl_ctrl, req);
+	pr_debug("%s: msc cmd done\n", __func__);
+	return 0;
+
+cbus_send_fail:
+	return -EFAULT;
+}
+
+static void mhl_cbus_isr(struct mhl_tx_ctrl *mhl_ctrl)
+{
+	uint8_t regval;
+	int req_done = 0;
+	uint8_t sub_cmd = 0x0;
+	uint8_t cmd_data = 0x0;
+	int msc_msg_recved = 0;
+	int rc = -1;
+	struct i2c_client *client = mhl_ctrl->i2c_handle;
+
+	regval = MHL_SII_REG_NAME_RD(REG_CBUS_INTR_STATUS);
+	if (regval == 0xff)
+		return;
+
+	if (regval)
+		MHL_SII_REG_NAME_WR(REG_CBUS_INTR_STATUS, regval);
+
+	pr_debug("%s: CBUS_INT = %02x\n", __func__, regval);
+
+	/* MSC_MSG (RCP/RAP) */
+	if (regval & BIT3) {
+		sub_cmd = MHL_SII_REG_NAME_RD(REG_CBUS_PRI_VS_CMD);
+		cmd_data = MHL_SII_REG_NAME_RD(REG_CBUS_PRI_VS_DATA);
+		msc_msg_recved = 1;
+	}
+	/* MSC_MT_ABRT/MSC_MR_ABRT/DDC_ABORT */
+	if (regval & (BIT6 | BIT5 | BIT2))
+		mhl_sii_cbus_process_errors(client, regval);
+
+	/* MSC_REQ_DONE */
+	if (regval & BIT4)
+		req_done = 1;
+
+	/* look for interrupts on CBUS_MSC_INT2 */
+	regval  = MHL_SII_REG_NAME_RD(REG_CBUS_MSC_INT2_STATUS);
+
+	/* clear all interrupts */
+	if (regval)
+		MHL_SII_REG_NAME_WR(REG_CBUS_MSC_INT2_STATUS, regval);
+
+	pr_debug("%s: CBUS_MSC_INT2 = %02x\n", __func__, regval);
+
+	/* received SET_INT */
+	if (regval & BIT2) {
+		uint8_t intr;
+		intr = MHL_SII_REG_NAME_RD(REG_CBUS_SET_INT_0);
+		MHL_SII_REG_NAME_WR(REG_CBUS_SET_INT_0, intr);
+		mhl_msc_recv_set_int(mhl_ctrl, 0, intr);
+
+		pr_debug("%s: MHL_INT_0 = %02x\n", __func__, intr);
+		intr = MHL_SII_REG_NAME_RD(REG_CBUS_SET_INT_1);
+		MHL_SII_REG_NAME_WR(REG_CBUS_SET_INT_1, intr);
+		mhl_msc_recv_set_int(mhl_ctrl, 1, intr);
+
+		pr_debug("%s: MHL_INT_1 = %02x\n", __func__, intr);
+		MHL_SII_REG_NAME_WR(REG_CBUS_SET_INT_2, 0xFF);
+		MHL_SII_REG_NAME_WR(REG_CBUS_SET_INT_3, 0xFF);
+	}
+
+	/* received WRITE_STAT */
+	if (regval & BIT3) {
+		uint8_t stat;
+		stat = MHL_SII_REG_NAME_RD(REG_CBUS_WRITE_STAT_0);
+		mhl_msc_recv_write_stat(mhl_ctrl, 0, stat);
+
+		pr_debug("%s: MHL_STATUS_0 = %02x\n", __func__, stat);
+		stat = MHL_SII_REG_NAME_RD(REG_CBUS_WRITE_STAT_1);
+		mhl_msc_recv_write_stat(mhl_ctrl, 1, stat);
+		pr_debug("%s: MHL_STATUS_1 = %02x\n", __func__, stat);
+
+		MHL_SII_REG_NAME_WR(REG_CBUS_WRITE_STAT_0, 0xFF);
+		MHL_SII_REG_NAME_WR(REG_CBUS_WRITE_STAT_1, 0xFF);
+		MHL_SII_REG_NAME_WR(REG_CBUS_WRITE_STAT_2, 0xFF);
+		MHL_SII_REG_NAME_WR(REG_CBUS_WRITE_STAT_3, 0xFF);
+	}
+
+	/* received MSC_MSG */
+	if (msc_msg_recved) {
+		/*mhl msc recv msc msg*/
+		rc = mhl_msc_recv_msc_msg(mhl_ctrl, sub_cmd, cmd_data);
+		if (rc)
+			pr_err("MHL: mhl msc recv msc msg failed(%d)!\n", rc);
+	}
+	/* complete last command */
+	if (req_done)
+		complete_all(&mhl_ctrl->msc_cmd_done);
+
 }
 
 static void clear_all_intrs(struct i2c_client *client)
@@ -937,11 +1341,11 @@
 		mhl_misc_isr(mhl_ctrl);
 
 		/*
-		 * Check for any peer messages for DCAP_CHG etc
+		 * Check for any peer messages for DCAP_CHG, MSC etc
 		 * Dispatch to have the CBUS module working only
 		 * once connected.
-		mhl_cbus_isr(mhl_ctrl);
 		 */
+		mhl_cbus_isr(mhl_ctrl);
 		mhl_hpd_stat_isr(mhl_ctrl);
 	}
 
@@ -1231,6 +1635,59 @@
 	 * such tx specific
 	 */
 	mhl_ctrl->disc_enabled = false;
+	INIT_WORK(&mhl_ctrl->mhl_msc_send_work, mhl_msc_send_work);
+	mhl_ctrl->cur_state = POWER_STATE_D0_MHL;
+	INIT_LIST_HEAD(&mhl_ctrl->list_cmd);
+	init_completion(&mhl_ctrl->msc_cmd_done);
+	mhl_ctrl->msc_send_workqueue = create_singlethread_workqueue
+		("mhl_msc_cmd_queue");
+
+	mhl_ctrl->input = input_allocate_device();
+	if (mhl_ctrl->input) {
+		int i;
+		struct input_dev *input = mhl_ctrl->input;
+
+		mhl_ctrl->rcp_key_code_tbl = vmalloc(
+			ARRAY_SIZE(support_rcp_key_code_tbl));
+		if (!mhl_ctrl->rcp_key_code_tbl) {
+			pr_err("%s: no alloc mem for rcp keycode tbl\n",
+			       __func__);
+			return -ENOMEM;
+		}
+
+		memcpy(mhl_ctrl->rcp_key_code_tbl,
+		       &support_rcp_key_code_tbl[0],
+		       ARRAY_SIZE(support_rcp_key_code_tbl));
+		mhl_ctrl->rcp_key_code_tbl_len = ARRAY_SIZE(
+			support_rcp_key_code_tbl);
+
+		input->phys = "cbus/input0";
+		input->id.bustype = BUS_VIRTUAL;
+		input->id.vendor  = 0x1095;
+		input->id.product = 0x8334;
+		input->id.version = 0xA;
+
+		input->name = "mhl-rcp";
+
+		input->keycode = support_rcp_key_code_tbl;
+		input->keycodesize = sizeof(u16);
+		input->keycodemax = ARRAY_SIZE(support_rcp_key_code_tbl);
+
+		input->evbit[0] = EV_KEY;
+		for (i = 0; i < ARRAY_SIZE(support_rcp_key_code_tbl); i++) {
+			if (support_rcp_key_code_tbl[i] > 1)
+				input_set_capability(input, EV_KEY,
+					support_rcp_key_code_tbl[i]);
+		}
+
+		if (input_register_device(input) < 0) {
+			pr_warn("%s: failed to register input device\n",
+				__func__);
+			input_free_device(input);
+			mhl_ctrl->input = NULL;
+		}
+	}
+
 	rc = mhl_tx_chip_init(mhl_ctrl);
 	if (rc) {
 		pr_err("%s: tx chip init failed [%d]\n",
@@ -1250,11 +1707,29 @@
 				 client->dev.driver->name, mhl_ctrl);
 	if (rc) {
 		pr_err("request_threaded_irq failed, status: %d\n",
-			rc);
+		       rc);
 		goto failed_probe;
 	} else {
 		pr_debug("request_threaded_irq succeeded\n");
 	}
+
+	mhl_ctrl->mhl_psy.name = "ext-vbus";
+	mhl_ctrl->mhl_psy.type = POWER_SUPPLY_TYPE_USB_DCP;
+	mhl_ctrl->mhl_psy.supplied_to = mhl_pm_power_supplied_to;
+	mhl_ctrl->mhl_psy.num_supplicants = ARRAY_SIZE(
+					mhl_pm_power_supplied_to);
+	mhl_ctrl->mhl_psy.properties = mhl_pm_power_props;
+	mhl_ctrl->mhl_psy.num_properties = ARRAY_SIZE(mhl_pm_power_props);
+	mhl_ctrl->mhl_psy.get_property = mhl_power_get_property;
+	mhl_ctrl->mhl_psy.set_property = mhl_power_set_property;
+
+	rc = power_supply_register(&client->dev, &mhl_ctrl->mhl_psy);
+	if (rc < 0) {
+		dev_err(&client->dev, "%s:power_supply_register ext_vbus_psy failed\n",
+			__func__);
+		goto failed_probe;
+	}
+
 	pr_debug("%s: i2c client addr is [%x]\n", __func__, client->addr);
 
 	mhl_info = devm_kzalloc(&client->dev, sizeof(*mhl_info), GFP_KERNEL);
@@ -1270,6 +1745,8 @@
 		goto failed_probe;
 	}
 	mhl_ctrl->mhl_info = mhl_info;
+	mhl_register_msc(mhl_ctrl);
+	mhl_ctrl->tmds_enabled = check_tmds_enabled;
 	return 0;
 failed_probe:
 	mhl_gpio_config(mhl_ctrl, 0);
diff --git a/drivers/video/msm/msm_fb.c b/drivers/video/msm/msm_fb.c
index 9fe5d8f..e4e93eb 100644
--- a/drivers/video/msm/msm_fb.c
+++ b/drivers/video/msm/msm_fb.c
@@ -726,36 +726,11 @@
 		   },
 };
 
-#if defined(CONFIG_HAS_EARLYSUSPEND) && defined(CONFIG_FB_MSM_MDP303)
-static void memset32_io(u32 __iomem *_ptr, u32 val, size_t count)
-{
-	count >>= 2;
-	while (count--)
-		writel(val, _ptr++);
-}
-#endif
-
 #ifdef CONFIG_HAS_EARLYSUSPEND
 static void msmfb_early_suspend(struct early_suspend *h)
 {
 	struct msm_fb_data_type *mfd = container_of(h, struct msm_fb_data_type,
 						    early_suspend);
-#if defined(CONFIG_FB_MSM_MDP303)
-	/*
-	* For MDP with overlay, set framebuffer with black pixels
-	* to show black screen on HDMI.
-	*/
-	struct fb_info *fbi = mfd->fbi;
-	switch (mfd->fbi->var.bits_per_pixel) {
-	case 32:
-		memset32_io((void *)fbi->screen_base, 0xFF000000,
-							fbi->fix.smem_len);
-		break;
-	default:
-		memset32_io((void *)fbi->screen_base, 0x00, fbi->fix.smem_len);
-		break;
-	}
-#endif
 	msm_fb_suspend_sub(mfd);
 }
 
@@ -3144,6 +3119,7 @@
 #endif
 
 DEFINE_SEMAPHORE(msm_fb_ioctl_ppp_sem);
+DEFINE_SEMAPHORE(msm_fb_ioctl_vsync_sem);
 DEFINE_MUTEX(msm_fb_ioctl_lut_sem);
 
 /* Set color conversion matrix from user space */
@@ -3384,12 +3360,12 @@
 #endif
 	case MSMFB_VSYNC_CTRL:
 	case MSMFB_OVERLAY_VSYNC_CTRL:
-		down(&msm_fb_ioctl_ppp_sem);
+		down(&msm_fb_ioctl_vsync_sem);
 		if (mdp_rev >= MDP_REV_40)
 			ret = msmfb_overlay_vsync_ctrl(info, argp);
 		else
 			ret = msmfb_vsync_ctrl(info, argp);
-		up(&msm_fb_ioctl_ppp_sem);
+		up(&msm_fb_ioctl_vsync_sem);
 		break;
 	case MSMFB_BLIT:
 		down(&msm_fb_ioctl_ppp_sem);
diff --git a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl.c b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl.c
index 91cf3ae..1b7bed6 100644
--- a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl.c
+++ b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
diff --git a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_properties.c b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_properties.c
index 95f4bf0..5cf2f9c 100644
--- a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_properties.c
+++ b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_properties.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2010-2013, Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -1115,14 +1115,21 @@
 				encoder->client_output_buf_req.sz/num_slices;
 				encoder->client_output_buf_req.sz =
 				DDL_ALIGN(output_buf_size, DDL_KILO_BYTE(4));
+				if (encoder->client_output_buf_req. \
+					actual_count < encoder-> \
+					client_output_buf_req.min_count) {
+					encoder->client_output_buf_req. \
+					actual_count = encoder-> \
+					client_output_buf_req.min_count;
+				}
 				encoder->output_buf_req =
 				encoder->client_output_buf_req;
-				DDL_MSG_HIGH("%s num_mb = %u num_slices = %u "
-				"output_buf_count = %u "
-				"output_buf_size = %u aligned size = %u\n",
+				DDL_MSG_HIGH("%s num_mb = %u num_slices = %u" \
+				" min_count = %u act_count = %u" \
+				" aligned size = %u\n",
 				__func__, num_mb, num_slices,
 				encoder->client_output_buf_req.min_count,
-				output_buf_size,
+				encoder->client_output_buf_req.actual_count,
 				encoder->client_output_buf_req.sz);
 				vcd_status = VCD_S_SUCCESS;
 			}
diff --git a/drivers/video/msm/vidc/common/enc/venc.c b/drivers/video/msm/vidc/common/enc/venc.c
index c05e568..c18bb92 100644
--- a/drivers/video/msm/vidc/common/enc/venc.c
+++ b/drivers/video/msm/vidc/common/enc/venc.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -35,6 +35,7 @@
 #include "vcd_res_tracker_api.h"
 
 #define VID_ENC_NAME	"msm_vidc_enc"
+static char *node_name[2] = {"", "_sec"};
 
 #if DEBUG
 #define DBG(x...) printk(KERN_DEBUG x)
@@ -50,7 +51,6 @@
 static struct class *vid_enc_class;
 static long vid_enc_ioctl(struct file *file,
 	unsigned cmd, unsigned long arg);
-static int stop_cmd;
 
 static s32 vid_enc_get_empty_client_index(void)
 {
@@ -483,7 +483,7 @@
 
 	mutex_lock(&vid_enc_device_p->lock);
 
-	if (!stop_cmd) {
+	if (!client_ctx->stop_called) {
 		vcd_status = vcd_stop(client_ctx->vcd_handle);
 		DBG("Waiting for VCD_STOP: Before Timeout\n");
 		if (!vcd_status) {
@@ -520,13 +520,13 @@
 		sizeof(struct video_client_ctx));
 
 	vid_enc_device_p->num_clients--;
-	stop_cmd = 0;
+	client_ctx->stop_called = 0;
 	mutex_unlock(&vid_enc_device_p->lock);
 	return true;
 }
 
-
-static int vid_enc_open(struct inode *inode, struct file *file)
+static int vid_enc_open_client(struct video_client_ctx **vid_clnt_ctx,
+							   int flags)
 {
 	s32 client_index;
 	struct video_client_ctx *client_ctx;
@@ -534,22 +534,25 @@
 	u8 client_count = 0;
 
 	INFO("\n msm_vidc_enc: Inside %s()", __func__);
-
-	mutex_lock(&vid_enc_device_p->lock);
-
-	stop_cmd = 0;
+	if (!vid_clnt_ctx) {
+		ERR("Invalid input\n");
+		rc = -EINVAL;
+		goto client_failure;
+	}
+	*vid_clnt_ctx = NULL;
 	client_count = vcd_get_num_of_clients();
 	if (client_count == VIDC_MAX_NUM_CLIENTS) {
-		ERR("ERROR : vid_enc_open() max number of clients"
-		    "limit reached\n");
-		mutex_unlock(&vid_enc_device_p->lock);
-		return -ENODEV;
+		ERR("ERROR : vid_enc_open() max number of clients\n");
+		rc = -ENODEV;
+		goto client_failure;
 	}
 
 	DBG(" Virtual Address of ioremap is %p\n", vid_enc_device_p->virt_base);
 	if (!vid_enc_device_p->num_clients) {
-		if (!vidc_load_firmware())
-			return -ENODEV;
+		if (!vidc_load_firmware()) {
+			rc = -ENODEV;
+			goto client_failure;
+		}
 	}
 
 	client_index = vid_enc_get_empty_client_index();
@@ -557,7 +560,8 @@
 	if (client_index == -1) {
 		ERR("%s() : No free clients client_index == -1\n",
 			__func__);
-		return -ENODEV;
+		rc = -ENODEV;
+		goto client_failure;
 	}
 
 	client_ctx =
@@ -573,27 +577,46 @@
 		client_ctx->user_ion_client = vcd_get_ion_client();
 		if (!client_ctx->user_ion_client) {
 			ERR("vcd_open ion get client failed");
-			return -EFAULT;
+			rc = -EFAULT;
+			goto client_failure;
 		}
 	}
 	rc = vcd_open(vid_enc_device_p->device_handle, false,
-		vid_enc_vcd_cb, client_ctx, 0);
+		vid_enc_vcd_cb, client_ctx, flags);
 	client_ctx->stop_msg = 0;
+	client_ctx->stop_called = 1;
 
 	if (!rc) {
 		wait_for_completion(&client_ctx->event);
 		if (client_ctx->event_status) {
 			ERR("callback for vcd_open returned error: %u",
 				client_ctx->event_status);
-			mutex_unlock(&vid_enc_device_p->lock);
-			return -EFAULT;
+			rc =  -EFAULT;
+			goto client_failure;
 		}
 	} else {
 		ERR("vcd_open returned error: %u", rc);
-		mutex_unlock(&vid_enc_device_p->lock);
-		return rc;
+		goto client_failure;
 	}
-	file->private_data = client_ctx;
+	*vid_clnt_ctx = client_ctx;
+client_failure:
+	return rc;
+}
+static int vid_enc_open(struct inode *inode, struct file *file)
+{
+	int rc = 0;
+	struct video_client_ctx *client_ctx = NULL;
+	INFO("msm_vidc_venc: Inside %s()", __func__);
+	mutex_lock(&vid_enc_device_p->lock);
+	rc = vid_enc_open_client(&client_ctx, 0);
+	if (rc)
+		pr_err("%s() open failed rc=%d\n", __func__, rc);
+	else if (!client_ctx) {
+		pr_err("%s() client_ctx is NULL\n", __func__);
+		rc = -ENOMEM;
+	}
+	if (!rc)
+		file->private_data = client_ctx;
 	mutex_unlock(&vid_enc_device_p->lock);
 	return rc;
 }
@@ -610,12 +633,62 @@
 	INFO("\n msm_vidc_enc: Return from %s()", __func__);
 	return 0;
 }
+static int vid_enc_open_secure(struct inode *inode, struct file *file)
+{
+	int rc = 0, vcd_status = 0;
+	struct video_client_ctx *client_ctx = NULL;
+	struct vcd_property_hdr vcd_property_hdr;
+	struct vcd_property_sps_pps_for_idr_enable idr_enable;
 
-static const struct file_operations vid_enc_fops = {
-	.owner = THIS_MODULE,
-	.open = vid_enc_open,
-	.release = vid_enc_release,
-	.unlocked_ioctl = vid_enc_ioctl,
+	INFO("msm_vidc_enc: Inside %s()", __func__);
+	mutex_lock(&vid_enc_device_p->lock);
+	rc = vid_enc_open_client(&client_ctx, VCD_CP_SESSION);
+	if (rc || !client_ctx) {
+		pr_err("%s() open failed rc=%d\n", __func__, rc);
+		if (!client_ctx)
+			rc = -ENOMEM;
+		goto error;
+	}
+	file->private_data = client_ctx;
+	vcd_property_hdr.prop_id = VCD_I_ENABLE_SPS_PPS_FOR_IDR;
+	vcd_property_hdr.sz =
+		sizeof(struct vcd_property_sps_pps_for_idr_enable);
+	idr_enable.sps_pps_for_idr_enable_flag = 1;
+	vcd_status = vcd_set_property(client_ctx->vcd_handle,
+				&vcd_property_hdr, &idr_enable);
+	if (vcd_status) {
+		ERR("Setting SPS with IDR failed\n");
+		rc = -EACCES;
+		goto close_client;
+	}
+
+	if (res_trk_open_secure_session()) {
+		rc = -EACCES;
+		goto close_client;
+	}
+	mutex_unlock(&vid_enc_device_p->lock);
+	return rc;
+
+close_client:
+	vid_enc_close_client(client_ctx);
+	ERR("Secure session operation failure\n");
+error:
+	mutex_unlock(&vid_enc_device_p->lock);
+	return rc;
+}
+static const struct file_operations vid_enc_fops[NUM_OF_DRIVER_NODES] = {
+	{
+		.owner = THIS_MODULE,
+		.open = vid_enc_open,
+		.release = vid_enc_release,
+		.unlocked_ioctl = vid_enc_ioctl,
+	},
+	{
+		.owner = THIS_MODULE,
+		.open = vid_enc_open_secure,
+		.release = vid_enc_release,
+		.unlocked_ioctl = vid_enc_ioctl,
+	},
 };
 
 void vid_enc_interrupt_deregister(void)
@@ -680,7 +753,7 @@
 
 static int __init vid_enc_init(void)
 {
-	int rc = 0;
+	int rc = 0, i = 0, j = 0;
 	struct device *class_devp;
 
 	INFO("\n msm_vidc_enc: Inside %s()", __func__);
@@ -691,14 +764,13 @@
 			__func__);
 		return -ENOMEM;
 	}
-
-	rc = alloc_chrdev_region(&vid_enc_dev_num, 0, 1, VID_ENC_NAME);
+	rc = alloc_chrdev_region(&vid_enc_dev_num, 0, NUM_OF_DRIVER_NODES,
+			VID_ENC_NAME);
 	if (rc < 0) {
 		ERR("%s: alloc_chrdev_region Failed rc = %d\n",
 			__func__, rc);
 		goto error_vid_enc_alloc_chrdev_region;
 	}
-
 	vid_enc_class = class_create(THIS_MODULE, VID_ENC_NAME);
 	if (IS_ERR(vid_enc_class)) {
 		rc = PTR_ERR(vid_enc_class);
@@ -706,32 +778,40 @@
 			__func__, rc);
 		goto error_vid_enc_class_create;
 	}
+	for (i = 0; i < NUM_OF_DRIVER_NODES; i++) {
+		class_devp = device_create(vid_enc_class, NULL,
+					(vid_enc_dev_num + i), NULL,
+					VID_ENC_NAME "%s", node_name[i]);
 
-	class_devp = device_create(vid_enc_class, NULL,
-				vid_enc_dev_num, NULL, VID_ENC_NAME);
+		if (IS_ERR(class_devp)) {
+			rc = PTR_ERR(class_devp);
+			ERR("%s: class device_create failed %d\n",
+			__func__, rc);
+			if (!i)
+				goto error_vid_enc_class_device_create;
+			else
+				goto error_vid_enc_cdev_add;
+		}
 
-	if (IS_ERR(class_devp)) {
-		rc = PTR_ERR(class_devp);
-		ERR("%s: class device_create failed %d\n",
-		__func__, rc);
-		goto error_vid_enc_class_device_create;
-	}
+		vid_enc_device_p->device[i] = class_devp;
 
-	vid_enc_device_p->device = class_devp;
+		cdev_init(&vid_enc_device_p->cdev[i], &vid_enc_fops[i]);
+		vid_enc_device_p->cdev[i].owner = THIS_MODULE;
+		rc = cdev_add(&(vid_enc_device_p->cdev[i]),
+					 (vid_enc_dev_num + i), 1);
 
-	cdev_init(&vid_enc_device_p->cdev, &vid_enc_fops);
-	vid_enc_device_p->cdev.owner = THIS_MODULE;
-	rc = cdev_add(&(vid_enc_device_p->cdev), vid_enc_dev_num, 1);
-
-	if (rc < 0) {
-		ERR("%s: cdev_add failed %d\n",
-		__func__, rc);
-		goto error_vid_enc_cdev_add;
+		if (rc < 0) {
+			ERR("%s: cdev_add failed %d\n",
+			__func__, rc);
+			goto error_vid_enc_cdev_add;
+		}
 	}
 	vid_enc_vcd_init();
 	return 0;
 
 error_vid_enc_cdev_add:
+	for (j = i-1; j >= 0; j--)
+		cdev_del(&(vid_enc_device_p->cdev[j]));
 	device_destroy(vid_enc_class, vid_enc_dev_num);
 error_vid_enc_class_device_create:
 	class_destroy(vid_enc_class);
@@ -745,8 +825,10 @@
 
 static void __exit vid_enc_exit(void)
 {
+	int i = 0;
 	INFO("\n msm_vidc_enc: Inside %s()", __func__);
-	cdev_del(&(vid_enc_device_p->cdev));
+	for (i = 0; i < NUM_OF_DRIVER_NODES; i++)
+		cdev_del(&(vid_enc_device_p->cdev[i]));
 	device_destroy(vid_enc_class, vid_enc_dev_num);
 	class_destroy(vid_enc_class);
 	unregister_chrdev_region(vid_enc_dev_num, 1);
@@ -944,7 +1026,8 @@
 		if (!result) {
 			ERR("setting VEN_IOCTL_CMD_START failed\n");
 			return -EIO;
-		}
+		} else
+			client_ctx->stop_called = 0;
 		break;
 	}
 	case VEN_IOCTL_CMD_STOP:
@@ -955,7 +1038,7 @@
 			ERR("setting VEN_IOCTL_CMD_STOP failed\n");
 			return -EIO;
 		}
-		stop_cmd = 1;
+		client_ctx->stop_called = 1;
 		break;
 	}
 	case VEN_IOCTL_CMD_PAUSE:
diff --git a/drivers/video/msm/vidc/common/enc/venc_internal.h b/drivers/video/msm/vidc/common/enc/venc_internal.h
index 17cefbb..b7b8c98 100644
--- a/drivers/video/msm/vidc/common/enc/venc_internal.h
+++ b/drivers/video/msm/vidc/common/enc/venc_internal.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -18,6 +18,7 @@
 #include <linux/cdev.h>
 #include <media/msm/vidc_init.h>
 
+#define NUM_OF_DRIVER_NODES 2
 #define VID_ENC_MAX_NUM_OF_BUFF 100
 
 enum venc_buffer_dir{
@@ -32,8 +33,8 @@
 
 struct vid_enc_dev {
 
-	struct cdev cdev;
-	struct device *device;
+	struct cdev cdev[NUM_OF_DRIVER_NODES];
+	struct device *device[NUM_OF_DRIVER_NODES];
 	resource_size_t phys_base;
 	void __iomem *virt_base;
 	unsigned int irq;
diff --git a/drivers/video/msm/vidc/common/vcd/vcd_api.c b/drivers/video/msm/vidc/common/vcd/vcd_api.c
index 0dbbf57..3d7474f 100644
--- a/drivers/video/msm/vidc/common/vcd/vcd_api.c
+++ b/drivers/video/msm/vidc/common/vcd/vcd_api.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -117,36 +117,20 @@
 	int is_secure;
 	struct client_security_info sec_info;
 	int client_count = 0;
-	int secure_session_running = 0;
+	int secure_session_running = 0, non_secure_runnung = 0;
 	is_secure = (flags & VCD_CP_SESSION) ? 1 : 0;
 	client_count = vcd_get_clients_security_info(&sec_info);
 	secure_session_running = (sec_info.secure_enc > 0) ||
 			(sec_info.secure_dec > 0);
-	if (!decoding && is_secure) {
-		if ((sec_info.secure_dec == 1))
-			VCD_MSG_LOW("SE-SD: SUCCESS\n");
-		else {
-			VCD_MSG_LOW("SE is permitted only with SD: FAILURE\n");
-			return -EACCES;
-		}
-	} else if (!decoding && !is_secure) {
+	non_secure_runnung = sec_info.non_secure_dec + sec_info.non_secure_enc;
+	if (!is_secure) {
 		if (secure_session_running) {
-			VCD_MSG_LOW("SD-NSE: FAILURE\n");
-			VCD_MSG_LOW("SE-NSE: FAILURE\n");
-			return -EACCES;
-		}
-	} else if (decoding && is_secure) {
-		if (client_count > 0) {
-			VCD_MSG_LOW("S/NS-SD: FAILURE\n");
-			if (sec_info.secure_enc > 0 ||
-				sec_info.non_secure_enc > 0) {
-				return -EAGAIN;
-			}
+			pr_err("non secure session failed secure running\n");
 			return -EACCES;
 		}
 	} else {
-		if (sec_info.secure_dec > 0) {
-			VCD_MSG_LOW("SD-NSD: FAILURE\n");
+		if (non_secure_runnung) {
+			pr_err("Secure session failed non secure running\n");
 			return -EACCES;
 		}
 	}
diff --git a/drivers/video/msm/vidc/common/vcd/vcd_client_sm.c b/drivers/video/msm/vidc/common/vcd/vcd_client_sm.c
index 983923b..884050b 100644
--- a/drivers/video/msm/vidc/common/vcd/vcd_client_sm.c
+++ b/drivers/video/msm/vidc/common/vcd/vcd_client_sm.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2010-2013, Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -1750,7 +1750,7 @@
 	 vcd_get_buffer_requirements_cmn,
 	 NULL,
 	 NULL,
-	 NULL,
+	 vcd_free_buffer_cmn,
 	 vcd_fill_output_buffer_cmn,
 	 vcd_clnt_cb_in_flushing,
 	 },
diff --git a/include/linux/Kbuild b/include/linux/Kbuild
index 46ae59f..9a7081d 100644
--- a/include/linux/Kbuild
+++ b/include/linux/Kbuild
@@ -439,6 +439,7 @@
 header-y += msm_audio_sbc.h
 header-y += msm_ipc.h
 header-y += msm_charm.h
+header-y += msm_rmnet.h
 header-y += qseecom.h
 header-y += qcedev.h
 header-y += idle_stats_device.h
diff --git a/include/linux/coresight.h b/include/linux/coresight.h
index 0bdacffa..b167b44 100644
--- a/include/linux/coresight.h
+++ b/include/linux/coresight.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -30,7 +30,11 @@
 #define CORESIGHT_COMPIDR2	(0xFF8)
 #define CORESIGHT_COMPIDR3	(0xFFC)
 
+#define ETM_ARCH_V1_0		(0x00)
+#define ETM_ARCH_V1_2		(0x02)
 #define ETM_ARCH_V3_3		(0x23)
+#define ETM_ARCH_V3_5		(0x25)
+#define PFT_ARCH_MAJOR		(0x30)
 #define PFT_ARCH_V1_1		(0x31)
 
 enum coresight_clk_rate {
diff --git a/include/linux/diagchar.h b/include/linux/diagchar.h
index 43daaf2..4bd8885 100644
--- a/include/linux/diagchar.h
+++ b/include/linux/diagchar.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2008-2012, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2008-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -112,7 +112,7 @@
 /* This needs to be modified manually now, when we add
  a new RANGE of SSIDs to the msg_mask_tbl */
 #define MSG_MASK_TBL_CNT		24
-#define EVENT_LAST_ID			0x08C5
+#define EVENT_LAST_ID			0x099F
 
 #define MSG_SSID_0			0
 #define MSG_SSID_0_LAST			93
@@ -692,7 +692,7 @@
 /* LOG CODES */
 
 #define LOG_0	0x0
-#define LOG_1	0x1636
+#define LOG_1	0x1750
 #define LOG_2	0x0
 #define LOG_3	0x0
 #define LOG_4	0x4910
diff --git a/include/linux/mfd/pm8xxx/pm8921-bms.h b/include/linux/mfd/pm8xxx/pm8921-bms.h
index 6db6204..8ab3ac2 100644
--- a/include/linux/mfd/pm8xxx/pm8921-bms.h
+++ b/include/linux/mfd/pm8xxx/pm8921-bms.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2011-2013, 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
@@ -123,9 +123,11 @@
 int pm8921_bms_get_simultaneous_battery_voltage_and_current(int *ibat_ua,
 								int *vbat_uv);
 /**
- * pm8921_bms_get_rbatt - function to get the battery resistance in mOhm.
+ * pm8921_bms_get_current_max
+ *	- function to get the max current that can be drawn from
+ *	  the battery before it dips below the min allowed voltage
  */
-int pm8921_bms_get_rbatt(void);
+int pm8921_bms_get_current_max(void);
 /**
  * pm8921_bms_invalidate_shutdown_soc - function to notify the bms driver that
  *					the battery was replaced between reboot
@@ -184,6 +186,10 @@
 {
 	return -ENXIO;
 }
+static inline int pm8921_bms_get_current_max(void)
+{
+	return -ENXIO;
+}
 #endif
 
 #endif
diff --git a/include/linux/mhl_8334.h b/include/linux/mhl_8334.h
index d3597dc..cb74b73 100644
--- a/include/linux/mhl_8334.h
+++ b/include/linux/mhl_8334.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -18,6 +18,7 @@
 #include <linux/platform_device.h>
 #include <mach/board.h>
 #include <linux/mhl_devcap.h>
+#include <linux/power_supply.h>
 #include <linux/mhl_defs.h>
 
 #define MHL_DEVICE_NAME "sii8334"
@@ -96,6 +97,65 @@
 	struct msc_command_struct* (*msc_command_get_work) (void);
 };
 
+#ifdef CONFIG_FB_MSM_MDSS_HDMI_MHL_SII8334
+enum mhl_gpio_type {
+	MHL_TX_RESET_GPIO,
+	MHL_TX_INTR_GPIO,
+	MHL_TX_PMIC_PWR_GPIO,
+	MHL_TX_MAX_GPIO,
+};
+
+enum mhl_vreg_type {
+	MHL_TX_3V_VREG,
+	MHL_TX_MAX_VREG,
+};
+
+
+struct mhl_tx_platform_data {
+	/* Data filled from device tree nodes */
+	struct dss_gpio *gpios[MHL_TX_MAX_GPIO];
+	struct dss_vreg *vregs[MHL_TX_MAX_VREG];
+	int irq;
+};
+
+struct mhl_tx_ctrl {
+	struct platform_device *pdev;
+	struct mhl_tx_platform_data *pdata;
+	struct i2c_client *i2c_handle;
+	uint8_t cur_state;
+	uint8_t chip_rev_id;
+	int mhl_mode;
+	struct completion rgnd_done;
+	void (*notify_usb_online)(int online);
+	struct usb_ext_notification *mhl_info;
+	bool disc_enabled;
+	struct power_supply mhl_psy;
+	bool vbus_active;
+	int current_val;
+	struct completion msc_cmd_done;
+	uint8_t devcap[16];
+	uint8_t devcap_state;
+	uint8_t path_en_state;
+	uint8_t (*tmds_enabled)(void);
+	struct work_struct mhl_msc_send_work;
+	struct list_head list_cmd;
+	struct input_dev *input;
+	struct workqueue_struct *msc_send_workqueue;
+	u16 *rcp_key_code_tbl;
+	size_t rcp_key_code_tbl_len;
+};
+
+int mhl_i2c_reg_read(struct i2c_client *client,
+		     uint8_t slave_addr_index, uint8_t reg_offset);
+int mhl_i2c_reg_write(struct i2c_client *client,
+		      uint8_t slave_addr_index, uint8_t reg_offset,
+		      uint8_t value);
+void mhl_i2c_reg_modify(struct i2c_client *client,
+			uint8_t slave_addr_index, uint8_t reg_offset,
+			uint8_t mask, uint8_t val);
+
+#endif /* CONFIG_FB_MSM_MDSS_HDMI_MHL_SII8334 */
+
 enum {
 	TX_PAGE_TPI          = 0x00,
 	TX_PAGE_L0           = 0x01,
@@ -204,6 +264,7 @@
 
 #define REG_TMDS_CSTAT	((TX_PAGE_3 << 16) | 0x0040)
 
+#define REG_CBUS_INTR_STATUS            ((TX_PAGE_CBUS << 16) | 0x0008)
 #define REG_CBUS_INTR_ENABLE            ((TX_PAGE_CBUS << 16) | 0x0009)
 
 #define REG_DDC_ABORT_REASON            ((TX_PAGE_CBUS << 16) | 0x000B)
diff --git a/include/linux/mhl_defs.h b/include/linux/mhl_defs.h
index 062bdf9..f23be79 100644
--- a/include/linux/mhl_defs.h
+++ b/include/linux/mhl_defs.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -149,6 +149,7 @@
 
 #define MHL_RCPE_NO_ERROR			0x00
 #define MHL_RCPE_UNSUPPORTED_KEY_CODE		0x01
+#define MHL_RCPE_INEFFECTIVE_KEY_CODE		0x01
 #define MHL_RCPE_BUSY				0x02
 
 #define MHL_RAPK_NO_ERROR			0x00
@@ -156,6 +157,8 @@
 #define MHL_RAPK_UNSUPPORTED_ACTION_CODE	0x02
 #define MHL_RAPK_BUSY				0x03
 
+#define T_ABORT_NEXT                    (2050)
+
 /* MHL spec related defines*/
 enum {
 	/* Command or Data byte acknowledge */
@@ -196,6 +199,8 @@
 	MHL_GET_SC3_ERRORCODE		= 0x6D,
 };
 
+/* Polling. */
+#define MHL_RAP_POLL                    0x00
 /* Turn content streaming ON. */
 #define	MHL_RAP_CONTENT_ON		0x10
 /* Turn content streaming OFF. */
diff --git a/include/linux/mmc/card.h b/include/linux/mmc/card.h
index 3e5c8cb..8ec2c73 100644
--- a/include/linux/mmc/card.h
+++ b/include/linux/mmc/card.h
@@ -198,6 +198,7 @@
 	REL_WRITE,
 	THRESHOLD,
 	LARGE_SEC_ALIGN,
+	RANDOM,
 	MAX_REASONS,
 };
 
@@ -261,57 +262,48 @@
 /**
  * struct mmc_bkops_info - BKOPS data
  * @dw:	Idle time bkops delayed work
- * @host_suspend_tout_ms:	The host controller idle time,
- * before getting into suspend
+ * @host_delay_ms:	The host controller time to start bkops
  * @delay_ms:	The time to start the BKOPS
  *        delayed work once MMC thread is idle
+ * @min_sectors_to_queue_delayed_work: the changed
+ *        number of sectors that should issue check for BKOPS
+ *        need
+ * @size_percentage_to_queue_delayed_work: the changed
+ *        percentage of sectors that should issue check for
+ *        BKOPS need
+ * @bkops_stats: BKOPS statistics
  * @poll_for_completion:	Poll on BKOPS completion
  * @cancel_delayed_work: A flag to indicate if the delayed work
  *        should be cancelled
- * @started_delayed_bkops:  A flag to indicate if the delayed
- *        work was scheduled
+ * @sectors_changed:  number of  sectors written or
+ *       discard since the last idle BKOPS were scheduled
  */
 struct mmc_bkops_info {
 	struct delayed_work	dw;
-	unsigned int		host_suspend_tout_ms;
+	unsigned int		host_delay_ms;
 	unsigned int		delay_ms;
-	struct mmc_bkops_stats  bkops_stats;    /* BKOPS statistics */
+	unsigned int		min_sectors_to_queue_delayed_work;
+	unsigned int		size_percentage_to_queue_delayed_work;
+	struct mmc_bkops_stats  bkops_stats;
 /*
  * A default time for checking the need for non urgent BKOPS once mmcqd
  * is idle.
  */
-#define MMC_IDLE_BKOPS_TIME_MS 2000
+#define MMC_IDLE_BKOPS_TIME_MS 200
 	struct work_struct	poll_for_completion;
 /* Polling timeout and interval for waiting on non-blocking BKOPs completion */
-#define BKOPS_COMPLETION_POLLING_TIMEOUT_MS 10000 /* in ms */
+#define BKOPS_COMPLETION_POLLING_TIMEOUT_MS (4 * 60 * 1000) /* in ms */
 #define BKOPS_COMPLETION_POLLING_INTERVAL_MS 1000 /* in ms */
 	bool			cancel_delayed_work;
-	bool			started_delayed_bkops;
-};
-
-/**
- * struct mmc_async_event_stats - async events stats data
- *
- * @enabled	A boolean indicating if the stats are initiated
- *		and enabled
- * The rest of the members in this struct are counters which are
- * incremented at strategic locations in the async events flows.
+	unsigned int		sectors_changed;
+/*
+ * Since canceling the delayed work might have significant effect on the
+ * performance of small requests we won't queue the delayed work every time
+ * mmcqd thread is idle.
+ * The delayed work for idle BKOPS will be scheduled only after a significant
+ * amount of write or discard data.
  */
-struct mmc_async_event_stats {
-	bool enabled;
-	u32 cmd_retry;
-	u32 new_request_flag;
-	u32 null_fetched;
-	u32 wakeup_new;
-	u32 q_no_waiting;
-	u32 done_flag;
-	u32 no_mmc_request_action;
-	u32 wakeup_mq_thread;
-	u32 fetch_due_to_new_req;
-	u32 returned_new_req;
-	u32 done_when_new_req_event_on;
-	u32 new_req_when_new_marked;
-	bool print_in_read;
+#define BKOPS_SIZE_PERCENTAGE_TO_QUEUE_DELAYED_WORK 1 /* 1% */
 };
 
 /*
@@ -337,6 +329,7 @@
 #define MMC_CARD_REMOVED	(1<<7)		/* card has been removed */
 #define MMC_STATE_HIGHSPEED_200	(1<<8)		/* card is in HS200 mode */
 #define MMC_STATE_DOING_BKOPS	(1<<10)		/* card is doing BKOPS */
+#define MMC_STATE_NEED_BKOPS	(1<<11)		/* card needs to do BKOPS */
 	unsigned int		quirks; 	/* card quirks */
 #define MMC_QUIRK_LENIENT_FN0	(1<<0)		/* allow SDIO FN0 writes outside of the VS CCCR range */
 #define MMC_QUIRK_BLKSZ_FOR_BYTE_MODE (1<<1)	/* use func->cur_blksize */
@@ -387,8 +380,6 @@
 	struct mmc_wr_pack_stats wr_pack_stats; /* packed commands stats*/
 
 	struct mmc_bkops_info	bkops_info;
-	/* async events flow stats */
-	struct mmc_async_event_stats async_event_stats;
 };
 
 /*
@@ -511,6 +502,7 @@
 #define mmc_card_ext_capacity(c) ((c)->state & MMC_CARD_SDXC)
 #define mmc_card_removed(c)	((c) && ((c)->state & MMC_CARD_REMOVED))
 #define mmc_card_doing_bkops(c)	((c)->state & MMC_STATE_DOING_BKOPS)
+#define mmc_card_need_bkops(c)	((c)->state & MMC_STATE_NEED_BKOPS)
 
 #define mmc_card_set_present(c)	((c)->state |= MMC_STATE_PRESENT)
 #define mmc_card_set_readonly(c) ((c)->state |= MMC_STATE_READONLY)
@@ -524,7 +516,8 @@
 #define mmc_card_set_removed(c) ((c)->state |= MMC_CARD_REMOVED)
 #define mmc_card_set_doing_bkops(c)	((c)->state |= MMC_STATE_DOING_BKOPS)
 #define mmc_card_clr_doing_bkops(c)	((c)->state &= ~MMC_STATE_DOING_BKOPS)
-
+#define mmc_card_set_need_bkops(c)	((c)->state |= MMC_STATE_NEED_BKOPS)
+#define mmc_card_clr_need_bkops(c)	((c)->state &= ~MMC_STATE_NEED_BKOPS)
 /*
  * Quirk add/remove for MMC products.
  */
@@ -617,5 +610,5 @@
 extern struct mmc_wr_pack_stats *mmc_blk_get_packed_statistics(
 			struct mmc_card *card);
 extern void mmc_blk_init_packed_statistics(struct mmc_card *card);
-extern void mmc_blk_init_async_event_statistics(struct mmc_card *card);
+
 #endif /* LINUX_MMC_CARD_H */
diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h
index 6982c45..f9e0627 100644
--- a/include/linux/mmc/host.h
+++ b/include/linux/mmc/host.h
@@ -315,6 +315,7 @@
 
 	struct delayed_work	detect;
 	struct wake_lock	detect_wake_lock;
+	const char		*wlock_name;
 	int			detect_change;	/* card detect flag */
 	struct mmc_hotplug	hotplug;
 
diff --git a/include/linux/msm_ion.h b/include/linux/msm_ion.h
index d423b26..14492ea 100644
--- a/include/linux/msm_ion.h
+++ b/include/linux/msm_ion.h
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright (c) 2012, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
  *
  * This software is licensed under the terms of the GNU General Public
  * License version 2, as published by the Free Software Foundation, and
@@ -75,6 +75,13 @@
 #define ION_SECURE (1 << ION_HEAP_ID_RESERVED)
 
 /**
+ * Flag for clients to force contiguous memort allocation
+ *
+ * Use of this flag is carefully monitored!
+ */
+#define ION_FORCE_CONTIGUOUS (1 << 30)
+
+/**
  * Macro should be used with ion_heap_ids defined above.
  */
 #define ION_HEAP(bit) (1 << (bit))
diff --git a/include/linux/msm_mdp.h b/include/linux/msm_mdp.h
index aa2d948..7e67db0 100644
--- a/include/linux/msm_mdp.h
+++ b/include/linux/msm_mdp.h
@@ -145,6 +145,7 @@
 #define MDP_DITHER 0x8
 #define MDP_BLUR 0x10
 #define MDP_BLEND_FG_PREMULT 0x20000
+#define MDP_IS_FG 0x40000
 #define MDP_DEINTERLACE 0x80000000
 #define MDP_SHARPENING  0x40000000
 #define MDP_NO_DMA_BARRIER_START	0x20000000
diff --git a/include/linux/msm_rmnet.h b/include/linux/msm_rmnet.h
index 063a8f1..d41b55c 100644
--- a/include/linux/msm_rmnet.h
+++ b/include/linux/msm_rmnet.h
@@ -1,16 +1,3 @@
-/* Copyright (c) 2010, 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.
- *
- */
-
 #ifndef _MSM_RMNET_H_
 #define _MSM_RMNET_H_
 
diff --git a/include/linux/remote_spinlock.h b/include/linux/remote_spinlock.h
index 8d7c7e7..e39846f 100644
--- a/include/linux/remote_spinlock.h
+++ b/include/linux/remote_spinlock.h
@@ -1,4 +1,5 @@
-/* Copyright (c) 2008-2009, 2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2008-2009, 2011, 2013 The Linux Foundation.
+ * All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -89,6 +90,9 @@
 #define remote_spin_release_all(pid) \
 	_remote_spin_release_all(pid)
 
+#define remote_spin_owner(lock) \
+	_remote_spin_owner(&((lock)->remote))
+
 typedef struct {
 	struct mutex local;
 	_remote_mutex_t remote;
diff --git a/include/linux/test-iosched.h b/include/linux/test-iosched.h
index b933069..295c02d 100644
--- a/include/linux/test-iosched.h
+++ b/include/linux/test-iosched.h
@@ -38,6 +38,7 @@
 typedef char* (get_test_case_str_fn) (struct test_data *);
 typedef void (blk_dev_test_init_fn) (void);
 typedef void (blk_dev_test_exit_fn) (void);
+typedef struct gendisk* (get_rq_disk_fn) (void);
 
 /**
  * enum test_state - defines the state of the test
@@ -142,6 +143,7 @@
 	post_test_fn *post_test_fn;
 	get_test_case_str_fn *get_test_case_str_fn;
 	unsigned long test_duration;
+	get_rq_disk_fn *get_rq_disk_fn;
 	void *data;
 };
 
diff --git a/include/linux/usb/msm_hsusb.h b/include/linux/usb/msm_hsusb.h
index 279b72f..9240277 100644
--- a/include/linux/usb/msm_hsusb.h
+++ b/include/linux/usb/msm_hsusb.h
@@ -2,7 +2,7 @@
  *
  * Copyright (C) 2008 Google, Inc.
  * Author: Brian Swetland <swetland@google.com>
- * Copyright (c) 2009-2012, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2009-2013, The Linux Foundation. All rights reserved.
  *
  * This software is licensed under the terms of the GNU General Public
  * License version 2, as published by the Free Software Foundation, and
@@ -340,7 +340,7 @@
 	struct delayed_work suspend_work;
 	enum usb_chg_state chg_state;
 	enum usb_chg_type chg_type;
-	u8 dcd_retries;
+	unsigned dcd_time;
 	struct wake_lock wlock;
 	struct notifier_block usbdev_nb;
 	unsigned mA_port;
@@ -456,6 +456,13 @@
 	u32 desc_fifo_size;
 };
 
+enum usb_bam {
+	SSUSB_BAM = 0,
+	HSUSB_BAM,
+	HSIC_BAM,
+	MAX_BAMS,
+};
+
 /**
  * struct msm_usb_bam_platform_data: pipe connection information
  * between USB/HSIC BAM and another BAM. USB/HSIC BAM can be
@@ -474,13 +481,7 @@
 	u32 total_bam_num;
 	u32 usb_base_address;
 	bool ignore_core_reset_ack;
-};
-
-enum usb_bam {
-	SSUSB_BAM = 0,
-	HSUSB_BAM,
-	HSIC_BAM,
-	MAX_BAMS,
+	bool reset_on_connect[MAX_BAMS];
 };
 
 /**
diff --git a/include/sound/q6afe-v2.h b/include/sound/q6afe-v2.h
index 444b432..3da152c 100644
--- a/include/sound/q6afe-v2.h
+++ b/include/sound/q6afe-v2.h
@@ -73,6 +73,8 @@
 	IDX_RT_PROXY_PORT_001_TX = 31,
 	IDX_AFE_PORT_ID_QUATERNARY_MI2S_RX = 32,
 	IDX_AFE_PORT_ID_QUATERNARY_MI2S_TX = 33,
+	IDX_AFE_PORT_ID_SECONDARY_MI2S_RX = 34,
+	IDX_AFE_PORT_ID_SECONDARY_MI2S_TX = 35,
 	AFE_MAX_PORTS
 };
 
diff --git a/include/sound/q6asm.h b/include/sound/q6asm.h
index 6b4c17b..dcdd816 100644
--- a/include/sound/q6asm.h
+++ b/include/sound/q6asm.h
@@ -74,10 +74,12 @@
 /* Enable Sample_Rate/Channel_Mode notification event from Decoder */
 #define SR_CM_NOTIFY_ENABLE	0x0004
 
-#define ASYNC_IO_MODE	0x0002
-#define SYNC_IO_MODE	0x0001
-#define NO_TIMESTAMP    0xFF00
-#define SET_TIMESTAMP   0x0000
+#define TUN_WRITE_IO_MODE 0x0008 /* tunnel read write mode */
+#define TUN_READ_IO_MODE  0x0004 /* tunnel read write mode */
+#define ASYNC_IO_MODE	  0x0002
+#define SYNC_IO_MODE	  0x0001
+#define NO_TIMESTAMP      0xFF00
+#define SET_TIMESTAMP     0x0000
 
 #define SOFT_PAUSE_ENABLE	1
 #define SOFT_PAUSE_DISABLE	0
diff --git a/lib/qmi_encdec.c b/lib/qmi_encdec.c
index 40273d0..5c489cf 100644
--- a/lib/qmi_encdec.c
+++ b/lib/qmi_encdec.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -82,7 +82,7 @@
 
 static int _qmi_kernel_encode(struct elem_info *ei_array,
 			      void *out_buf, void *in_c_struct,
-			      int enc_level);
+			      uint32_t out_buf_len, int enc_level);
 
 static int _qmi_kernel_decode(struct elem_info *ei_array,
 			      void *out_c_struct,
@@ -114,7 +114,7 @@
 		return -ETOOSMALL;
 
 	return _qmi_kernel_encode(desc->ei_array, out_buf,
-				  in_c_struct, enc_level);
+				  in_c_struct, out_buf_len, enc_level);
 }
 EXPORT_SYMBOL(qmi_kernel_encode);
 
@@ -152,6 +152,7 @@
  * @buf_dst: Buffer to store the encoded information.
  * @buf_src: Buffer containing the elements to be encoded.
  * @elem_len: Number of elements, in the buf_src, to be encoded.
+ * @out_buf_len: Available space in the encode buffer.
  * @enc_level: Depth of the nested structure from the main structure.
  *
  * @return: Mumber of bytes of encoded information, on success.
@@ -165,14 +166,16 @@
  */
 static int qmi_encode_struct_elem(struct elem_info *ei_array,
 				  void *buf_dst, void *buf_src,
-				  uint32_t elem_len, int enc_level)
+				  uint32_t elem_len, uint32_t out_buf_len,
+				  int enc_level)
 {
 	int i, rc, encoded_bytes = 0;
 	struct elem_info *temp_ei = ei_array;
 
 	for (i = 0; i < elem_len; i++) {
-		rc = _qmi_kernel_encode(temp_ei->ei_array,
-					buf_dst, buf_src, enc_level);
+		rc = _qmi_kernel_encode(temp_ei->ei_array, buf_dst, buf_src,
+					(out_buf_len - encoded_bytes),
+					enc_level);
 		if (rc < 0) {
 			pr_err("%s: STRUCT Encode failure\n", __func__);
 			return rc;
@@ -214,6 +217,7 @@
  * @ei_array: Struct info array describing the structure to be encoded.
  * @out_buf: Buffer to hold the encoded QMI message.
  * @in_c_struct: Pointer to the C structure to be encoded.
+ * @out_buf_len: Available space in the encode buffer.
  * @enc_level: Encode level to indicate the depth of the nested structure,
  *             within the main structure, being encoded.
  *
@@ -222,7 +226,7 @@
  */
 static int _qmi_kernel_encode(struct elem_info *ei_array,
 			      void *out_buf, void *in_c_struct,
-			      int enc_level)
+			      uint32_t out_buf_len, int enc_level)
 {
 	struct elem_info *temp_ei = ei_array;
 	uint8_t opt_flag_value = 0;
@@ -268,6 +272,13 @@
 			memcpy(&data_len_value, buf_src, temp_ei->elem_size);
 			data_len_sz = temp_ei->elem_size == sizeof(uint8_t) ?
 					sizeof(uint8_t) : sizeof(uint16_t);
+			/* Check to avoid out of range buffer access */
+			if ((data_len_sz + encoded_bytes + TLV_LEN_SIZE +
+			    TLV_TYPE_SIZE) > out_buf_len) {
+				pr_err("%s: Too Small Buffer @DATA_LEN\n",
+					__func__);
+				return -ETOOSMALL;
+			}
 			rc = qmi_encode_basic_elem(buf_dst, &data_len_value,
 						   1, data_len_sz);
 			if (data_len_value) {
@@ -285,6 +296,14 @@
 		case QMI_UNSIGNED_8_BYTE:
 		case QMI_SIGNED_2_BYTE_ENUM:
 		case QMI_SIGNED_4_BYTE_ENUM:
+			/* Check to avoid out of range buffer access */
+			if (((data_len_value * temp_ei->elem_size) +
+			    encoded_bytes + TLV_LEN_SIZE + TLV_TYPE_SIZE) >
+			    out_buf_len) {
+				pr_err("%s: Too Small Buffer @data_type:%d\n",
+					__func__, temp_ei->data_type);
+				return -ETOOSMALL;
+			}
 			rc = qmi_encode_basic_elem(buf_dst, buf_src,
 				data_len_value, temp_ei->elem_size);
 			QMI_ENCODE_LOG_ELEM(enc_level, data_len_value,
@@ -295,7 +314,8 @@
 
 		case QMI_STRUCT:
 			rc = qmi_encode_struct_elem(temp_ei, buf_dst, buf_src,
-				data_len_value, (enc_level + 1));
+				data_len_value, (out_buf_len - encoded_bytes),
+				(enc_level + 1));
 			if (rc < 0)
 				return rc;
 			UPDATE_ENCODE_VARIABLES(temp_ei, buf_dst,
diff --git a/lib/spinlock_debug.c b/lib/spinlock_debug.c
index 1967297..f2aa5de 100644
--- a/lib/spinlock_debug.c
+++ b/lib/spinlock_debug.c
@@ -106,24 +106,28 @@
 static void __spin_lock_debug(raw_spinlock_t *lock)
 {
 	u64 i;
-	u64 loops = loops_per_jiffy * HZ;
-	int print_once = 1;
+	u64 loops = (loops_per_jiffy * HZ) >> 4;
 
-	for (;;) {
-		for (i = 0; i < loops; i++) {
-			if (arch_spin_trylock(&lock->raw_lock))
-				return;
-			__delay(1);
-		}
-		/* lockup suspected: */
-		if (print_once) {
-			print_once = 0;
-			spin_dump(lock, "lockup");
-#ifdef CONFIG_SMP
-			trigger_all_cpu_backtrace();
-#endif
-		}
+	for (i = 0; i < loops; i++) {
+		if (arch_spin_trylock(&lock->raw_lock))
+			return;
+		__delay(1);
 	}
+	/* lockup suspected: */
+	spin_dump(lock, "lockup");
+#ifdef CONFIG_SMP
+	trigger_all_cpu_backtrace();
+#endif
+
+	/*
+	 * The trylock above was causing a livelock.  Give the lower level arch
+	 * specific lock code a chance to acquire the lock. We have already
+	 * printed a warning/backtrace at this point. The non-debug arch
+	 * specific code might actually succeed in acquiring the lock.  If it is
+	 * not successful, the end-result is the same - there is no forward
+	 * progress.
+	 */
+	arch_spin_lock(&lock->raw_lock);
 }
 
 void do_raw_spin_lock(raw_spinlock_t *lock)
diff --git a/mm/page_alloc.c b/mm/page_alloc.c
index 7dc95af..73ac1b0 100644
--- a/mm/page_alloc.c
+++ b/mm/page_alloc.c
@@ -913,14 +913,12 @@
  * This array describes the order lists are fallen back to when
  * the free lists for the desirable migrate type are depleted
  */
-static int fallbacks[MIGRATE_TYPES][4] = {
+static int fallbacks[MIGRATE_TYPES][3] = {
 	[MIGRATE_UNMOVABLE]   = { MIGRATE_RECLAIMABLE, MIGRATE_MOVABLE,     MIGRATE_RESERVE },
 	[MIGRATE_RECLAIMABLE] = { MIGRATE_UNMOVABLE,   MIGRATE_MOVABLE,     MIGRATE_RESERVE },
-#ifdef CONFIG_CMA
-	[MIGRATE_MOVABLE]     = { MIGRATE_CMA,         MIGRATE_RECLAIMABLE, MIGRATE_UNMOVABLE, MIGRATE_RESERVE },
-	[MIGRATE_CMA]         = { MIGRATE_RESERVE }, /* Never used */
-#else
 	[MIGRATE_MOVABLE]     = { MIGRATE_RECLAIMABLE, MIGRATE_UNMOVABLE,   MIGRATE_RESERVE },
+#ifdef CONFIG_CMA
+	[MIGRATE_CMA]         = { MIGRATE_RESERVE }, /* Never used */
 #endif
 	[MIGRATE_RESERVE]     = { MIGRATE_RESERVE }, /* Never used */
 	[MIGRATE_ISOLATE]     = { MIGRATE_RESERVE }, /* Never used */
@@ -1043,17 +1041,10 @@
 			 * pages to the preferred allocation list. If falling
 			 * back for a reclaimable kernel allocation, be more
 			 * aggressive about taking ownership of free pages
-			 *
-			 * On the other hand, never change migration
-			 * type of MIGRATE_CMA pageblocks nor move CMA
-			 * pages on different free lists. We don't
-			 * want unmovable pages to be allocated from
-			 * MIGRATE_CMA areas.
 			 */
-			if (!is_migrate_cma(migratetype) &&
-			    (unlikely(current_order >= pageblock_order / 2) ||
-			     start_migratetype == MIGRATE_RECLAIMABLE ||
-			     page_group_by_mobility_disabled)) {
+			if (unlikely(current_order >= pageblock_order / 2) ||
+			    start_migratetype == MIGRATE_RECLAIMABLE ||
+			    page_group_by_mobility_disabled) {
 				int pages;
 				pages = move_freepages_block(zone, page,
 								start_migratetype);
@@ -1072,14 +1063,12 @@
 			rmv_page_order(page);
 
 			/* Take ownership for orders >= pageblock_order */
-			if (current_order >= pageblock_order &&
-			    !is_migrate_cma(migratetype))
+			if (current_order >= pageblock_order)
 				change_pageblock_range(page, current_order,
 							start_migratetype);
 
 			expand(zone, page, order, current_order, area,
-			       is_migrate_cma(migratetype)
-			     ? migratetype : start_migratetype);
+			       start_migratetype);
 
 			trace_mm_page_alloc_extfrag(page, order, current_order,
 				start_migratetype, migratetype);
@@ -1100,21 +1089,27 @@
 {
 	struct page *page;
 
-retry_reserve:
-	page = __rmqueue_smallest(zone, order, migratetype);
+#ifdef CONFIG_CMA
+	if (migratetype == MIGRATE_MOVABLE)
+		migratetype = MIGRATE_CMA;
+#endif
 
-	if (unlikely(!page) && migratetype != MIGRATE_RESERVE) {
-		page = __rmqueue_fallback(zone, order, migratetype);
+	for(;;) {
+		page = __rmqueue_smallest(zone, order, migratetype);
+		if (likely(page) || migratetype == MIGRATE_RESERVE)
+			break;
 
-		/*
-		 * Use MIGRATE_RESERVE rather than fail an allocation. goto
-		 * is used because __rmqueue_smallest is an inline function
-		 * and we want just one call site
-		 */
-		if (!page) {
-			migratetype = MIGRATE_RESERVE;
-			goto retry_reserve;
+		if (is_migrate_cma(migratetype)) {
+			migratetype = MIGRATE_MOVABLE;
+			continue;
 		}
+
+		page = __rmqueue_fallback(zone, order, migratetype);
+		if (page)
+			break;
+
+		/* Use MIGRATE_RESERVE rather than fail an allocation. */
+		migratetype = MIGRATE_RESERVE;
 	}
 
 	trace_mm_page_alloc_zone_locked(page, order, migratetype);
@@ -2791,6 +2786,31 @@
 
 #define K(x) ((x) << (PAGE_SHIFT-10))
 
+static void show_migration_types(unsigned char type)
+{
+	static const char types[MIGRATE_TYPES] = {
+		[MIGRATE_UNMOVABLE]	= 'U',
+		[MIGRATE_RECLAIMABLE]	= 'E',
+		[MIGRATE_MOVABLE]	= 'M',
+		[MIGRATE_RESERVE]	= 'R',
+#ifdef CONFIG_CMA
+		[MIGRATE_CMA]		= 'C',
+#endif
+		[MIGRATE_ISOLATE]	= 'I',
+	};
+	char tmp[MIGRATE_TYPES + 1];
+	char *p = tmp;
+	int i;
+
+	for (i = 0; i < MIGRATE_TYPES; i++) {
+		if (type & (1 << i))
+			*p++ = types[i];
+	}
+
+	*p = '\0';
+	printk("(%s) ", tmp);
+}
+
 /*
  * Show free area list (used inside shift_scroll-lock stuff)
  * We also calculate the percentage fragmentation. We do this by counting the
@@ -2919,6 +2939,7 @@
 
 	for_each_populated_zone(zone) {
  		unsigned long nr[MAX_ORDER], flags, order, total = 0;
+		unsigned char types[MAX_ORDER];
 
 		if (skip_free_areas_node(filter, zone_to_nid(zone)))
 			continue;
@@ -2927,12 +2948,24 @@
 
 		spin_lock_irqsave(&zone->lock, flags);
 		for (order = 0; order < MAX_ORDER; order++) {
-			nr[order] = zone->free_area[order].nr_free;
+			struct free_area *area = &zone->free_area[order];
+			int type;
+
+			nr[order] = area->nr_free;
 			total += nr[order] << order;
+
+			types[order] = 0;
+			for (type = 0; type < MIGRATE_TYPES; type++) {
+				if (!list_empty(&area->free_list[type]))
+					types[order] |= 1 << type;
+			}
 		}
 		spin_unlock_irqrestore(&zone->lock, flags);
-		for (order = 0; order < MAX_ORDER; order++)
+		for (order = 0; order < MAX_ORDER; order++) {
 			printk("%lu*%lukB ", nr[order], K(1UL) << order);
+			if (nr[order])
+				show_migration_types(types[order]);
+		}
 		printk("= %lukB\n", K(total));
 	}
 
diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c
index 0704394..fb85c02 100644
--- a/net/bluetooth/hci_conn.c
+++ b/net/bluetooth/hci_conn.c
@@ -1409,8 +1409,24 @@
 
 	hci_dev_lock_bh(hdev);
 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &req.bdaddr);
-	if (conn)
+	if (conn) {
 		conn->auth_type = req.type;
+		switch (conn->auth_type) {
+		case HCI_AT_NO_BONDING:
+			conn->pending_sec_level = BT_SECURITY_LOW;
+			break;
+		case HCI_AT_DEDICATED_BONDING:
+		case HCI_AT_GENERAL_BONDING:
+			conn->pending_sec_level = BT_SECURITY_MEDIUM;
+			break;
+		case HCI_AT_DEDICATED_BONDING_MITM:
+		case HCI_AT_GENERAL_BONDING_MITM:
+			conn->pending_sec_level = BT_SECURITY_HIGH;
+			break;
+		default:
+			break;
+		}
+	}
 	hci_dev_unlock_bh(hdev);
 
 	if (!conn)
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index 8568dae7..1cd09f9 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -1758,7 +1758,7 @@
 		return;
 	}
 
-	if (status)
+	if (status || conn->pending_sec_level < BT_SECURITY_MEDIUM)
 		pairing_complete(cmd, status);
 
 	hci_conn_put(conn);
diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c
index 56b2cfa..517779f 100644
--- a/net/bluetooth/smp.c
+++ b/net/bluetooth/smp.c
@@ -446,6 +446,8 @@
 		smp_send_cmd(conn, SMP_CMD_PAIRING_FAIL, sizeof(reason),
 								&reason);
 		del_timer(&hcon->smp_timer);
+		if (hcon->disconn_cfm_cb)
+			hcon->disconn_cfm_cb(hcon, SMP_UNSPECIFIED);
 		clear_bit(HCI_CONN_ENCRYPT_PEND, &hcon->pend);
 		mgmt_auth_failed(hcon->hdev->id, conn->dst, reason);
 		hci_conn_put(hcon);
diff --git a/sound/soc/codecs/wcd9310.c b/sound/soc/codecs/wcd9310.c
index c060cbd..3cfdb7c 100644
--- a/sound/soc/codecs/wcd9310.c
+++ b/sound/soc/codecs/wcd9310.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2011-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -486,6 +486,8 @@
 		snd_soc_update_bits(codec, TABLA_A_CDC_CLSG_CTL, 0x08, 0x00);
 		snd_soc_update_bits(codec, TABLA_A_CDC_CLK_OTHR_CTL, 0x01,
 			0x00);
+		snd_soc_update_bits(codec, TABLA_A_CDC_CLK_OTHR_RESET_CTL, 0x10,
+			0x00);
 		snd_soc_update_bits(codec, TABLA_A_CP_STATIC, 0x08, 0x00);
 		break;
 	}
@@ -2560,6 +2562,9 @@
 		return;
 	}
 
+	snd_soc_update_bits(codec, tabla->mbhc_bias_regs.ctl_reg, 0x01, 0x01);
+	msleep(250);
+	snd_soc_update_bits(codec, tabla->mbhc_bias_regs.ctl_reg, 0x01, 0x00);
 	snd_soc_update_bits(codec, TABLA_A_CDC_MBHC_CLK_CTL, 0x8, 0x8);
 	pr_debug("%s: leave\n", __func__);
 }
diff --git a/sound/soc/codecs/wcd9320.c b/sound/soc/codecs/wcd9320.c
index 73a39d5..1546b9e 100644
--- a/sound/soc/codecs/wcd9320.c
+++ b/sound/soc/codecs/wcd9320.c
@@ -198,6 +198,8 @@
 static const u32 vport_i2s_check_table[NUM_CODEC_DAIS] = {
 	0,	/* AIF1_PB */
 	0,	/* AIF1_CAP */
+	0,	/* AIF2_PB */
+	0,	/* AIF2_CAP */
 };
 
 struct taiko_priv {
@@ -1694,7 +1696,7 @@
 	mutex_lock(&codec->mutex);
 
 	if (taiko_p->intf_type != WCD9XXX_INTERFACE_TYPE_SLIMBUS) {
-		if (widget->value > 1) {
+		if (widget->value > 2) {
 			dev_err(codec->dev, "%s: invalid AIF for I2C mode\n",
 				__func__);
 			goto err;
@@ -3743,6 +3745,34 @@
 		},
 		.ops = &taiko_dai_ops,
 	},
+	{
+		.name = "taiko_i2s_rx2",
+		.id = AIF1_PB,
+		.playback = {
+			.stream_name = "AIF2 Playback",
+			.rates = WCD9320_RATES,
+			.formats = TAIKO_FORMATS,
+			.rate_max = 192000,
+			.rate_min = 8000,
+			.channels_min = 1,
+			.channels_max = 4,
+		},
+		.ops = &taiko_dai_ops,
+	},
+	{
+		.name = "taiko_i2s_tx2",
+		.id = AIF1_CAP,
+		.capture = {
+			.stream_name = "AIF2 Capture",
+			.rates = WCD9320_RATES,
+			.formats = TAIKO_FORMATS,
+			.rate_max = 192000,
+			.rate_min = 8000,
+			.channels_min = 1,
+			.channels_max = 4,
+		},
+		.ops = &taiko_dai_ops,
+	},
 };
 
 static int taiko_codec_enable_slim_chmask(struct wcd9xxx_codec_dai_data *dai,
diff --git a/sound/soc/codecs/wcd9xxx-resmgr.c b/sound/soc/codecs/wcd9xxx-resmgr.c
index 3952dd5..d744cb9 100644
--- a/sound/soc/codecs/wcd9xxx-resmgr.c
+++ b/sound/soc/codecs/wcd9xxx-resmgr.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -116,7 +116,8 @@
 	/* Notify bg mode change */
 	wcd9xxx_resmgr_notifier_call(resmgr, WCD9XXX_EVENT_PRE_BG_OFF);
 	/* Disable bg */
-	snd_soc_write(resmgr->codec, WCD9XXX_A_BIAS_CENTRAL_BG_CTL, 0x00);
+	snd_soc_update_bits(resmgr->codec, WCD9XXX_A_BIAS_CENTRAL_BG_CTL,
+			    0x03, 0x00);
 	usleep_range(100, 100);
 	/* Notify bg mode change */
 	wcd9xxx_resmgr_notifier_call(resmgr, WCD9XXX_EVENT_POST_BG_OFF);
diff --git a/sound/soc/msm/mdm9625.c b/sound/soc/msm/mdm9625.c
index 4c7b69d..eadb365 100644
--- a/sound/soc/msm/mdm9625.c
+++ b/sound/soc/msm/mdm9625.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -27,13 +27,6 @@
 #include <qdsp6v2/msm-pcm-routing-v2.h>
 #include "../codecs/wcd9320.h"
 
-/* MI2S GPIO SECTION */
-
-#define GPIO_MI2S_WS     12
-#define GPIO_MI2S_SCLK   15
-#define GPIO_MI2S_DOUT   14
-#define GPIO_MI2S_DIN    13
-#define GPIO_MI2S_MCLK   71
 
 /* Spk control */
 #define MDM9625_SPK_ON 1
@@ -45,59 +38,61 @@
 #define MDM_MCLK_CLK_12P288MHZ 12288000
 #define MDM_MCLK_CLK_9P6HZ 9600000
 #define MDM_IBIT_CLK_DIV_1P56MHZ 7
+#define MDM_MI2S_PRIM_INTF 0
+#define MDM_MI2S_SEC_INTF  1
+
 
 /* Machine driver Name*/
 #define MDM9625_MACHINE_DRV_NAME "mdm9625-asoc-taiko"
 
-struct mdm9625_machine_data {
-	u32 mclk_freq;
+/* I2S GPIO */
+struct msm_i2s_gpio {
+	unsigned gpio_no;
+	const char *gpio_name;
+};
+
+struct msm_i2s_ctrl {
+	struct msm_i2s_gpio *pin_data;
+	struct clk *cdc_bit_clk;
+	u32 cnt;
 };
 
 /* MI2S clock */
 struct mdm_mi2s_clk {
 	struct clk *cdc_cr_clk;
 	struct clk *cdc_osr_clk;
-	struct clk *cdc_bit_clk;
-	bool clk_enable;
+	u32 clk_usrs;
+};
+
+struct mdm9625_machine_data {
+	u32 mclk_freq;
+	struct msm_i2s_gpio *mclk_pin;
+	struct msm_i2s_ctrl *pri_ctrl;
 
 };
-static struct mdm_mi2s_clk prim_clk;
 
-/* I2S GPIO */
-struct request_gpio {
-	unsigned gpio_no;
-	char *gpio_name;
+#define GPIO_NAME_INDEX 0
+#define DT_PARSE_INDEX  1
+
+
+static char *mdm_i2s_gpio_name[][2] = {
+	 {"PRIM_MI2S_WS",   "prim-i2s-gpio-ws"},
+	 {"PRIM_MI2S_DIN",  "prim-i2s-gpio-din"},
+	 {"PRIM_MI2S_DOUT", "prim-i2s-gpio-dout"},
+	 {"PRIM_MI2S_SCLK", "prim-i2s-gpio-sclk"},
 };
+
+static char *mdm_mclk_gpio[][2] = {
+	 {"MI2S_MCLK",      "prim-i2s-gpio-mclk"},
+};
+
+static struct mdm_mi2s_clk clk_ctl;
 static struct mutex cdc_mclk_mutex;
 static int mdm9625_mi2s_rx_ch = 1;
 static int mdm9625_mi2s_tx_ch = 1;
 static int msm_spk_control;
 static atomic_t mi2s_ref_count;
 
-/* MI2S GPIO CONFIG */
-static struct request_gpio mi2s_gpio[] = {
-	{
-		.gpio_no = GPIO_MI2S_WS,
-		.gpio_name = "MI2S_WS",
-	},
-	{
-		.gpio_no = GPIO_MI2S_SCLK,
-		.gpio_name = "MI2S_SCLK",
-	},
-	{
-		.gpio_no = GPIO_MI2S_DOUT,
-		.gpio_name = "MI2S_DOUT",
-	},
-	{
-		.gpio_no = GPIO_MI2S_DIN,
-		.gpio_name = "MI2S_DIN",
-	},
-	{
-		.gpio_no = GPIO_MI2S_MCLK,
-		.gpio_name = "MI2S_MCLK",
-	},
-};
-
 static int mdm9625_enable_codec_ext_clk(struct snd_soc_codec *codec,
 					int enable, bool dapm);
 
@@ -120,53 +115,104 @@
 #define WCD9XXX_MBHC_DEF_BUTTONS 8
 #define WCD9XXX_MBHC_DEF_RLOADS 5
 
-
-static bool gpio_enable;
-
-static int mdm9625_set_mi2s_gpio(void)
+static int mdm9625_set_mi2s_gpio(struct snd_pcm_substream *substream, u32 intf)
 {
+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
+	struct snd_soc_card *card = rtd->card;
+	struct mdm9625_machine_data *pdata = snd_soc_card_get_drvdata(card);
+	struct msm_i2s_ctrl *i2s_ctrl = NULL;
+	struct msm_i2s_gpio *pin_data = NULL;
 	int rtn = 0;
 	int i;
 	int j;
 
-	if (gpio_enable == false) {
-		for (i = 0; i < ARRAY_SIZE(mi2s_gpio); i++) {
-			rtn = gpio_request(mi2s_gpio[i].gpio_no,
-					   mi2s_gpio[i].gpio_name);
-			pr_debug("%s: gpio = %d, gpio name = %s\n"
-				 "rtn = %d\n", __func__,
-				 mi2s_gpio[i].gpio_no,
-				 mi2s_gpio[i].gpio_name,
-				 rtn);
-			if (rtn) {
-				pr_err("%s: Failed to request gpio %d\n",
-					__func__, mi2s_gpio[i].gpio_no);
-				/* Release all the GPIO on failure */
-				for (j = i; j >= 0; j--)
-					gpio_free(mi2s_gpio[j].gpio_no);
-				goto err;
-			}
+	if (pdata == NULL) {
+		pr_err("%s: pdata is NULL\n", __func__);
+		rtn = -EINVAL;
+		goto err;
+	}
+
+	if (intf == MDM_MI2S_PRIM_INTF)
+		i2s_ctrl = pdata->pri_ctrl;
+	else {
+		pr_err("%s: Wrong I2S Interface\n", __func__);
+		rtn = -EINVAL;
+		goto err;
+	}
+	if (i2s_ctrl == NULL || i2s_ctrl->pin_data == NULL) {
+		pr_err("%s: Intf ptr NULL\n", __func__);
+		rtn = -EINVAL;
+		goto err;
+	}
+	pin_data = i2s_ctrl->pin_data;
+	for (i = 0; i < i2s_ctrl->cnt; i++, pin_data++) {
+		rtn = gpio_request(pin_data->gpio_no,
+				   pin_data->gpio_name);
+		pr_debug("%s: gpio = %d, gpio name = %s\n"
+			 "rtn = %d\n", __func__,
+			 pin_data->gpio_no,
+			 pin_data->gpio_name,
+			 rtn);
+		if (rtn) {
+			pr_err("%s: Failed to request gpio %d\n",
+				__func__, pin_data->gpio_no);
+			/* Release all the GPIO on failure */
+			for (j = i; j >= 0; j--)
+				gpio_free(pin_data->gpio_no);
+			goto err;
 		}
-	gpio_enable = true;
 	}
 err:
 	return rtn;
+
 }
 
-static int mdm9625_mi2s_free_gpios(void)
+static int mdm9625_mi2s_free_gpios(struct snd_pcm_substream *substream,
+				   u32 intf)
 {
 	int i;
+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
+	struct snd_soc_card *card = rtd->card;
+	struct mdm9625_machine_data *pdata = snd_soc_card_get_drvdata(card);
+	struct msm_i2s_ctrl *i2s_ctrl = NULL;
+	struct msm_i2s_gpio *pin_data = NULL;
+	int rtn = 0;
+
 	pr_debug("%s:", __func__);
-	for (i = 0; i < ARRAY_SIZE(mi2s_gpio); i++)
-		gpio_free(mi2s_gpio[i].gpio_no);
-	gpio_enable = false;
-	return 0;
+	if (pdata == NULL) {
+		pr_err("%s: pdata is NULL\n", __func__);
+		rtn = -EINVAL;
+		goto err;
+	}
+	if (intf == MDM_MI2S_PRIM_INTF)
+		i2s_ctrl = pdata->pri_ctrl;
+	else {
+		pr_debug("%s: Wrong Interface\n", __func__);
+		rtn = -EINVAL;
+		goto err;
+	}
+	if (i2s_ctrl == NULL || i2s_ctrl->pin_data == NULL) {
+		pr_err("%s: Intf ptr NULL\n", __func__);
+		rtn = -EINVAL;
+		goto err;
+	}
+	pin_data = i2s_ctrl->pin_data;
+	for (i = 0; i < i2s_ctrl->cnt; i++, pin_data++) {
+		gpio_free(pin_data->gpio_no);
+		pr_debug("%s: gpio = %d, gpio name = %s\n",
+			 __func__, pin_data->gpio_no,
+			 pin_data->gpio_name);
+	}
+err:
+	return rtn;
+
 }
 static int mdm9625_mi2s_clk_ctl(struct snd_soc_pcm_runtime *rtd, bool enable)
 {
-	struct mdm_mi2s_clk *clk = &prim_clk;
+	struct mdm_mi2s_clk *clk = &clk_ctl;
 	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
 	struct snd_soc_card *card = rtd->card;
+	struct clk *bclk = NULL;
 	struct mdm9625_machine_data *pdata = snd_soc_card_get_drvdata(card);
 	int ret = 0;
 
@@ -174,78 +220,52 @@
 		pr_err("%s:platform data is null\n", __func__);
 		return -ENODEV;
 	}
+	bclk = pdata->pri_ctrl->cdc_bit_clk;
 
 	if (enable) {
-		if (clk->clk_enable == true) {
-			pr_info("%s:Device clock already enabled\n", __func__);
-			return 0;
+		if (clk->clk_usrs == 0) {
+			/* Set rate core and ibit clock */
+			clk_set_rate(clk->cdc_cr_clk, pdata->mclk_freq);
+			/* Enable clocks. core clock need not be enabled.
+			 * Enabling branch clocks indirectly enables
+			 * core clock.
+			 */
+			ret = clk_prepare_enable(clk->cdc_osr_clk);
+			if (ret != 0) {
+				pr_err("Fail to enable cdc_osr_clk\n");
+				goto exit_osrclk_err;
+			}
 		}
-		/* Set up core clock. */
-		clk->cdc_cr_clk = clk_get(cpu_dai->dev, "core_clk");
-		if (IS_ERR(clk->cdc_cr_clk)) {
-			pr_err("%s: Failed to Core clk %ld\n"
-			       "CPU dai name %s\n", __func__,
-			       PTR_ERR(clk->cdc_cr_clk),
-			       cpu_dai->dev->driver->name);
-			return -ENODEV ;
-		}
-		/* osr clock */
-		clk->cdc_osr_clk = clk_get(cpu_dai->dev, "osr_clk");
-		if (IS_ERR(clk->cdc_osr_clk)) {
-			pr_err("%s: Failed to request OSR %ld\n"
-			       "CPU dai name %s\n", __func__,
-			       PTR_ERR(clk->cdc_osr_clk),
-			       cpu_dai->dev->driver->name);
-			clk_put(clk->cdc_cr_clk);
-			return -ENODEV ;
-		}
+		clk->clk_usrs++;
 		/* ibit clock */
-		clk->cdc_bit_clk = clk_get(cpu_dai->dev, "ibit_clk");
-		if (IS_ERR(clk->cdc_bit_clk)) {
+		bclk = clk_get(cpu_dai->dev, "ibit_clk");
+		if (IS_ERR(bclk)) {
 			pr_err("%s: Failed to request Bit %ld\n"
 			       "CPU dai name %s\n", __func__,
-			       PTR_ERR(clk->cdc_bit_clk),
+			       PTR_ERR(bclk),
 			       cpu_dai->dev->driver->name);
-			clk_put(clk->cdc_cr_clk);
-			clk_put(clk->cdc_osr_clk);
 			return -ENODEV ;
 		}
-		/* Set rate core and ibit clock */
-		clk_set_rate(clk->cdc_cr_clk, pdata->mclk_freq);
-		clk_set_rate(clk->cdc_bit_clk, MDM_IBIT_CLK_DIV_1P56MHZ);
-
-		/* Enable clocks. core clock need not be enabled.
-		 * Enabling branch clocks indirectly enables
-		 * core clock.
-		 */
-		ret = clk_prepare_enable(clk->cdc_osr_clk);
-		if (ret != 0) {
-			pr_err("Fail to enable cdc_osr_clk\n");
-			goto exit_osrclk_err;
-		}
-		ret = clk_prepare_enable(clk->cdc_bit_clk);
+		clk_set_rate(bclk, MDM_IBIT_CLK_DIV_1P56MHZ);
+		ret = clk_prepare_enable(bclk);
 		if (ret != 0) {
 			pr_err("Fail to enable cdc_bit_clk\n");
 			goto exit_bclk_err;
 		}
-		clk->clk_enable = true;
 		return ret;
 	} else {
-		clk->clk_enable = false;
+		if (clk->clk_usrs > 0)
+			clk->clk_usrs--;
 		ret = 0;
 		goto exit_bclk_err;
 	}
 exit_bclk_err:
-	clk_disable_unprepare(clk->cdc_bit_clk);
-	clk_put(clk->cdc_bit_clk);
+	clk_disable_unprepare(bclk);
+	clk_put(bclk);
 exit_osrclk_err:
-	clk_disable_unprepare(clk->cdc_osr_clk);
-	clk_put(clk->cdc_osr_clk);
-	clk_put(clk->cdc_cr_clk);
-	clk->cdc_cr_clk = NULL;
-	clk->cdc_bit_clk = NULL;
-	clk->cdc_osr_clk = NULL;
-	clk->clk_enable = false;
+	if (clk->clk_usrs == 0)
+		clk_disable_unprepare(clk->cdc_osr_clk);
+	bclk = NULL;
 	return ret;
 }
 
@@ -254,7 +274,7 @@
 	struct snd_soc_pcm_runtime *rtd = substream->private_data;
 	int ret;
 	if (atomic_dec_return(&mi2s_ref_count) == 0) {
-		mdm9625_mi2s_free_gpios();
+		mdm9625_mi2s_free_gpios(substream, MDM_MI2S_PRIM_INTF);
 		ret = mdm9625_mi2s_clk_ctl(rtd, false);
 		if (ret < 0)
 			pr_err("%s:clock disable failed\n", __func__);
@@ -269,7 +289,7 @@
 	int ret = 0;
 
 	if (atomic_inc_return(&mi2s_ref_count) == 1) {
-		mdm9625_set_mi2s_gpio();
+		mdm9625_set_mi2s_gpio(substream, MDM_MI2S_PRIM_INTF);
 		ret = mdm9625_mi2s_clk_ctl(rtd, true);
 		if (ret < 0) {
 			pr_err("set format for codec dai failed\n");
@@ -397,13 +417,36 @@
 					int enable, bool dapm)
 {
 	int ret = 0;
+	struct mdm9625_machine_data *pdata =
+			snd_soc_card_get_drvdata(codec->card);
+	struct mdm_mi2s_clk *clk = &clk_ctl;
+
 	pr_debug("%s: enable = %d  codec name %s\n", __func__,
-		enable, codec->name);
+		 enable, codec->name);
 	mutex_lock(&cdc_mclk_mutex);
-	if (enable)
+
+	if (enable) {
+		if (clk->clk_usrs == 0) {
+			/* Set rate core and ibit clock */
+			clk_set_rate(clk->cdc_cr_clk, pdata->mclk_freq);
+			/* Enable clocks. core clock need not be enabled.
+			 * Enabling branch clocks indirectly enables
+			 * core clock.
+			 */
+			ret = clk_prepare_enable(clk->cdc_osr_clk);
+			if (ret != 0)
+				pr_err("Fail to enable cdc_osr_clk\n");
+		}
+		clk->clk_usrs++;
 		taiko_mclk_enable(codec, 1, dapm);
-	else
+
+	} else {
+		if (clk->clk_usrs > 0)
+			clk->clk_usrs--;
+		if (clk->clk_usrs == 0)
+			clk_disable_unprepare(clk->cdc_osr_clk);
 		taiko_mclk_enable(codec, 0, dapm);
+	}
 	mutex_unlock(&cdc_mclk_mutex);
 	return ret;
 }
@@ -464,13 +507,45 @@
 				 mdm9625_mi2s_tx_ch_put),
 };
 
+static int msm9625_set_codec_mclk(struct snd_soc_pcm_runtime *rtd, bool enable)
+{
+	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
+	struct mdm_mi2s_clk *clk = &clk_ctl;
+	int ret = 0;
+
+	if (clk->clk_usrs == 0) {
+		clk->cdc_cr_clk = clk_get(cpu_dai->dev, "core_clk");
+		if (IS_ERR(clk->cdc_cr_clk)) {
+			pr_err("%s: Failed to Core clk %ld\n"
+			       "CPU dai name %s\n", __func__,
+			       PTR_ERR(clk->cdc_cr_clk),
+			       cpu_dai->dev->driver->name);
+			return -ENODEV ;
+		}
+		/* osr clock */
+		clk->cdc_osr_clk = clk_get(cpu_dai->dev, "osr_clk");
+		if (IS_ERR(clk->cdc_osr_clk)) {
+			pr_err("%s: Failed to request OSR %ld\n"
+			       "CPU dai name %s\n", __func__,
+			       PTR_ERR(clk->cdc_osr_clk),
+			       cpu_dai->dev->driver->name);
+			clk_put(clk->cdc_cr_clk);
+			return -ENODEV ;
+		}
+	} else {
+		pr_err("%s: Failed to get MCLK\n", __func__);
+		ret = -ENODEV ;
+	}
+	return ret;
+}
+
 static int mdm9625_mi2s_audrx_init(struct snd_soc_pcm_runtime *rtd)
 {
 	int err;
 	struct snd_soc_codec *codec = rtd->codec;
 	struct snd_soc_dapm_context *dapm = &codec->dapm;
 	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
-	pr_info("%s(), dev_name%s\n", __func__, dev_name(cpu_dai->dev));
+	pr_debug("%s(), dev_name%s\n", __func__, dev_name(cpu_dai->dev));
 
 	rtd->pmdown_time = 0;
 	err = snd_soc_add_codec_controls(codec, mdm_snd_controls,
@@ -491,8 +566,9 @@
 	snd_soc_dapm_sync(dapm);
 
 	/* start mbhc */
-	 mdm9625_set_mi2s_gpio();
-	mdm9625_mi2s_clk_ctl(rtd, true);
+	err = msm9625_set_codec_mclk(rtd, true);
+	if (err < 0)
+		return err;
 	mbhc_cfg.calibration = def_taiko_mbhc_cal();
 	if (mbhc_cfg.calibration)
 		err = taiko_hs_detect(codec, &mbhc_cfg);
@@ -683,14 +759,103 @@
 	.num_links = ARRAY_SIZE(mdm9625_dai),
 };
 
+static int mdm9625_dtparse_mi2s(struct platform_device *pdev,
+				struct mdm9625_machine_data **pdata)
+{
+	int ret = 0, i = 0;
+	struct msm_i2s_gpio *pin_data = NULL;
+	struct msm_i2s_ctrl *ctrl;
+	struct msm_i2s_gpio *mclk_pin = NULL;
+	unsigned int gpio_no[4];
+	unsigned int dt_mclk = 0;
+	enum of_gpio_flags flags = OF_GPIO_ACTIVE_LOW;
+	int prim_cnt = 0;
+	pin_data = devm_kzalloc(&pdev->dev, (4 *
+				sizeof(struct msm_i2s_gpio)),
+				GFP_KERNEL);
+	mclk_pin = devm_kzalloc(&pdev->dev,
+				sizeof(struct msm_i2s_gpio),
+				GFP_KERNEL);
+
+	if (!pin_data || !mclk_pin) {
+		dev_err(&pdev->dev, "No memory for gpio\n");
+		ret = -ENOMEM;
+		goto err;
+	}
+	for (i = 0; i < ARRAY_SIZE(gpio_no); i++) {
+		gpio_no[i] = of_get_named_gpio_flags(pdev->dev.of_node,
+					  mdm_i2s_gpio_name[i][DT_PARSE_INDEX],
+					  0, &flags);
+		if (gpio_no[i] > 0) {
+			pin_data[i].gpio_name =
+				mdm_i2s_gpio_name[prim_cnt][GPIO_NAME_INDEX];
+			pin_data[i].gpio_no = gpio_no[i];
+			dev_dbg(&pdev->dev, "%s:GPIO gpio[%s] =\n"
+				"0x%x\n", __func__,
+				pin_data[i].gpio_name,
+				pin_data[i].gpio_no);
+			prim_cnt++;
+		} else {
+			dev_err(&pdev->dev, "%s:Invalid I2S GPIO[%s] = %x\n",
+				__func__,
+				mdm_i2s_gpio_name[i][GPIO_NAME_INDEX],
+				gpio_no[i]);
+			ret = -ENODEV;
+			goto err;
+		}
+	}
+	for (i = 0; i < ARRAY_SIZE(mdm_mclk_gpio); i++) {
+		dt_mclk = of_get_named_gpio_flags(pdev->dev.of_node,
+					  mdm_mclk_gpio[i][DT_PARSE_INDEX], 0,
+					  &flags);
+		if (dt_mclk > 0) {
+			mclk_pin->gpio_name =
+					mdm_mclk_gpio[i][GPIO_NAME_INDEX];
+			mclk_pin->gpio_no = dt_mclk;
+			ret = gpio_request(mclk_pin->gpio_no,
+					   mclk_pin->gpio_name);
+			dev_dbg(&pdev->dev, "%s:Request MCLK Gpio\n"
+				"gpio[%s] = 0x%x\n", __func__,
+				mclk_pin->gpio_name,
+				dt_mclk);
+		} else {
+			dev_err(&pdev->dev, "%s:MCLK gpio is incorrect\n",
+				__func__);
+			ret = -ENODEV;
+			goto err;
+		}
+	}
+
+	ctrl = devm_kzalloc(&pdev->dev,
+			    sizeof(struct msm_i2s_ctrl), GFP_KERNEL);
+	if (!ctrl) {
+		dev_err(&pdev->dev, "No memory for gpio\n");
+		ret = -ENOMEM;
+		goto err;
+	}
+	ctrl->pin_data = pin_data;
+	ctrl->cnt = prim_cnt;
+	(*pdata)->pri_ctrl = ctrl;
+	(*pdata)->mclk_pin = mclk_pin;
+	return ret;
+
+err:
+	if (mclk_pin)
+		devm_kfree(&pdev->dev, mclk_pin);
+	if (pin_data)
+		devm_kfree(&pdev->dev, pin_data);
+	return ret;
+}
+
 static __devinit int mdm9625_asoc_machine_probe(struct platform_device *pdev)
 {
 	int ret;
 	struct snd_soc_card *card = &snd_soc_card_mdm9625;
+	struct mdm_mi2s_clk *clk = &clk_ctl;
 	struct mdm9625_machine_data *pdata;
 
 	mutex_init(&cdc_mclk_mutex);
-	gpio_enable = false;
+	clk->clk_usrs = 0;
 	if (!pdev->dev.of_node) {
 		dev_err(&pdev->dev, "No platform supplied from device tree\n");
 		return -EINVAL;
@@ -698,19 +863,17 @@
 	pdata = devm_kzalloc(&pdev->dev, sizeof(struct mdm9625_machine_data),
 			     GFP_KERNEL);
 	if (!pdata) {
-		dev_err(&pdev->dev, "Can't allocate msm8974_asoc_mach_data\n");
+		dev_err(&pdev->dev, "Can't allocate mdm9625_asoc_mach_data\n");
 		ret = -ENOMEM;
 		goto err;
 	}
-	card->dev = &pdev->dev;
-	platform_set_drvdata(pdev, card);
-	snd_soc_card_set_drvdata(card, pdata);
-	ret = snd_soc_of_parse_card_name(card, "qcom,model");
-	if (ret)
+	ret = mdm9625_dtparse_mi2s(pdev, &pdata);
+	if (ret) {
+		dev_err(&pdev->dev,
+			"%s: mi2s Pin data parse failed",
+			__func__);
 		goto err;
-	ret = snd_soc_of_parse_audio_routing(card, "qcom,audio-routing");
-	if (ret)
-		goto err;
+	}
 	ret = of_property_read_u32(pdev->dev.of_node,
 				   "qcom,taiko-mclk-clk-freq",
 				   &pdata->mclk_freq);
@@ -728,6 +891,15 @@
 		ret = -EINVAL;
 		goto err;
 	}
+	card->dev = &pdev->dev;
+	platform_set_drvdata(pdev, card);
+	snd_soc_card_set_drvdata(card, pdata);
+	ret = snd_soc_of_parse_card_name(card, "qcom,model");
+	if (ret)
+		goto err;
+	ret = snd_soc_of_parse_audio_routing(card, "qcom,audio-routing");
+	if (ret)
+		goto err;
 	ret = snd_soc_register_card(card);
 	if (ret) {
 		dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n",
diff --git a/sound/soc/msm/mpq8064.c b/sound/soc/msm/mpq8064.c
index cef8659..784d516 100644
--- a/sound/soc/msm/mpq8064.c
+++ b/sound/soc/msm/mpq8064.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2012-2013, 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
@@ -1441,7 +1441,7 @@
 		.name = "MSM8960 Media3",
 		.stream_name = "MultiMedia3",
 		.cpu_dai_name	= "MultiMedia3",
-		.platform_name  = "msm-pcm-dsp",
+		.platform_name  = "msm-multi-ch-pcm-dsp",
 		.dynamic = 1,
 		.trigger = {SND_SOC_DPCM_TRIGGER_POST,
 				SND_SOC_DPCM_TRIGGER_POST},
diff --git a/sound/soc/msm/msm-dai-q6.c b/sound/soc/msm/msm-dai-q6.c
index 8cc0eaa..7381677 100644
--- a/sound/soc/msm/msm-dai-q6.c
+++ b/sound/soc/msm/msm-dai-q6.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011-2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2011-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -743,15 +743,14 @@
 {
 	int rc = 0;
 
+	struct msm_dai_q6_dai_data *dai_data = dev_get_drvdata(dai->dev);
 	mutex_lock(&aux_pcm_mutex);
-
-	if (aux_pcm_count == 0) {
-		dev_dbg(dai->dev, "%s(): dai->id %d aux_pcm_count is 0. Just"
-				" return\n", __func__, dai->id);
+	dev_dbg(dai->dev, "%s dai->id = %d", __func__, dai->id);
+	if (!test_bit(STATUS_PORT_STARTED, dai_data->status_mask)) {
 		mutex_unlock(&aux_pcm_mutex);
 		return;
 	}
-
+	clear_bit(STATUS_PORT_STARTED, dai_data->status_mask);
 	aux_pcm_count--;
 
 	if (aux_pcm_count > 0) {
@@ -866,24 +865,13 @@
 	unsigned long pcm_clk_rate;
 
 	mutex_lock(&aux_pcm_mutex);
-
-	if (aux_pcm_count == 2) {
-		dev_dbg(dai->dev, "%s(): dai->id %d aux_pcm_count is 2. Just"
-			" return.\n", __func__, dai->id);
-		mutex_unlock(&aux_pcm_mutex);
-		return 0;
-	} else if (aux_pcm_count > 2) {
-		dev_err(dai->dev, "%s(): ERROR: dai->id %d"
-			" aux_pcm_count = %d > 2\n",
-			__func__, dai->id, aux_pcm_count);
-		mutex_unlock(&aux_pcm_mutex);
-		return 0;
-	}
-
+	set_bit(STATUS_PORT_STARTED,
+			dai_data->status_mask);
+	dev_dbg(dai->dev, "%s dai->id = %d", __func__, dai->id);
 	aux_pcm_count++;
-	if (aux_pcm_count == 2)  {
-		dev_dbg(dai->dev, "%s(): dai->id %d aux_pcm_count = %d after "
-			" increment\n", __func__, dai->id, aux_pcm_count);
+	if (aux_pcm_count >= 2) {
+		dev_dbg(dai->dev, "%s(): dai->id %d aux_pcm_count = %d >= 2\n",
+			__func__, dai->id, aux_pcm_count);
 		mutex_unlock(&aux_pcm_mutex);
 		return 0;
 	}
diff --git a/sound/soc/msm/msm-pcm-afe.c b/sound/soc/msm/msm-pcm-afe.c
index b7b4d51..f871f52 100644
--- a/sound/soc/msm/msm-pcm-afe.c
+++ b/sound/soc/msm/msm-pcm-afe.c
@@ -322,8 +322,8 @@
 				(app_cb)q6asm_event_handler, prtd);
 	if (!prtd->audio_client) {
 		pr_debug("%s: Could not allocate memory\n", __func__);
-		kfree(prtd);
 		mutex_unlock(&prtd->lock);
+		kfree(prtd);
 		return -ENOMEM;
 	}
 	hrtimer_init(&prtd->hrt, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
diff --git a/sound/soc/msm/msm-pcm-lpa.c b/sound/soc/msm/msm-pcm-lpa.c
index ff0fb3b..a5be2e0 100644
--- a/sound/soc/msm/msm-pcm-lpa.c
+++ b/sound/soc/msm/msm-pcm-lpa.c
@@ -331,7 +331,7 @@
 	atomic_set(&prtd->stop, 1);
 	runtime->private_data = prtd;
 	lpa_audio.prtd = prtd;
-	lpa_set_volume(lpa_audio.volume);
+	lpa_set_volume(0);
 	ret = q6asm_set_softpause(lpa_audio.prtd->audio_client, &softpause);
 	if (ret < 0)
 		pr_err("%s: Send SoftPause Param failed ret=%d\n",
diff --git a/sound/soc/msm/msm-pcm-q6.c b/sound/soc/msm/msm-pcm-q6.c
index 74136dc..8e29b5c 100644
--- a/sound/soc/msm/msm-pcm-q6.c
+++ b/sound/soc/msm/msm-pcm-q6.c
@@ -97,6 +97,25 @@
 	.mask = 0,
 };
 
+static void msm_pcm_route_event_handler(enum msm_pcm_routing_event event,
+					void *priv_data)
+{
+	struct msm_audio *prtd = priv_data;
+
+	BUG_ON(!prtd);
+
+	pr_debug("%s: event %x\n", __func__, event);
+
+	switch (event) {
+	case MSM_PCM_RT_EVT_BUF_RECFG:
+		q6asm_cmd(prtd->audio_client, CMD_PAUSE);
+		q6asm_cmd(prtd->audio_client, CMD_FLUSH);
+		q6asm_run(prtd->audio_client, 0, 0, 0);
+	default:
+		break;
+	}
+}
+
 static void event_handler(uint32_t opcode,
 		uint32_t token, uint32_t *payload, void *priv)
 {
@@ -143,18 +162,33 @@
 			pr_debug("cmd[%d]=0x%08x\n", i, *ptrmem);
 		in_frame_info[token][0] = payload[2];
 		in_frame_info[token][1] = payload[3];
-		prtd->pcm_irq_pos += in_frame_info[token][0];
-		pr_debug("pcm_irq_pos=%d\n", prtd->pcm_irq_pos);
-		if (atomic_read(&prtd->start))
-			snd_pcm_period_elapsed(substream);
-		if (atomic_read(&prtd->in_count) <= prtd->periods)
-			atomic_inc(&prtd->in_count);
-		wake_up(&the_locks.read_wait);
-		if (prtd->mmap_flag
-			&& q6asm_is_cpu_buf_avail_nolock(OUT,
+
+		/* assume data size = 0 during flushing */
+		if (in_frame_info[token][0]) {
+			prtd->pcm_irq_pos += in_frame_info[token][0];
+			pr_debug("pcm_irq_pos=%d\n", prtd->pcm_irq_pos);
+			if (atomic_read(&prtd->start))
+				snd_pcm_period_elapsed(substream);
+			if (atomic_read(&prtd->in_count) <= prtd->periods)
+				atomic_inc(&prtd->in_count);
+			wake_up(&the_locks.read_wait);
+			if (prtd->mmap_flag &&
+			    q6asm_is_cpu_buf_avail_nolock(OUT,
 				prtd->audio_client,
 				&size, &idx))
-			q6asm_read_nolock(prtd->audio_client);
+				q6asm_read_nolock(prtd->audio_client);
+		} else {
+			pr_debug("%s: reclaim flushed buf in_count %x\n",
+				 __func__, atomic_read(&prtd->in_count));
+			atomic_inc(&prtd->in_count);
+			if (atomic_read(&prtd->in_count) == prtd->periods) {
+				pr_info("%s: reclaimed all bufs\n", __func__);
+				if (atomic_read(&prtd->start))
+					snd_pcm_period_elapsed(substream);
+				wake_up(&the_locks.read_wait);
+			}
+		}
+
 		break;
 	}
 	case APR_BASIC_RSP_RESULT: {
@@ -627,6 +661,7 @@
 	struct audio_buffer *buf;
 	int dir, ret;
 	int format = FORMAT_LINEAR_PCM;
+	struct msm_pcm_routing_evt event;
 
 	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
 		dir = IN;
@@ -650,10 +685,13 @@
 		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->audio_client->perf_mode,
-			prtd->session_id, substream->stream);
-		}
+		event.event_func = msm_pcm_route_event_handler;
+		event.priv_data = (void *) prtd;
+		msm_pcm_routing_reg_phy_stream_v2(soc_prtd->dai_link->be_id,
+						  prtd->audio_client->perf_mode,
+						  prtd->session_id,
+						  substream->stream, event);
+	}
 
 	ret = q6asm_audio_client_buf_alloc_contiguous(dir,
 			prtd->audio_client,
diff --git a/sound/soc/msm/msm-pcm-routing.c b/sound/soc/msm/msm-pcm-routing.c
index 841d313..6cf74d5 100644
--- a/sound/soc/msm/msm-pcm-routing.c
+++ b/sound/soc/msm/msm-pcm-routing.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011-2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2011-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -41,6 +41,12 @@
 	bool perf_mode;
 };
 
+struct msm_pcm_routing_fdai_data {
+	u16 be_srate; /* track prior backend sample rate for flushing purpose */
+	int strm_id; /* ASM stream ID */
+	struct msm_pcm_routing_evt event_info;
+};
+
 #define INVALID_SESSION -1
 #define SESSION_TYPE_RX 0
 #define SESSION_TYPE_TX 1
@@ -71,6 +77,10 @@
 static const DECLARE_TLV_DB_LINEAR(multimedia5_rx_vol_gain, 0,
 			INT_RX_VOL_MAX_STEPS);
 
+static int msm_route_multimedia3_vol_control;
+static const DECLARE_TLV_DB_LINEAR(multimedia3_rx_vol_gain, 0,
+			INT_RX_VOL_MAX_STEPS);
+
 static int msm_route_compressed_vol_control;
 static const DECLARE_TLV_DB_LINEAR(compressed_rx_vol_gain, 0,
 			INT_RX_VOL_MAX_STEPS);
@@ -78,6 +88,10 @@
 static int msm_route_compressed2_vol_control;
 static const DECLARE_TLV_DB_LINEAR(compressed2_rx_vol_gain, 0,
 			INT_RX_VOL_MAX_STEPS);
+
+static int msm_route_compressed3_vol_control;
+static const DECLARE_TLV_DB_LINEAR(compressed3_rx_vol_gain, 0,
+			INT_RX_VOL_MAX_STEPS);
 static int msm_route_ec_ref_rx;
 
 /* Equal to Frontend after last of the MULTIMEDIA SESSIONS */
@@ -234,25 +248,35 @@
 
 
 /* Track ASM playback & capture sessions of DAI */
-static int fe_dai_map[MSM_FRONTEND_DAI_MM_SIZE][2] = {
+static struct msm_pcm_routing_fdai_data
+	fe_dai_map[MSM_FRONTEND_DAI_MM_SIZE][2] = {
 	/* MULTIMEDIA1 */
-	{INVALID_SESSION, INVALID_SESSION},
+	{{0, INVALID_SESSION, {NULL, NULL} },
+	{0, INVALID_SESSION, {NULL, NULL} } },
 	/* MULTIMEDIA2 */
-	{INVALID_SESSION, INVALID_SESSION},
+	{{0, INVALID_SESSION, {NULL, NULL} },
+	{0, INVALID_SESSION, {NULL, NULL} } },
 	/* MULTIMEDIA3 */
-	{INVALID_SESSION, INVALID_SESSION},
+	{{0, INVALID_SESSION, {NULL, NULL} },
+	{0, INVALID_SESSION, {NULL, NULL} } },
 	/* MULTIMEDIA4 */
-	{INVALID_SESSION, INVALID_SESSION},
+	{{0, INVALID_SESSION, {NULL, NULL} },
+	{0, INVALID_SESSION,  {NULL, NULL} } },
 	/* MULTIMEDIA5 */
-	{INVALID_SESSION, INVALID_SESSION},
+	{{0, INVALID_SESSION, {NULL, NULL} },
+	{0, INVALID_SESSION, {NULL, NULL} } },
 	/* MULTIMEDIA6 */
-	{INVALID_SESSION, INVALID_SESSION},
+	{{0, INVALID_SESSION, {NULL, NULL} },
+	{0, INVALID_SESSION, {NULL, NULL} } },
 	/* MULTIMEDIA7*/
-	{INVALID_SESSION, INVALID_SESSION},
+	{{0, INVALID_SESSION, {NULL, NULL} },
+	{0, INVALID_SESSION, {NULL, NULL} } },
 	/* MULTIMEDIA8 */
-	{INVALID_SESSION, INVALID_SESSION},
+	{{0, INVALID_SESSION, {NULL, NULL} },
+	{0, INVALID_SESSION, {NULL, NULL} } },
 	/* PSEUDO */
-	{INVALID_SESSION, INVALID_SESSION},
+	{{0, INVALID_SESSION, {NULL, NULL} },
+	{0, INVALID_SESSION, {NULL, NULL} } },
 };
 
 static uint8_t is_be_dai_extproc(int be_dai)
@@ -312,10 +336,12 @@
 	}
 
 	mutex_lock(&routing_lock);
+
 	if (enable)
-		fe_dai_map[fedai_id][session_type] = dspst_id;
+		fe_dai_map[fedai_id][session_type].strm_id = dspst_id;
 	else
-		fe_dai_map[fedai_id][session_type] = INVALID_SESSION;
+		fe_dai_map[fedai_id][session_type].strm_id = INVALID_SESSION;
+
 	for (i = 0; i < MSM_BACKEND_DAI_MAX; i++) {
 		if (!is_be_dai_extproc(i) &&
 		   (afe_get_port_type(msm_bedais[i].port_id) == port_type) &&
@@ -414,7 +440,7 @@
 	mutex_lock(&routing_lock);
 
 	payload.num_copps = 0; /* only RX needs to use payload */
-	fe_dai_map[fedai_id][session_type] = dspst_id;
+	fe_dai_map[fedai_id][session_type].strm_id = dspst_id;
 	/* re-enable EQ if active */
 	if (eq_data[fedai_id].enable)
 		msm_send_eq_values(fedai_id);
@@ -464,6 +490,19 @@
 
 	mutex_unlock(&routing_lock);
 }
+void msm_pcm_routing_reg_phy_stream_v2(int fedai_id, bool perf_mode,
+				       int dspst_id, int stream_type,
+				       struct msm_pcm_routing_evt event_info)
+{
+	msm_pcm_routing_reg_phy_stream(fedai_id, perf_mode, dspst_id,
+				       stream_type);
+
+	if (stream_type == SNDRV_PCM_STREAM_PLAYBACK)
+		fe_dai_map[fedai_id][SESSION_TYPE_RX].event_info = event_info;
+	else
+		fe_dai_map[fedai_id][SESSION_TYPE_TX].event_info = event_info;
+
+}
 
 void msm_pcm_routing_dereg_pseudo_stream(int fedai_id, int dspst_id)
 {
@@ -522,8 +561,8 @@
 		}
 	}
 
-	fe_dai_map[fedai_id][session_type] = INVALID_SESSION;
-
+	fe_dai_map[fedai_id][session_type].strm_id = INVALID_SESSION;
+	fe_dai_map[fedai_id][session_type].be_srate = 0;
 	mutex_unlock(&routing_lock);
 }
 
@@ -548,6 +587,7 @@
 {
 	int session_type, path_type;
 	u32 channels;
+	struct msm_pcm_routing_fdai_data *fdai;
 
 	pr_debug("%s: reg %x val %x set %x\n", __func__, reg, val, set);
 
@@ -574,11 +614,24 @@
 			voc_start_playback(set);
 
 		set_bit(val, &msm_bedais[reg].fe_sessions);
-		if (msm_bedais[reg].active && fe_dai_map[val][session_type] !=
+		fdai = &fe_dai_map[val][session_type];
+		if (msm_bedais[reg].active && fdai->strm_id !=
 			INVALID_SESSION) {
 
 			channels = msm_bedais[reg].channel;
 
+			if (session_type == SESSION_TYPE_TX && fdai->be_srate &&
+			    (fdai->be_srate != msm_bedais[reg].sample_rate)) {
+				pr_debug("%s: flush strm %d due diff BE rates\n",
+					__func__, fdai->strm_id);
+
+				if (fdai->event_info.event_func)
+					fdai->event_info.event_func(
+						MSM_PCM_RT_EVT_BUF_RECFG,
+						fdai->event_info.priv_data);
+				fdai->be_srate = 0; /* might not need it */
+			}
+
 			if ((session_type == SESSION_TYPE_RX) &&
 				((channels == 1) || (channels == 2))
 				&& msm_bedais[reg].perf_mode) {
@@ -606,7 +659,7 @@
 
 
 			msm_pcm_routing_build_matrix(val,
-				fe_dai_map[val][session_type], path_type);
+				fdai->strm_id, path_type);
 			srs_port_id = msm_bedais[reg].port_id;
 			srs_send_params(srs_port_id, 1, 0);
 		}
@@ -615,11 +668,13 @@
 			(msm_bedais[reg].port_id == VOICE_PLAYBACK_TX))
 			voc_start_playback(set);
 		clear_bit(val, &msm_bedais[reg].fe_sessions);
-		if (msm_bedais[reg].active && fe_dai_map[val][session_type] !=
+		fdai = &fe_dai_map[val][session_type];
+		if (msm_bedais[reg].active && fdai->strm_id !=
 			INVALID_SESSION) {
+			fdai->be_srate = msm_bedais[reg].sample_rate;
 			adm_close(msm_bedais[reg].port_id);
 			msm_pcm_routing_build_matrix(val,
-				fe_dai_map[val][session_type], path_type);
+				fdai->strm_id, path_type);
 		}
 	}
 	if ((msm_bedais[reg].port_id == VOICE_RECORD_RX)
@@ -982,6 +1037,23 @@
 	return 0;
 }
 
+static int msm_routing_get_multimedia3_vol_mixer(struct snd_kcontrol *kcontrol,
+				struct snd_ctl_elem_value *ucontrol)
+{
+	ucontrol->value.integer.value[0] = msm_route_multimedia3_vol_control;
+	return 0;
+}
+
+static int msm_routing_set_multimedia3_vol_mixer(struct snd_kcontrol *kcontrol,
+				struct snd_ctl_elem_value *ucontrol)
+{
+	if (!multi_ch_pcm_set_volume(ucontrol->value.integer.value[0]))
+		msm_route_multimedia3_vol_control =
+			ucontrol->value.integer.value[0];
+
+	return 0;
+}
+
 static int msm_routing_get_compressed_vol_mixer(struct snd_kcontrol *kcontrol,
 				struct snd_ctl_elem_value *ucontrol)
 {
@@ -1016,6 +1088,22 @@
 	return 0;
 }
 
+static int msm_routing_get_compressed3_vol_mixer(struct snd_kcontrol *kcontrol,
+				struct snd_ctl_elem_value *ucontrol)
+{
+	ucontrol->value.integer.value[0] = msm_route_compressed3_vol_control;
+	return 0;
+}
+
+static int msm_routing_set_compressed3_vol_mixer(struct snd_kcontrol *kcontrol,
+				struct snd_ctl_elem_value *ucontrol)
+{
+	if (!compressed_set_volume(ucontrol->value.integer.value[0]))
+		msm_route_compressed3_vol_control =
+			ucontrol->value.integer.value[0];
+	return 0;
+}
+
 static int msm_routing_get_srs_trumedia_control(struct snd_kcontrol *kcontrol,
 				struct snd_ctl_elem_value *ucontrol)
 {
@@ -1171,12 +1259,12 @@
 static void msm_send_eq_values(int eq_idx)
 {
 	int result;
-	struct audio_client *ac =
-		q6asm_get_audio_client(fe_dai_map[eq_idx][SESSION_TYPE_RX]);
+	struct audio_client *ac = q6asm_get_audio_client(
+				fe_dai_map[eq_idx][SESSION_TYPE_RX].strm_id);
 
 	if (ac == NULL) {
 		pr_err("%s: Could not get audio client for session: %d\n",
-		      __func__, fe_dai_map[eq_idx][SESSION_TYPE_RX]);
+		      __func__, fe_dai_map[eq_idx][SESSION_TYPE_RX].strm_id);
 		goto done;
 	}
 
@@ -2124,6 +2212,12 @@
 	msm_routing_set_multimedia5_vol_mixer, multimedia5_rx_vol_gain),
 };
 
+static const struct snd_kcontrol_new multimedia3_vol_mixer_controls[] = {
+	SOC_SINGLE_EXT_TLV("HIFI4 RX Volume", SND_SOC_NOPM, 0,
+	INT_RX_VOL_GAIN, 0, msm_routing_get_multimedia3_vol_mixer,
+	msm_routing_set_multimedia3_vol_mixer, multimedia3_rx_vol_gain),
+};
+
 static const struct snd_kcontrol_new compressed_vol_mixer_controls[] = {
 	SOC_SINGLE_EXT_TLV("COMPRESSED RX Volume", SND_SOC_NOPM, 0,
 	INT_RX_VOL_GAIN, 0, msm_routing_get_compressed_vol_mixer,
@@ -2136,6 +2230,12 @@
 	msm_routing_set_compressed2_vol_mixer, compressed2_rx_vol_gain),
 };
 
+static const struct snd_kcontrol_new compressed3_vol_mixer_controls[] = {
+	SOC_SINGLE_EXT_TLV("COMPRESSED3 RX Volume", SND_SOC_NOPM, 0,
+	INT_RX_VOL_GAIN, 0, msm_routing_get_compressed3_vol_mixer,
+	msm_routing_set_compressed3_vol_mixer, compressed3_rx_vol_gain),
+};
+
 static const struct snd_kcontrol_new lpa_SRS_trumedia_controls[] = {
 	{.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
 	.name = "SRS TruMedia",
@@ -3028,7 +3128,9 @@
 	mutex_lock(&routing_lock);
 
 	for_each_set_bit(i, &bedai->fe_sessions, MSM_FRONTEND_DAI_MM_SIZE) {
-		if (fe_dai_map[i][session_type] != INVALID_SESSION) {
+		if (fe_dai_map[i][session_type].strm_id != INVALID_SESSION) {
+			fe_dai_map[i][session_type].be_srate =
+				bedai->sample_rate;
 			adm_close(bedai->port_id);
 			srs_port_id = -1;
 		}
@@ -3051,6 +3153,7 @@
 	struct msm_pcm_routing_bdai_data *bedai;
 	u32 channels;
 	bool playback, capture;
+	struct msm_pcm_routing_fdai_data *fdai;
 
 	if (be_id >= MSM_BACKEND_DAI_MAX) {
 		pr_err("%s: unexpected be_id %d\n", __func__, be_id);
@@ -3082,7 +3185,21 @@
 	capture  = substream->stream == SNDRV_PCM_STREAM_CAPTURE;
 
 	for_each_set_bit(i, &bedai->fe_sessions, MSM_FRONTEND_DAI_MM_SIZE) {
-		if (fe_dai_map[i][session_type] != INVALID_SESSION) {
+		fdai = &fe_dai_map[i][session_type];
+		if (fdai->strm_id != INVALID_SESSION) {
+			if (session_type == SESSION_TYPE_TX && fdai->be_srate &&
+			    (fdai->be_srate != bedai->sample_rate)) {
+				pr_debug("%s: flush strm %d due diff BE rates\n",
+					__func__,
+					fdai->strm_id);
+
+				if (fdai->event_info.event_func)
+					fdai->event_info.event_func(
+						MSM_PCM_RT_EVT_BUF_RECFG,
+						fdai->event_info.priv_data);
+				fdai->be_srate = 0; /* might not need it */
+			}
+
 			channels = bedai->channel;
 			if (bedai->port_id == PSEUDOPORT_01) {
 				adm_multi_ch_copp_pseudo_open_v3(bedai->port_id,
@@ -3116,7 +3233,7 @@
 				DEFAULT_COPP_TOPOLOGY);
 
 			msm_pcm_routing_build_matrix(i,
-				fe_dai_map[i][session_type], path_type);
+				fdai->strm_id, path_type);
 			srs_port_id = bedai->port_id;
 			srs_send_params(srs_port_id, 1, 0);
 		}
@@ -3188,13 +3305,22 @@
 			ARRAY_SIZE(multimedia5_vol_mixer_controls));
 
 	snd_soc_add_platform_controls(platform,
+				multimedia3_vol_mixer_controls,
+			ARRAY_SIZE(multimedia3_vol_mixer_controls));
+
+	snd_soc_add_platform_controls(platform,
 				compressed_vol_mixer_controls,
 			ARRAY_SIZE(compressed_vol_mixer_controls));
+
 	snd_soc_add_platform_controls(platform,
 				compressed2_vol_mixer_controls,
 			ARRAY_SIZE(compressed2_vol_mixer_controls));
 
 	snd_soc_add_platform_controls(platform,
+				compressed3_vol_mixer_controls,
+			ARRAY_SIZE(compressed3_vol_mixer_controls));
+
+	snd_soc_add_platform_controls(platform,
 				lpa_SRS_trumedia_controls,
 			ARRAY_SIZE(lpa_SRS_trumedia_controls));
 
diff --git a/sound/soc/msm/msm-pcm-routing.h b/sound/soc/msm/msm-pcm-routing.h
index 0c0d3b4..b571483 100644
--- a/sound/soc/msm/msm-pcm-routing.h
+++ b/sound/soc/msm/msm-pcm-routing.h
@@ -113,6 +113,10 @@
 	MSM_BACKEND_DAI_MAX,
 };
 
+enum msm_pcm_routing_event {
+	MSM_PCM_RT_EVT_BUF_RECFG,
+	MSM_PCM_RT_EVT_MAX,
+};
 /* dai_id: front-end ID,
  * dspst_id:  DSP audio stream ID
  * stream_type: playback or capture
@@ -128,6 +132,15 @@
 
 void msm_pcm_routing_dereg_pseudo_stream(int fedai_id, int dspst_id);
 
+struct msm_pcm_routing_evt {
+	void (*event_func)(enum msm_pcm_routing_event, void *);
+	void *priv_data;
+};
+
+void msm_pcm_routing_reg_phy_stream_v2(int fedai_id, bool perf_mode,
+				       int dspst_id, int stream_type,
+				       struct msm_pcm_routing_evt event_info);
+
 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 bb9f2be..196cb44 100644
--- a/sound/soc/msm/msm8930.c
+++ b/sound/soc/msm/msm8930.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -170,8 +170,12 @@
 				}
 			} else {
 
-				if (machine_is_msm8930_mtp()
-					|| machine_is_msm8930_fluid()) {
+				/*
+				 * 8930 CDP does not have a 5V speaker boost,
+				 * hence the GPIO enable for speaker boost is
+				 * only required for platforms other than CDP
+				 */
+				if (!machine_is_msm8930_cdp()) {
 					ret = msm8930_cfg_spkr_gpio(
 					  SPKR_BOOST_GPIO, 1, "SPKR_BOOST");
 					if (ret) {
@@ -208,8 +212,7 @@
 			return;
 		}
 
-		if (machine_is_msm8930_mtp()
-			|| machine_is_msm8930_fluid()) {
+		if (!machine_is_msm8930_cdp()) {
 			pr_debug("%s: Free speaker boost gpio %u\n",
 					__func__, SPKR_BOOST_GPIO);
 			gpio_direction_output(SPKR_BOOST_GPIO, 0);
@@ -1132,6 +1135,22 @@
 		.ignore_pmdown_time = 1,
 		.be_id = MSM_FRONTEND_DAI_MULTIMEDIA5,
 	},
+	{
+		.name = "MSM8960 FM",
+		.stream_name = "MultiMedia6",
+		.cpu_dai_name	= "MultiMedia6",
+		.platform_name  = "msm-pcm-loopback",
+		.dynamic = 1,
+		.codec_dai_name = "snd-soc-dummy-dai",
+		.codec_name = "snd-soc-dummy",
+		.trigger = {SND_SOC_DPCM_TRIGGER_POST,
+				SND_SOC_DPCM_TRIGGER_POST},
+		.ignore_suspend = 1,
+		.no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
+		/* this dainlink has playback support */
+		.ignore_pmdown_time = 1,
+		.be_id = MSM_FRONTEND_DAI_MULTIMEDIA6,
+	},
 	/* Backend DAI Links */
 	{
 		.name = LPASS_BE_SLIMBUS_0_RX,
diff --git a/sound/soc/msm/qdsp6/q6asm.c b/sound/soc/msm/qdsp6/q6asm.c
index 52e481a..8fd5840 100644
--- a/sound/soc/msm/qdsp6/q6asm.c
+++ b/sound/soc/msm/qdsp6/q6asm.c
@@ -220,7 +220,7 @@
 	int rc = 0;
 	pr_debug("%s: Session id %d\n", __func__, ac->session);
 	mutex_lock(&ac->cmd_lock);
-	if (ac->io_mode == SYNC_IO_MODE) {
+	if (ac->io_mode & SYNC_IO_MODE) {
 		port = &ac->port[dir];
 		if (!port->buf) {
 			mutex_unlock(&ac->cmd_lock);
@@ -351,7 +351,7 @@
 	if (!ac || !ac->session)
 		return;
 	pr_debug("%s: Session id %d\n", __func__, ac->session);
-	if (ac->io_mode == SYNC_IO_MODE) {
+	if (ac->io_mode & SYNC_IO_MODE) {
 		for (loopcnt = 0; loopcnt <= OUT; loopcnt++) {
 			port = &ac->port[loopcnt];
 			if (!port->buf)
@@ -386,14 +386,20 @@
 		pr_err("%s APR handle NULL\n", __func__);
 		return -EINVAL;
 	}
-	if ((mode == ASYNC_IO_MODE) || (mode == SYNC_IO_MODE)) {
-		ac->io_mode = mode;
-		pr_debug("%s:Set Mode to %d\n", __func__, ac->io_mode);
-		return 0;
+
+	if (mode == ASYNC_IO_MODE) {
+		ac->io_mode &= ~SYNC_IO_MODE;
+		ac->io_mode |= ASYNC_IO_MODE;
+	} else if (mode == SYNC_IO_MODE) {
+		ac->io_mode &= ~ASYNC_IO_MODE;
+		ac->io_mode |= SYNC_IO_MODE;
 	} else {
 		pr_err("%s:Not an valid IO Mode:%d\n", __func__, ac->io_mode);
 		return -EINVAL;
 	}
+
+	pr_debug("%s:Set Mode to %d\n", __func__, ac->io_mode);
+	return 0;
 }
 
 struct audio_client *q6asm_audio_client_alloc(app_cb cb, void *priv)
@@ -498,7 +504,7 @@
 	if (ac->session <= 0 || ac->session > 8)
 		goto fail;
 
-	if (ac->io_mode == SYNC_IO_MODE) {
+	if (ac->io_mode & SYNC_IO_MODE) {
 		if (ac->port[dir].buf) {
 			pr_debug("%s: buffer already allocated\n", __func__);
 			return 0;
@@ -942,7 +948,7 @@
 		pr_debug("%s: Rxed opcode[0x%x] status[0x%x] token[%d]",
 				__func__, payload[0], payload[1],
 				data->token);
-		if (ac->io_mode == SYNC_IO_MODE) {
+		if (ac->io_mode & SYNC_IO_MODE) {
 			if (port->buf == NULL) {
 				pr_err("%s: Unexpected Write Done\n",
 								__func__);
@@ -1024,7 +1030,7 @@
 		if (in_enable_flag)
 			in_cont_index++;
 #endif
-		if (ac->io_mode == SYNC_IO_MODE) {
+		if (ac->io_mode & SYNC_IO_MODE) {
 			if (port->buf == NULL) {
 				pr_err("%s: Unexpected Write Done\n", __func__);
 				return -EINVAL;
@@ -1203,7 +1209,7 @@
 	if (!ac || ((dir != IN) && (dir != OUT)))
 		return NULL;
 
-	if (ac->io_mode == SYNC_IO_MODE) {
+	if (ac->io_mode & SYNC_IO_MODE) {
 		port = &ac->port[dir];
 
 		mutex_lock(&port->lock);
@@ -1297,7 +1303,7 @@
 	if (!ac || (dir != OUT))
 		return ret;
 
-	if (ac->io_mode == SYNC_IO_MODE) {
+	if (ac->io_mode & SYNC_IO_MODE) {
 		port = &ac->port[dir];
 
 		mutex_lock(&port->lock);
@@ -1430,6 +1436,9 @@
 			rc);
 		goto fail_cmd;
 	}
+
+	ac->io_mode |= TUN_READ_IO_MODE;
+
 	return 0;
 fail_cmd:
 	return -EINVAL;
@@ -1716,6 +1725,9 @@
 		pr_err("%s: format = %x not supported\n", __func__, format);
 		goto fail_cmd;
 	}
+
+	ac->io_mode |= TUN_WRITE_IO_MODE;
+
 	return 0;
 fail_cmd:
 	return -EINVAL;
@@ -3440,7 +3452,7 @@
 		pr_err("APR handle NULL\n");
 		return -EINVAL;
 	}
-	if (ac->io_mode == SYNC_IO_MODE) {
+	if (ac->io_mode & SYNC_IO_MODE) {
 		port = &ac->port[OUT];
 
 		q6asm_add_hdr(ac, &read.hdr, sizeof(read), FALSE);
@@ -3492,7 +3504,7 @@
 		pr_err("APR handle NULL\n");
 		return -EINVAL;
 	}
-	if (ac->io_mode == SYNC_IO_MODE) {
+	if (ac->io_mode & SYNC_IO_MODE) {
 		port = &ac->port[OUT];
 
 		q6asm_add_hdr_async(ac, &read.hdr, sizeof(read), FALSE);
@@ -3516,7 +3528,7 @@
 		read.hdr.token = port->dsp_buf;
 
 		port->dsp_buf = (port->dsp_buf + 1) & (port->max_buf_cnt - 1);
-		pr_debug("%s:buf add[0x%x] token[%d] uid[%d]\n", __func__,
+		pr_info("%s:buf add[0x%x] token[%d] uid[%d]\n", __func__,
 					read.buf_add,
 					read.hdr.token,
 					read.uid);
@@ -3677,7 +3689,7 @@
 		return -EINVAL;
 	}
 	pr_debug("%s: session[%d] len=%d", __func__, ac->session, len);
-	if (ac->io_mode == SYNC_IO_MODE) {
+	if (ac->io_mode & SYNC_IO_MODE) {
 		port = &ac->port[IN];
 
 		q6asm_add_hdr(ac, &write.hdr, sizeof(write),
@@ -3759,7 +3771,7 @@
 		return -EINVAL;
 	}
 	pr_debug("%s: session[%d] len=%d", __func__, ac->session, len);
-	if (ac->io_mode == SYNC_IO_MODE) {
+	if (ac->io_mode & SYNC_IO_MODE) {
 		port = &ac->port[IN];
 
 		q6asm_add_hdr_async(ac, &write.hdr, sizeof(write),
@@ -3961,9 +3973,11 @@
 {
 	int cnt = 0;
 	int loopcnt = 0;
+	int used;
 	struct audio_port_data *port = NULL;
 
-	if (ac->io_mode == SYNC_IO_MODE) {
+	if (ac->io_mode & SYNC_IO_MODE) {
+		used = (ac->io_mode & TUN_WRITE_IO_MODE ? 1 : 0);
 		mutex_lock(&ac->cmd_lock);
 		for (loopcnt = 0; loopcnt <= OUT; loopcnt++) {
 			port = &ac->port[loopcnt];
@@ -3973,7 +3987,7 @@
 			while (cnt >= 0) {
 				if (!port->buf)
 					continue;
-				port->buf[cnt].used = 1;
+				port->buf[cnt].used = used;
 				cnt--;
 			}
 		}
diff --git a/sound/soc/msm/qdsp6v2/msm-dai-q6-v2.c b/sound/soc/msm/qdsp6v2/msm-dai-q6-v2.c
index 2f4c256..a7a80a6 100644
--- a/sound/soc/msm/qdsp6v2/msm-dai-q6-v2.c
+++ b/sound/soc/msm/qdsp6v2/msm-dai-q6-v2.c
@@ -1259,6 +1259,12 @@
 	SOC_ENUM_EXT("PRI MI2S TX Format", mi2s_config_enum[0],
 		     msm_dai_q6_mi2s_format_get,
 		     msm_dai_q6_mi2s_format_put),
+	SOC_ENUM_EXT("SEC MI2S RX Format", mi2s_config_enum[0],
+		     msm_dai_q6_mi2s_format_get,
+		     msm_dai_q6_mi2s_format_put),
+	SOC_ENUM_EXT("SEC MI2S TX Format", mi2s_config_enum[0],
+		     msm_dai_q6_mi2s_format_get,
+		     msm_dai_q6_mi2s_format_put),
 };
 
 static int msm_dai_q6_dai_mi2s_probe(struct snd_soc_dai *dai)
@@ -1267,26 +1273,37 @@
 			dev_get_drvdata(dai->dev);
 	struct snd_kcontrol *kcontrol = NULL;
 	int rc = 0;
+	const struct snd_kcontrol_new *ctrl = NULL;
 
 	if (mi2s_dai_data->rx_dai.mi2s_dai_data.port_config.i2s.channel_mode) {
-		kcontrol = snd_ctl_new1(&mi2s_config_controls[0],
+		if (!strncmp(dai->name, "msm-dai-q6-mi2s.0", 17))
+			ctrl = &mi2s_config_controls[0];
+		if (!strncmp(dai->name, "msm-dai-q6-mi2s.1", 17))
+			ctrl = &mi2s_config_controls[3];
+		kcontrol = snd_ctl_new1(ctrl,
 					&mi2s_dai_data->rx_dai.mi2s_dai_data);
 		rc = snd_ctl_add(dai->card->snd_card, kcontrol);
 
 		if (IS_ERR_VALUE(rc)) {
-			dev_err(dai->dev, "%s: err add RX fmt ctl\n", __func__);
+			dev_err(dai->dev, "%s: err add RX fmt ctl DAI = %s\n",
+				__func__, dai->name);
 			goto rtn;
 		}
 	}
 	if (mi2s_dai_data->tx_dai.mi2s_dai_data.port_config.i2s.channel_mode) {
+		if (!strncmp(dai->name, "msm-dai-q6-mi2s.0", 17))
+			ctrl = &mi2s_config_controls[2];
+		if (!strncmp(dai->name, "msm-dai-q6-mi2s.1", 17))
+			ctrl = &mi2s_config_controls[4];
 		rc = snd_ctl_add(dai->card->snd_card,
-				snd_ctl_new1(&mi2s_config_controls[2],
+				snd_ctl_new1(ctrl,
 				&mi2s_dai_data->tx_dai.mi2s_dai_data));
 
 		if (IS_ERR_VALUE(rc)) {
 			if (kcontrol)
 				snd_ctl_remove(dai->card->snd_card, kcontrol);
-			dev_err(dai->dev, "%s: err add TX fmt ctl\n", __func__);
+			dev_err(dai->dev, "%s: err add TX fmt ctl DAI = %s\n",
+				__func__, dai->name);
 		}
 	}
 rtn:
diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c b/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c
index 58300c4..26f634b 100644
--- a/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c
+++ b/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c
@@ -188,6 +188,8 @@
 	{ SLIMBUS_EXTPROC_RX, 0, 0, 0, 0, 0},
 	{ AFE_PORT_ID_QUATERNARY_MI2S_RX, 0, 0, 0, 0, 0},
 	{ AFE_PORT_ID_QUATERNARY_MI2S_TX, 0, 0, 0, 0, 0},
+	{ AFE_PORT_ID_SECONDARY_MI2S_RX, 0, 0, 0, 0, 0},
+	{ AFE_PORT_ID_SECONDARY_MI2S_TX, 0, 0, 0, 0, 0},
 };
 
 
@@ -1106,6 +1108,21 @@
 	msm_routing_put_audio_mixer),
 };
 
+static const struct snd_kcontrol_new secondary_mi2s_rx_mixer_controls[] = {
+	SOC_SINGLE_EXT("MultiMedia1", MSM_BACKEND_DAI_SECONDARY_MI2S_RX ,
+	MSM_FRONTEND_DAI_MULTIMEDIA1, 1, 0, msm_routing_get_audio_mixer,
+	msm_routing_put_audio_mixer),
+	SOC_SINGLE_EXT("MultiMedia2", MSM_BACKEND_DAI_SECONDARY_MI2S_RX,
+	MSM_FRONTEND_DAI_MULTIMEDIA2, 1, 0, msm_routing_get_audio_mixer,
+	msm_routing_put_audio_mixer),
+	SOC_SINGLE_EXT("MultiMedia3", MSM_BACKEND_DAI_SECONDARY_MI2S_RX,
+	MSM_FRONTEND_DAI_MULTIMEDIA3, 1, 0, msm_routing_get_audio_mixer,
+	msm_routing_put_audio_mixer),
+	SOC_SINGLE_EXT("MultiMedia4", MSM_BACKEND_DAI_SECONDARY_MI2S_RX,
+	MSM_FRONTEND_DAI_MULTIMEDIA4, 1, 0, msm_routing_get_audio_mixer,
+	msm_routing_put_audio_mixer),
+};
+
 static const struct snd_kcontrol_new hdmi_mixer_controls[] = {
 	SOC_SINGLE_EXT("MultiMedia1", MSM_BACKEND_DAI_HDMI_RX,
 	MSM_FRONTEND_DAI_MULTIMEDIA1, 1, 0, msm_routing_get_audio_mixer,
@@ -1209,6 +1226,9 @@
 	SOC_SINGLE_EXT("QUAT_MI2S_TX", MSM_BACKEND_DAI_QUATERNARY_MI2S_TX,
 		MSM_FRONTEND_DAI_MULTIMEDIA1, 1, 0, msm_routing_get_audio_mixer,
 		msm_routing_put_audio_mixer),
+	SOC_SINGLE_EXT("SEC_MI2S_TX", MSM_BACKEND_DAI_SECONDARY_MI2S_TX,
+		MSM_FRONTEND_DAI_MULTIMEDIA1, 1, 0, msm_routing_get_audio_mixer,
+		msm_routing_put_audio_mixer),
 	SOC_SINGLE_EXT("SLIM_0_TX", MSM_BACKEND_DAI_SLIMBUS_0_TX,
 		MSM_FRONTEND_DAI_MULTIMEDIA1, 1, 0, msm_routing_get_audio_mixer,
 		msm_routing_put_audio_mixer),
@@ -1852,11 +1872,14 @@
 	SND_SOC_DAPM_AIF_OUT("MI2S_RX", "MI2S Playback", 0, 0, 0, 0),
 	SND_SOC_DAPM_AIF_OUT("QUAT_MI2S_RX", "Quaternary MI2S Playback",
 						0, 0, 0, 0),
-
+	SND_SOC_DAPM_AIF_OUT("SEC_MI2S_RX", "Secondary 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("MI2S_TX", "MI2S Capture", 0, 0, 0, 0),
 	SND_SOC_DAPM_AIF_IN("QUAT_MI2S_TX", "Quaternary MI2S Capture",
 						0, 0, 0, 0),
+	SND_SOC_DAPM_AIF_IN("SEC_MI2S_TX", "Secondary MI2S Capture",
+			    0, 0, 0, 0),
 	SND_SOC_DAPM_AIF_IN("SLIMBUS_0_TX", "Slimbus Capture", 0, 0, 0, 0),
 	SND_SOC_DAPM_AIF_OUT("INT_BT_SCO_RX", "Internal BT-SCO Playback",
 				0, 0, 0 , 0),
@@ -1919,6 +1942,9 @@
 	SND_SOC_DAPM_MIXER("QUAT_MI2S_RX Audio Mixer", SND_SOC_NOPM, 0, 0,
 				quaternary_mi2s_rx_mixer_controls,
 				ARRAY_SIZE(quaternary_mi2s_rx_mixer_controls)),
+	SND_SOC_DAPM_MIXER("SEC_MI2S_RX Audio Mixer", SND_SOC_NOPM, 0, 0,
+			   secondary_mi2s_rx_mixer_controls,
+			   ARRAY_SIZE(secondary_mi2s_rx_mixer_controls)),
 	SND_SOC_DAPM_MIXER("MultiMedia1 Mixer", SND_SOC_NOPM, 0, 0,
 	mmul1_mixer_controls, ARRAY_SIZE(mmul1_mixer_controls)),
 	SND_SOC_DAPM_MIXER("MultiMedia2 Mixer", SND_SOC_NOPM, 0, 0,
@@ -2068,6 +2094,13 @@
 	{"QUAT_MI2S_RX Audio Mixer", "MultiMedia4", "MM_DL4"},
 	{"QUAT_MI2S_RX", NULL, "QUAT_MI2S_RX Audio Mixer"},
 
+
+	{"SEC_MI2S_RX Audio Mixer", "MultiMedia1", "MM_DL1"},
+	{"SEC_MI2S_RX Audio Mixer", "MultiMedia2", "MM_DL2"},
+	{"SEC_MI2S_RX Audio Mixer", "MultiMedia3", "MM_DL3"},
+	{"SEC_MI2S_RX Audio Mixer", "MultiMedia4", "MM_DL4"},
+	{"SEC_MI2S_RX", NULL, "SEC_MI2S_RX Audio Mixer"},
+
 	{"MultiMedia1 Mixer", "PRI_TX", "PRI_I2S_TX"},
 	{"MultiMedia1 Mixer", "MI2S_TX", "MI2S_TX"},
 	{"MultiMedia2 Mixer", "MI2S_TX", "MI2S_TX"},
@@ -2075,6 +2108,7 @@
 	{"MultiMedia1 Mixer", "SLIM_0_TX", "SLIMBUS_0_TX"},
 	{"MultiMedia1 Mixer", "AUX_PCM_UL_TX", "AUX_PCM_TX"},
 	{"MultiMedia2 Mixer", "SLIM_0_TX", "SLIMBUS_0_TX"},
+	{"MultiMedia1 Mixer", "SEC_MI2S_TX", "SEC_MI2S_TX"},
 
 	{"INTERNAL_BT_SCO_RX Audio Mixer", "MultiMedia1", "MM_DL1"},
 	{"INTERNAL_BT_SCO_RX Audio Mixer", "MultiMedia2", "MM_DL2"},
@@ -2249,10 +2283,11 @@
 	{"BE_OUT", NULL, "HDMI"},
 	{"BE_OUT", NULL, "MI2S_RX"},
 	{"BE_OUT", NULL, "QUAT_MI2S_RX"},
-
+	{"BE_OUT", NULL, "SEC_MI2S_RX"},
 	{"PRI_I2S_TX", NULL, "BE_IN"},
 	{"MI2S_TX", NULL, "BE_IN"},
 	{"QUAT_MI2S_TX", NULL, "BE_IN"},
+	{"SEC_MI2S_TX", NULL, "BE_IN"},
 	{"SLIMBUS_0_TX", NULL, "BE_IN" },
 	{"SLIMBUS_1_TX", NULL, "BE_IN" },
 	{"SLIMBUS_3_TX", NULL, "BE_IN" },
diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.h b/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.h
index be646ed..69b3fe3 100644
--- a/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.h
+++ b/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.h
@@ -35,6 +35,8 @@
 #define LPASS_BE_MI2S_TX "MI2S_TX"
 #define LPASS_BE_QUAT_MI2S_RX "QUAT_MI2S_RX"
 #define LPASS_BE_QUAT_MI2S_TX "QUAT_MI2S_TX"
+#define LPASS_BE_SEC_MI2S_RX "SEC_MI2S_RX"
+#define LPASS_BE_SEC_MI2S_TX "SEC_MI2S_TX"
 #define LPASS_BE_STUB_RX "STUB_RX"
 #define LPASS_BE_STUB_TX "STUB_TX"
 #define LPASS_BE_SLIMBUS_1_RX "SLIMBUS_1_RX"
@@ -99,6 +101,8 @@
 	MSM_BACKEND_DAI_EXTPROC_EC_TX,
 	MSM_BACKEND_DAI_QUATERNARY_MI2S_RX,
 	MSM_BACKEND_DAI_QUATERNARY_MI2S_TX,
+	MSM_BACKEND_DAI_SECONDARY_MI2S_RX,
+	MSM_BACKEND_DAI_SECONDARY_MI2S_TX,
 	MSM_BACKEND_DAI_MAX,
 };
 
diff --git a/sound/soc/msm/qdsp6v2/q6afe.c b/sound/soc/msm/qdsp6v2/q6afe.c
index 9387d21..d836610 100644
--- a/sound/soc/msm/qdsp6v2/q6afe.c
+++ b/sound/soc/msm/qdsp6v2/q6afe.c
@@ -174,6 +174,7 @@
 	case VOICE_PLAYBACK_TX:
 	case RT_PROXY_PORT_001_RX:
 	case AFE_PORT_ID_QUATERNARY_MI2S_RX:
+	case AFE_PORT_ID_SECONDARY_MI2S_RX:
 		ret = MSM_AFE_PORT_TYPE_RX;
 		break;
 
@@ -193,6 +194,7 @@
 	case INT_BT_SCO_TX:
 	case RT_PROXY_PORT_001_TX:
 	case AFE_PORT_ID_QUATERNARY_MI2S_TX:
+	case AFE_PORT_ID_SECONDARY_MI2S_TX:
 		ret = MSM_AFE_PORT_TYPE_TX;
 		break;
 
@@ -564,6 +566,11 @@
 		return IDX_AFE_PORT_ID_QUATERNARY_MI2S_RX;
 	case AFE_PORT_ID_QUATERNARY_MI2S_TX:
 		return IDX_AFE_PORT_ID_QUATERNARY_MI2S_TX;
+	case AFE_PORT_ID_SECONDARY_MI2S_RX:
+		return IDX_AFE_PORT_ID_SECONDARY_MI2S_RX;
+	case AFE_PORT_ID_SECONDARY_MI2S_TX:
+		return IDX_AFE_PORT_ID_SECONDARY_MI2S_TX;
+
 	default: return -EINVAL;
 	}
 }
diff --git a/sound/soc/msm/qdsp6v2/q6audio-v2.c b/sound/soc/msm/qdsp6v2/q6audio-v2.c
index 033cb8e..5e2e618 100644
--- a/sound/soc/msm/qdsp6v2/q6audio-v2.c
+++ b/sound/soc/msm/qdsp6v2/q6audio-v2.c
@@ -52,6 +52,11 @@
 		return IDX_AFE_PORT_ID_QUATERNARY_MI2S_RX;
 	case AFE_PORT_ID_QUATERNARY_MI2S_TX:
 		return IDX_AFE_PORT_ID_QUATERNARY_MI2S_TX;
+	case AFE_PORT_ID_SECONDARY_MI2S_RX:
+		return IDX_AFE_PORT_ID_SECONDARY_MI2S_RX;
+	case AFE_PORT_ID_SECONDARY_MI2S_TX:
+		return IDX_AFE_PORT_ID_SECONDARY_MI2S_TX;
+
 	default: return -EINVAL;
 	}
 }
@@ -89,6 +94,10 @@
 			     return AFE_PORT_ID_QUATERNARY_MI2S_RX;
 	case AFE_PORT_ID_QUATERNARY_MI2S_TX:
 			     return AFE_PORT_ID_QUATERNARY_MI2S_TX;
+	case AFE_PORT_ID_SECONDARY_MI2S_RX:
+			     return AFE_PORT_ID_SECONDARY_MI2S_RX;
+	case AFE_PORT_ID_SECONDARY_MI2S_TX:
+			     return AFE_PORT_ID_SECONDARY_MI2S_TX;
 
 	default: return -EINVAL;
 	}
@@ -147,6 +156,8 @@
 	case RT_PROXY_PORT_001_TX:
 	case AFE_PORT_ID_QUATERNARY_MI2S_RX:
 	case AFE_PORT_ID_QUATERNARY_MI2S_TX:
+	case AFE_PORT_ID_SECONDARY_MI2S_RX:
+	case AFE_PORT_ID_SECONDARY_MI2S_TX:
 	{
 		ret = 0;
 		break;