Merge "msm: pil: Support relocatable images in secure PIL"
diff --git a/Documentation/devicetree/bindings/arm/msm/ipc-spinlock.txt b/Documentation/devicetree/bindings/arm/msm/ipc-spinlock.txt
new file mode 100644
index 0000000..c71b190
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/msm/ipc-spinlock.txt
@@ -0,0 +1,14 @@
+Qualcomm Interprocessor Communication Spinlock
+
+Required properties:
+- compatible : should be "qcom,ipc-spinlock"
+- reg : the location and size of the spinlock hardware
+- qcom,num-locks : the number of locks supported
+
+Example:
+
+	qcom,ipc-spinlock@fd484000 {
+		compatible = "qcom,ipc-spinlock";
+		reg = <0xfd484000 0x1000>;
+		qcom,num-locks = <32>;
+	};
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/arm/msm/msm_iommu_domains.txt b/Documentation/devicetree/bindings/arm/msm/msm_iommu_domains.txt
new file mode 100644
index 0000000..7d69749
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/msm/msm_iommu_domains.txt
@@ -0,0 +1,50 @@
+IOMMU Domains
+
+An IOMMU domain is a collection of IOMMU context banks and an optional
+virtual address space that is to be used with the domain. Domains that are
+defined will be created at bootup and associated with an iommu group. Clients
+can then refer to the iommu group and perform operations on the iommu group
+instead of individual devices/contexts.
+
+Required properties
+
+- compatible: "qcom,iommu-domains"
+
+- At least one child that defines a domain is required with the
+  following properties:
+
+	- label: Name of the domain
+	- qcom,iommu-contexts: List of phandles to context that belongs to
+	  this domain.
+
+	Optional properties
+
+		- qcom,virtual-addr-pool: List of <start_address size> pairs
+		  that define the virtual address space for this domain.
+		- qcom,secure-domain: boolean indicating that this is a secure
+		  domain that is to be programmed by Trustzone.
+		- qcom,l2-redirect: boolean indicating that page tables should
+		  be cached in L2 cache.
+Example:
+	qcom,iommu-domains {
+		compatible = "qcom,iommu-domains";
+
+		qcom,iommu-domain1 {
+			label = "lpass_secure";
+			qcom,iommu-contexts = <&lpass_q6_fw>;
+			qcom,virtual-addr-pool = <0x00000000 0x0FFFFFFF
+						  0xF0000000 0x0FFFFFFF>;
+		};
+
+		qcom,iommu-domain2 {
+			label = "lpass_audio";
+			qcom,iommu-contexts = <&lpass_audio_shared>;
+			qcom,virtual-addr-pool = <0x10000000 0x0FFFFFFF>;
+		};
+
+		qcom,iommu-domain3 {
+			label = "lpass_video";
+			qcom,iommu-contexts = <&lpass_video_shared>;
+			qcom,virtual-addr-pool = <0x20000000 0x0FFFFFFF>;
+		};
+	};
diff --git a/Documentation/devicetree/bindings/gpio/gpio-msm.txt b/Documentation/devicetree/bindings/gpio/gpio-msm.txt
index a5d50fd..1f88037 100644
--- a/Documentation/devicetree/bindings/gpio/gpio-msm.txt
+++ b/Documentation/devicetree/bindings/gpio/gpio-msm.txt
@@ -10,6 +10,9 @@
 - #interrupt-cells : Should be 2.
 - interrupt-controller: Mark the device node as an interrupt controller
 - interrupts : Specify the TLMM summary interrupt number
+- ngpio : Specify the number of MSM GPIOs
+- qcom,direct-connect-irqs : Specifies the number of GPIOs that can be used as
+  direct connect interrupts
 
 Example:
 
@@ -21,6 +24,8 @@
 		#interrupt-cells = <2>;
 		reg = <0xfd510000 0x4000>;
 		interrupts = <0 208 0>;
+		ngpio = <150>;
+		qcom,direct-connect-irqs = <8>;
 	};
 
 To specify gpios for a device:
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 d686523..5d10940 100644
--- a/Documentation/devicetree/bindings/usb/msm-ssusb.txt
+++ b/Documentation/devicetree/bindings/usb/msm-ssusb.txt
@@ -40,6 +40,8 @@
   otherwise depend on PHY.
 - 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.
 
 Example MSM USB3.0 controller device node :
 	usb@f9200000 {
@@ -56,6 +58,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>;
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 53fd3b2..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
@@ -1808,7 +1809,7 @@
 config OABI_COMPAT
 	bool "Allow old ABI binaries to run with this kernel (EXPERIMENTAL)"
 	depends on AEABI && EXPERIMENTAL && !THUMB2_KERNEL
-	default y
+	default y if !SMP
 	help
 	  This option preserves the old syscall interface along with the
 	  new (ARM EABI) one. It also provides a compatibility layer to
diff --git a/arch/arm/boot/dts/mpq8092.dtsi b/arch/arm/boot/dts/mpq8092.dtsi
index 0ab0a0c..339faa9 100644
--- a/arch/arm/boot/dts/mpq8092.dtsi
+++ b/arch/arm/boot/dts/mpq8092.dtsi
@@ -35,7 +35,9 @@
 		interrupt-controller;
 		#interrupt-cells = <2>;
 		reg = <0xfd510000 0x4000>;
+		ngpio = <146>;
 		interrupts = <0 208 0>;
+		qcom,direct-connect-irqs = <8>;
 	};
 
 	timer {
diff --git a/arch/arm/boot/dts/msm-iommu-v1.dtsi b/arch/arm/boot/dts/msm-iommu-v1.dtsi
index 5a08f51..ea4fa75 100644
--- a/arch/arm/boot/dts/msm-iommu-v1.dtsi
+++ b/arch/arm/boot/dts/msm-iommu-v1.dtsi
@@ -21,28 +21,28 @@
 		label = "lpass_iommu";
 		status = "disabled";
 
-		qcom,iommu-ctx@fd000000 {
+		lpass_q6_fw: qcom,iommu-ctx@fd000000 {
 			reg = <0xfd000000 0x1000>;
 			interrupts = <0 250 0>;
 			qcom,iommu-ctx-mids = <0 15>;
 			label = "q6_fw";
 		};
 
-		qcom,iommu-ctx@fd001000 {
+		lpass_audio_shared: qcom,iommu-ctx@fd001000 {
 			reg = <0xfd001000 0x1000>;
 			interrupts = <0 250 0>;
 			qcom,iommu-ctx-mids = <1>;
 			label = "audio_shared";
 		};
 
-		qcom,iommu-ctx@fd002000 {
+		lpass_video_shared: qcom,iommu-ctx@fd002000 {
 			reg = <0xfd002000 0x1000>;
 			interrupts = <0 250 0>;
 			qcom,iommu-ctx-mids = <2>;
 			label = "video_shared";
 		};
 
-		qcom,iommu-ctx@fd003000 {
+		lpass_q6_spare: qcom,iommu-ctx@fd003000 {
 			reg = <0xfd003000 0x1000>;
 			interrupts = <0 250 0>;
 			qcom,iommu-ctx-mids = <3 4 5 6 7 8 9 10 11 12 13 14>;
diff --git a/arch/arm/boot/dts/msm-iommu.dtsi b/arch/arm/boot/dts/msm-iommu.dtsi
index 8343c7a..32d49e2 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
@@ -18,6 +18,7 @@
 		ranges;
 		reg = <0xfda64000 0x10000>;
 		vdd-supply = <&gdsc_jpeg>;
+		qcom,needs-alt-core-clk;
 		status = "disabled";
 
 		qcom,iommu-bfb-regs =  <0x204c
@@ -281,6 +282,7 @@
 		ranges;
 		reg = <0xfda44000 0x10000>;
 		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 3c8ea84..bc07d84 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";
@@ -34,7 +35,9 @@
 		reg = <0xfd510000 0x4000>;
 		gpio-controller;
 		#gpio-cells = <2>;
+		ngpio = <117>;
 		interrupts = <0 208 0>;
+		qcom,direct-connect-irqs = <8>;
 	};
 
 	timer {
@@ -83,6 +86,15 @@
 		compatible = "qcom,android-usb";
 	};
 
+	wcd9xxx_intc: wcd9xxx-irq {
+		compatible = "qcom,wcd9xxx-irq";
+		interrupt-controller;
+		#interrupt-cells = <1>;
+		interrupt-parent = <&msmgpio>;
+		interrupts = <68 0>;
+		interrupt-names = "cdc-int";
+	};
+
 	slim@fe12f000 {
 		cell-index = <1>;
 		compatible = "qcom,slim-ngd";
@@ -91,6 +103,212 @@
 		reg-names = "slimbus_physical", "slimbus_bam_physical";
 		interrupts = <0 163 0>, <0 164 0>;
 		interrupt-names = "slimbus_irq", "slimbus_bam_irq";
+
+		tapan_codec {
+			compatible = "qcom,tapan-slim-pgd";
+			elemental-addr = [00 01 E0 00 17 02];
+
+			interrupt-parent = <&wcd9xxx_intc>;
+			interrupts = <0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
+					17 18 19 20 21 22 23 24 25 26 27 28>;
+			qcom,cdc-reset-gpio = <&msmgpio 72 0>;
+
+			cdc-vdd-buck-supply = <&pm8026_s4>;
+			qcom,cdc-vdd-buck-voltage = <2100000 2100000>;
+			qcom,cdc-vdd-buck-current = <650000>;
+
+			cdc-vdd-h-supply = <&pm8026_l6>;
+			qcom,cdc-vdd-h-voltage = <1800000 1800000>;
+			qcom,cdc-vdd-h-current = <25000>;
+
+			cdc-vdd-px-supply = <&pm8026_l6>;
+			qcom,cdc-vdd-px-voltage = <1800000 1800000>;
+			qcom,cdc-vdd-px-current = <25000>;
+
+			cdc-vdd-a-1p2v-supply = <&pm8026_l4>;
+			qcom,cdc-vdd-a-1p2v-voltage = <1200000 1200000>;
+			qcom,cdc-vdd-a-1p2v-current = <10000>;
+
+			cdc-vdd-cx-supply = <&pm8026_l4>;
+			qcom,cdc-vdd-cx-voltage = <1200000 1200000>;
+			qcom,cdc-vdd-cx-current = <10000>;
+
+			qcom,cdc-micbias-ldoh-v = <0x3>;
+			qcom,cdc-micbias-cfilt1-mv = <1800>;
+			qcom,cdc-micbias-cfilt2-mv = <1800>;
+			qcom,cdc-micbias-cfilt3-mv = <1800>;
+
+			qcom,cdc-micbias1-cfilt-sel = <0x0>;
+			qcom,cdc-micbias2-cfilt-sel = <0x1>;
+			qcom,cdc-micbias3-cfilt-sel = <0x2>;
+
+			qcom,cdc-mclk-clk-rate = <9600000>;
+			qcom,cdc-slim-ifd = "tapan-slim-ifd";
+			qcom,cdc-slim-ifd-elemental-addr = [00 00 E0 00 17 02];
+		};
+	};
+
+	qcom,msm-adsp-loader {
+		compatible = "qcom,adsp-loader";
+		qcom,adsp-state = <0>;
+	};
+
+	sound {
+		compatible = "qcom,msm8226-audio-tapan";
+		qcom,model = "msm8226-tapan-snd-card";
+
+		qcom,audio-routing =
+			"RX_BIAS", "MCLK",
+			"LDO_H", "MCLK",
+			"AMIC1", "MIC BIAS1 Internal1",
+			"MIC BIAS1 Internal1", "Handset Mic",
+			"AMIC2", "MIC BIAS2 External",
+			"MIC BIAS2 External", "Headset Mic",
+			"AMIC3", "MIC BIAS2 External",
+			"MIC BIAS2 External", "ANCRight Headset Mic",
+			"AMIC4", "MIC BIAS2 External",
+			"MIC BIAS2 External", "ANCLeft Headset Mic",
+			"DMIC1", "MIC BIAS1 External",
+			"MIC BIAS1 External", "Digital Mic1",
+			"DMIC2", "MIC BIAS1 External",
+			"MIC BIAS1 External", "Digital Mic2",
+			"DMIC3", "MIC BIAS3 External",
+			"MIC BIAS3 External", "Digital Mic3",
+			"DMIC4", "MIC BIAS3 External",
+			"MIC BIAS3 External", "Digital Mic4",
+			"DMIC5", "MIC BIAS4 External",
+			"MIC BIAS4 External", "Digital Mic5",
+			"DMIC6", "MIC BIAS4 External",
+			"MIC BIAS4 External", "Digital Mic6";
+		qcom,tapan-mclk-clk-freq = <9600000>;
+	};
+
+	qcom,msm-pcm {
+		compatible = "qcom,msm-pcm-dsp";
+	};
+
+	qcom,msm-pcm-routing {
+		compatible = "qcom,msm-pcm-routing";
+	};
+
+	qcom,msm-pcm-lpa {
+		compatible = "qcom,msm-pcm-lpa";
+	};
+
+	qcom,msm-compr-dsp {
+		compatible = "qcom,msm-compr-dsp";
+	};
+
+	qcom,msm-voip-dsp {
+		compatible = "qcom,msm-voip-dsp";
+	};
+
+	qcom,msm-pcm-voice {
+		compatible = "qcom,msm-pcm-voice";
+	};
+
+	qcom,msm-stub-codec {
+		compatible = "qcom,msm-stub-codec";
+	};
+
+	qcom,msm-dai-fe {
+		compatible = "qcom,msm-dai-fe";
+	};
+
+	qcom,msm-pcm-afe {
+		compatible = "qcom,msm-pcm-afe";
+	};
+
+	qcom,msm-dai-q6-hdmi {
+		compatible = "qcom,msm-dai-q6-hdmi";
+		qcom,msm-dai-q6-dev-id = <8>;
+	};
+
+	qcom,msm-dai-q6 {
+		compatible = "qcom,msm-dai-q6";
+		qcom,msm-dai-q6-sb-0-rx {
+			compatible = "qcom,msm-dai-q6-dev";
+			qcom,msm-dai-q6-dev-id = <16384>;
+		};
+
+		qcom,msm-dai-q6-sb-0-tx {
+			compatible = "qcom,msm-dai-q6-dev";
+			qcom,msm-dai-q6-dev-id = <16385>;
+		};
+
+		qcom,msm-dai-q6-sb-1-rx {
+			compatible = "qcom,msm-dai-q6-dev";
+			qcom,msm-dai-q6-dev-id = <16386>;
+		};
+
+		qcom,msm-dai-q6-sb-1-tx {
+			compatible = "qcom,msm-dai-q6-dev";
+			qcom,msm-dai-q6-dev-id = <16387>;
+		};
+
+		qcom,msm-dai-q6-sb-3-rx {
+			compatible = "qcom,msm-dai-q6-dev";
+			qcom,msm-dai-q6-dev-id = <16390>;
+		};
+
+		qcom,msm-dai-q6-sb-3-tx {
+			compatible = "qcom,msm-dai-q6-dev";
+			qcom,msm-dai-q6-dev-id = <16391>;
+		};
+
+		qcom,msm-dai-q6-sb-4-rx {
+			compatible = "qcom,msm-dai-q6-dev";
+			qcom,msm-dai-q6-dev-id = <16392>;
+		};
+
+		qcom,msm-dai-q6-sb-4-tx {
+			compatible = "qcom,msm-dai-q6-dev";
+			qcom,msm-dai-q6-dev-id = <16393>;
+		};
+
+		qcom,msm-dai-q6-bt-sco-rx {
+			compatible = "qcom,msm-dai-q6-dev";
+			qcom,msm-dai-q6-dev-id = <12288>;
+		};
+
+		qcom,msm-dai-q6-bt-sco-tx {
+			compatible = "qcom,msm-dai-q6-dev";
+			qcom,msm-dai-q6-dev-id = <12289>;
+		};
+
+		qcom,msm-dai-q6-int-fm-rx {
+			compatible = "qcom,msm-dai-q6-dev";
+			qcom,msm-dai-q6-dev-id = <12292>;
+		};
+
+		qcom,msm-dai-q6-int-fm-tx {
+			compatible = "qcom,msm-dai-q6-dev";
+			qcom,msm-dai-q6-dev-id = <12293>;
+		};
+
+		qcom,msm-dai-q6-be-afe-pcm-rx {
+			compatible = "qcom,msm-dai-q6-dev";
+			qcom,msm-dai-q6-dev-id = <224>;
+		};
+
+		qcom,msm-dai-q6-be-afe-pcm-tx {
+			compatible = "qcom,msm-dai-q6-dev";
+			qcom,msm-dai-q6-dev-id = <225>;
+		};
+
+		qcom,msm-dai-q6-afe-proxy-rx {
+			compatible = "qcom,msm-dai-q6-dev";
+			qcom,msm-dai-q6-dev-id = <241>;
+		};
+
+		qcom,msm-dai-q6-afe-proxy-tx {
+			compatible = "qcom,msm-dai-q6-dev";
+			qcom,msm-dai-q6-dev-id = <240>;
+		};
+	};
+
+	qcom,msm-pcm-hostless {
+		compatible = "qcom,msm-pcm-hostless";
 	};
 
 	qcom,wdt@f9017000 {
diff --git a/arch/arm/boot/dts/msm8910-iommu-domains.dtsi b/arch/arm/boot/dts/msm8910-iommu-domains.dtsi
new file mode 100644
index 0000000..dbdbd5f
--- /dev/null
+++ b/arch/arm/boot/dts/msm8910-iommu-domains.dtsi
@@ -0,0 +1,36 @@
+/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+/ {
+	qcom,iommu-domains {
+		compatible = "qcom,iommu-domains";
+
+		qcom,iommu-domain1 {
+			label = "lpass_secure";
+			qcom,iommu-contexts = <&lpass_q6_fw>;
+			qcom,virtual-addr-pool = <0x00000000 0x0FFFFFFF
+						  0xF0000000 0x0FFFFFFF>;
+		};
+
+		qcom,iommu-domain2 {
+			label = "lpass_audio";
+			qcom,iommu-contexts = <&lpass_audio_shared>;
+			qcom,virtual-addr-pool = <0x10000000 0x0FFFFFFF>;
+		};
+
+		qcom,iommu-domain3 {
+			label = "lpass_video";
+			qcom,iommu-contexts = <&lpass_video_shared>;
+			qcom,virtual-addr-pool = <0x20000000 0x0FFFFFFF>;
+		};
+	};
+};
diff --git a/arch/arm/boot/dts/msm8910.dtsi b/arch/arm/boot/dts/msm8910.dtsi
index 61f1dcd..a08c165 100644
--- a/arch/arm/boot/dts/msm8910.dtsi
+++ b/arch/arm/boot/dts/msm8910.dtsi
@@ -35,7 +35,9 @@
 		reg = <0xfd510000 0x4000>;
 		gpio-controller;
 		#gpio-cells = <2>;
+		ngpio = <102>;
 		interrupts = <0 208 0>;
+		qcom,direct-connect-irqs = <8>;
 	};
 
 	timer {
@@ -340,5 +342,7 @@
 	status = "ok";
 };
 
+/include/ "msm8910-iommu-domains.dtsi"
+
 /include/ "msm8910-regulator.dtsi"
 /include/ "msm-pm8110.dtsi"
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.dtsi b/arch/arm/boot/dts/msm8974.dtsi
index bd0711c..e43ff69 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
@@ -40,7 +40,9 @@
 		interrupt-controller;
 		#interrupt-cells = <2>;
 		reg = <0xfd510000 0x4000>;
+		ngpio = <146>;
 		interrupts = <0 208 0>;
+		qcom,direct-connect-irqs = <8>;
 	};
 
 	wcd9xxx_intc: wcd9xxx-irq {
@@ -68,6 +70,7 @@
 			<783360 410000000>,
 			<489600 266670000>,
 			<244800 133330000>;
+		hfi = "venus";
 	};
 
 	qcom,wfd {
@@ -97,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";
@@ -1112,6 +1117,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.dtsi b/arch/arm/boot/dts/msm9625.dtsi
index bf66de6..2fbff6d 100644
--- a/arch/arm/boot/dts/msm9625.dtsi
+++ b/arch/arm/boot/dts/msm9625.dtsi
@@ -42,7 +42,9 @@
 		interrupt-controller;
 		#interrupt-cells = <2>;
 		reg = <0xfd510000 0x4000>;
+		ngpio = <76>;
 		interrupts = <0 208 0>;
+		qcom,direct-connect-irqs = <8>;
 	};
 
 	timer: msm-qtimer@f9021000 {
@@ -79,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;
 	};
@@ -468,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 {
diff --git a/arch/arm/configs/msm8910_defconfig b/arch/arm/configs/msm8910_defconfig
index 67fabd4..4b1e3f2 100644
--- a/arch/arm/configs/msm8910_defconfig
+++ b/arch/arm/configs/msm8910_defconfig
@@ -36,6 +36,7 @@
 CONFIG_ARCH_MSM=y
 CONFIG_ARCH_MSM8910=y
 CONFIG_ARCH_MSM8226=y
+CONFIG_SND_SOC_MSM8226=y
 # CONFIG_MSM_STACKED_MEMORY is not set
 CONFIG_CPU_HAS_L2_PMU=y
 # CONFIG_MSM_FIQ_SUPPORT is not set
@@ -45,6 +46,7 @@
 # CONFIG_MSM_HW3D is not set
 CONFIG_MSM_DIRECT_SCLK_ACCESS=y
 CONFIG_MSM_WATCHDOG_V2=y
+CONFIG_MSM_ADSP_LOADER=m
 CONFIG_NO_HZ=y
 CONFIG_HIGH_RES_TIMERS=y
 CONFIG_SMP=y
@@ -104,8 +106,12 @@
 CONFIG_SPMI=y
 CONFIG_SPMI_MSM_PMIC_ARB=y
 CONFIG_MSM_QPNP_INT=y
+CONFIG_SLIMBUS=y
+CONFIG_SLIMBUS_MSM_NGD=y
 CONFIG_DEBUG_GPIO=y
 CONFIG_GPIO_SYSFS=y
+CONFIG_I2C=y
+CONFIG_WCD9306_CODEC=y
 # CONFIG_HWMON is not set
 CONFIG_REGULATOR=y
 CONFIG_REGULATOR_STUB=y
@@ -130,7 +136,6 @@
 CONFIG_MMC_BLOCK_MINORS=32
 CONFIG_MMC_TEST=m
 CONFIG_MMC_MSM=y
-CONFIG_MMC_MSM_SPS_SUPPORT=y
 CONFIG_STAGING=y
 CONFIG_ANDROID=y
 CONFIG_ANDROID_BINDER_IPC=y
@@ -138,9 +143,10 @@
 CONFIG_ANDROID_RAM_CONSOLE=y
 CONFIG_ANDROID_TIMED_GPIO=y
 CONFIG_ANDROID_LOW_MEMORY_KILLER=y
+CONFIG_MSM_IOMMU=y
 CONFIG_SPS=y
 CONFIG_SPS_SUPPORT_NDP_BAM=y
-CONFIG_MSM_IOMMU=y
+CONFIG_MMC_MSM_SPS_SUPPORT=y
 CONFIG_EXT2_FS=y
 CONFIG_EXT2_FS_XATTR=y
 CONFIG_EXT3_FS=y
@@ -157,7 +163,6 @@
 CONFIG_DEBUG_FS=y
 CONFIG_SCHEDSTATS=y
 CONFIG_TIMER_STATS=y
-# CONFIG_DEBUG_PREEMPT is not set
 CONFIG_DEBUG_INFO=y
 CONFIG_DEBUG_MEMORY_INIT=y
 CONFIG_DYNAMIC_DEBUG=y
diff --git a/arch/arm/configs/msm8960-perf_defconfig b/arch/arm/configs/msm8960-perf_defconfig
index 1aaf7ea..f464a55 100644
--- a/arch/arm/configs/msm8960-perf_defconfig
+++ b/arch/arm/configs/msm8960-perf_defconfig
@@ -246,7 +246,6 @@
 CONFIG_RFKILL=y
 CONFIG_GENLOCK=y
 CONFIG_GENLOCK_MISCDEVICE=y
-CONFIG_CMA=y
 CONFIG_BLK_DEV_LOOP=y
 CONFIG_BLK_DEV_RAM=y
 CONFIG_TSPP=m
@@ -454,6 +453,8 @@
 CONFIG_MMC_MSM_SDC3_SUPPORT=y
 CONFIG_MMC_MSM_SDC3_WP_SUPPORT=y
 CONFIG_MMC_MSM_SPS_SUPPORT=y
+CONFIG_IOSCHED_TEST=y
+CONFIG_MMC_BLOCK_TEST=y
 CONFIG_LEDS_PM8XXX=y
 CONFIG_LEDS_TRIGGERS=y
 CONFIG_LEDS_TRIGGER_HEARTBEAT=y
diff --git a/arch/arm/configs/msm8960_defconfig b/arch/arm/configs/msm8960_defconfig
index 94d12e0..e54459d 100644
--- a/arch/arm/configs/msm8960_defconfig
+++ b/arch/arm/configs/msm8960_defconfig
@@ -251,7 +251,6 @@
 CONFIG_RFKILL=y
 CONFIG_GENLOCK=y
 CONFIG_GENLOCK_MISCDEVICE=y
-CONFIG_CMA=y
 CONFIG_BLK_DEV_LOOP=y
 CONFIG_BLK_DEV_RAM=y
 CONFIG_TSPP=m
@@ -457,6 +456,8 @@
 CONFIG_MMC_MSM_SDC3_SUPPORT=y
 CONFIG_MMC_MSM_SDC3_WP_SUPPORT=y
 CONFIG_MMC_MSM_SPS_SUPPORT=y
+CONFIG_IOSCHED_TEST=y
+CONFIG_MMC_BLOCK_TEST=y
 CONFIG_LEDS_PM8XXX=y
 CONFIG_LEDS_TRIGGERS=y
 CONFIG_LEDS_TRIGGER_HEARTBEAT=y
diff --git a/arch/arm/configs/msm8974-perf_defconfig b/arch/arm/configs/msm8974-perf_defconfig
index 8debb93..136cb5a 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
@@ -217,7 +216,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
@@ -373,6 +372,8 @@
 CONFIG_MMC_SDHCI_PLTFM=y
 CONFIG_MMC_MSM=y
 CONFIG_MMC_MSM_SPS_SUPPORT=y
+CONFIG_IOSCHED_TEST=y
+CONFIG_MMC_BLOCK_TEST=y
 CONFIG_LEDS_QPNP=y
 CONFIG_LEDS_TRIGGERS=y
 CONFIG_LEDS_TRIGGER_BACKLIGHT=y
@@ -388,7 +389,6 @@
 CONFIG_ANDROID_RAM_CONSOLE=y
 CONFIG_ANDROID_TIMED_GPIO=y
 CONFIG_ANDROID_LOW_MEMORY_KILLER=y
-CONFIG_MSM_SSBI=y
 CONFIG_SPS=y
 CONFIG_USB_BAM=y
 CONFIG_SPS_SUPPORT_BAMDMA=y
@@ -429,3 +429,5 @@
 CONFIG_CRYPTO_DEV_QCE=m
 CONFIG_CRYPTO_DEV_QCEDEV=m
 CONFIG_CRC_CCITT=y
+CONFIG_SYNC=y
+CONFIG_SW_SYNC=y
diff --git a/arch/arm/configs/msm8974_defconfig b/arch/arm/configs/msm8974_defconfig
index 0f8c469..eb3c315 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
@@ -219,7 +218,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
@@ -374,6 +373,8 @@
 CONFIG_MMC_SDHCI_PLTFM=y
 CONFIG_MMC_MSM=y
 CONFIG_MMC_MSM_SPS_SUPPORT=y
+CONFIG_IOSCHED_TEST=y
+CONFIG_MMC_BLOCK_TEST=y
 CONFIG_LEDS_QPNP=y
 CONFIG_LEDS_TRIGGERS=y
 CONFIG_LEDS_TRIGGER_BACKLIGHT=y
@@ -389,7 +390,6 @@
 CONFIG_ANDROID_RAM_CONSOLE=y
 CONFIG_ANDROID_TIMED_GPIO=y
 CONFIG_ANDROID_LOW_MEMORY_KILLER=y
-CONFIG_MSM_SSBI=y
 CONFIG_SPS=y
 CONFIG_USB_BAM=y
 CONFIG_SPS_SUPPORT_BAMDMA=y
@@ -419,7 +419,6 @@
 CONFIG_TIMER_STATS=y
 CONFIG_DEBUG_KMEMLEAK=y
 CONFIG_DEBUG_KMEMLEAK_DEFAULT_OFF=y
-# CONFIG_DEBUG_PREEMPT is not set
 CONFIG_DEBUG_SPINLOCK=y
 CONFIG_DEBUG_MUTEXES=y
 CONFIG_DEBUG_ATOMIC_SLEEP=y
@@ -444,3 +443,5 @@
 CONFIG_CRYPTO_DEV_QCE=m
 CONFIG_CRYPTO_DEV_QCEDEV=m
 CONFIG_CRC_CCITT=y
+CONFIG_SYNC=y
+CONFIG_SW_SYNC=y
diff --git a/arch/arm/configs/msm9625_defconfig b/arch/arm/configs/msm9625_defconfig
index cbdcc5b..decd8f2 100644
--- a/arch/arm/configs/msm9625_defconfig
+++ b/arch/arm/configs/msm9625_defconfig
@@ -88,7 +88,13 @@
 CONFIG_NF_CONNTRACK=y
 CONFIG_NF_CONNTRACK_EVENTS=y
 CONFIG_NF_CONNTRACK_TIMESTAMP=y
+CONFIG_NF_CT_PROTO_UDPLITE=y
+CONFIG_NF_CONNTRACK_AMANDA=y
 CONFIG_NF_CONNTRACK_FTP=y
+CONFIG_NF_CONNTRACK_H323=y
+CONFIG_NF_CONNTRACK_IRC=y
+CONFIG_NF_CONNTRACK_NETBIOS_NS=y
+CONFIG_NF_CONNTRACK_SNMP=y
 CONFIG_NF_CONNTRACK_PPTP=y
 CONFIG_NF_CONNTRACK_SIP=y
 CONFIG_NF_CONNTRACK_TFTP=y
@@ -97,6 +103,8 @@
 CONFIG_NETFILTER_XT_MATCH_ADDRTYPE=y
 CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=y
 CONFIG_NETFILTER_XT_MATCH_CONNTRACK=y
+CONFIG_NETFILTER_XT_MATCH_DSCP=y
+CONFIG_NETFILTER_XT_MATCH_ESP=y
 CONFIG_NETFILTER_XT_MATCH_IPRANGE=y
 CONFIG_NETFILTER_XT_MATCH_MULTIPORT=y
 CONFIG_NETFILTER_XT_MATCH_PKTTYPE=y
@@ -230,6 +238,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
@@ -262,3 +271,32 @@
 CONFIG_CRYPTO_DEV_QCEDEV=m
 CONFIG_CRC_CCITT=y
 CONFIG_LIBCRC32C=y
+CONFIG_USB=y
+CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
+CONFIG_USB_SUSPEND=y
+CONFIG_USB_EHCI_HCD=y
+CONFIG_USB_EHCI_EHSET=y
+CONFIG_USB_EHCI_MSM=y
+CONFIG_USB_STORAGE=y
+CONFIG_USB_STORAGE_DEBUG=y
+CONFIG_USB_STORAGE_DATAFAB=y
+CONFIG_USB_STORAGE_FREECOM=y
+CONFIG_USB_STORAGE_ISD200=y
+CONFIG_USB_STORAGE_USBAT=y
+CONFIG_USB_STORAGE_SDDR09=y
+CONFIG_USB_STORAGE_SDDR55=y
+CONFIG_USB_STORAGE_JUMPSHOT=y
+CONFIG_USB_STORAGE_ALAUDA=y
+CONFIG_USB_STORAGE_ONETOUCH=y
+CONFIG_USB_STORAGE_KARMA=y
+CONFIG_USB_STORAGE_CYPRESS_ATACB=y
+CONFIG_USB_EHSET_TEST_FIXTURE=y
+CONFIG_SCSI=y
+CONFIG_SCSI_TGT=y
+CONFIG_BLK_DEV_SD=y
+CONFIG_CHR_DEV_SG=y
+CONFIG_CHR_DEV_SCH=y
+CONFIG_SCSI_MULTI_LUN=y
+CONFIG_SCSI_CONSTANTS=y
+CONFIG_SCSI_LOGGING=y
+CONFIG_SCSI_SCAN_ASYNC=y
diff --git a/arch/arm/include/asm/hardware/cache-l2x0.h b/arch/arm/include/asm/hardware/cache-l2x0.h
index 5dc9a66..27ecb3a 100644
--- a/arch/arm/include/asm/hardware/cache-l2x0.h
+++ b/arch/arm/include/asm/hardware/cache-l2x0.h
@@ -69,7 +69,6 @@
 #define L2X0_CACHE_ID_REV_MASK		(0x3f)
 #define L2X0_CACHE_ID_PART_MASK		(0xf << 6)
 #define L2X0_CACHE_ID_PART_L210		(1 << 6)
-#define L2X0_CACHE_ID_PART_L220         (2 << 6)
 #define L2X0_CACHE_ID_PART_L310		(3 << 6)
 #define L2X0_CACHE_ID_RTL_MASK          0x3f
 #define L2X0_CACHE_ID_RTL_R0P0          0x0
@@ -105,7 +104,6 @@
 #define L2X0_LATENCY_CTRL_WR_SHIFT	8
 
 #define L2X0_ADDR_FILTER_EN		1
-#define L2X0_INTR_MASK_ECNTR           1
 
 #define REV_PL310_R2P0				4
 
@@ -118,6 +116,7 @@
 #define L2X0_PREFETCH_CTRL_WRAP8_SHIFT		30
 
 #ifndef __ASSEMBLY__
+extern void __iomem *l2x0_base;
 extern void l2cc_suspend(void);
 extern void l2cc_resume(void);
 extern void l2x0_cache_sync(void);
@@ -148,49 +147,6 @@
 
 extern struct l2x0_regs l2x0_saved_regs;
 
-#ifdef CONFIG_HW_PERF_EVENTS
-/* L220/PL310 Event control register values */
-#define L2X0_EVENT_CNT_ENABLE_MASK             1
-#define L2X0_EVENT_CNT_ENABLE                  1
-#define L2X0_EVENT_CNT_RESET(x)                (1 << (x+1))
-
-/* Bit-shifted event counter config values */
-enum l2x0_perf_types {
-	L2X0_EVENT_CNT_CFG_DISABLED             = 0x0,
-	L2X0_EVENT_CNT_CFG_CO                   = 0x1,
-	L2X0_EVENT_CNT_CFG_DRHIT                = 0x2,
-	L2X0_EVENT_CNT_CFG_DRREQ                = 0x3,
-	L2X0_EVENT_CNT_CFG_DWHIT                = 0x4,
-	L2X0_EVENT_CNT_CFG_DWREQ                = 0x5,
-	L2X0_EVENT_CNT_CFG_DWTREQ               = 0x6,
-	L2X0_EVENT_CNT_CFG_IRHIT                = 0x7,
-	L2X0_EVENT_CNT_CFG_IRREQ                = 0x8,
-	L2X0_EVENT_CNT_CFG_WA                   = 0x9,
-
-	/* PL310 only */
-	L2X0_EVENT_CNT_CFG_IPFALLOC             = 0xA,
-	L2X0_EVENT_CNT_CFG_EPFHIT               = 0xB,
-	L2X0_EVENT_CNT_CFG_EPFALLOC             = 0xC,
-	L2X0_EVENT_CNT_CFG_SRRCVD               = 0xD,
-	L2X0_EVENT_CNT_CFG_SRCONF               = 0xE,
-	L2X0_EVENT_CNT_CFG_EPFRCVD              = 0xF,
-};
-
-#define L220_EVENT_CNT_CFG_MAX                 L2X0_EVENT_CNT_CFG_WA
-#define PL310_EVENT_CNT_CFG_MAX                L2X0_EVENT_CNT_CFG_EPFRCVD
-
-#define L2X0_EVENT_CNT_CFG_SHIFT               2
-#define L2X0_EVENT_CNT_CFG_MASK                (0xF << 2)
-
-#define L2X0_EVENT_CNT_CFG_INTR_MASK           0x3
-#define L2X0_EVENT_CNT_CFG_INTR_DISABLED       0x0
-#define L2X0_EVENT_CNT_CFG_INTR_INCREMENT      0x1
-#define L2X0_EVENT_CNT_CFG_INTR_OVERFLOW       0x2
-
-#define L2X0_NUM_COUNTERS                      2
-
-#endif /* CONFIG_HW_PERF_EVENTS */
-
 #endif /* __ASSEMBLY__ */
 
 #endif
diff --git a/arch/arm/mach-msm/Kconfig b/arch/arm/mach-msm/Kconfig
index 8dd8579..afb9ab6 100644
--- a/arch/arm/mach-msm/Kconfig
+++ b/arch/arm/mach-msm/Kconfig
@@ -346,6 +346,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"
@@ -372,6 +373,7 @@
 	select MSM_QDSP6_APRV2
 	select MSM_QDSP6V2_CODECS
 	select MSM_AUDIO_QDSP6V2 if SND_SOC
+	select CPU_HAS_L2_PMU
 
 config ARCH_MSM8910
 	bool "MSM8910"
@@ -402,6 +404,9 @@
 	select MSM_GPIOMUX
 	select MSM_NATIVE_RESTART
 	select MSM_RESTART_V2
+	select MSM_QDSP6_APRV2
+	select MSM_QDSP6V2_CODECS
+	select MSM_AUDIO_QDSP6V2 if SND_SOC
 endmenu
 
 choice
@@ -478,6 +483,7 @@
 	select ARCH_MSM_CORTEXMP
 	select MIGHT_HAVE_CACHE_L2X0
 	select ARM_HAS_SG_CHAIN
+	select CPU_HAS_L2_PMU
 
 config  MSM_VIC
 	bool
@@ -1562,6 +1568,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
@@ -2736,4 +2752,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 ff21190..2d617a9 100644
--- a/arch/arm/mach-msm/Makefile
+++ b/arch/arm/mach-msm/Makefile
@@ -33,7 +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
@@ -133,6 +138,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
diff --git a/arch/arm/mach-msm/acpuclock-8064.c b/arch/arm/mach-msm/acpuclock-8064.c
index db77a34..e8c7680 100644
--- a/arch/arm/mach-msm/acpuclock-8064.c
+++ b/arch/arm/mach-msm/acpuclock-8064.c
@@ -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 },
@@ -241,12 +241,12 @@
 
 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 +259,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 +277,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 +295,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 +313,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 +331,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 +349,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 +367,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 +386,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 +405,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 +424,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 +443,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 +462,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 +481,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 },
diff --git a/arch/arm/mach-msm/acpuclock-8625q.c b/arch/arm/mach-msm/acpuclock-8625q.c
index 0a6dfbe..80cb0ae 100644
--- a/arch/arm/mach-msm/acpuclock-8625q.c
+++ b/arch/arm/mach-msm/acpuclock-8625q.c
@@ -121,7 +121,11 @@
 # define DELTA_LEVEL_2_UV 75000
 # define DELTA_LEVEL_3_UV 150000
 
-
+/*
+ * The default initialization is according to the requirements of
+ * SKUD_prime. If the target is quad core, we reinitialize this table using
+ * the reinitalize_freq_table() function.
+ */
 static struct clkctl_acpu_speed acpu_freq_tbl_cmn[] = {
 	{ 0, 19200, ACPU_PLL_TCXO, 0, 0, 2400, 3, 0, 30720 },
 	{ 1, 245760, ACPU_PLL_1, 1, 0, 30720, 3, MAX_NOMINAL_VOLTAGE, 61440 },
@@ -552,11 +556,40 @@
 		return 0;
 }
 
+static int reinitialize_freq_table(bool target_select)
+{
+	/*
+	 * target_flag is set only if it is a Quad core chip,
+	 * In that case, we modify the initialization
+	 * of the table according to the specific requirement
+	 * for this target. Otherwise the default initialized table is
+	 * used for SKUD_prime.
+	 */
+	if (target_select) {
+		struct clkctl_acpu_speed *tbl;
+		for (tbl = acpu_freq_tbl; tbl->a11clk_khz; tbl++) {
+
+			if (tbl->a11clk_khz >= 1008000) {
+				tbl->axiclk_khz = 300000;
+				if (tbl->a11clk_khz == 1209600)
+					tbl->vdd = 0;
+			} else {
+				if (tbl->a11clk_khz != 600000
+					&& tbl->a11clk_khz != 19200)
+					tbl->vdd = 1050000;
+				if (tbl->a11clk_khz == 700800)
+					tbl->axiclk_khz = 245000;
+			}
+		}
+
+	}
+	return 0;
+}
+
 #define MHZ 1000000
 
 static void __devinit select_freq_plan(unsigned int pvs_voltage,
-					unsigned int nominal_vol_uv,
-					unsigned int default_vol_uv)
+							bool target_sel)
 {
 	unsigned long pll_mhz[ACPU_PLL_END];
 	int i;
@@ -617,6 +650,8 @@
 		}
 	}
 
+	reinitialize_freq_table(target_sel);
+
 	/*
 	 *PVS Voltage calculation  formula
 	 *1.4 Ghz device
@@ -630,8 +665,6 @@
 	*/
 	for (tbl = acpu_freq_tbl; tbl->a11clk_khz; tbl++) {
 		if (tbl->a11clk_khz >= 1008000) {
-			if (tbl->a11clk_khz == 1209600)
-				tbl->vdd = default_vol_uv;
 			/*
 			 * Change voltage as per PVS formula,
 			 * i is initialized above with 2 or 1
@@ -643,9 +676,7 @@
 
 			tbl->vdd = max((int)(pvs_voltage - delta[i]), tbl->vdd);
 			i--;
-		} else if (tbl->a11clk_khz != 600000
-					&& tbl->a11clk_khz != 19200)
-			tbl->vdd = nominal_vol_uv;
+		}
 	}
 
 
@@ -729,8 +760,7 @@
 {
 	const struct acpuclk_pdata_8625q *pdata = pdev->dev.platform_data;
 	unsigned int pvs_voltage = pdata->pvs_voltage_uv;
-	unsigned int nom_vol_uv = pdata->nominal_voltage;
-	unsigned int default_vol_uv = pdata->default_turbo_voltage;
+	bool target_sel = pdata->flag;
 
 	drv_state.max_speed_delta_khz = pdata->acpu_clk_data->
 						max_speed_delta_khz;
@@ -739,7 +769,7 @@
 	BUG_ON(IS_ERR(drv_state.ebi1_clk));
 
 	mutex_init(&drv_state.lock);
-	select_freq_plan(pvs_voltage, nom_vol_uv, default_vol_uv);
+	select_freq_plan(pvs_voltage, target_sel);
 	acpuclk_8625q_data.wait_for_irq_khz = find_wait_for_irq_khz();
 
 	if (acpuclk_hw_init() < 0)
diff --git a/arch/arm/mach-msm/acpuclock-8625q.h b/arch/arm/mach-msm/acpuclock-8625q.h
index c91e3bd..ced2f70 100644
--- a/arch/arm/mach-msm/acpuclock-8625q.h
+++ b/arch/arm/mach-msm/acpuclock-8625q.h
@@ -23,8 +23,7 @@
 struct acpuclk_pdata_8625q {
 	struct acpuclk_pdata *acpu_clk_data;
 	unsigned int pvs_voltage_uv;
-	unsigned int nominal_voltage;
-	unsigned int default_turbo_voltage;
+	bool flag;
 };
 
 #endif /* __ARCH_ARM_MACH_MSM_ACPUCLOCK_8625Q_H */
diff --git a/arch/arm/mach-msm/acpuclock-8930.c b/arch/arm/mach-msm/acpuclock-8930.c
index 948ecdd..40326cb 100644
--- a/arch/arm/mach-msm/acpuclock-8930.c
+++ b/arch/arm/mach-msm/acpuclock-8930.c
@@ -132,9 +132,8 @@
 	.name = "acpuclk-8930",
 };
 
-/* TODO: Update vdd_dig, vdd_mem and bw when data is available. */
 static struct l2_level l2_freq_tbl[] __initdata = {
-	[0]  = { {  384000, PLL_8, 0, 0x00 },  LVL_NOM, 1050000, 1 },
+	[0]  = { {  384000, PLL_8, 0, 0x00 },  LVL_LOW, 1050000, 1 },
 	[1]  = { {  432000, HFPLL, 2, 0x20 },  LVL_NOM, 1050000, 2 },
 	[2]  = { {  486000, HFPLL, 2, 0x24 },  LVL_NOM, 1050000, 2 },
 	[3]  = { {  540000, HFPLL, 2, 0x28 },  LVL_NOM, 1050000, 2 },
diff --git a/arch/arm/mach-msm/acpuclock-8930aa.c b/arch/arm/mach-msm/acpuclock-8930aa.c
index 8d48b54..7d1ce09 100644
--- a/arch/arm/mach-msm/acpuclock-8930aa.c
+++ b/arch/arm/mach-msm/acpuclock-8930aa.c
@@ -96,9 +96,8 @@
 	.name = "acpuclk-8930aa",
 };
 
-/* TODO: Update vdd_dig, vdd_mem and bw when data is available. */
 static struct l2_level l2_freq_tbl[] __initdata = {
-	[0]  = { {  384000, PLL_8, 0, 0x00 },  LVL_NOM, 1050000, 1 },
+	[0]  = { {  384000, PLL_8, 0, 0x00 },  LVL_LOW, 1050000, 1 },
 	[1]  = { {  432000, HFPLL, 2, 0x20 },  LVL_NOM, 1050000, 2 },
 	[2]  = { {  486000, HFPLL, 2, 0x24 },  LVL_NOM, 1050000, 2 },
 	[3]  = { {  540000, HFPLL, 2, 0x28 },  LVL_NOM, 1050000, 2 },
diff --git a/arch/arm/mach-msm/board-8064-display.c b/arch/arm/mach-msm/board-8064-display.c
index b717973..b0dc20b 100644
--- a/arch/arm/mach-msm/board-8064-display.c
+++ b/arch/arm/mach-msm/board-8064-display.c
@@ -818,12 +818,13 @@
 		return 0;
 
 	/* TBD: PM8921 regulator instead of 8901 */
-	if (!reg_ext_3p3v) {
+	if (!reg_ext_3p3v &&
+		(!(machine_is_mpq8064_hrd() || machine_is_mpq8064_dtv()))) {
 		reg_ext_3p3v = regulator_get(&hdmi_msm_device.dev,
-					     "hdmi_mux_vdd");
+						"hdmi_mux_vdd");
 		if (IS_ERR_OR_NULL(reg_ext_3p3v)) {
 			pr_err("could not get reg_ext_3p3v, rc = %ld\n",
-			       PTR_ERR(reg_ext_3p3v));
+				PTR_ERR(reg_ext_3p3v));
 			reg_ext_3p3v = NULL;
 			return -ENODEV;
 		}
@@ -831,7 +832,7 @@
 
 	if (!reg_8921_lvs7) {
 		reg_8921_lvs7 = regulator_get(&hdmi_msm_device.dev,
-					      "hdmi_vdda");
+						"hdmi_vdda");
 		if (IS_ERR(reg_8921_lvs7)) {
 			pr_err("could not get reg_8921_lvs7, rc = %ld\n",
 				PTR_ERR(reg_8921_lvs7));
@@ -841,7 +842,7 @@
 	}
 	if (!reg_8921_s4) {
 		reg_8921_s4 = regulator_get(&hdmi_msm_device.dev,
-					    "hdmi_lvl_tsl");
+						"hdmi_lvl_tsl");
 		if (IS_ERR(reg_8921_s4)) {
 			pr_err("could not get reg_8921_s4, rc = %ld\n",
 				PTR_ERR(reg_8921_s4));
@@ -860,17 +861,22 @@
 		 * Configure 3P3V_BOOST_EN as GPIO, 8mA drive strength,
 		 * pull none, out-high
 		 */
-		rc = regulator_set_optimum_mode(reg_ext_3p3v, 290000);
-		if (rc < 0) {
-			pr_err("set_optimum_mode ext_3p3v failed, rc=%d\n", rc);
-			return -EINVAL;
+		if (!(machine_is_mpq8064_hrd() || machine_is_mpq8064_dtv())) {
+			rc = regulator_set_optimum_mode(reg_ext_3p3v, 290000);
+			if (rc < 0) {
+				pr_err("set_optimum_mode ext_3p3v failed," \
+					"rc=%d\n", rc);
+				return -EINVAL;
+			}
+
+			rc = regulator_enable(reg_ext_3p3v);
+			if (rc) {
+				pr_err("enable reg_ext_3p3v failed, rc=%d\n",
+					rc);
+				return rc;
+			}
 		}
 
-		rc = regulator_enable(reg_ext_3p3v);
-		if (rc) {
-			pr_err("enable reg_ext_3p3v failed, rc=%d\n", rc);
-			return rc;
-		}
 		rc = regulator_enable(reg_8921_lvs7);
 		if (rc) {
 			pr_err("'%s' regulator enable failed, rc=%d\n",
@@ -885,11 +891,15 @@
 		}
 		pr_debug("%s(on): success\n", __func__);
 	} else {
-		rc = regulator_disable(reg_ext_3p3v);
-		if (rc) {
-			pr_err("disable reg_ext_3p3v failed, rc=%d\n", rc);
-			return -ENODEV;
+		if (!(machine_is_mpq8064_hrd() || machine_is_mpq8064_dtv())) {
+			rc = regulator_disable(reg_ext_3p3v);
+			if (rc) {
+				pr_err("disable reg_ext_3p3v failed, rc=%d\n",
+					rc);
+				return -ENODEV;
+			}
 		}
+
 		rc = regulator_disable(reg_8921_lvs7);
 		if (rc) {
 			pr_err("disable reg_8921_l23 failed, rc=%d\n", rc);
@@ -910,7 +920,8 @@
 error2:
 	regulator_disable(reg_8921_lvs7);
 error1:
-	regulator_disable(reg_ext_3p3v);
+	if (!(machine_is_mpq8064_hrd() || machine_is_mpq8064_dtv()))
+		regulator_disable(reg_ext_3p3v);
 	return rc;
 }
 
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..a6f0e32 100644
--- a/arch/arm/mach-msm/board-8064-regulator.c
+++ b/arch/arm/mach-msm/board-8064-regulator.c
@@ -299,7 +299,6 @@
 };
 VREG_CONSUMERS(EXT_5V) = {
 	REGULATOR_SUPPLY("ext_5v",		NULL),
-	REGULATOR_SUPPLY("ext_ddr3",		NULL),
 	REGULATOR_SUPPLY("vbus",		"msm_ehci_host.0"),
 };
 
diff --git a/arch/arm/mach-msm/board-8064.c b/arch/arm/mach-msm/board-8064.c
index d5fa3a7..4ebe5dc 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>
@@ -298,7 +299,6 @@
 	.reusable = FMEM_ENABLED,
 	.mem_is_fmem = FMEM_ENABLED,
 	.fixed_position = FIXED_MIDDLE,
-	.is_cma = 1,
 	.no_nonsecure_alloc = 1,
 };
 
@@ -2073,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");
 }
 
@@ -3539,20 +3540,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);
@@ -3583,7 +3570,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));
@@ -3657,7 +3644,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;
diff --git a/arch/arm/mach-msm/board-8092-gpiomux.c b/arch/arm/mach-msm/board-8092-gpiomux.c
index 823ef70..7cefe8a 100644
--- a/arch/arm/mach-msm/board-8092-gpiomux.c
+++ b/arch/arm/mach-msm/board-8092-gpiomux.c
@@ -43,9 +43,9 @@
 {
 	int rc;
 
-	rc = msm_gpiomux_init(NR_GPIO_IRQS);
+	rc = msm_gpiomux_init_dt();
 	if (rc) {
-		pr_err(KERN_ERR "mpq8092_init_gpiomux failed %d\n", rc);
+		pr_err("%s failed %d\n", __func__, rc);
 		return;
 	}
 
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 eb88ef4..7a53b24 100644
--- a/arch/arm/mach-msm/board-8226-gpiomux.c
+++ b/arch/arm/mach-msm/board-8226-gpiomux.c
@@ -17,13 +17,68 @@
 #include <mach/gpio.h>
 #include <mach/gpiomux.h>
 
+#define KS8851_IRQ_GPIO 75
+
+#if defined(CONFIG_KS8851) || defined(CONFIG_KS8851_MODULE)
+static struct gpiomux_setting gpio_eth_config = {
+	.pull = GPIOMUX_PULL_UP,
+	.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[] = {
+	{
+		.gpio = KS8851_IRQ_GPIO,
+		.settings = {
+			[GPIOMUX_SUSPENDED] = &gpio_eth_config,
+		}
+	},
+};
+
+static struct msm_gpiomux_config msm_blsp_configs[] __initdata = {
+	{
+		.gpio      = 0,		/* BLSP1 QUP2 SPI_DATA_MOSI */
+		.settings = {
+			[GPIOMUX_SUSPENDED] = &gpio_spi_config,
+		},
+	},
+	{
+		.gpio      = 1,		/* BLSP1 QUP2 SPI_DATA_MISO */
+		.settings = {
+			[GPIOMUX_SUSPENDED] = &gpio_spi_config,
+		},
+	},
+	{
+		.gpio      = 2,		/* BLSP1 QUP2 SPI_CS_N */
+		.settings = {
+			[GPIOMUX_SUSPENDED] = &gpio_spi_config,
+		},
+	},
+	{
+		.gpio      = 3,		/* BLSP1 QUP2 SPI_CLK */
+		.settings = {
+			[GPIOMUX_SUSPENDED] = &gpio_spi_config,
+		},
+	},
+};
+#endif
+
 void __init msm8226_init_gpiomux(void)
 {
 	int rc;
 
-	rc = msm_gpiomux_init(NR_GPIO_IRQS);
+	rc = msm_gpiomux_init_dt();
 	if (rc) {
-		pr_err(KERN_ERR "msm_8226_init_gpiomux failed %d\n", rc);
+		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
 }
diff --git a/arch/arm/mach-msm/board-8226.c b/arch/arm/mach-msm/board-8226.c
index a5cb481..54531a6 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>
@@ -73,6 +74,20 @@
 	CLK_DUMMY("iface_clk",	NULL,		"msm_sdcc.2", OFF),
 	CLK_DUMMY("core_clk",	NULL,		"msm_sdcc.2", OFF),
 	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 = {
@@ -107,14 +122,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-gpiomux.c b/arch/arm/mach-msm/board-8910-gpiomux.c
index a67f916..a295a17 100644
--- a/arch/arm/mach-msm/board-8910-gpiomux.c
+++ b/arch/arm/mach-msm/board-8910-gpiomux.c
@@ -21,9 +21,9 @@
 {
 	int rc;
 
-	rc = msm_gpiomux_init(NR_GPIO_IRQS);
+	rc = msm_gpiomux_init_dt();
 	if (rc) {
-		pr_err(KERN_ERR "msm_8910_init_gpiomux failed %d\n", rc);
+		pr_err("%s failed %d\n", __func__, rc);
 		return;
 	}
 }
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 1a953da..aefa648 100644
--- a/arch/arm/mach-msm/board-8930.c
+++ b/arch/arm/mach-msm/board-8930.c
@@ -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>
@@ -343,7 +344,6 @@
 	.reusable = FMEM_ENABLED,
 	.mem_is_fmem = FMEM_ENABLED,
 	.fixed_position = FIXED_MIDDLE,
-	.is_cma	= 1,
 	.no_nonsecure_alloc = 1,
 };
 
@@ -1465,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)
diff --git a/arch/arm/mach-msm/board-8960.c b/arch/arm/mach-msm/board-8960.c
index 9b19810..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>
@@ -366,7 +367,6 @@
 	.fixed_position = FIXED_MIDDLE,
 	.iommu_map_all = 1,
 	.iommu_2x_map_domain = VIDEO_DOMAIN,
-	.is_cma = 1,
 	.no_nonsecure_alloc = 1,
 };
 
@@ -1487,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)
@@ -3002,6 +3002,9 @@
 		kgsl_3d0_pdata->chipid = ADRENO_CHIPID(3, 2, 1, 0);
 		/* 8960PRO nominal clock rate is 320Mhz */
 		kgsl_3d0_pdata->pwrlevel[1].gpu_freq = 320000000;
+#ifdef CONFIG_MSM_BUS_SCALING
+		kgsl_3d0_pdata->bus_scale_table = &grp3d_bus_scale_pdata_ab;
+#endif
 
 		/*
 		 * If this an A320 GPU device (MSM8960AB), then
diff --git a/arch/arm/mach-msm/board-8974-gpiomux.c b/arch/arm/mach-msm/board-8974-gpiomux.c
index 4bd100d..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,
 };
 
@@ -862,9 +867,9 @@
 {
 	int rc;
 
-	rc = msm_gpiomux_init(NR_GPIO_IRQS);
+	rc = msm_gpiomux_init_dt();
 	if (rc) {
-		pr_err(KERN_ERR "msm_8974_init_gpiomux failed %d\n", rc);
+		pr_err("%s failed %d\n", __func__, rc);
 		return;
 	}
 
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 686bb41..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
@@ -280,9 +280,9 @@
 {
 	int rc;
 
-	rc = msm_gpiomux_init(NR_GPIO_IRQS);
+	rc = msm_gpiomux_init_dt();
 	if (rc) {
-		pr_err(KERN_ERR "msm9625_init_gpiomux failed %d\n", rc);
+		pr_err("%s failed %d\n", __func__, rc);
 		return;
 	}
 
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-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-8974.c b/arch/arm/mach-msm/clock-8974.c
index 1b0ac74..be20ebd 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
@@ -5281,6 +5281,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 +5298,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 +5453,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 +5557,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 +5576,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 ccf6755..151f192 100644
--- a/arch/arm/mach-msm/clock-9625.c
+++ b/arch/arm/mach-msm/clock-9625.c
@@ -2101,8 +2101,7 @@
 	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("alt_core_clk", gcc_usb_hsic_xcvr_fs_clk.c,
-							  "f9a15000.hsic"),
+	CLK_LOOKUP("alt_core_clk", gcc_usb_hsic_xcvr_fs_clk.c, ""),
 
 	CLK_LOOKUP("core_clk", gcc_ce1_clk.c, "fd400000.qcom,qcedev"),
 	CLK_LOOKUP("iface_clk", gcc_ce1_ahb_clk.c, "fd400000.qcom,qcedev"),
@@ -2126,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 +2174,7 @@
 	CLK_LOOKUP("core_clk", qdss_clk.c, "fc319000.funnel"),
 	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_a_clk", qdss_clk.c, "fc322000.tmc"),
 	CLK_LOOKUP("core_a_clk", qdss_clk.c, "fc318000.tpiu"),
@@ -2180,6 +2184,7 @@
 	CLK_LOOKUP("core_a_clk", qdss_clk.c, "fc319000.funnel"),
 	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"),
 
 };
 
diff --git a/arch/arm/mach-msm/cpufreq.c b/arch/arm/mach-msm/cpufreq.c
index d862d6d..4ffa66a 100644
--- a/arch/arm/mach-msm/cpufreq.c
+++ b/arch/arm/mach-msm/cpufreq.c
@@ -299,20 +299,24 @@
 	.notifier_call = msm_cpufreq_cpu_callback,
 };
 
-static int msm_cpufreq_suspend(void)
+/*
+ * Define suspend/resume for cpufreq_driver. Kernel will call
+ * these during suspend/resume with interrupts disabled. This
+ * helps the suspend/resume variable get's updated before cpufreq
+ * governor tries to change the frequency after coming out of suspend.
+ */
+static int msm_cpufreq_suspend(struct cpufreq_policy *policy)
 {
 	int cpu;
 
 	for_each_possible_cpu(cpu) {
-		mutex_lock(&per_cpu(cpufreq_suspend, cpu).suspend_mutex);
 		per_cpu(cpufreq_suspend, cpu).device_suspended = 1;
-		mutex_unlock(&per_cpu(cpufreq_suspend, cpu).suspend_mutex);
 	}
 
-	return NOTIFY_DONE;
+	return 0;
 }
 
-static int msm_cpufreq_resume(void)
+static int msm_cpufreq_resume(struct cpufreq_policy *policy)
 {
 	int cpu;
 
@@ -320,28 +324,9 @@
 		per_cpu(cpufreq_suspend, cpu).device_suspended = 0;
 	}
 
-	return NOTIFY_DONE;
+	return 0;
 }
 
-static int msm_cpufreq_pm_event(struct notifier_block *this,
-				unsigned long event, void *ptr)
-{
-	switch (event) {
-	case PM_POST_HIBERNATION:
-	case PM_POST_SUSPEND:
-		return msm_cpufreq_resume();
-	case PM_HIBERNATION_PREPARE:
-	case PM_SUSPEND_PREPARE:
-		return msm_cpufreq_suspend();
-	default:
-		return NOTIFY_DONE;
-	}
-}
-
-static struct notifier_block msm_cpufreq_pm_notifier = {
-	.notifier_call = msm_cpufreq_pm_event,
-};
-
 static struct freq_attr *msm_freq_attr[] = {
 	&cpufreq_freq_attr_scaling_available_freqs,
 	NULL,
@@ -354,6 +339,8 @@
 	.verify		= msm_cpufreq_verify,
 	.target		= msm_cpufreq_target,
 	.get		= msm_cpufreq_get_freq,
+	.suspend	= msm_cpufreq_suspend,
+	.resume		= msm_cpufreq_resume,
 	.name		= "msm",
 	.attr		= msm_freq_attr,
 };
@@ -369,7 +356,6 @@
 
 	register_hotcpu_notifier(&msm_cpufreq_cpu_notifier);
 
-	register_pm_notifier(&msm_cpufreq_pm_notifier);
 	return cpufreq_register_driver(&msm_cpufreq_driver);
 }
 
diff --git a/arch/arm/mach-msm/devices-8960.c b/arch/arm/mach-msm/devices-8960.c
index 4780c57..446f3f2 100644
--- a/arch/arm/mach-msm/devices-8960.c
+++ b/arch/arm/mach-msm/devices-8960.c
@@ -19,6 +19,7 @@
 #include <linux/gpio.h>
 #include <linux/coresight.h>
 #include <asm/clkdev.h>
+#include <mach/gpio.h>
 #include <mach/kgsl.h>
 #include <linux/android_pmem.h>
 #include <mach/irqs-8960.h>
@@ -3131,6 +3132,81 @@
 	},
 };
 
+struct msm_bus_vectors grp3d_init_vectors_1[] = {
+	{
+		.src = MSM_BUS_MASTER_GRAPHICS_3D,
+		.dst = MSM_BUS_SLAVE_EBI_CH0,
+		.ab = 0,
+		.ib = 0,
+	},
+	{
+		.src = MSM_BUS_MASTER_GRAPHICS_3D_PORT1,
+		.dst = MSM_BUS_SLAVE_EBI_CH0,
+		.ab = 0,
+		.ib = 0,
+	},
+};
+
+struct msm_bus_vectors grp3d_low_vectors_1[] = {
+	{
+		.src = MSM_BUS_MASTER_GRAPHICS_3D,
+		.dst = MSM_BUS_SLAVE_EBI_CH0,
+		.ab = 0,
+		.ib = KGSL_CONVERT_TO_MBPS(1000),
+	},
+	{
+		.src = MSM_BUS_MASTER_GRAPHICS_3D_PORT1,
+		.dst = MSM_BUS_SLAVE_EBI_CH0,
+		.ab = 0,
+		.ib = KGSL_CONVERT_TO_MBPS(1000),
+	},
+};
+
+struct msm_bus_vectors grp3d_nominal_low_vectors_1[] = {
+	{
+		.src = MSM_BUS_MASTER_GRAPHICS_3D,
+		.dst = MSM_BUS_SLAVE_EBI_CH0,
+		.ab = 0,
+		.ib = KGSL_CONVERT_TO_MBPS(2048),
+	},
+	{
+		.src = MSM_BUS_MASTER_GRAPHICS_3D_PORT1,
+		.dst = MSM_BUS_SLAVE_EBI_CH0,
+		.ab = 0,
+		.ib = KGSL_CONVERT_TO_MBPS(2048),
+	},
+};
+
+struct msm_bus_vectors grp3d_nominal_high_vectors_1[] = {
+	{
+		.src = MSM_BUS_MASTER_GRAPHICS_3D,
+		.dst = MSM_BUS_SLAVE_EBI_CH0,
+		.ab = 0,
+		.ib = KGSL_CONVERT_TO_MBPS(2656),
+	},
+	{
+		.src = MSM_BUS_MASTER_GRAPHICS_3D_PORT1,
+		.dst = MSM_BUS_SLAVE_EBI_CH0,
+		.ab = 0,
+		.ib = KGSL_CONVERT_TO_MBPS(2656),
+	},
+};
+
+struct msm_bus_vectors grp3d_max_vectors_1[] = {
+	{
+		.src = MSM_BUS_MASTER_GRAPHICS_3D,
+		.dst = MSM_BUS_SLAVE_EBI_CH0,
+		.ab = 0,
+		.ib = KGSL_CONVERT_TO_MBPS(3968),
+	},
+	{
+		.src = MSM_BUS_MASTER_GRAPHICS_3D_PORT1,
+		.dst = MSM_BUS_SLAVE_EBI_CH0,
+		.ab = 0,
+		.ib = KGSL_CONVERT_TO_MBPS(3968),
+	},
+};
+
 static struct msm_bus_paths grp3d_bus_scale_usecases[] = {
 	{
 		ARRAY_SIZE(grp3d_init_vectors),
@@ -3154,12 +3230,41 @@
 	},
 };
 
+struct msm_bus_paths grp3d_bus_scale_usecases_1[] = {
+	{
+		ARRAY_SIZE(grp3d_init_vectors_1),
+		grp3d_init_vectors_1,
+	},
+	{
+		ARRAY_SIZE(grp3d_low_vectors_1),
+		grp3d_low_vectors_1,
+	},
+	{
+		ARRAY_SIZE(grp3d_nominal_low_vectors_1),
+		grp3d_nominal_low_vectors_1,
+	},
+	{
+		ARRAY_SIZE(grp3d_nominal_high_vectors_1),
+		grp3d_nominal_high_vectors_1,
+	},
+	{
+		ARRAY_SIZE(grp3d_max_vectors_1),
+		grp3d_max_vectors_1,
+	},
+};
+
 static struct msm_bus_scale_pdata grp3d_bus_scale_pdata = {
 	grp3d_bus_scale_usecases,
 	ARRAY_SIZE(grp3d_bus_scale_usecases),
 	.name = "grp3d",
 };
 
+struct msm_bus_scale_pdata grp3d_bus_scale_pdata_ab = {
+	grp3d_bus_scale_usecases_1,
+	ARRAY_SIZE(grp3d_bus_scale_usecases_1),
+	.name = "grp3d",
+};
+
 static struct msm_bus_vectors grp2d0_init_vectors[] = {
 	{
 		.src = MSM_BUS_MASTER_GRAPHICS_2D_CORE0,
@@ -4438,11 +4543,17 @@
 	},
 };
 
+static struct msm_gpio_pdata msm8960_gpio_pdata = {
+	.ngpio = 152,
+	.direct_connect_irqs = 8,
+};
+
 struct platform_device msm_gpio_device = {
-	.name = "msmgpio",
-	.id = -1,
-	.num_resources	= ARRAY_SIZE(msm_gpio_resources),
-	.resource	= msm_gpio_resources,
+	.name			= "msmgpio",
+	.id			= -1,
+	.num_resources		= ARRAY_SIZE(msm_gpio_resources),
+	.resource		= msm_gpio_resources,
+	.dev.platform_data	= &msm8960_gpio_pdata,
 };
 
 struct platform_device mdm_sglte_device = {
diff --git a/arch/arm/mach-msm/devices-9615.c b/arch/arm/mach-msm/devices-9615.c
index fc65cb7..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>
@@ -34,6 +35,7 @@
 #include <mach/dma.h>
 #include "pm.h"
 #include "devices.h"
+#include <mach/gpio.h>
 #include <mach/mpm.h>
 #include "spm.h"
 #include "rpm_resources.h"
@@ -1514,11 +1516,17 @@
 	},
 };
 
+static struct msm_gpio_pdata msm9615_gpio_pdata = {
+	.ngpio = 88,
+	.direct_connect_irqs = 8,
+};
+
 struct platform_device msm_gpio_device = {
-	.name = "msmgpio",
-	.id = -1,
-	.num_resources	= ARRAY_SIZE(msm_gpio_resources),
-	.resource	= msm_gpio_resources,
+	.name			= "msmgpio",
+	.id			= -1,
+	.num_resources		= ARRAY_SIZE(msm_gpio_resources),
+	.resource		= msm_gpio_resources,
+	.dev.platform_data	= &msm9615_gpio_pdata,
 };
 
 void __init msm9615_device_init(void)
@@ -1538,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 2d9872e..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,
 	},
 };
@@ -2047,8 +2047,7 @@
 	return ret;
 }
 
-static int __init msm_acpuclock_init(int nominal_voltage,
-					int default_turbo_voltage)
+static int __init msm_acpuclock_init(bool flag)
 {
 	struct cpr_info_type *acpu_info = NULL;
 	acpu_info = kzalloc(sizeof(struct cpr_info_type), GFP_KERNEL);
@@ -2060,8 +2059,7 @@
 	msm8625q_acpuclk_pdata.pvs_voltage_uv =
 			msm_c2_pmic_mv[acpu_info->pvs_fuse & 0x1F];
 	kfree(acpu_info);
-	msm8625q_acpuclk_pdata.nominal_voltage = nominal_voltage;
-	msm8625q_acpuclk_pdata.default_turbo_voltage = default_turbo_voltage;
+	msm8625q_acpuclk_pdata.flag = flag;
 	return 0;
 }
 
@@ -2077,11 +2075,11 @@
 	if (cpu_is_msm7x27aa() || cpu_is_msm7x25ab())
 		platform_device_register(&msm7x27aa_device_acpuclk);
 	else if (cpu_is_msm8625q()) {
-			msm_acpuclock_init(1050000, 0);
-			platform_device_register(&msm8625q_device_acpuclk);
+		msm_acpuclock_init(1);
+		platform_device_register(&msm8625q_device_acpuclk);
 	} else if (cpu_is_msm8625()) {
 		if (machine_is_qrd_skud_prime()) {
-			msm_acpuclock_init(1150000, 1275000);
+			msm_acpuclock_init(0);
 			platform_device_register(&msm8625q_device_acpuclk);
 		} else if (msm8625_cpu_id() == MSM8625)
 			platform_device_register(&msm7x27aa_device_acpuclk);
@@ -2098,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);
 
@@ -2149,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();
 }
 
@@ -2165,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-msm8x60.c b/arch/arm/mach-msm/devices-msm8x60.c
index 0a080b1..5a517df 100644
--- a/arch/arm/mach-msm/devices-msm8x60.c
+++ b/arch/arm/mach-msm/devices-msm8x60.c
@@ -108,11 +108,17 @@
 	},
 };
 
+static struct msm_gpio_pdata msm8660_gpio_pdata = {
+	.ngpio = 173,
+	.direct_connect_irqs = 10,
+};
+
 struct platform_device msm_gpio_device = {
-	.name = "msmgpio",
-	.id = -1,
-	.num_resources	= ARRAY_SIZE(msm_gpio_resources),
-	.resource	= msm_gpio_resources,
+	.name			= "msmgpio",
+	.id			= -1,
+	.num_resources		= ARRAY_SIZE(msm_gpio_resources),
+	.resource		= msm_gpio_resources,
+	.dev.platform_data	= &msm8660_gpio_pdata,
 };
 
 static void charm_ap2mdm_kpdpwr_on(void)
diff --git a/arch/arm/mach-msm/devices.h b/arch/arm/mach-msm/devices.h
index b676518..2339706 100644
--- a/arch/arm/mach-msm/devices.h
+++ b/arch/arm/mach-msm/devices.h
@@ -330,6 +330,9 @@
 
 extern struct resource kgsl_3d0_resources_8960ab[];
 extern int kgsl_num_resources_8960ab;
+#ifdef CONFIG_MSM_BUS_SCALING
+extern struct msm_bus_scale_pdata grp3d_bus_scale_pdata_ab;
+#endif
 
 extern struct platform_device msm_mipi_dsi1_device;
 extern struct platform_device mipi_dsi_device;
diff --git a/arch/arm/mach-msm/gpiomux.c b/arch/arm/mach-msm/gpiomux.c
index 85936ba..0af83e8 100644
--- a/arch/arm/mach-msm/gpiomux.c
+++ b/arch/arm/mach-msm/gpiomux.c
@@ -10,6 +10,7 @@
  * GNU General Public License for more details.
  */
 #include <linux/module.h>
+#include <linux/of.h>
 #include <linux/slab.h>
 #include <linux/spinlock.h>
 #include <mach/gpiomux.h>
@@ -148,3 +149,26 @@
 	}
 }
 EXPORT_SYMBOL(msm_gpiomux_install);
+
+int msm_gpiomux_init_dt(void)
+{
+	int rc;
+	unsigned int ngpio;
+	struct device_node *of_gpio_node;
+
+	of_gpio_node = of_find_compatible_node(NULL, NULL, "qcom,msm-gpio");
+	if (!of_gpio_node) {
+		pr_err("%s: Failed to find qcom,msm-gpio node\n", __func__);
+		return -ENODEV;
+	}
+
+	rc = of_property_read_u32(of_gpio_node, "ngpio", &ngpio);
+	if (rc) {
+		pr_err("%s: Failed to find ngpio property in msm-gpio device node %d\n"
+				, __func__, rc);
+		return rc;
+	}
+
+	return msm_gpiomux_init(ngpio);
+}
+EXPORT_SYMBOL(msm_gpiomux_init_dt);
diff --git a/arch/arm/mach-msm/include/mach/gpio.h b/arch/arm/mach-msm/include/mach/gpio.h
index a0bcd2b..137d243 100644
--- a/arch/arm/mach-msm/include/mach/gpio.h
+++ b/arch/arm/mach-msm/include/mach/gpio.h
@@ -40,6 +40,11 @@
 	const char *label;
 };
 
+struct msm_gpio_pdata {
+	int ngpio;
+	int direct_connect_irqs;
+};
+
 /**
  * msm_gpios_request_enable() - request and enable set of GPIOs
  *
diff --git a/arch/arm/mach-msm/include/mach/gpiomux.h b/arch/arm/mach-msm/include/mach/gpiomux.h
index f75b0e0..f16caed 100644
--- a/arch/arm/mach-msm/include/mach/gpiomux.h
+++ b/arch/arm/mach-msm/include/mach/gpiomux.h
@@ -117,6 +117,11 @@
  */
 int msm_gpiomux_init(size_t ngpio);
 
+/* DT Variant of msm_gpiomux_init. This will look up the number of gpios from
+ * device tree rather than relying on NR_GPIO_IRQS
+ */
+int msm_gpiomux_init_dt(void);
+
 /* Install a block of gpiomux configurations in gpiomux.  This is functionally
  * identical to calling msm_gpiomux_write many times.
  */
diff --git a/arch/arm/mach-msm/include/mach/iommu.h b/arch/arm/mach-msm/include/mach/iommu.h
index 8ebd0cf..8b39e34 100644
--- a/arch/arm/mach-msm/include/mach/iommu.h
+++ b/arch/arm/mach-msm/include/mach/iommu.h
@@ -130,6 +130,7 @@
  * @secure_context	true if this is a secure context programmed by
 			the secure environment, false otherwise
  * @asid		ASID used with this context.
+ * @attach_count	Number of time this context has been attached.
  *
  * A msm_iommu_ctx_drvdata holds the driver data for a single context bank
  * within each IOMMU hardware instance
@@ -144,6 +145,7 @@
 	unsigned int nsid;
 	unsigned int secure_context;
 	int asid;
+	int attach_count;
 };
 
 /*
diff --git a/arch/arm/mach-msm/include/mach/iommu_domains.h b/arch/arm/mach-msm/include/mach/iommu_domains.h
index 01bc479..07f82ec 100644
--- a/arch/arm/mach-msm/include/mach/iommu_domains.h
+++ b/arch/arm/mach-msm/include/mach/iommu_domains.h
@@ -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
@@ -77,6 +77,7 @@
 #if defined(CONFIG_MSM_IOMMU)
 
 extern struct iommu_domain *msm_get_iommu_domain(int domain_num);
+extern int msm_find_domain_no(const struct iommu_domain *domain);
 
 extern int msm_allocate_iova_address(unsigned int iommu_domain,
 					unsigned int partition_no,
@@ -123,6 +124,10 @@
 	*msm_get_iommu_domain(int subsys_id) { return NULL; }
 
 
+static inline int msm_find_domain_no(const struct iommu_domain *domain)
+{
+	return -EINVAL;
+}
 
 static inline int msm_allocate_iova_address(unsigned int iommu_domain,
 					unsigned int partition_no,
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/irqs-8x60.h b/arch/arm/mach-msm/include/mach/irqs-8x60.h
index d08f645..1e2c606 100644
--- a/arch/arm/mach-msm/include/mach/irqs-8x60.h
+++ b/arch/arm/mach-msm/include/mach/irqs-8x60.h
@@ -242,7 +242,6 @@
 #define SMPSS_SPARE_6				(GIC_SPI_START + 222)
 #define SMPSS_SPARE_7				(GIC_SPI_START + 223)
 
-#define NR_TLMM_MSM_DIR_CONN_IRQ 10
 #define NR_GPIO_IRQS 173
 #define NR_MSM_GPIOS NR_GPIO_IRQS
 #define NR_MSM_IRQS 256
diff --git a/arch/arm/mach-msm/include/mach/irqs-9615.h b/arch/arm/mach-msm/include/mach/irqs-9615.h
index b9c66c3..35b5848 100644
--- a/arch/arm/mach-msm/include/mach/irqs-9615.h
+++ b/arch/arm/mach-msm/include/mach/irqs-9615.h
@@ -181,7 +181,6 @@
 #define NR_WCD9XXX_IRQS 49
 #define NR_TABLA_IRQS NR_WCD9XXX_IRQS
 #define NR_BOARD_IRQS (NR_PM8018_IRQS + NR_WCD9XXX_IRQS)
-#define NR_TLMM_MSM_DIR_CONN_IRQ 8 /*Need to Verify this Count*/
 #define NR_MSM_GPIOS NR_GPIO_IRQS
 
 /* Backwards compatible IRQ macros. */
diff --git a/arch/arm/mach-msm/include/mach/irqs-9625.h b/arch/arm/mach-msm/include/mach/irqs-9625.h
index 9ba77af..278c6a5 100644
--- a/arch/arm/mach-msm/include/mach/irqs-9625.h
+++ b/arch/arm/mach-msm/include/mach/irqs-9625.h
@@ -20,10 +20,6 @@
 #define APCC_QGICL2PERFMONIRPTREQ	(GIC_SPI_START + 1)
 #define SC_SICL2PERFMONIRPTREQ		APCC_QGICL2PERFMONIRPTREQ
 
-#define NR_MSM_IRQS 288
-#define NR_GPIO_IRQS 76
-#define NR_BOARD_IRQS 0
 #define NR_TLMM_MSM_DIR_CONN_IRQ 8 /*Need to Verify this Count*/
-#define NR_MSM_GPIOS NR_GPIO_IRQS
 
 #endif
diff --git a/arch/arm/mach-msm/include/mach/irqs.h b/arch/arm/mach-msm/include/mach/irqs.h
index 8c6b959..6955c80 100644
--- a/arch/arm/mach-msm/include/mach/irqs.h
+++ b/arch/arm/mach-msm/include/mach/irqs.h
@@ -37,22 +37,6 @@
 #include "irqs-8092.h"
 #endif
 
-#define NR_MSM_IRQS 1020 /* Should be 256 - but higher due to bug in sim */
-#define NR_GPIO_IRQS 146
-#define NR_QPNP_IRQS 32768
-#define NR_BOARD_IRQS NR_QPNP_IRQS
-#define NR_TLMM_MSM_DIR_CONN_IRQ 8
-#define NR_MSM_GPIOS NR_GPIO_IRQS
-
-#elif defined(CONFIG_ARCH_MSM8910) || defined(CONFIG_ARCH_MSM8226)
-
-#define NR_MSM_IRQS 256
-#define NR_GPIO_IRQS 117
-#define NR_QPNP_IRQS 32768
-#define NR_BOARD_IRQS NR_QPNP_IRQS
-#define NR_TLMM_MSM_DIR_CONN_IRQ 8
-#define NR_MSM_GPIOS NR_GPIO_IRQS
-
 #elif defined(CONFIG_ARCH_MSM8960) || defined(CONFIG_ARCH_APQ8064) || \
 	defined(CONFIG_ARCH_MSM8930)
 
@@ -85,7 +69,6 @@
 #define NR_BOARD_IRQS (NR_PM8921_IRQS + NR_PM8821_IRQS + \
 		NR_WCD9XXX_IRQS + NR_GPIO_EXPANDER_IRQS)
 #endif
-#define NR_TLMM_MSM_DIR_CONN_IRQ 8 /*Need to Verify this Count*/
 #define NR_MSM_GPIOS NR_GPIO_IRQS
 
 #else
@@ -113,17 +96,36 @@
 #elif defined(CONFIG_ARCH_FSM9XXX)
 #include "irqs-fsm9xxx.h"
 #include "sirc.h"
-#else
-#error "Unknown architecture specification"
 #endif
 
 #endif
 
 #if !defined(CONFIG_SPARSE_IRQ)
+
+#if defined(CONFIG_ARCH_MSM8974) || defined(CONFIG_ARCH_MPQ8092)
+#define NR_MSM_IRQS 1020 /* Should be 256 - but higher due to bug in sim */
+#define NR_GPIO_IRQS 146
+#define NR_QPNP_IRQS 32768
+#define NR_BOARD_IRQS NR_QPNP_IRQS
+
+#elif defined(CONFIG_ARCH_MSM8910) || defined(CONFIG_ARCH_MSM8226)
+#define NR_MSM_IRQS 256
+#define NR_GPIO_IRQS 117
+#define NR_QPNP_IRQS 32768
+#define NR_BOARD_IRQS NR_QPNP_IRQS
+
+#elif defined(CONFIG_ARCH_MSM9625)
+#define NR_MSM_IRQS 288
+#define NR_GPIO_IRQS 76
+#define NR_BOARD_IRQS 0
+
+#endif
+
 #define NR_IRQS (NR_MSM_IRQS + NR_GPIO_IRQS + NR_BOARD_IRQS)
 #define MSM_GPIO_TO_INT(n) (NR_MSM_IRQS + (n))
 #define FIRST_GPIO_IRQ MSM_GPIO_TO_INT(0)
 #define MSM_INT_TO_REG(base, irq) (base + irq / 32)
+
 #endif
 
 #if defined(CONFIG_PCI_MSI) && defined(CONFIG_MSM_PCIE)
diff --git a/arch/arm/mach-msm/include/mach/msm_fb.h b/arch/arm/mach-msm/include/mach/msm_fb.h
index 3bbaa25..3e42048 100644
--- a/arch/arm/mach-msm/include/mach/msm_fb.h
+++ b/arch/arm/mach-msm/include/mach/msm_fb.h
@@ -77,7 +77,7 @@
 			     uint32_t reg);
 	uint32_t (*remote_read)(struct msm_mddi_client_data *, uint32_t reg);
 	void (*auto_hibernate)(struct msm_mddi_client_data *, int);
-	/* custom data that needs to be passed from the board file to a 
+	/* custom data that needs to be passed from the board file to a
 	 * particular client */
 	void *private_client_data;
 	struct resource *fb_resource;
@@ -190,7 +190,7 @@
 
 struct mdp_v4l2_req;
 int msm_fb_v4l2_enable(struct mdp_overlay *req, bool enable, void **par);
-int msm_fb_v4l2_update(void *par,
+int msm_fb_v4l2_update(void *par, bool bUserPtr,
 	unsigned long srcp0_addr, unsigned long srcp0_size,
 	unsigned long srcp1_addr, unsigned long srcp1_size,
 	unsigned long srcp2_addr, unsigned long srcp2_size);
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/qdsp6v2/audio_acdb.h b/arch/arm/mach-msm/include/mach/qdsp6v2/audio_acdb.h
index 88cb94a..b830134 100644
--- a/arch/arm/mach-msm/include/mach/qdsp6v2/audio_acdb.h
+++ b/arch/arm/mach-msm/include/mach/qdsp6v2/audio_acdb.h
@@ -14,7 +14,9 @@
 #define _AUDIO_ACDB_H
 
 #include <linux/msm_audio_acdb.h>
-#if defined CONFIG_ARCH_MSM8974 || defined CONFIG_ARCH_MSM9625
+#if defined(CONFIG_ARCH_MSM8974) || defined(CONFIG_ARCH_MSM9625) \
+	|| defined(CONFIG_ARCH_MSM8226)
+
 #include <sound/q6adm-v2.h>
 #else
 #include <sound/q6adm.h>
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/include/mach/usb_bam.h b/arch/arm/mach-msm/include/mach/usb_bam.h
index 5e1ef6f..b3fb8af 100644
--- a/arch/arm/mach-msm/include/mach/usb_bam.h
+++ b/arch/arm/mach-msm/include/mach/usb_bam.h
@@ -102,6 +102,22 @@
 	 int (*callback)(void *), void* param);
 
 /**
+ * Register a callback for peer BAM reset.
+ *
+ * @idx - Connection index.
+ *
+ * @callback - the callback function that will be called in USB
+ *				driver upon a peer bam reset
+ *
+ * @param - context that the caller can supply
+ *
+ * @return 0 on success, negative value on error
+ *
+ */
+int usb_bam_register_peer_reset_cb(u8 idx,
+	 int (*callback)(void *), void *param);
+
+/**
  * Disconnect USB-to-Periperal SPS connection.
  *
  * @idx - Connection index.
@@ -132,6 +148,21 @@
 	u32 *usb_bam_handle, u32 *usb_bam_pipe_idx, u32 *peer_pipe_idx,
 	struct sps_mem_buffer *desc_fifo, struct sps_mem_buffer *data_fifo);
 
+/**
+ * Resets the entire USB BAM.
+ *
+ */
+int usb_bam_reset(void);
+
+/**
+ * Indicates if the client of the USB BAM is ready to start
+ * sending/receiving transfers.
+ *
+ * @ready - TRUE to enable, FALSE to disable.
+ *
+ */
+int usb_bam_client_ready(bool ready);
+
 #else
 static inline int usb_bam_connect(u8 idx, u32 *src_pipe_idx, u32 *dst_pipe_idx)
 {
@@ -156,6 +187,12 @@
 	return -ENODEV;
 }
 
+static inline int usb_bam_register_peer_reset_cb(u8 idx,
+	 int (*callback)(void *), void *param)
+{
+	return -ENODEV;
+}
+
 static inline int usb_bam_disconnect_pipe(u8 idx)
 {
 	return -ENODEV;
@@ -168,5 +205,16 @@
 {
 	return;
 }
+
+static inline int usb_bam_reset(void)
+{
+	return -ENODEV;
+}
+
+static inline int usb_bam_client_ready(bool ready)
+{
+	return -ENODEV;
+}
+
 #endif
 #endif				/* _USB_BAM_H_ */
diff --git a/arch/arm/mach-msm/iommu_domains.c b/arch/arm/mach-msm/iommu_domains.c
index 75e56fe..dc67403 100644
--- a/arch/arm/mach-msm/iommu_domains.c
+++ b/arch/arm/mach-msm/iommu_domains.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
@@ -25,6 +25,9 @@
 #include <mach/iommu_domains.h>
 #include <mach/socinfo.h>
 #include <mach/msm_subsystem_map.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_device.h>
 
 /* dummy 64K for overmapping */
 char iommu_dummy[2*SZ_64K-4];
@@ -269,6 +272,27 @@
 }
 EXPORT_SYMBOL(msm_get_iommu_domain);
 
+int msm_find_domain_no(const struct iommu_domain *domain)
+{
+	struct rb_root *root = &domain_root;
+	struct rb_node *n;
+	struct msm_iova_data *node;
+	int domain_num = -EINVAL;
+
+	mutex_lock(&domain_mutex);
+
+	for (n = rb_first(root); n; n = rb_next(n)) {
+		node = rb_entry(n, struct msm_iova_data, node);
+		if (node->domain == domain) {
+			domain_num = node->domain_num;
+			break;
+		}
+	}
+	mutex_unlock(&domain_mutex);
+	return domain_num;
+}
+EXPORT_SYMBOL(msm_find_domain_no);
+
 int msm_allocate_iova_address(unsigned int iommu_domain,
 					unsigned int partition_no,
 					unsigned long size,
@@ -411,7 +435,170 @@
 }
 EXPORT_SYMBOL(msm_register_domain);
 
-static int __init iommu_domain_probe(struct platform_device *pdev)
+static int find_and_add_contexts(struct iommu_group *group,
+				 const struct device_node *node,
+				 unsigned int num_contexts)
+{
+	unsigned int i;
+	struct device *ctx;
+	const char *name;
+	struct device_node *ctx_node;
+	int ret_val = 0;
+
+	for (i = 0; i < num_contexts; ++i) {
+		ctx_node = of_parse_phandle((struct device_node *) node,
+					    "qcom,iommu-contexts", i);
+		if (!ctx_node) {
+			pr_err("Unable to parse phandle #%u\n", i);
+			ret_val = -EINVAL;
+			goto out;
+		}
+		if (of_property_read_string(ctx_node, "label", &name)) {
+			pr_err("Could not find label property\n");
+			ret_val = -EINVAL;
+			goto out;
+		}
+		ctx = msm_iommu_get_ctx(name);
+		if (!ctx) {
+			pr_err("Unable to find context %s\n", name);
+			ret_val = -EINVAL;
+			goto out;
+		}
+		iommu_group_add_device(group, ctx);
+	}
+out:
+	return ret_val;
+}
+
+static int create_and_add_domain(struct iommu_group *group,
+				 const struct device_node *node)
+{
+	unsigned int ret_val = 0;
+	unsigned int i;
+	struct msm_iova_layout l;
+	struct msm_iova_partition *part = 0;
+	struct iommu_domain *domain = 0;
+	unsigned int *addr_array;
+	unsigned int array_size;
+	int domain_no;
+	int secure_domain;
+	int l2_redirect;
+
+	if (of_get_property(node, "qcom,virtual-addr-pool", &array_size)) {
+		l.npartitions = array_size / sizeof(unsigned int) / 2;
+		part = kmalloc(
+			sizeof(struct msm_iova_partition) * l.npartitions,
+			       GFP_KERNEL);
+		if (!part) {
+			pr_err("%s: could not allocate space for partition",
+				__func__);
+			ret_val = -ENOMEM;
+			goto out;
+		}
+		addr_array = kmalloc(array_size, GFP_KERNEL);
+		if (!addr_array) {
+			pr_err("%s: could not allocate space for partition",
+				__func__);
+			ret_val = -ENOMEM;
+			goto free_mem;
+		}
+
+		ret_val = of_property_read_u32_array(node,
+					"qcom,virtual-addr-pool",
+					addr_array,
+					array_size/sizeof(unsigned int));
+		if (ret_val) {
+			ret_val = -EINVAL;
+			goto free_mem;
+		}
+
+		for (i = 0; i < l.npartitions * 2; i += 2) {
+			part[i].start = addr_array[i];
+			part[i].size = addr_array[i+1];
+		}
+	} else {
+		l.npartitions = 1;
+		part = kmalloc(
+			sizeof(struct msm_iova_partition) * l.npartitions,
+			       GFP_KERNEL);
+		if (!part) {
+			pr_err("%s: could not allocate space for partition",
+				__func__);
+			ret_val = -ENOMEM;
+			goto out;
+		}
+		part[0].start = 0x0;
+		part[0].size = 0xFFFFFFFF;
+	}
+
+	l.partitions = part;
+
+	secure_domain = of_property_read_bool(node, "qcom,secure-domain");
+	l.is_secure = (secure_domain) ? MSM_IOMMU_DOMAIN_SECURE : 0;
+
+	l2_redirect = of_property_read_bool(node, "qcom,l2-redirect");
+	l.domain_flags = (l2_redirect) ? MSM_IOMMU_DOMAIN_PT_CACHEABLE : 0;
+
+	domain_no = msm_register_domain(&l);
+	if (domain_no >= 0)
+		domain = msm_get_iommu_domain(domain_no);
+	else
+		ret_val = domain_no;
+
+	iommu_group_set_iommudata(group, domain, NULL);
+
+free_mem:
+	kfree(part);
+out:
+	return ret_val;
+}
+
+static int iommu_domain_parse_dt(const struct device_node *dt_node)
+{
+	struct device_node *node;
+	int sz;
+	unsigned int num_contexts;
+	int ret_val = 0;
+	struct iommu_group *group = 0;
+	const char *name;
+
+	for_each_child_of_node(dt_node, node) {
+		group = iommu_group_alloc();
+		if (IS_ERR(group)) {
+			ret_val = PTR_ERR(group);
+			goto out;
+		}
+		if (of_property_read_string(node, "label", &name)) {
+			ret_val = -EINVAL;
+			goto free_group;
+		}
+		iommu_group_set_name(group, name);
+
+		if (!of_get_property(node, "qcom,iommu-contexts", &sz)) {
+			pr_err("Could not find qcom,iommu-contexts property\n");
+			ret_val = -EINVAL;
+			goto free_group;
+		}
+		num_contexts = sz / sizeof(unsigned int);
+
+		ret_val = find_and_add_contexts(group, node, num_contexts);
+		if (ret_val) {
+			ret_val = -EINVAL;
+			goto free_group;
+		}
+		ret_val = create_and_add_domain(group, node);
+		if (ret_val) {
+			ret_val = -EINVAL;
+			goto free_group;
+		}
+	}
+free_group:
+	/* No iommu_group_free() function */
+out:
+	return ret_val;
+}
+
+static int iommu_domain_probe(struct platform_device *pdev)
 {
 	struct iommu_domains_pdata *p  = pdev->dev.platform_data;
 	int i, j;
@@ -419,7 +606,9 @@
 	if (!msm_use_iommu())
 		return -ENODEV;
 
-	if (!p)
+	if (pdev->dev.of_node)
+		return iommu_domain_parse_dt(pdev->dev.of_node);
+	else if (!p)
 		return -ENODEV;
 
 	for (i = 0; i < p->ndomains; i++) {
@@ -465,26 +654,48 @@
 			continue;
 
 		if (iommu_attach_device(domain, ctx)) {
-			WARN(1, "%s: could not attach domain %p to context %s."
-				" iommu programming will not occur.\n",
-				__func__, domain,
-				p->domain_names[i].name);
+			WARN(1, "%s: could not attach domain %p to context %s. iommu programming will not occur.\n",
+				__func__, domain, p->domain_names[i].name);
 			continue;
 		}
 	}
-
 	return 0;
 }
 
+static int __devexit iommu_domain_exit(struct platform_device *pdev)
+{
+	return 0;
+}
+
+static struct of_device_id msm_iommu_domain_match_table[] = {
+	{ .name = "qcom,iommu-domains", },
+	{}
+};
+
 static struct platform_driver iommu_domain_driver = {
 	.driver         = {
 		.name = "iommu_domains",
+		.of_match_table = msm_iommu_domain_match_table,
 		.owner = THIS_MODULE
 	},
+	.probe		= iommu_domain_probe,
+	.remove		= __devexit_p(iommu_domain_exit),
 };
 
 static int __init msm_subsystem_iommu_init(void)
 {
-	return platform_driver_probe(&iommu_domain_driver, iommu_domain_probe);
+	int ret;
+	ret = platform_driver_register(&iommu_domain_driver);
+	if (ret != 0)
+		pr_err("Failed to register IOMMU domain driver\n");
+	return ret;
 }
+
+static void __exit msm_subsystem_iommu_exit(void)
+{
+	platform_driver_unregister(&iommu_domain_driver);
+}
+
 device_initcall(msm_subsystem_iommu_init);
+module_exit(msm_subsystem_iommu_exit);
+
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_core.h b/arch/arm/mach-msm/msm_bus/msm_bus_core.h
index 2c6efb8..027cc37 100644
--- a/arch/arm/mach-msm/msm_bus/msm_bus_core.h
+++ b/arch/arm/mach-msm/msm_bus/msm_bus_core.h
@@ -205,20 +205,39 @@
 };
 
 uint64_t msm_bus_div64(unsigned int width, uint64_t bw);
-int msm_bus_remote_hw_commit(struct msm_bus_fabric_registration
-	*fab_pdata, void *hw_data, void **cdata);
 int msm_bus_fabric_device_register(struct msm_bus_fabric_device *fabric);
 void msm_bus_fabric_device_unregister(struct msm_bus_fabric_device *fabric);
 struct msm_bus_fabric_device *msm_bus_get_fabric_device(int fabid);
 int msm_bus_get_num_fab(void);
 
-void msm_bus_rpm_fill_cdata_buffer(int *curr, char *buf, const int max_size,
-	void *cdata, int nmasters, int nslaves, int ntslaves);
 
 int msm_bus_hw_fab_init(struct msm_bus_fabric_registration *pdata,
 	struct msm_bus_hw_algorithm *hw_algo);
+#if defined(CONFIG_MSM_RPM) || defined(CONFIG_MSM_RPM_SMD)
 int msm_bus_rpm_hw_init(struct msm_bus_fabric_registration *pdata,
 	struct msm_bus_hw_algorithm *hw_algo);
+int msm_bus_remote_hw_commit(struct msm_bus_fabric_registration
+	*fab_pdata, void *hw_data, void **cdata);
+void msm_bus_rpm_fill_cdata_buffer(int *curr, char *buf, const int max_size,
+	void *cdata, int nmasters, int nslaves, int ntslaves);
+#else
+static inline int msm_bus_rpm_hw_init(struct msm_bus_fabric_registration *pdata,
+	struct msm_bus_hw_algorithm *hw_algo)
+{
+	return 0;
+}
+static inline int msm_bus_remote_hw_commit(struct msm_bus_fabric_registration
+	*fab_pdata, void *hw_data, void **cdata)
+{
+	return 0;
+}
+static inline void msm_bus_rpm_fill_cdata_buffer(int *curr, char *buf,
+	const int max_size, void *cdata, int nmasters, int nslaves,
+	int ntslaves)
+{
+}
+#endif
+
 int msm_bus_noc_hw_init(struct msm_bus_fabric_registration *pdata,
 	struct msm_bus_hw_algorithm *hw_algo);
 int msm_bus_bimc_hw_init(struct msm_bus_fabric_registration *pdata,
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/perf_event_msm_pl310.c b/arch/arm/mach-msm/perf_event_msm_pl310.c
new file mode 100644
index 0000000..e2a580f
--- /dev/null
+++ b/arch/arm/mach-msm/perf_event_msm_pl310.c
@@ -0,0 +1,432 @@
+/*
+ * Copyright (C) 2007 ARM Limited
+ * 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/irq.h>
+#include <linux/io.h>
+#include <linux/err.h>
+#include <linux/init.h>
+#include <linux/spinlock.h>
+#include <linux/platform_device.h>
+
+#include <asm/pmu.h>
+#include <asm/hardware/cache-l2x0.h>
+#include <mach/socinfo.h>
+
+static u32 rev1;
+
+/*
+ * Store dynamic PMU type after registration,
+ * to uniquely identify this PMU at runtime.
+ */
+static u32 pmu_type;
+
+/* This controller only supports 16 Events.*/
+PMU_FORMAT_ATTR(l2_config, "config:0-4");
+
+static struct attribute *arm_l2_ev_formats[] = {
+	&format_attr_l2_config.attr,
+	NULL,
+};
+
+/*
+ * Format group is essential to access PMU's from userspace
+ * via their .name field.
+ */
+static struct attribute_group arm_l2_pmu_format_group = {
+	.name = "format",
+	.attrs = arm_l2_ev_formats,
+};
+
+static const struct attribute_group *arm_l2_pmu_attr_grps[] = {
+	&arm_l2_pmu_format_group,
+	NULL,
+};
+
+#define L2X0_AUX_CTRL_EVENT_MONITOR_SHIFT	20
+#define L2X0_INTR_MASK_ECNTR		1
+
+/* L220/PL310 Event control register values */
+#define L2X0_EVENT_CNT_ENABLE_MASK		1
+#define L2X0_EVENT_CNT_ENABLE			1
+#define L2X0_EVENT_CNT_RESET(x)			(1 << (x+1))
+
+/* Bit-shifted event counter config values */
+enum l2x0_perf_types {
+	L2X0_EVENT_CNT_CFG_DISABLED		= 0x0,
+	L2X0_EVENT_CNT_CFG_CO			= 0x1,
+	L2X0_EVENT_CNT_CFG_DRHIT		= 0x2,
+	L2X0_EVENT_CNT_CFG_DRREQ		= 0x3,
+	L2X0_EVENT_CNT_CFG_DWHIT		= 0x4,
+	L2X0_EVENT_CNT_CFG_DWREQ		= 0x5,
+	L2X0_EVENT_CNT_CFG_DWTREQ		= 0x6,
+	L2X0_EVENT_CNT_CFG_IRHIT		= 0x7,
+	L2X0_EVENT_CNT_CFG_IRREQ		= 0x8,
+	L2X0_EVENT_CNT_CFG_WA			= 0x9,
+
+	/* PL310 only */
+	L2X0_EVENT_CNT_CFG_IPFALLOC		= 0xA,
+	L2X0_EVENT_CNT_CFG_EPFHIT		= 0xB,
+	L2X0_EVENT_CNT_CFG_EPFALLOC		= 0xC,
+	L2X0_EVENT_CNT_CFG_SRRCVD		= 0xD,
+	L2X0_EVENT_CNT_CFG_SRCONF		= 0xE,
+	L2X0_EVENT_CNT_CFG_EPFRCVD		= 0xF,
+};
+
+#define PL310_EVENT_CNT_CFG_MAX			L2X0_EVENT_CNT_CFG_EPFRCVD
+
+#define L2X0_EVENT_CNT_CFG_SHIFT		2
+#define L2X0_EVENT_CNT_CFG_MASK			(0xF << 2)
+
+#define L2X0_EVENT_CNT_CFG_INTR_MASK		0x3
+#define L2X0_EVENT_CNT_CFG_INTR_DISABLED	0x0
+#define L2X0_EVENT_CNT_CFG_INTR_INCREMENT	0x1
+#define L2X0_EVENT_CNT_CFG_INTR_OVERFLOW	0x2
+
+#define L2X0_NUM_COUNTERS			2
+static struct arm_pmu l2x0_pmu;
+
+static u32 l2x0pmu_max_event_id = 0xf;
+
+static struct perf_event *events[2];
+static unsigned long used_mask[BITS_TO_LONGS(2)];
+static struct pmu_hw_events l2x0pmu_hw_events = {
+	.events = events,
+	.used_mask = used_mask,
+	.pmu_lock = __RAW_SPIN_LOCK_UNLOCKED(l2x0pmu_hw_events.pmu_lock),
+};
+
+#define COUNTER_CFG_ADDR(idx)	(l2x0_base + L2X0_EVENT_CNT0_CFG - 4*idx)
+
+#define COUNTER_CTRL_ADDR	(l2x0_base + L2X0_EVENT_CNT_CTRL)
+
+#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);
+}
+
+static struct pmu_hw_events *l2x0pmu_get_hw_events(void)
+{
+	return &l2x0pmu_hw_events;
+}
+
+static u32 l2x0pmu_read_ctrl(void)
+{
+	return readl_relaxed(COUNTER_CTRL_ADDR);
+}
+
+static void l2x0pmu_write_ctrl(u32 val)
+{
+	writel_relaxed(val, COUNTER_CTRL_ADDR);
+}
+
+static u32 l2x0pmu_read_cfg(int idx)
+{
+	return readl_relaxed(COUNTER_CFG_ADDR(idx));
+}
+
+static void l2x0pmu_write_cfg(u32 val, int idx)
+{
+	writel_relaxed(val, COUNTER_CFG_ADDR(idx));
+}
+
+static void l2x0pmu_enable_counter(u32 cfg, int idx)
+{
+	cfg |= L2X0_EVENT_CNT_CFG_INTR_OVERFLOW;
+	l2x0pmu_write_cfg(cfg, idx);
+}
+
+static u32 l2x0pmu_disable_counter(int idx)
+{
+	u32 cfg, oldcfg;
+
+	cfg = oldcfg = l2x0pmu_read_cfg(idx);
+
+	cfg &= ~L2X0_EVENT_CNT_CFG_MASK;
+	cfg &= ~L2X0_EVENT_CNT_CFG_INTR_MASK;
+	l2x0pmu_write_cfg(cfg, idx);
+
+	return oldcfg;
+}
+
+static u32 l2x0pmu_read_counter(int idx)
+{
+	u32 val = readl_relaxed(COUNTER_ADDR(idx));
+
+	return val;
+}
+
+static void l2x0pmu_write_counter(int idx, u32 val)
+{
+	/*
+	 * L2X0 counters can only be written to when they are disabled.
+	 * As perf core does not disable counters before writing to them
+	 * under interrupts, we must do so here.
+	 */
+	u32 cfg = l2x0pmu_disable_counter(idx);
+	writel_relaxed(val, COUNTER_ADDR(idx));
+	l2x0pmu_write_cfg(cfg, idx);
+}
+
+static int counter_is_saturated(int idx)
+{
+	return l2x0pmu_read_counter(idx) == 0xFFFFFFFF;
+}
+
+static void l2x0pmu_start(void)
+{
+	unsigned long flags;
+	u32 val;
+
+	raw_spin_lock_irqsave(&l2x0pmu_hw_events.pmu_lock, flags);
+
+	if (!rev1)
+		l2x0_enable_counter_interrupt();
+
+	val = l2x0pmu_read_ctrl();
+
+	val |= L2X0_EVENT_CNT_ENABLE;
+	l2x0pmu_write_ctrl(val);
+
+	raw_spin_unlock_irqrestore(&l2x0pmu_hw_events.pmu_lock, flags);
+}
+
+static void l2x0pmu_stop(void)
+{
+	unsigned long flags;
+	u32 val;
+
+	raw_spin_lock_irqsave(&l2x0pmu_hw_events.pmu_lock, flags);
+
+	val = l2x0pmu_read_ctrl();
+	val &= ~L2X0_EVENT_CNT_ENABLE_MASK;
+	l2x0pmu_write_ctrl(val);
+
+	if (!rev1)
+		l2x0_disable_counter_interrupt();
+
+	raw_spin_unlock_irqrestore(&l2x0pmu_hw_events.pmu_lock, flags);
+}
+
+static void l2x0pmu_enable(struct hw_perf_event *event, int idx, int cpu)
+{
+	unsigned long flags;
+	u32 cfg;
+
+	raw_spin_lock_irqsave(&l2x0pmu_hw_events.pmu_lock, flags);
+
+	cfg = (event->config_base << L2X0_EVENT_CNT_CFG_SHIFT) &
+						L2X0_EVENT_CNT_CFG_MASK;
+	l2x0pmu_enable_counter(cfg, idx);
+
+	raw_spin_unlock_irqrestore(&l2x0pmu_hw_events.pmu_lock, flags);
+}
+
+static void l2x0pmu_disable(struct hw_perf_event *event, int idx)
+{
+	unsigned long flags;
+
+	raw_spin_lock_irqsave(&l2x0pmu_hw_events.pmu_lock, flags);
+	l2x0pmu_disable_counter(idx);
+	raw_spin_unlock_irqrestore(&l2x0pmu_hw_events.pmu_lock, flags);
+}
+
+static int l2x0pmu_get_event_idx(struct pmu_hw_events *events,
+					struct hw_perf_event *hwc)
+{
+	int idx;
+
+	/* Counters are identical. Just grab a free one. */
+	for (idx = 0; idx < L2X0_NUM_COUNTERS; ++idx) {
+		if (!test_and_set_bit(idx, l2x0pmu_hw_events.used_mask))
+			return idx;
+	}
+
+	return -EAGAIN;
+}
+
+/*
+ * As System PMUs are affine to CPU0, the fact that interrupts are disabled
+ * during interrupt handling is enough to serialise our actions and make this
+ * safe. We do not need to grab our pmu_lock here.
+ */
+static irqreturn_t l2x0pmu_handle_irq(int irq, void *dev)
+{
+	irqreturn_t status = IRQ_NONE;
+	struct perf_sample_data data;
+	struct pt_regs *regs;
+	int idx;
+
+	regs = get_irq_regs();
+
+	for (idx = 0; idx < L2X0_NUM_COUNTERS; ++idx) {
+		struct perf_event *event = l2x0pmu_hw_events.events[idx];
+		struct hw_perf_event *hwc;
+
+		if (!counter_is_saturated(idx))
+			continue;
+
+		status = IRQ_HANDLED;
+
+		hwc = &event->hw;
+
+		/*
+		 * The armpmu_* functions expect counters to overflow, but
+		 * L220/PL310 counters saturate instead. Fake the overflow
+		 * here so the hardware is in sync with what the framework
+		 * expects.
+		 */
+		l2x0pmu_write_counter(idx, 0);
+
+		armpmu_event_update(event, hwc, idx);
+		data.period = event->hw.last_period;
+
+		if (!armpmu_event_set_period(event, hwc, idx))
+			continue;
+
+		if (perf_event_overflow(event, &data, regs))
+			l2x0pmu_disable_counter(idx);
+	}
+
+	l2x0_clear_interrupts(L2X0_INTR_MASK_ECNTR);
+
+	irq_work_run();
+
+	return status;
+}
+
+static int map_l2x0_raw_event(u64 config)
+{
+	return (config <= l2x0pmu_max_event_id) ? config : -ENOENT;
+}
+
+static int l2x0pmu_map_event(struct perf_event *event)
+{
+	u64 config = event->attr.config;
+	u64 supported_samples = (PERF_SAMPLE_TIME	|
+				 PERF_SAMPLE_ID		|
+				 PERF_SAMPLE_PERIOD	|
+				 PERF_SAMPLE_STREAM_ID	|
+				 PERF_SAMPLE_RAW);
+
+	if ((pmu_type == 0) || (pmu_type != event->attr.type))
+		return -ENOENT;
+
+	if (event->attr.sample_type & ~supported_samples)
+		return -ENOENT;
+
+	return map_l2x0_raw_event(config);
+}
+
+static int
+arm_l2_pmu_generic_request_irq(int irq, irq_handler_t *handle_irq)
+{
+	return request_irq(irq, *handle_irq,
+			IRQF_DISABLED | IRQF_NOBALANCING,
+			"arm-l2-armpmu", NULL);
+}
+
+static void
+arm_l2_pmu_generic_free_irq(int irq)
+{
+	if (irq >= 0)
+		free_irq(irq, NULL);
+}
+
+static struct arm_pmu l2x0_pmu = {
+	.id		= ARM_PERF_PMU_ID_L2X0,
+	.type		= ARM_PMU_DEVICE_L2CC,
+	.name		= "msm-l2",
+	.start		= l2x0pmu_start,
+	.stop		= l2x0pmu_stop,
+	.handle_irq	= l2x0pmu_handle_irq,
+	.enable		= l2x0pmu_enable,
+	.disable	= l2x0pmu_disable,
+	.get_event_idx	= l2x0pmu_get_event_idx,
+	.read_counter	= l2x0pmu_read_counter,
+	.write_counter	= l2x0pmu_write_counter,
+	.map_event	= l2x0pmu_map_event,
+	.num_events	= 2,
+	.max_period	= 0xFFFFFFFF,
+	.get_hw_events	= l2x0pmu_get_hw_events,
+	.pmu.attr_groups = arm_l2_pmu_attr_grps,
+	.request_pmu_irq = arm_l2_pmu_generic_request_irq,
+	.free_pmu_irq	= arm_l2_pmu_generic_free_irq,
+};
+
+static int __devinit l2x0pmu_device_probe(struct platform_device *pdev)
+{
+	u32 aux = readl_relaxed(l2x0_base + L2X0_AUX_CTRL);
+	u32 debug = readl_relaxed(l2x0_base + L2X0_DEBUG_CTRL);
+	l2x0_pmu.plat_device = pdev;
+
+	if (!(aux & (1 << L2X0_AUX_CTRL_EVENT_MONITOR_SHIFT))) {
+		pr_err("Ev Monitor is OFF. L2 counters disabled.\n");
+		return -EOPNOTSUPP;
+	}
+
+	pr_info("L2CC PMU device found. DEBUG_CTRL: %x\n", debug);
+
+	/* Get value of dynamically allocated PMU type. */
+	if (!armpmu_register(&l2x0_pmu, "msm-l2", -1))
+		pmu_type = l2x0_pmu.pmu.type;
+	else {
+		pr_err("l2x0_pmu registration failed\n");
+		return -EOPNOTSUPP;
+	}
+
+	return 0;
+}
+
+static struct platform_driver l2x0pmu_driver = {
+	.driver		= {
+		.name	= "l2-arm-pmu",
+	},
+	.probe		= l2x0pmu_device_probe,
+};
+
+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-q6v5.c b/arch/arm/mach-msm/pil-q6v5.c
index ab88749..de3a544 100644
--- a/arch/arm/mach-msm/pil-q6v5.c
+++ b/arch/arm/mach-msm/pil-q6v5.c
@@ -118,7 +118,7 @@
 	val &= ~(Q6SS_L2DATA_SLP_NRET_N | Q6SS_SLP_RET_N |
 		 Q6SS_L2TAG_SLP_NRET_N | Q6SS_ETB_SLP_NRET_N |
 		 Q6SS_L2DATA_STBY_N);
-	writel_relaxed(Q6SS_CLAMP_IO, drv->reg_base + QDSP6SS_PWR_CTL);
+	writel_relaxed(val, drv->reg_base + QDSP6SS_PWR_CTL);
 
 	/* Assert Q6 resets */
 	val = readl_relaxed(drv->reg_base + QDSP6SS_RESET);
diff --git a/arch/arm/mach-msm/pm2.c b/arch/arm/mach-msm/pm2.c
index ec9f030..a2da8b0 100644
--- a/arch/arm/mach-msm/pm2.c
+++ b/arch/arm/mach-msm/pm2.c
@@ -894,12 +894,23 @@
 
 	msm_pm_irq_extns->enter_sleep1(true, from_idle,
 						&msm_pm_smem_data->irq_mask);
-	msm_sirc_enter_sleep();
-	msm_gpio_enter_sleep(from_idle);
 
 	msm_pm_smem_data->sleep_time = sleep_delay;
 	msm_pm_smem_data->resources_used = sleep_limit;
 
+	saved_acpuclk_rate = acpuclk_power_collapse();
+	MSM_PM_DPRINTK(MSM_PM_DEBUG_CLOCK, KERN_INFO,
+		"%s(): change clock rate (old rate = %lu)\n", __func__,
+		saved_acpuclk_rate);
+
+	if (saved_acpuclk_rate == 0) {
+		ret = -EAGAIN;
+		goto acpu_set_clock_fail;
+	}
+
+	msm_sirc_enter_sleep();
+	msm_gpio_enter_sleep(from_idle);
+
 	/* Enter PWRC/PWRC_SUSPEND */
 
 	if (from_idle)
@@ -952,16 +963,6 @@
 	msm_pm_config_hw_before_power_down();
 	MSM_PM_DEBUG_PRINT_STATE("msm_pm_power_collapse(): pre power down");
 
-	saved_acpuclk_rate = acpuclk_power_collapse();
-	MSM_PM_DPRINTK(MSM_PM_DEBUG_CLOCK, KERN_INFO,
-		"%s(): change clock rate (old rate = %lu)\n", __func__,
-		saved_acpuclk_rate);
-
-	if (saved_acpuclk_rate == 0) {
-		msm_pm_config_hw_after_power_up();
-		goto power_collapse_early_exit;
-	}
-
 	msm_pm_boot_config_before_pc(smp_processor_id(),
 			virt_to_phys(msm_pm_collapse_exit));
 
@@ -1052,14 +1053,6 @@
 		KERN_INFO,
 		"%s(): msm_pm_collapse returned %d\n", __func__, collapsed);
 
-	MSM_PM_DPRINTK(MSM_PM_DEBUG_CLOCK, KERN_INFO,
-		"%s(): restore clock rate to %lu\n", __func__,
-		saved_acpuclk_rate);
-	if (acpuclk_set_rate(smp_processor_id(), saved_acpuclk_rate,
-			SETRATE_PC) < 0)
-		printk(KERN_ERR "%s(): failed to restore clock rate(%lu)\n",
-			__func__, saved_acpuclk_rate);
-
 	msm_pm_irq_extns->exit_sleep1(msm_pm_smem_data->irq_mask,
 		msm_pm_smem_data->wakeup_reason,
 		msm_pm_smem_data->pending_irqs);
@@ -1132,6 +1125,14 @@
 		goto power_collapse_restore_gpio_bail;
 	}
 
+	MSM_PM_DPRINTK(MSM_PM_DEBUG_CLOCK, KERN_INFO,
+		"%s(): restore clock rate to %lu\n", __func__,
+		saved_acpuclk_rate);
+	if (acpuclk_set_rate(smp_processor_id(), saved_acpuclk_rate,
+			SETRATE_PC) < 0)
+		pr_err("%s(): failed to restore clock rate(%lu)\n",
+			__func__, saved_acpuclk_rate);
+
 	/* DEM Master == RUN */
 
 	MSM_PM_DEBUG_PRINT_STATE("msm_pm_power_collapse(): WFPI RUN");
@@ -1212,10 +1213,18 @@
 
 	MSM_PM_DEBUG_PRINT_STATE("msm_pm_power_collapse(): RUN");
 
+	MSM_PM_DPRINTK(MSM_PM_DEBUG_CLOCK, KERN_INFO,
+		"%s(): restore clock rate to %lu\n", __func__,
+		saved_acpuclk_rate);
+	if (acpuclk_set_rate(smp_processor_id(), saved_acpuclk_rate,
+			SETRATE_PC) < 0)
+		pr_err("%s(): failed to restore clock rate(%lu)\n",
+			__func__, saved_acpuclk_rate);
+
 	if (collapsed)
 		smd_sleep_exit();
 
-	/* Call CPR resume only for "idlePC" case */
+acpu_set_clock_fail:
 	if (msm_cpr_ops && from_idle)
 		msm_cpr_ops->cpr_resume();
 
diff --git a/arch/arm/mach-msm/pmu.c b/arch/arm/mach-msm/pmu.c
index f0b83f9..cb191fc 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[] = {
@@ -168,6 +183,7 @@
 #ifdef CONFIG_ARCH_MSM8625
 	if (cpu_is_msm8625()) {
 		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_mvs.c b/arch/arm/mach-msm/qdsp5/audio_mvs.c
index d45043d..5f126bc 100644
--- a/arch/arm/mach-msm/qdsp5/audio_mvs.c
+++ b/arch/arm/mach-msm/qdsp5/audio_mvs.c
@@ -1613,6 +1613,19 @@
 
 	MM_DBG("\n");
 
+	mutex_lock(&audio_mvs_info.lock);
+
+	if (audio_mvs_info.state != AUDIO_MVS_CLOSED) {
+		MM_ERR("MVS driver exists, state %d\n",
+				audio_mvs_info.state);
+
+		rc = -EBUSY;
+		mutex_unlock(&audio_mvs_info.lock);
+		goto done;
+	}
+
+	mutex_unlock(&audio_mvs_info.lock);
+
 	audio_mvs_info.rpc_endpt = msm_rpc_connect_compatible(MVS_PROG,
 					MVS_VERS_COMP_VER2,
 					MSM_RPC_UNINTERRUPTIBLE);
@@ -1652,26 +1665,18 @@
 
 	mutex_lock(&audio_mvs_info.lock);
 
-	if (audio_mvs_info.state == AUDIO_MVS_CLOSED) {
-
-		if (audio_mvs_info.task != NULL ||
+	if (audio_mvs_info.task != NULL ||
 			audio_mvs_info.rpc_endpt != NULL) {
-			rc = audio_mvs_alloc_buf(&audio_mvs_info);
+		rc = audio_mvs_alloc_buf(&audio_mvs_info);
 
-			if (rc == 0) {
-				audio_mvs_info.state = AUDIO_MVS_OPENED;
-				file->private_data = &audio_mvs_info;
-			}
-		}  else {
-			MM_ERR("MVS thread and RPC end point do not exist\n");
-
-			rc = -ENODEV;
+		if (rc == 0) {
+			audio_mvs_info.state = AUDIO_MVS_OPENED;
+			file->private_data = &audio_mvs_info;
 		}
-	} else {
-		MM_ERR("MVS driver exists, state %d\n",
-		       audio_mvs_info.state);
+	}  else {
+		MM_ERR("MVS thread and RPC end point do not exist\n");
 
-		rc = -EBUSY;
+		rc = -ENODEV;
 	}
 
 	mutex_unlock(&audio_mvs_info.lock);
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 666323b..f2a84aa 100644
--- a/arch/arm/mach-msm/qdsp5/audmgr.c
+++ b/arch/arm/mach-msm/qdsp5/audmgr.c
@@ -3,7 +3,7 @@
  * interface to "audmgr" service on the baseband cpu
  *
  * Copyright (C) 2008 Google, Inc.
- * Copyright (c) 2009, 2012 Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2009, 2012, 2013 Code Aurora Forum. 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
@@ -46,6 +46,8 @@
 	struct msm_rpc_endpoint *ept;
 	struct task_struct *task;
 	uint32_t rpc_version;
+	uint32_t rx_device;
+	uint32_t tx_device;
 	int cad;
 	struct device_info_callback *device_cb[MAX_DEVICE_INFO_CALLBACK];
 
@@ -156,6 +158,22 @@
 			return;
 		if (am->state != STATE_ENABLED)
 			am->state = STATE_ENABLED;
+		if (!amg->cad)
+			break;
+
+		if (am->evt.session_info == SESSION_PLAYBACK &&
+			am->evt.dev_type.rx_device != amg->rx_device) {
+			am->evt.dev_type.rx_device = amg->rx_device;
+			am->evt.dev_type.tx_device = 0;
+			am->evt.acdb_id = am->evt.dev_type.rx_device;
+		}
+		if (am->evt.session_info == SESSION_RECORDING &&
+			am->evt.dev_type.tx_device != amg->tx_device) {
+			am->evt.dev_type.rx_device = 0;
+			am->evt.dev_type.tx_device = amg->tx_device;
+			am->evt.acdb_id = am->evt.dev_type.tx_device;
+		}
+
 		while ((amg->device_cb[i] != NULL) &&
 				(i < MAX_DEVICE_INFO_CALLBACK) &&
 				(amg->cad)) {
@@ -209,11 +227,13 @@
 					be32_to_cpu(temp->d.rx_device);
 			am->evt.dev_type.tx_device = 0;
 			am->evt.acdb_id = am->evt.dev_type.rx_device;
+			amg->rx_device = am->evt.dev_type.rx_device;
 		} else if (am->evt.session_info == SESSION_RECORDING) {
 			am->evt.dev_type.rx_device = 0;
 			am->evt.dev_type.tx_device =
 					be32_to_cpu(temp->d.tx_device);
 			am->evt.acdb_id = am->evt.dev_type.tx_device;
+			amg->tx_device = am->evt.dev_type.tx_device;
 		}
 		am->evt.dev_type.ear_mute =
 					be32_to_cpu(temp->d.ear_mute);
diff --git a/arch/arm/mach-msm/qdsp6v2/q6audio_common.h b/arch/arm/mach-msm/qdsp6v2/q6audio_common.h
index 3bc8454..5ffffd2 100644
--- a/arch/arm/mach-msm/qdsp6v2/q6audio_common.h
+++ b/arch/arm/mach-msm/qdsp6v2/q6audio_common.h
@@ -15,7 +15,9 @@
 #ifndef __Q6_AUDIO_COMMON_H__
 #define __Q6_AUDIO_COMMON_H__
 
-#if defined(CONFIG_ARCH_MSM8974) || defined(CONFIG_ARCH_MSM9625)
+#if defined(CONFIG_ARCH_MSM8974) || defined(CONFIG_ARCH_MSM9625) \
+	|| defined(CONFIG_ARCH_MSM8226)
+
 #include <sound/apr_audio-v2.h>
 #include <sound/q6asm-v2.h>
 #else
diff --git a/arch/arm/mach-msm/remote_spinlock.c b/arch/arm/mach-msm/remote_spinlock.c
index 2480433..98a3278 100644
--- a/arch/arm/mach-msm/remote_spinlock.c
+++ b/arch/arm/mach-msm/remote_spinlock.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2008-2009, 2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2008-2009, 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
@@ -15,6 +15,10 @@
 #include <linux/kernel.h>
 #include <linux/string.h>
 #include <linux/delay.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
 
 #include <asm/system.h>
 
@@ -22,7 +26,6 @@
 #include <mach/remote_spinlock.h>
 #include <mach/dal.h>
 #include "smd_private.h"
-#include <linux/module.h>
 
 static void remote_spin_release_all_locks(uint32_t pid, int count);
 
@@ -30,31 +33,85 @@
 #define SFPB_SPINLOCK_COUNT 8
 #define MSM_SFPB_MUTEX_REG_BASE 0x01200600
 #define MSM_SFPB_MUTEX_REG_SIZE	(33 * 4)
+#define SFPB_SPINLOCK_OFFSET 4
+#define SFPB_SPINLOCK_SIZE 4
+
+static uint32_t lock_count;
+static phys_addr_t reg_base;
+static uint32_t reg_size;
+static uint32_t lock_offset; /* offset into the hardware block before lock 0 */
+static uint32_t lock_size;
 
 static void *hw_mutex_reg_base;
 static DEFINE_MUTEX(hw_map_init_lock);
 
+static char *compatible_string = "qcom,ipc-spinlock";
+
+static int init_hw_mutex(struct device_node *node)
+{
+	struct resource r;
+	int rc;
+
+	rc = of_address_to_resource(node, 0, &r);
+	if (rc)
+		BUG();
+
+	rc = of_property_read_u32(node, "qcom,num-locks", &lock_count);
+	if (rc)
+		BUG();
+
+	reg_base = r.start;
+	reg_size = (uint32_t)(resource_size(&r));
+	lock_offset = 0;
+	lock_size = reg_size / lock_count;
+
+	return 0;
+}
+
+static void find_and_init_hw_mutex(void)
+{
+	struct device_node *node;
+
+	node = of_find_compatible_node(NULL, NULL, compatible_string);
+	if (node) {
+		init_hw_mutex(node);
+	} else {
+		lock_count = SFPB_SPINLOCK_COUNT;
+		reg_base = MSM_SFPB_MUTEX_REG_BASE;
+		reg_size = MSM_SFPB_MUTEX_REG_SIZE;
+		lock_offset = SFPB_SPINLOCK_OFFSET;
+		lock_size = SFPB_SPINLOCK_SIZE;
+	}
+	hw_mutex_reg_base = ioremap(reg_base, reg_size);
+	BUG_ON(hw_mutex_reg_base == NULL);
+}
+
 static int remote_spinlock_init_address(int id, _remote_spinlock_t *lock)
 {
-	if (id >= SFPB_SPINLOCK_COUNT)
-		return -EINVAL;
-
+	/*
+	 * Optimistic locking.  Init only needs to be done once by the first
+	 * caller.  After that, serializing inits between different callers
+	 * is unnecessary.  The second check after the lock ensures init
+	 * wasn't previously completed by someone else before the lock could
+	 * be grabbed.
+	 */
 	if (!hw_mutex_reg_base) {
 		mutex_lock(&hw_map_init_lock);
 		if (!hw_mutex_reg_base)
-			hw_mutex_reg_base = ioremap(MSM_SFPB_MUTEX_REG_BASE,
-				   MSM_SFPB_MUTEX_REG_SIZE);
+			find_and_init_hw_mutex();
 		mutex_unlock(&hw_map_init_lock);
-		BUG_ON(hw_mutex_reg_base == NULL);
 	}
 
-	*lock = hw_mutex_reg_base + 0x4 + id * 4;
+	if (id >= lock_count)
+		return -EINVAL;
+
+	*lock = hw_mutex_reg_base + lock_offset + id * lock_size;
 	return 0;
 }
 
 void _remote_spin_release_all(uint32_t pid)
 {
-	remote_spin_release_all_locks(pid, SFPB_SPINLOCK_COUNT);
+	remote_spin_release_all_locks(pid, lock_count);
 }
 
 #else
diff --git a/arch/arm/mach-msm/restart.c b/arch/arm/mach-msm/restart.c
index 7966177..58d445e 100644
--- a/arch/arm/mach-msm/restart.c
+++ b/arch/arm/mach-msm/restart.c
@@ -266,6 +266,9 @@
 {
 	int rc;
 
+	if (use_restart_v2())
+		return 0;
+
 	if (pmic_reset_irq != 0) {
 		rc = request_any_context_irq(pmic_reset_irq,
 					resout_irq_handler, IRQF_TRIGGER_HIGH,
diff --git a/arch/arm/mach-msm/rpm-smd.c b/arch/arm/mach-msm/rpm-smd.c
index 1db3d34..ccd0861 100644
--- a/arch/arm/mach-msm/rpm-smd.c
+++ b/arch/arm/mach-msm/rpm-smd.c
@@ -822,6 +822,7 @@
 int msm_rpm_wait_for_ack(uint32_t msg_id)
 {
 	struct msm_rpm_wait_data *elem;
+	int rc = 0;
 
 	if (!msg_id) {
 		pr_err("%s(): Invalid msg id\n", __func__);
@@ -829,20 +830,22 @@
 	}
 
 	if (msg_id == 1)
-		return 0;
+		return rc;
 
 	if (standalone)
-		return 0;
+		return rc;
 
 	elem = msm_rpm_get_entry_from_msg_id(msg_id);
 	if (!elem)
-		return 0;
+		return rc;
 
 	wait_for_completion(&elem->ack);
 	trace_rpm_ack_recd(0, msg_id);
 
+	rc = elem->errno;
 	msm_rpm_free_list_entry(elem);
-	return elem->errno;
+
+	return rc;
 }
 EXPORT_SYMBOL(msm_rpm_wait_for_ack);
 
diff --git a/arch/arm/mach-msm/sdio_cmux.c b/arch/arm/mach-msm/sdio_cmux.c
index d04a0b0..48ca6b7 100644
--- a/arch/arm/mach-msm/sdio_cmux.c
+++ b/arch/arm/mach-msm/sdio_cmux.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2011, 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
@@ -68,6 +68,7 @@
 	struct list_head tx_list;
 
 	void *priv;
+	struct mutex rx_cb_lock;
 	void (*receive_cb)(void *, int, void *);
 	void (*write_done)(void *, int, void *);
 	void (*status_callback)(int, void *);
@@ -171,6 +172,7 @@
 	mutex_init(&logical_ch[id].tx_lock);
 
 	logical_ch[id].priv = NULL;
+	mutex_init(&logical_ch[id].rx_cb_lock);
 	logical_ch[id].receive_cb = NULL;
 	logical_ch[id].write_done = NULL;
 	return 0;
@@ -197,8 +199,10 @@
 		kfree(list_elem);
 	}
 	mutex_unlock(&logical_ch[id].tx_lock);
+	mutex_lock(&logical_ch[id].rx_cb_lock);
 	if (logical_ch[id].receive_cb)
 		logical_ch[id].receive_cb(NULL, 0, logical_ch[id].priv);
+	mutex_unlock(&logical_ch[id].rx_cb_lock);
 	if (logical_ch[id].write_done)
 		logical_ch[id].write_done(NULL, 0, logical_ch[id].priv);
 	mutex_unlock(&logical_ch[id].lc_lock);
@@ -300,9 +304,10 @@
 	}
 	logical_ch[id].is_local_open = 1;
 	logical_ch[id].priv = priv;
-	logical_ch[id].receive_cb = receive_cb;
 	logical_ch[id].write_done = write_done;
 	logical_ch[id].status_callback = status_callback;
+	mutex_lock(&logical_ch[id].rx_cb_lock);
+	logical_ch[id].receive_cb = receive_cb;
 	if (logical_ch[id].receive_cb) {
 		mutex_lock(&temp_rx_lock);
 		list_for_each_entry_safe(list_elem, list_elem_tmp,
@@ -319,6 +324,7 @@
 		}
 		mutex_unlock(&temp_rx_lock);
 	}
+	mutex_unlock(&logical_ch[id].rx_cb_lock);
 	mutex_unlock(&logical_ch[id].lc_lock);
 	sdio_cmux_write_cmd(id, OPEN);
 	return 0;
@@ -338,7 +344,9 @@
 
 	ch = &logical_ch[id];
 	mutex_lock(&ch->lc_lock);
+	mutex_lock(&logical_ch[id].rx_cb_lock);
 	ch->receive_cb = NULL;
+	mutex_unlock(&logical_ch[id].rx_cb_lock);
 	mutex_lock(&ch->tx_lock);
 	ch->write_done = NULL;
 	mutex_unlock(&ch->tx_lock);
@@ -564,12 +572,20 @@
 
 		data = (void *)((char *)pkt + sizeof(struct sdio_cmux_hdr));
 		data_size = (int)(((struct sdio_cmux_hdr *)pkt)->pkt_len);
+		mutex_unlock(&logical_ch[id].lc_lock);
+		/*
+		 * The lc_lock is released before the call to receive_cb
+		 * to avoid a dead lock where in the receive_cb would call a
+		 * function that tries to acquire a rx_lock which is already
+		 * acquired by a Thread that is waiting on lc_lock.
+		 */
+		mutex_lock(&logical_ch[id].rx_cb_lock);
 		if (logical_ch[id].receive_cb)
 			logical_ch[id].receive_cb(data, data_size,
 						logical_ch[id].priv);
 		else
 			copy_packet(pkt, size);
-		mutex_unlock(&logical_ch[id].lc_lock);
+		mutex_unlock(&logical_ch[id].rx_cb_lock);
 		break;
 
 	case STATUS:
diff --git a/arch/arm/mach-msm/smd.c b/arch/arm/mach-msm/smd.c
index ad42505..c607202 100644
--- a/arch/arm/mach-msm/smd.c
+++ b/arch/arm/mach-msm/smd.c
@@ -657,8 +657,8 @@
 };
 
 struct smd_channel {
-	volatile void *send; /* some variant of smd_half_channel */
-	volatile void *recv; /* some variant of smd_half_channel */
+	volatile void __iomem *send; /* some variant of smd_half_channel */
+	volatile void __iomem *recv; /* some variant of smd_half_channel */
 	unsigned char *send_data;
 	unsigned char *recv_data;
 	unsigned fifo_size;
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/smd_private.c b/arch/arm/mach-msm/smd_private.c
index 5a78b6f..4cde8eb 100644
--- a/arch/arm/mach-msm/smd_private.c
+++ b/arch/arm/mach-msm/smd_private.c
@@ -12,227 +12,256 @@
 
 #include "smd_private.h"
 
-void set_state(volatile void *half_channel, unsigned data)
+void set_state(volatile void __iomem *half_channel, unsigned data)
 {
-	((struct smd_half_channel *)(half_channel))->state = data;
+	((struct smd_half_channel __force *)(half_channel))->state = data;
 }
 
-unsigned get_state(volatile void *half_channel)
+unsigned get_state(volatile void __iomem *half_channel)
 {
-	return ((struct smd_half_channel *)(half_channel))->state;
+	return ((struct smd_half_channel __force *)(half_channel))->state;
 }
 
-void set_fDSR(volatile void *half_channel, unsigned char data)
+void set_fDSR(volatile void __iomem *half_channel, unsigned char data)
 {
-	((struct smd_half_channel *)(half_channel))->fDSR = data;
+	((struct smd_half_channel __force *)(half_channel))->fDSR = data;
 }
 
-unsigned get_fDSR(volatile void *half_channel)
+unsigned get_fDSR(volatile void __iomem *half_channel)
 {
-	return ((struct smd_half_channel *)(half_channel))->fDSR;
+	return ((struct smd_half_channel __force *)(half_channel))->fDSR;
 }
 
-void set_fCTS(volatile void *half_channel, unsigned char data)
+void set_fCTS(volatile void __iomem *half_channel, unsigned char data)
 {
-	((struct smd_half_channel *)(half_channel))->fCTS = data;
+	((struct smd_half_channel __force *)(half_channel))->fCTS = data;
 }
 
-unsigned get_fCTS(volatile void *half_channel)
+unsigned get_fCTS(volatile void __iomem *half_channel)
 {
-	return ((struct smd_half_channel *)(half_channel))->fCTS;
+	return ((struct smd_half_channel __force *)(half_channel))->fCTS;
 }
 
-void set_fCD(volatile void *half_channel, unsigned char data)
+void set_fCD(volatile void __iomem *half_channel, unsigned char data)
 {
-	((struct smd_half_channel *)(half_channel))->fCD = data;
+	((struct smd_half_channel __force *)(half_channel))->fCD = data;
 }
 
-unsigned get_fCD(volatile void *half_channel)
+unsigned get_fCD(volatile void __iomem *half_channel)
 {
-	return ((struct smd_half_channel *)(half_channel))->fCD;
+	return ((struct smd_half_channel __force *)(half_channel))->fCD;
 }
 
-void set_fRI(volatile void *half_channel, unsigned char data)
+void set_fRI(volatile void __iomem *half_channel, unsigned char data)
 {
-	((struct smd_half_channel *)(half_channel))->fRI = data;
+	((struct smd_half_channel __force *)(half_channel))->fRI = data;
 }
 
-unsigned get_fRI(volatile void *half_channel)
+unsigned get_fRI(volatile void __iomem *half_channel)
 {
-	return ((struct smd_half_channel *)(half_channel))->fRI;
+	return ((struct smd_half_channel __force *)(half_channel))->fRI;
 }
 
-void set_fHEAD(volatile void *half_channel, unsigned char data)
+void set_fHEAD(volatile void __iomem *half_channel, unsigned char data)
 {
-	((struct smd_half_channel *)(half_channel))->fHEAD = data;
+	((struct smd_half_channel __force *)(half_channel))->fHEAD = data;
 }
 
-unsigned get_fHEAD(volatile void *half_channel)
+unsigned get_fHEAD(volatile void __iomem *half_channel)
 {
-	return ((struct smd_half_channel *)(half_channel))->fHEAD;
+	return ((struct smd_half_channel __force *)(half_channel))->fHEAD;
 }
 
-void set_fTAIL(volatile void *half_channel, unsigned char data)
+void set_fTAIL(volatile void __iomem *half_channel, unsigned char data)
 {
-	((struct smd_half_channel *)(half_channel))->fTAIL = data;
+	((struct smd_half_channel __force *)(half_channel))->fTAIL = data;
 }
 
-unsigned get_fTAIL(volatile void *half_channel)
+unsigned get_fTAIL(volatile void __iomem *half_channel)
 {
-	return ((struct smd_half_channel *)(half_channel))->fTAIL;
+	return ((struct smd_half_channel __force *)(half_channel))->fTAIL;
 }
 
-void set_fSTATE(volatile void *half_channel, unsigned char data)
+void set_fSTATE(volatile void __iomem *half_channel, unsigned char data)
 {
-	((struct smd_half_channel *)(half_channel))->fSTATE = data;
+	((struct smd_half_channel __force *)(half_channel))->fSTATE = data;
 }
 
-unsigned get_fSTATE(volatile void *half_channel)
+unsigned get_fSTATE(volatile void __iomem *half_channel)
 {
-	return ((struct smd_half_channel *)(half_channel))->fSTATE;
+	return ((struct smd_half_channel __force *)(half_channel))->fSTATE;
 }
 
-void set_fBLOCKREADINTR(volatile void *half_channel, unsigned char data)
+void set_fBLOCKREADINTR(volatile void __iomem *half_channel, unsigned char data)
 {
-	((struct smd_half_channel *)(half_channel))->fBLOCKREADINTR = data;
+	((struct smd_half_channel __force *)
+				(half_channel))->fBLOCKREADINTR = data;
 }
 
-unsigned get_fBLOCKREADINTR(volatile void *half_channel)
+unsigned get_fBLOCKREADINTR(volatile void __iomem *half_channel)
 {
-	return ((struct smd_half_channel *)(half_channel))->fBLOCKREADINTR;
+	return ((struct smd_half_channel __force *)
+				(half_channel))->fBLOCKREADINTR;
 }
 
-void set_tail(volatile void *half_channel, unsigned data)
+void set_tail(volatile void __iomem *half_channel, unsigned data)
 {
-	((struct smd_half_channel *)(half_channel))->tail = data;
+	((struct smd_half_channel __force *)(half_channel))->tail = data;
 }
 
-unsigned get_tail(volatile void *half_channel)
+unsigned get_tail(volatile void __iomem *half_channel)
 {
-	return ((struct smd_half_channel *)(half_channel))->tail;
+	return ((struct smd_half_channel __force *)(half_channel))->tail;
 }
 
-void set_head(volatile void *half_channel, unsigned data)
+void set_head(volatile void __iomem *half_channel, unsigned data)
 {
-	((struct smd_half_channel *)(half_channel))->head = data;
+	((struct smd_half_channel __force *)(half_channel))->head = data;
 }
 
-unsigned get_head(volatile void *half_channel)
+unsigned get_head(volatile void __iomem *half_channel)
 {
-	return ((struct smd_half_channel *)(half_channel))->head;
+	return ((struct smd_half_channel __force *)(half_channel))->head;
 }
 
-void set_state_word_access(volatile void *half_channel, unsigned data)
+void set_state_word_access(volatile void __iomem *half_channel, unsigned data)
 {
-	((struct smd_half_channel_word_access *)(half_channel))->state = data;
+	((struct smd_half_channel_word_access __force *)
+					(half_channel))->state = data;
 }
 
-unsigned get_state_word_access(volatile void *half_channel)
+unsigned get_state_word_access(volatile void __iomem *half_channel)
 {
-	return ((struct smd_half_channel_word_access *)(half_channel))->state;
+	return ((struct smd_half_channel_word_access __force *)
+					(half_channel))->state;
 }
 
-void set_fDSR_word_access(volatile void *half_channel, unsigned char data)
+void set_fDSR_word_access(volatile void __iomem *half_channel,
+						unsigned char data)
 {
-	((struct smd_half_channel_word_access *)(half_channel))->fDSR = data;
+	((struct smd_half_channel_word_access __force *)
+					(half_channel))->fDSR = data;
 }
 
-unsigned get_fDSR_word_access(volatile void *half_channel)
+unsigned get_fDSR_word_access(volatile void __iomem *half_channel)
 {
-	return ((struct smd_half_channel_word_access *)(half_channel))->fDSR;
+	return ((struct smd_half_channel_word_access __force *)
+					(half_channel))->fDSR;
 }
 
-void set_fCTS_word_access(volatile void *half_channel, unsigned char data)
+void set_fCTS_word_access(volatile void __iomem *half_channel,
+						unsigned char data)
 {
-	((struct smd_half_channel_word_access *)(half_channel))->fCTS = data;
+	((struct smd_half_channel_word_access __force *)
+					(half_channel))->fCTS = data;
 }
 
-unsigned get_fCTS_word_access(volatile void *half_channel)
+unsigned get_fCTS_word_access(volatile void __iomem *half_channel)
 {
-	return ((struct smd_half_channel_word_access *)(half_channel))->fCTS;
+	return ((struct smd_half_channel_word_access __force *)
+					(half_channel))->fCTS;
 }
 
-void set_fCD_word_access(volatile void *half_channel, unsigned char data)
+void set_fCD_word_access(volatile void __iomem *half_channel,
+						unsigned char data)
 {
-	((struct smd_half_channel_word_access *)(half_channel))->fCD = data;
+	((struct smd_half_channel_word_access __force *)
+					(half_channel))->fCD = data;
 }
 
-unsigned get_fCD_word_access(volatile void *half_channel)
+unsigned get_fCD_word_access(volatile void __iomem *half_channel)
 {
-	return ((struct smd_half_channel_word_access *)(half_channel))->fCD;
+	return ((struct smd_half_channel_word_access __force *)
+					(half_channel))->fCD;
 }
 
-void set_fRI_word_access(volatile void *half_channel, unsigned char data)
+void set_fRI_word_access(volatile void __iomem *half_channel,
+						unsigned char data)
 {
-	((struct smd_half_channel_word_access *)(half_channel))->fRI = data;
+	((struct smd_half_channel_word_access __force *)
+					(half_channel))->fRI = data;
 }
 
-unsigned get_fRI_word_access(volatile void *half_channel)
+unsigned get_fRI_word_access(volatile void __iomem *half_channel)
 {
-	return ((struct smd_half_channel_word_access *)(half_channel))->fRI;
+	return ((struct smd_half_channel_word_access __force *)
+					(half_channel))->fRI;
 }
 
-void set_fHEAD_word_access(volatile void *half_channel, unsigned char data)
+void set_fHEAD_word_access(volatile void __iomem *half_channel,
+						unsigned char data)
 {
-	((struct smd_half_channel_word_access *)(half_channel))->fHEAD = data;
+	((struct smd_half_channel_word_access __force *)
+					(half_channel))->fHEAD = data;
 }
 
-unsigned get_fHEAD_word_access(volatile void *half_channel)
+unsigned get_fHEAD_word_access(volatile void __iomem *half_channel)
 {
-	return ((struct smd_half_channel_word_access *)(half_channel))->fHEAD;
+	return ((struct smd_half_channel_word_access __force *)
+					(half_channel))->fHEAD;
 }
 
-void set_fTAIL_word_access(volatile void *half_channel, unsigned char data)
+void set_fTAIL_word_access(volatile void __iomem *half_channel,
+						unsigned char data)
 {
-	((struct smd_half_channel_word_access *)(half_channel))->fTAIL = data;
+	((struct smd_half_channel_word_access __force *)
+					(half_channel))->fTAIL = data;
 }
 
-unsigned get_fTAIL_word_access(volatile void *half_channel)
+unsigned get_fTAIL_word_access(volatile void __iomem *half_channel)
 {
-	return ((struct smd_half_channel_word_access *)(half_channel))->fTAIL;
+	return ((struct smd_half_channel_word_access __force *)
+					(half_channel))->fTAIL;
 }
 
-void set_fSTATE_word_access(volatile void *half_channel, unsigned char data)
+void set_fSTATE_word_access(volatile void __iomem *half_channel,
+						unsigned char data)
 {
-	((struct smd_half_channel_word_access *)(half_channel))->fSTATE = data;
+	((struct smd_half_channel_word_access __force *)
+					(half_channel))->fSTATE = data;
 }
 
-unsigned get_fSTATE_word_access(volatile void *half_channel)
+unsigned get_fSTATE_word_access(volatile void __iomem *half_channel)
 {
-	return ((struct smd_half_channel_word_access *)(half_channel))->fSTATE;
+	return ((struct smd_half_channel_word_access __force *)
+					(half_channel))->fSTATE;
 }
 
-void set_fBLOCKREADINTR_word_access(volatile void *half_channel,
+void set_fBLOCKREADINTR_word_access(volatile void __iomem *half_channel,
 							unsigned char data)
 {
-	((struct smd_half_channel_word_access *)
+	((struct smd_half_channel_word_access __force *)
 					(half_channel))->fBLOCKREADINTR = data;
 }
 
-unsigned get_fBLOCKREADINTR_word_access(volatile void *half_channel)
+unsigned get_fBLOCKREADINTR_word_access(volatile void __iomem *half_channel)
 {
-	return ((struct smd_half_channel_word_access *)
-						(half_channel))->fBLOCKREADINTR;
+	return ((struct smd_half_channel_word_access __force *)
+					(half_channel))->fBLOCKREADINTR;
 }
 
-void set_tail_word_access(volatile void *half_channel, unsigned data)
+void set_tail_word_access(volatile void __iomem *half_channel, unsigned data)
 {
-	((struct smd_half_channel_word_access *)(half_channel))->tail = data;
+	((struct smd_half_channel_word_access __force *)
+					(half_channel))->tail = data;
 }
 
-unsigned get_tail_word_access(volatile void *half_channel)
+unsigned get_tail_word_access(volatile void __iomem *half_channel)
 {
-	return ((struct smd_half_channel_word_access *)(half_channel))->tail;
+	return ((struct smd_half_channel_word_access __force *)
+					(half_channel))->tail;
 }
 
-void set_head_word_access(volatile void *half_channel, unsigned data)
+void set_head_word_access(volatile void __iomem *half_channel, unsigned data)
 {
-	((struct smd_half_channel_word_access *)(half_channel))->head = data;
+	((struct smd_half_channel_word_access __force *)
+					(half_channel))->head = data;
 }
 
-unsigned get_head_word_access(volatile void *half_channel)
+unsigned get_head_word_access(volatile void __iomem *half_channel)
 {
-	return ((struct smd_half_channel_word_access *)(half_channel))->head;
+	return ((struct smd_half_channel_word_access __force *)
+					(half_channel))->head;
 }
 
 int is_word_access_ch(unsigned ch_type)
diff --git a/arch/arm/mach-msm/smd_private.h b/arch/arm/mach-msm/smd_private.h
index 7f39a24..2033fbe 100644
--- a/arch/arm/mach-msm/smd_private.h
+++ b/arch/arm/mach-msm/smd_private.h
@@ -147,29 +147,36 @@
 };
 
 struct smd_half_channel_access {
-	void (*set_state)(volatile void *half_channel, unsigned data);
-	unsigned (*get_state)(volatile void *half_channel);
-	void (*set_fDSR)(volatile void *half_channel, unsigned char data);
-	unsigned (*get_fDSR)(volatile void *half_channel);
-	void (*set_fCTS)(volatile void *half_channel, unsigned char data);
-	unsigned (*get_fCTS)(volatile void *half_channel);
-	void (*set_fCD)(volatile void *half_channel, unsigned char data);
-	unsigned (*get_fCD)(volatile void *half_channel);
-	void (*set_fRI)(volatile void *half_channel, unsigned char data);
-	unsigned (*get_fRI)(volatile void *half_channel);
-	void (*set_fHEAD)(volatile void *half_channel, unsigned char data);
-	unsigned (*get_fHEAD)(volatile void *half_channel);
-	void (*set_fTAIL)(volatile void *half_channel, unsigned char data);
-	unsigned (*get_fTAIL)(volatile void *half_channel);
-	void (*set_fSTATE)(volatile void *half_channel, unsigned char data);
-	unsigned (*get_fSTATE)(volatile void *half_channel);
-	void (*set_fBLOCKREADINTR)(volatile void *half_channel,
+	void (*set_state)(volatile void __iomem *half_channel, unsigned data);
+	unsigned (*get_state)(volatile void __iomem *half_channel);
+	void (*set_fDSR)(volatile void __iomem *half_channel,
 					unsigned char data);
-	unsigned (*get_fBLOCKREADINTR)(volatile void *half_channel);
-	void (*set_tail)(volatile void *half_channel, unsigned data);
-	unsigned (*get_tail)(volatile void *half_channel);
-	void (*set_head)(volatile void *half_channel, unsigned data);
-	unsigned (*get_head)(volatile void *half_channel);
+	unsigned (*get_fDSR)(volatile void __iomem *half_channel);
+	void (*set_fCTS)(volatile void __iomem *half_channel,
+					unsigned char data);
+	unsigned (*get_fCTS)(volatile void __iomem *half_channel);
+	void (*set_fCD)(volatile void __iomem *half_channel,
+					unsigned char data);
+	unsigned (*get_fCD)(volatile void __iomem *half_channel);
+	void (*set_fRI)(volatile void __iomem *half_channel,
+					unsigned char data);
+	unsigned (*get_fRI)(volatile void __iomem *half_channel);
+	void (*set_fHEAD)(volatile void __iomem *half_channel,
+					unsigned char data);
+	unsigned (*get_fHEAD)(volatile void __iomem *half_channel);
+	void (*set_fTAIL)(volatile void __iomem *half_channel,
+					unsigned char data);
+	unsigned (*get_fTAIL)(volatile void __iomem *half_channel);
+	void (*set_fSTATE)(volatile void __iomem *half_channel,
+					unsigned char data);
+	unsigned (*get_fSTATE)(volatile void __iomem *half_channel);
+	void (*set_fBLOCKREADINTR)(volatile void __iomem *half_channel,
+					unsigned char data);
+	unsigned (*get_fBLOCKREADINTR)(volatile void __iomem *half_channel);
+	void (*set_tail)(volatile void __iomem *half_channel, unsigned data);
+	unsigned (*get_tail)(volatile void __iomem *half_channel);
+	void (*set_head)(volatile void __iomem *half_channel, unsigned data);
+	unsigned (*get_head)(volatile void __iomem *half_channel);
 };
 
 int is_word_access_ch(unsigned ch_type);
diff --git a/arch/arm/mach-msm/socinfo.c b/arch/arm/mach-msm/socinfo.c
index 2743547..47d311c 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)
diff --git a/arch/arm/mach-msm/subsystem_restart.c b/arch/arm/mach-msm/subsystem_restart.c
index d862e0f..91bf62f 100644
--- a/arch/arm/mach-msm/subsystem_restart.c
+++ b/arch/arm/mach-msm/subsystem_restart.c
@@ -981,9 +981,6 @@
 		spin_lock_init(&restart_orders[i]->track.s_lock);
 	}
 
-	if (restart_orders == NULL || n_restart_orders < 1)
-		WARN_ON(1);
-
 	return 0;
 }
 
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/arch/arm/mm/cache-l2x0.c b/arch/arm/mm/cache-l2x0.c
index adab76d..1f2b868 100644
--- a/arch/arm/mm/cache-l2x0.c
+++ b/arch/arm/mm/cache-l2x0.c
@@ -23,16 +23,13 @@
 #include <linux/io.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
-#include <linux/platform_device.h>
 
 #include <asm/cacheflush.h>
 #include <asm/hardware/cache-l2x0.h>
-#include <asm/irq_regs.h>
-#include <asm/pmu.h>
 
 #define CACHE_LINE_SIZE		32
 
-static void __iomem *l2x0_base;
+void __iomem *l2x0_base;
 static DEFINE_RAW_SPINLOCK(l2x0_lock);
 static u32 l2x0_way_mask;	/* Bitmask of active ways */
 static u32 l2x0_size;
@@ -656,315 +653,3 @@
 	pl310_resume();
 	dmb();
 }
-
-#ifdef CONFIG_HW_PERF_EVENTS
-/*
- * L220/PL310 PMU-specific functionality.
- * TODO: Put this in a separate file and get the l2x0 driver to register
- * the PMU from l2x0_{of}_init.
- */
-
-static struct arm_pmu l2x0_pmu;
-
-static u64 l2x0pmu_max_event_id;
-
-static struct perf_event *events[2];
-static unsigned long used_mask[BITS_TO_LONGS(2)];
-static struct pmu_hw_events hw_events = {
-	.events = events,
-	.used_mask = used_mask,
-	.pmu_lock = __RAW_SPIN_LOCK_UNLOCKED(l2x0pmu_hw_events.pmu_lock),
-};
-
-#define COUNTER_CFG_ADDR(idx)	(l2x0_base + L2X0_EVENT_CNT0_CFG - 4*idx)
-
-#define COUNTER_CTRL_ADDR	(l2x0_base + L2X0_EVENT_CNT_CTRL)
-
-#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);
-}
-
-static struct pmu_hw_events *l2x0pmu_get_hw_events(void)
-{
-	return &hw_events;
-}
-
-static u32 l2x0pmu_read_ctrl(void)
-{
-	return readl_relaxed(COUNTER_CTRL_ADDR);
-}
-
-static void l2x0pmu_write_ctrl(u32 val)
-{
-	writel_relaxed(val, COUNTER_CTRL_ADDR);
-}
-
-static u32 l2x0pmu_read_cfg(int idx)
-{
-	return readl_relaxed(COUNTER_CFG_ADDR(idx));
-}
-
-static void l2x0pmu_write_cfg(u32 val, int idx)
-{
-	writel_relaxed(val, COUNTER_CFG_ADDR(idx));
-}
-
-static void l2x0pmu_enable_counter(u32 cfg, int idx)
-{
-	cfg |= L2X0_EVENT_CNT_CFG_INTR_OVERFLOW;
-	l2x0pmu_write_cfg(cfg, idx);
-}
-
-static u32 l2x0pmu_disable_counter(int idx)
-{
-	u32 cfg, oldcfg;
-
-	cfg = oldcfg = l2x0pmu_read_cfg(idx);
-	cfg &= ~L2X0_EVENT_CNT_CFG_MASK;
-	cfg &= ~L2X0_EVENT_CNT_CFG_INTR_MASK;
-	l2x0pmu_write_cfg(cfg, idx);
-
-	return oldcfg;
-}
-
-static u32 l2x0pmu_read_counter(int idx)
-{
-	return readl_relaxed(COUNTER_ADDR(idx));
-}
-
-static void l2x0pmu_write_counter(int idx, u32 val)
-{
-	/*
-	 * L2X0 counters can only be written to when they are disabled.
-	 * As perf core does not disable counters before writing to them
-	 * under interrupts, we must do so here.
-	 */
-	u32 cfg = l2x0pmu_disable_counter(idx);
-	writel_relaxed(val, COUNTER_ADDR(idx));
-	l2x0pmu_write_cfg(cfg, idx);
-}
-
-static int counter_is_saturated(int idx)
-{
-	return l2x0pmu_read_counter(idx) == 0xFFFFFFFF;
-}
-
-static void l2x0pmu_start(void)
-{
-	unsigned long flags;
-	u32 val;
-
-	raw_spin_lock_irqsave(&hw_events.pmu_lock, flags);
-
-	l2x0_enable_counter_interrupt();
-
-	val = l2x0pmu_read_ctrl();
-	val |= L2X0_EVENT_CNT_ENABLE;
-	l2x0pmu_write_ctrl(val);
-
-	raw_spin_unlock_irqrestore(&hw_events.pmu_lock, flags);
-}
-
-static void l2x0pmu_stop(void)
-{
-	unsigned long flags;
-	u32 val;
-
-	raw_spin_lock_irqsave(&hw_events.pmu_lock, flags);
-
-	val = l2x0pmu_read_ctrl();
-	val &= ~L2X0_EVENT_CNT_ENABLE_MASK;
-	l2x0pmu_write_ctrl(val);
-
-	l2x0_disable_counter_interrupt();
-
-	raw_spin_unlock_irqrestore(&hw_events.pmu_lock, flags);
-}
-
-static void l2x0pmu_enable(struct hw_perf_event *event, int idx, int cpu)
-{
-	unsigned long flags;
-	u32 cfg;
-
-	raw_spin_lock_irqsave(&hw_events.pmu_lock, flags);
-
-	cfg = (event->config_base << L2X0_EVENT_CNT_CFG_SHIFT) &
-						L2X0_EVENT_CNT_CFG_MASK;
-	l2x0pmu_enable_counter(cfg, idx);
-
-	raw_spin_unlock_irqrestore(&hw_events.pmu_lock, flags);
-}
-
-static void l2x0pmu_disable(struct hw_perf_event *event, int idx)
-{
-	unsigned long flags;
-
-	raw_spin_lock_irqsave(&hw_events.pmu_lock, flags);
-	l2x0pmu_disable_counter(idx);
-	raw_spin_unlock_irqrestore(&hw_events.pmu_lock, flags);
-}
-
-static int l2x0pmu_get_event_idx(struct pmu_hw_events *events,
-					struct hw_perf_event *hwc)
-{
-	int idx;
-
-	/* Counters are identical. Just grab a free one. */
-	for (idx = 0; idx < L2X0_NUM_COUNTERS; ++idx) {
-		if (!test_and_set_bit(idx, hw_events.used_mask))
-			return idx;
-	}
-
-	return -EAGAIN;
-}
-
-/*
- * As System PMUs are affine to CPU0, the fact that interrupts are disabled
- * during interrupt handling is enough to serialise our actions and make this
- * safe. We do not need to grab our pmu_lock here.
- */
-static irqreturn_t l2x0pmu_handle_irq(int irq, void *dev)
-{
-	irqreturn_t status = IRQ_NONE;
-	struct perf_sample_data data;
-	struct pt_regs *regs;
-	int idx;
-
-	regs = get_irq_regs();
-
-	for (idx = 0; idx < L2X0_NUM_COUNTERS; ++idx) {
-		struct perf_event *event = hw_events.events[idx];
-		struct hw_perf_event *hwc;
-
-		if (!counter_is_saturated(idx))
-			continue;
-
-		status = IRQ_HANDLED;
-
-		hwc = &event->hw;
-
-		/*
-		 * The armpmu_* functions expect counters to overflow, but
-		 * L220/PL310 counters saturate instead. Fake the overflow
-		 * here so the hardware is in sync with what the framework
-		 * expects.
-		 */
-		l2x0pmu_write_counter(idx, 0);
-
-		armpmu_event_update(event, hwc, idx);
-		data.period = event->hw.last_period;
-
-		if (!armpmu_event_set_period(event, hwc, idx))
-			continue;
-
-		if (perf_event_overflow(event, &data, regs))
-			l2x0pmu_disable_counter(idx);
-	}
-
-	l2x0_clear_interrupts(L2X0_INTR_MASK_ECNTR);
-
-	irq_work_run();
-
-	return status;
-}
-
-static int map_l2x0_raw_event(u64 config)
-{
-	return (config <= l2x0pmu_max_event_id) ? config : -ENOENT;
-}
-
-static int l2x0pmu_map_event(struct perf_event *event)
-{
-	u64 config = event->attr.config;
-	u64 supported_samples = (PERF_SAMPLE_TIME	|
-				 PERF_SAMPLE_ID		|
-				 PERF_SAMPLE_PERIOD	|
-				 PERF_SAMPLE_STREAM_ID	|
-				 PERF_SAMPLE_RAW);
-
-	if (event->attr.type != l2x0_pmu.pmu.type)
-		return -ENOENT;
-
-	/*
-	 * L2x0 counters are global across CPUs.
-	 * If userspace ask perf to monitor from multiple CPUs, each CPU will
-	 * report the shared total. When summed, this will be the actual value
-	 * multiplied by the number of CPUs. We limit monitoring to a single
-	 * CPU (0) to prevent confusion stemming from this.
-	 */
-	if (event->cpu != 0)
-		return -ENOENT;
-
-	if (event->attr.sample_type & ~supported_samples)
-		return -ENOENT;
-
-	return map_l2x0_raw_event(config);
-}
-
-static struct arm_pmu l2x0_pmu = {
-	.id		= ARM_PERF_PMU_ID_L2X0,
-	.type		= ARM_PMU_DEVICE_L2CC,
-	.name		= "ARM L220/PL310 L2 Cache controller",
-	.start		= l2x0pmu_start,
-	.stop		= l2x0pmu_stop,
-	.handle_irq	= l2x0pmu_handle_irq,
-	.enable		= l2x0pmu_enable,
-	.disable	= l2x0pmu_disable,
-	.get_event_idx	= l2x0pmu_get_event_idx,
-	.read_counter	= l2x0pmu_read_counter,
-	.write_counter	= l2x0pmu_write_counter,
-	.map_event	= l2x0pmu_map_event,
-	.num_events	= 2,
-	.max_period	= 0xFFFFFFFF,
-	.get_hw_events	= l2x0pmu_get_hw_events,
-};
-
-static int __devinit l2x0pmu_device_probe(struct platform_device *pdev)
-{
-	l2x0_pmu.plat_device = pdev;
-	/* FIXME: return code? */
-	armpmu_register(&l2x0_pmu, "l2x0", -1);
-	return 0;
-}
-
-static struct platform_driver l2x0pmu_driver = {
-	.driver		= {
-		.name	= "l2x0-pmu",
-	},
-	.probe		= l2x0pmu_device_probe,
-};
-
-static int __init register_pmu_driver(void)
-{
-	return platform_driver_register(&l2x0pmu_driver);
-}
-device_initcall(register_pmu_driver);
-
-#endif /* CONFIG_HW_PERF_EVENTS */
diff --git a/block/row-iosched.c b/block/row-iosched.c
index 483d97f..a4184da 100644
--- a/block/row-iosched.c
+++ b/block/row-iosched.c
@@ -58,6 +58,17 @@
 	false,	/* ROWQ_PRIO_LOW_SWRITE */
 };
 
+/* Flags indicating whether the queue can notify on urgent requests */
+static const bool urgent_queues[] = {
+	true,	/* ROWQ_PRIO_HIGH_READ */
+	true,	/* ROWQ_PRIO_REG_READ */
+	false,	/* ROWQ_PRIO_HIGH_SWRITE */
+	false,	/* ROWQ_PRIO_REG_SWRITE */
+	false,	/* ROWQ_PRIO_REG_WRITE */
+	false,	/* ROWQ_PRIO_LOW_READ */
+	false,	/* ROWQ_PRIO_LOW_SWRITE */
+};
+
 /* Default values for row queues quantums in each dispatch cycle */
 static const int queue_quantum[] = {
 	100,	/* ROWQ_PRIO_HIGH_READ */
@@ -271,10 +282,70 @@
 
 		rqueue->idle_data.last_insert_time = ktime_get();
 	}
-	row_log_rowq(rd, rqueue->prio, "added request");
+	if (urgent_queues[rqueue->prio] &&
+	    row_rowq_unserved(rd, rqueue->prio)) {
+		row_log_rowq(rd, rqueue->prio,
+			     "added urgent req curr_queue = %d",
+			     rd->curr_queue);
+	} else
+		row_log_rowq(rd, rqueue->prio, "added request");
 }
 
-/*
+/**
+ * row_reinsert_req() - Reinsert request back to the scheduler
+ * @q:	requests queue
+ * @rq:	request to add
+ *
+ * Reinsert the given request back to the queue it was
+ * dispatched from as if it was never dispatched.
+ *
+ * Returns 0 on success, error code otherwise
+ */
+static int row_reinsert_req(struct request_queue *q,
+			    struct request *rq)
+{
+	struct row_data    *rd = q->elevator->elevator_data;
+	struct row_queue   *rqueue = RQ_ROWQ(rq);
+
+	/* Verify rqueue is legitimate */
+	if (rqueue->prio >= ROWQ_MAX_PRIO) {
+		pr_err("\n\nROW BUG: row_reinsert_req() rqueue->prio = %d\n",
+			   rqueue->prio);
+		blk_dump_rq_flags(rq, "");
+		return -EIO;
+	}
+
+	list_add(&rq->queuelist, &rqueue->fifo);
+	rd->nr_reqs[rq_data_dir(rq)]++;
+
+	row_log_rowq(rd, rqueue->prio, "request reinserted");
+
+	return 0;
+}
+
+/**
+ * row_urgent_pending() - Return TRUE if there is an urgent
+ *			  request on scheduler
+ * @q:	requests queue
+ */
+static bool row_urgent_pending(struct request_queue *q)
+{
+	struct row_data *rd = q->elevator->elevator_data;
+	int i;
+
+	for (i = 0; i < ROWQ_MAX_PRIO; i++)
+		if (urgent_queues[i] && row_rowq_unserved(rd, i) &&
+		    !list_empty(&rd->row_queues[i].rqueue.fifo)) {
+			row_log_rowq(rd, i,
+				     "Urgent request pending (curr=%i)",
+				     rd->curr_queue);
+			return true;
+		}
+
+	return false;
+}
+
+/**
  * row_remove_request() -  Remove given request from scheduler
  * @q:	requests queue
  * @rq:	request to remove
@@ -664,6 +735,8 @@
 		.elevator_merge_req_fn		= row_merged_requests,
 		.elevator_dispatch_fn		= row_dispatch_requests,
 		.elevator_add_req_fn		= row_add_request,
+		.elevator_reinsert_req_fn	= row_reinsert_req,
+		.elevator_is_urgent_fn		= row_urgent_pending,
 		.elevator_former_req_fn		= elv_rb_former_request,
 		.elevator_latter_req_fn		= elv_rb_latter_request,
 		.elevator_set_req_fn		= row_set_request,
diff --git a/drivers/bluetooth/hci_smd.c b/drivers/bluetooth/hci_smd.c
index 6030520..9b60bda 100644
--- a/drivers/bluetooth/hci_smd.c
+++ b/drivers/bluetooth/hci_smd.c
@@ -44,6 +44,19 @@
 #define RX_Q_MONITOR		(500)	/* 500 milli second */
 #define HCI_REGISTER_SET	0
 
+/* SSR state machine to take care of back to back SSR requests
+ * and handling the incomming BT on/off,Airplane mode toggling and
+ * also spuriour SMD open notification while one SSr is in progress
+ */
+#define STATE_SSR_ON 0x1
+#define STATE_SSR_START 0x02
+#define STATE_SSR_CHANNEL_OPEN_PENDING 0x04
+#define STATE_SSR_PENDING_INIT  0x08
+#define STATE_SSR_COMPLETE 0x00
+#define STATE_SSR_OFF STATE_SSR_COMPLETE
+
+static int ssr_state = STATE_SSR_OFF;
+
 
 static int hcismd_set;
 static DEFINE_SEMAPHORE(hci_smd_enable);
@@ -341,25 +354,47 @@
 		break;
 	case SMD_EVENT_OPEN:
 		BT_INFO("opening HCI-SMD channel :%s", EVENT_CHANNEL);
-		hci_smd_open(hdev);
-		open_worker = kzalloc(sizeof(*open_worker), GFP_ATOMIC);
-		if (!open_worker) {
-			BT_ERR("Out of memory");
-			break;
+		BT_DBG("SSR state is : %x", ssr_state);
+		if ((ssr_state == STATE_SSR_OFF) ||
+			(ssr_state == STATE_SSR_CHANNEL_OPEN_PENDING)) {
+
+			hci_smd_open(hdev);
+			open_worker = kzalloc(sizeof(*open_worker), GFP_ATOMIC);
+			if (!open_worker) {
+				BT_ERR("Out of memory");
+				break;
+			}
+			if (ssr_state == STATE_SSR_CHANNEL_OPEN_PENDING) {
+				ssr_state = STATE_SSR_PENDING_INIT;
+				BT_INFO("SSR state is : %x", ssr_state);
+			}
+			INIT_WORK(open_worker, hci_dev_smd_open);
+			schedule_work(open_worker);
+
 		}
-		INIT_WORK(open_worker, hci_dev_smd_open);
-		schedule_work(open_worker);
 		break;
 	case SMD_EVENT_CLOSE:
 		BT_INFO("Closing HCI-SMD channel :%s", EVENT_CHANNEL);
-		hci_smd_close(hdev);
-		reset_worker = kzalloc(sizeof(*reset_worker), GFP_ATOMIC);
-		if (!reset_worker) {
-			BT_ERR("Out of memory");
-			break;
+		BT_DBG("SSR state is : %x", ssr_state);
+		if ((ssr_state == STATE_SSR_OFF) ||
+			(ssr_state == (STATE_SSR_PENDING_INIT))) {
+
+			hci_smd_close(hdev);
+			reset_worker = kzalloc(sizeof(*reset_worker),
+							GFP_ATOMIC);
+			if (!reset_worker) {
+				BT_ERR("Out of memory");
+				break;
+			}
+			ssr_state = STATE_SSR_ON;
+			BT_INFO("SSR state is : %x", ssr_state);
+			INIT_WORK(reset_worker, hci_dev_restart);
+			schedule_work(reset_worker);
+
+		} else if (ssr_state & STATE_SSR_ON) {
+				BT_ERR("SSR state is : %x", ssr_state);
 		}
-		INIT_WORK(reset_worker, hci_dev_restart);
-		schedule_work(reset_worker);
+
 		break;
 	default:
 		break;
@@ -403,19 +438,37 @@
 {
 	struct hci_dev *hdev;
 
-	hdev = hsmd->hdev;
-	if (test_and_set_bit(HCI_REGISTER_SET, &hsmd->flags)) {
-		BT_ERR("HCI device registered already");
+	if (hsmd->hdev)
+		hdev = hsmd->hdev;
+	else {
+		BT_ERR("hdev is NULL");
 		return 0;
-	} else
-		BT_INFO("HCI device registration is starting");
-	if (hci_register_dev(hdev) < 0) {
-		BT_ERR("Can't register HCI device");
-		hci_free_dev(hdev);
-		hsmd->hdev = NULL;
-		clear_bit(HCI_REGISTER_SET, &hsmd->flags);
-		return -ENODEV;
 	}
+	/* Allow the incomming SSR even the prev one at PENDING INIT STATE
+	 * since clenup need to be started again from the beging and ignore
+	 *  or bypass the prev one
+	 */
+	if ((ssr_state == STATE_SSR_OFF) ||
+			(ssr_state == STATE_SSR_PENDING_INIT)) {
+
+		if (test_and_set_bit(HCI_REGISTER_SET, &hsmd->flags)) {
+			BT_ERR("HCI device registered already");
+			return 0;
+		} else
+			BT_INFO("HCI device registration is starting");
+		if (hci_register_dev(hdev) < 0) {
+			BT_ERR("Can't register HCI device");
+			hci_free_dev(hdev);
+			hsmd->hdev = NULL;
+			clear_bit(HCI_REGISTER_SET, &hsmd->flags);
+			return -ENODEV;
+		}
+		if (ssr_state == STATE_SSR_PENDING_INIT) {
+			ssr_state = STATE_SSR_COMPLETE;
+			BT_INFO("SSR state is : %x", ssr_state);
+		}
+	} else if (ssr_state)
+		BT_ERR("Registration called in invalid context");
 	return 0;
 }
 
@@ -449,7 +502,10 @@
 	 */
 	setup_timer(&hsmd->rx_q_timer, schedule_timer,
 			(unsigned long) hsmd->hdev);
-
+	if (ssr_state == STATE_SSR_START) {
+		ssr_state = STATE_SSR_CHANNEL_OPEN_PENDING;
+		BT_INFO("SSR state is : %x", ssr_state);
+	}
 	/* Open the SMD Channel and device and register the callback function */
 	rc = smd_named_open_on_edge(EVENT_CHANNEL, SMD_APPS_WCNSS,
 			&hsmd->event_channel, hdev, hci_smd_notify_event);
@@ -478,21 +534,25 @@
 static void hci_smd_deregister_dev(struct hci_smd_data *hsmd)
 {
 	tasklet_kill(&hs.rx_task);
-
+	if (ssr_state)
+		BT_DBG("SSR state is : %x", ssr_state);
+	/* Though the hci_smd driver is not registered with the hci
+	 * need to close the opened channels as a part of cleaup
+	 */
 	if (!test_and_clear_bit(HCI_REGISTER_SET, &hsmd->flags)) {
 		BT_ERR("HCI device un-registered already");
-		return;
-	} else
+	} else {
 		BT_INFO("HCI device un-registration going on");
-	if (hsmd->hdev) {
-		if (hci_unregister_dev(hsmd->hdev) < 0)
-			BT_ERR("Can't unregister HCI device %s",
-				hsmd->hdev->name);
 
-		hci_free_dev(hsmd->hdev);
-		hsmd->hdev = NULL;
+		if (hsmd->hdev) {
+			if (hci_unregister_dev(hsmd->hdev) < 0)
+				BT_ERR("Can't unregister HCI device %s",
+					hsmd->hdev->name);
+
+			hci_free_dev(hsmd->hdev);
+			hsmd->hdev = NULL;
+		}
 	}
-
 	smd_close(hs.event_channel);
 	smd_close(hs.data_channel);
 
@@ -513,23 +573,47 @@
 {
 	down(&hci_smd_enable);
 	restart_in_progress = 1;
+	BT_DBG("SSR state is : %x", ssr_state);
+
+	if (ssr_state == STATE_SSR_ON) {
+		ssr_state = STATE_SSR_START;
+		BT_INFO("SSR state is : %x", ssr_state);
+	} else {
+		BT_ERR("restart triggered in wrong context");
+		up(&hci_smd_enable);
+		kfree(worker);
+		return;
+	}
 	hci_smd_deregister_dev(&hs);
 	hci_smd_register_smd(&hs);
 	up(&hci_smd_enable);
 	kfree(worker);
+
 }
 
 static void hci_dev_smd_open(struct work_struct *worker)
 {
 	down(&hci_smd_enable);
+	if (ssr_state)
+		BT_DBG("SSR state is : %x", ssr_state);
+
+	if ((ssr_state != STATE_SSR_OFF) &&
+			(ssr_state  !=  (STATE_SSR_PENDING_INIT))) {
+		up(&hci_smd_enable);
+		kfree(worker);
+		return;
+	}
+
 	if (restart_in_progress == 1) {
 		/* Allow wcnss to initialize */
 		restart_in_progress = 0;
 		msleep(10000);
 	}
+
 	hci_smd_hci_register_dev(&hs);
 	up(&hci_smd_enable);
 	kfree(worker);
+
 }
 
 static int hcismd_set_enable(const char *val, struct kernel_param *kp)
@@ -545,14 +629,23 @@
 	if (ret)
 		goto done;
 
+	/* Ignore the all incomming register de-register requests in case of
+	 * SSR is in-progress
+	 */
 	switch (hcismd_set) {
 
 	case 1:
-		if (hs.hdev == NULL)
+		if ((hs.hdev == NULL) && (ssr_state == STATE_SSR_OFF))
 			hci_smd_register_smd(&hs);
+		else if (ssr_state)
+			BT_ERR("SSR is in progress,state is : %x", ssr_state);
+
 	break;
 	case 0:
-		hci_smd_deregister_dev(&hs);
+		if (ssr_state == STATE_SSR_OFF)
+			hci_smd_deregister_dev(&hs);
+		else if (ssr_state)
+			BT_ERR("SSR is in progress,state is : %x", ssr_state);
 	break;
 	default:
 		ret = -EFAULT;
@@ -569,6 +662,7 @@
 	wake_lock_init(&hs.wake_lock_tx, WAKE_LOCK_SUSPEND,
 			 "msm_smd_Tx");
 	restart_in_progress = 0;
+	ssr_state = STATE_SSR_OFF;
 	hs.hdev = NULL;
 	return 0;
 }
diff --git a/drivers/char/diag/diag_masks.c b/drivers/char/diag/diag_masks.c
index 2a85a00..e8567db 100644
--- a/drivers/char/diag/diag_masks.c
+++ b/drivers/char/diag/diag_masks.c
@@ -26,6 +26,9 @@
 #define ALL_SSID		-1
 #define MAX_SSID_PER_RANGE	100
 
+#define FEATURE_MASK_LEN_BYTES		1
+#define APPS_RESPOND_LOG_ON_DEMAND	0x04
+
 struct mask_info {
 	int equip_id;
 	int num_items;
@@ -309,6 +312,7 @@
 						smd_info->peripheral);
 	diag_send_log_mask_update(smd_info->ch, ALL_EQUIP_ID);
 	diag_send_event_mask_update(smd_info->ch, diag_event_num_bytes);
+	diag_send_feature_mask_update(smd_info->ch, smd_info->peripheral);
 
 	smd_info->notify_context = 0;
 }
@@ -461,6 +465,42 @@
 	mutex_unlock(&driver->diag_cntl_mutex);
 }
 
+void diag_send_feature_mask_update(smd_channel_t *ch, int proc)
+{
+	void *buf = driver->buf_feature_mask_update;
+	int header_size = sizeof(struct diag_ctrl_feature_mask);
+	int wr_size = -ENOMEM, retry_count = 0, timer;
+	uint8_t feature_byte = 0;
+
+	mutex_lock(&driver->diag_cntl_mutex);
+	/* send feature mask update */
+	driver->feature_mask->ctrl_pkt_id = DIAG_CTRL_MSG_FEATURE;
+	driver->feature_mask->ctrl_pkt_data_len = 4 + FEATURE_MASK_LEN_BYTES;
+	driver->feature_mask->feature_mask_len = FEATURE_MASK_LEN_BYTES;
+	memcpy(buf, driver->feature_mask, header_size);
+	feature_byte |= APPS_RESPOND_LOG_ON_DEMAND;
+	memcpy(buf+header_size, &feature_byte, FEATURE_MASK_LEN_BYTES);
+
+	if (ch) {
+		while (retry_count < 3) {
+			wr_size = smd_write(ch, buf, header_size +
+						FEATURE_MASK_LEN_BYTES);
+			if (wr_size == -ENOMEM) {
+				retry_count++;
+				for (timer = 0; timer < 5; timer++)
+					udelay(2000);
+			} else
+				break;
+		}
+		if (wr_size != header_size + FEATURE_MASK_LEN_BYTES)
+			pr_err("diag: proc %d fail feature update %d, tried %d",
+			   proc, wr_size, header_size + FEATURE_MASK_LEN_BYTES);
+	} else
+		pr_err("diag: ch invalid, feature update on proc %d\n", proc);
+	mutex_unlock(&driver->diag_cntl_mutex);
+
+}
+
 int diag_process_apps_masks(unsigned char *buf, int len)
 {
 	int packet_type = 1;
@@ -671,6 +711,16 @@
 			return 0;
 		}
 #endif
+	} else if (*buf == 0x78) {
+		if (!(driver->smd_cntl[MODEM_DATA].ch) ||
+					(driver->log_on_demand_support)) {
+			driver->apps_rsp_buf[0] = 0x78;
+			/* Copy log code received */
+			*(uint16_t *)(driver->apps_rsp_buf+1) =
+							 *(uint16_t *)buf;
+			driver->apps_rsp_buf[3] = 0x1;/* Unknown */
+			encode_rsp_and_send(3);
+		}
 	}
 
 	return  packet_type;
@@ -727,6 +777,21 @@
 			goto err;
 		kmemleak_not_leak(driver->msg_masks);
 	}
+	if (driver->buf_feature_mask_update == NULL) {
+		driver->buf_feature_mask_update = kzalloc(sizeof(
+					struct diag_ctrl_feature_mask) +
+					FEATURE_MASK_LEN_BYTES, GFP_KERNEL);
+		if (driver->buf_feature_mask_update == NULL)
+			goto err;
+		kmemleak_not_leak(driver->buf_feature_mask_update);
+	}
+	if (driver->feature_mask == NULL) {
+		driver->feature_mask = kzalloc(sizeof(
+			struct diag_ctrl_feature_mask), GFP_KERNEL);
+		if (driver->feature_mask == NULL)
+			goto err;
+		kmemleak_not_leak(driver->feature_mask);
+	}
 	diag_create_msg_mask_table();
 	diag_event_num_bytes = 0;
 	if (driver->log_masks == NULL) {
@@ -751,6 +816,8 @@
 	kfree(driver->msg_masks);
 	kfree(driver->log_masks);
 	kfree(driver->event_masks);
+	kfree(driver->feature_mask);
+	kfree(driver->buf_feature_mask_update);
 }
 
 void diag_masks_exit(void)
@@ -761,4 +828,6 @@
 	kfree(driver->msg_masks);
 	kfree(driver->log_masks);
 	kfree(driver->event_masks);
+	kfree(driver->feature_mask);
+	kfree(driver->buf_feature_mask_update);
 }
diff --git a/drivers/char/diag/diag_masks.h b/drivers/char/diag/diag_masks.h
index f144774..53f72e8 100644
--- a/drivers/char/diag/diag_masks.h
+++ b/drivers/char/diag/diag_masks.h
@@ -21,6 +21,7 @@
 					 int ssid_last, int proc);
 void diag_send_log_mask_update(smd_channel_t *, int);
 void diag_mask_update_fn(struct work_struct *work);
+void diag_send_feature_mask_update(smd_channel_t *ch, int proc);
 int diag_process_apps_masks(unsigned char *buf, int len);
 void diag_masks_init(void);
 void diag_masks_exit(void);
diff --git a/drivers/char/diag/diagchar.h b/drivers/char/diag/diagchar.h
index 8c46a5d..79f20a4 100644
--- a/drivers/char/diag/diagchar.h
+++ b/drivers/char/diag/diagchar.h
@@ -231,6 +231,7 @@
 	struct diag_ctrl_event_mask *event_mask;
 	struct diag_ctrl_log_mask *log_mask;
 	struct diag_ctrl_msg_mask *msg_mask;
+	struct diag_ctrl_feature_mask *feature_mask;
 	/* State for diag forwarding */
 	struct diag_smd_info smd_data[NUM_SMD_DATA_CHANNELS];
 	struct diag_smd_info smd_cntl[NUM_SMD_CONTROL_CHANNELS];
@@ -242,6 +243,7 @@
 	unsigned char *buf_msg_mask_update;
 	unsigned char *buf_log_mask_update;
 	unsigned char *buf_event_mask_update;
+	unsigned char *buf_feature_mask_update;
 	int read_len_legacy;
 	unsigned char *hdlc_buf;
 	unsigned hdlc_count;
@@ -259,6 +261,7 @@
 	uint8_t *log_masks;
 	int log_masks_length;
 	uint8_t *event_masks;
+	uint8_t log_on_demand_support;
 	struct diag_master_table *table;
 	uint8_t *pkt_buf;
 	int pkt_length;
@@ -318,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..f6c26c3 100644
--- a/drivers/char/diag/diagchar_core.c
+++ b/drivers/char/diag/diagchar_core.c
@@ -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)))
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/char/diag/diagfwd_cntl.c b/drivers/char/diag/diagfwd_cntl.c
index a900d97..acac2fb 100644
--- a/drivers/char/diag/diagfwd_cntl.c
+++ b/drivers/char/diag/diagfwd_cntl.c
@@ -44,6 +44,7 @@
 								int total_recd)
 {
 	int data_len = 0, type = -1, count_bytes = 0, j, flag = 0;
+	int feature_mask_len;
 	struct bindpkt_params_per_process *pkt_params =
 		kzalloc(sizeof(struct bindpkt_params_per_process), GFP_KERNEL);
 	struct diag_ctrl_msg *msg;
@@ -115,6 +116,11 @@
 				pr_err("diag: drop reg proc %d\n",
 						smd_info->peripheral);
 			kfree(temp);
+		} else if ((type == DIAG_CTRL_MSG_FEATURE) &&
+				(smd_info->peripheral == MODEM_DATA)) {
+			feature_mask_len = *(int *)(buf + 8);
+			driver->log_on_demand_support = (*(uint8_t *)
+							 (buf + 12)) & 0x04;
 		} else if (type != DIAG_CTRL_MSG_REG) {
 			flag = 1;
 		}
@@ -209,6 +215,7 @@
 
 	reg_dirty = 0;
 	driver->polling_reg_flag = 0;
+	driver->log_on_demand_support = 1;
 	driver->diag_cntl_wq = create_singlethread_workqueue("diag_cntl_wq");
 
 	success = diag_smd_constructor(&driver->smd_cntl[MODEM_DATA],
diff --git a/drivers/char/diag/diagfwd_cntl.h b/drivers/char/diag/diagfwd_cntl.h
index aeb4ba1..8d262c4 100644
--- a/drivers/char/diag/diagfwd_cntl.h
+++ b/drivers/char/diag/diagfwd_cntl.h
@@ -77,6 +77,13 @@
 	/* Copy msg mask here */
 } __packed;
 
+struct diag_ctrl_feature_mask {
+	uint32_t ctrl_pkt_id;
+	uint32_t ctrl_pkt_data_len;
+	uint32_t feature_mask_len;
+	/* Copy feature mask here */
+} __packed;
+
 void diagfwd_cntl_init(void);
 void diagfwd_cntl_exit(void);
 void diag_read_smd_cntl_work_fn(struct work_struct *);
diff --git a/drivers/cpufreq/cpufreq_ondemand.c b/drivers/cpufreq/cpufreq_ondemand.c
index 8a75cd9..4147b44 100644
--- a/drivers/cpufreq/cpufreq_ondemand.c
+++ b/drivers/cpufreq/cpufreq_ondemand.c
@@ -999,10 +999,14 @@
 	}
 
 	if (policy->cur < policy->max) {
-		policy->cur = policy->max;
+		/*
+		 * Arch specific cpufreq driver may fail.
+		 * Don't update governor frequency upon failure.
+		 */
+		if (__cpufreq_driver_target(policy, policy->max,
+					CPUFREQ_RELATION_L) >= 0)
+			policy->cur = policy->max;
 
-		__cpufreq_driver_target(policy, policy->max,
-					CPUFREQ_RELATION_L);
 		this_dbs_info->prev_cpu_idle = get_cpu_idle_time(cpu,
 				&this_dbs_info->prev_cpu_wall);
 	}
diff --git a/drivers/gpio/gpio-msm-common.c b/drivers/gpio/gpio-msm-common.c
index 150c434..3332fc5 100644
--- a/drivers/gpio/gpio-msm-common.c
+++ b/drivers/gpio/gpio-msm-common.c
@@ -24,6 +24,7 @@
 #include <linux/of.h>
 #include <linux/err.h>
 #include <linux/platform_device.h>
+#include <linux/slab.h>
 
 #include <asm/mach/irq.h>
 
@@ -48,7 +49,7 @@
 };
 #endif
 
-static int tlmm_msm_summary_irq;
+static int tlmm_msm_summary_irq, nr_direct_connect_irqs;
 
 struct tlmm_field_cfg {
 	enum msm_tlmm_register reg;
@@ -117,9 +118,9 @@
  */
 struct msm_gpio_dev {
 	struct gpio_chip gpio_chip;
-	DECLARE_BITMAP(enabled_irqs, NR_MSM_GPIOS);
-	DECLARE_BITMAP(wake_irqs, NR_MSM_GPIOS);
-	DECLARE_BITMAP(dual_edge_irqs, NR_MSM_GPIOS);
+	unsigned long *enabled_irqs;
+	unsigned long *wake_irqs;
+	unsigned long *dual_edge_irqs;
 	struct irq_domain *domain;
 };
 
@@ -207,7 +208,6 @@
 	.gpio_chip = {
 		.label		  = "msmgpio",
 		.base             = 0,
-		.ngpio            = NR_MSM_GPIOS,
 		.direction_input  = msm_gpio_direction_input,
 		.direction_output = msm_gpio_direction_output,
 		.get              = msm_gpio_get,
@@ -362,12 +362,13 @@
 	unsigned long i;
 	struct irq_desc *desc = irq_to_desc(irq);
 	struct irq_chip *chip = irq_desc_get_chip(desc);
+	int ngpio = msm_gpio.gpio_chip.ngpio;
 
 	chained_irq_enter(chip, desc);
 
-	for (i = find_first_bit(msm_gpio.enabled_irqs, NR_MSM_GPIOS);
-	     i < NR_MSM_GPIOS;
-	     i = find_next_bit(msm_gpio.enabled_irqs, NR_MSM_GPIOS, i + 1)) {
+	for (i = find_first_bit(msm_gpio.enabled_irqs, ngpio);
+	     i < ngpio;
+	     i = find_next_bit(msm_gpio.enabled_irqs, ngpio, i + 1)) {
 		if (__msm_gpio_get_intr_status(i))
 			generic_handle_irq(msm_gpio_to_irq(&msm_gpio.gpio_chip,
 							   i));
@@ -380,14 +381,15 @@
 static int msm_gpio_irq_set_wake(struct irq_data *d, unsigned int on)
 {
 	int gpio = msm_irq_to_gpio(&msm_gpio.gpio_chip, d->irq);
+	int ngpio = msm_gpio.gpio_chip.ngpio;
 
 	if (on) {
-		if (bitmap_empty(msm_gpio.wake_irqs, NR_MSM_GPIOS))
+		if (bitmap_empty(msm_gpio.wake_irqs, ngpio))
 			irq_set_irq_wake(tlmm_msm_summary_irq, 1);
 		set_bit(gpio, msm_gpio.wake_irqs);
 	} else {
 		clear_bit(gpio, msm_gpio.wake_irqs);
-		if (bitmap_empty(msm_gpio.wake_irqs, NR_MSM_GPIOS))
+		if (bitmap_empty(msm_gpio.wake_irqs, ngpio))
 			irq_set_irq_wake(tlmm_msm_summary_irq, 0);
 	}
 
@@ -412,12 +414,13 @@
 {
 	unsigned long irq_flags;
 	unsigned long i;
+	int ngpio = msm_gpio.gpio_chip.ngpio;
 
 	spin_lock_irqsave(&tlmm_lock, irq_flags);
-	for_each_set_bit(i, msm_gpio.enabled_irqs, NR_MSM_GPIOS)
+	for_each_set_bit(i, msm_gpio.enabled_irqs, ngpio)
 		__msm_gpio_set_intr_cfg_enable(i, 0);
 
-	for_each_set_bit(i, msm_gpio.wake_irqs, NR_MSM_GPIOS)
+	for_each_set_bit(i, msm_gpio.wake_irqs, ngpio)
 		__msm_gpio_set_intr_cfg_enable(i, 1);
 	mb();
 	spin_unlock_irqrestore(&tlmm_lock, irq_flags);
@@ -428,12 +431,13 @@
 {
 	unsigned long irq_flags;
 	int i, irq, intstat;
+	int ngpio = msm_gpio.gpio_chip.ngpio;
 
 	if (!msm_show_resume_irq_mask)
 		return;
 
 	spin_lock_irqsave(&tlmm_lock, irq_flags);
-	for_each_set_bit(i, msm_gpio.wake_irqs, NR_MSM_GPIOS) {
+	for_each_set_bit(i, msm_gpio.wake_irqs, ngpio) {
 		intstat = __msm_gpio_get_intr_status(i);
 		if (intstat) {
 			irq = msm_gpio_to_irq(&msm_gpio.gpio_chip, i);
@@ -448,14 +452,15 @@
 {
 	unsigned long irq_flags;
 	unsigned long i;
+	int ngpio = msm_gpio.gpio_chip.ngpio;
 
 	msm_gpio_show_resume_irq();
 
 	spin_lock_irqsave(&tlmm_lock, irq_flags);
-	for_each_set_bit(i, msm_gpio.wake_irqs, NR_MSM_GPIOS)
+	for_each_set_bit(i, msm_gpio.wake_irqs, ngpio)
 		__msm_gpio_set_intr_cfg_enable(i, 0);
 
-	for_each_set_bit(i, msm_gpio.enabled_irqs, NR_MSM_GPIOS)
+	for_each_set_bit(i, msm_gpio.enabled_irqs, ngpio)
 		__msm_gpio_set_intr_cfg_enable(i, 1);
 	mb();
 	spin_unlock_irqrestore(&tlmm_lock, irq_flags);
@@ -502,8 +507,9 @@
 int gpio_tlmm_config(unsigned config, unsigned disable)
 {
 	unsigned gpio = GPIO_PIN(config);
+	int ngpio = msm_gpio.gpio_chip.ngpio;
 
-	if (gpio > NR_MSM_GPIOS)
+	if (gpio > ngpio)
 		return -EINVAL;
 
 	__gpio_tlmm_config(config);
@@ -517,8 +523,9 @@
 					unsigned int input_polarity)
 {
 	unsigned long irq_flags;
+	int ngpio = msm_gpio.gpio_chip.ngpio;
 
-	if (gpio >= NR_MSM_GPIOS || irq >= NR_TLMM_MSM_DIR_CONN_IRQ)
+	if (gpio >= ngpio || irq >= nr_direct_connect_irqs)
 		return -EINVAL;
 
 	spin_lock_irqsave(&tlmm_lock, irq_flags);
@@ -536,37 +543,89 @@
  */
 static struct lock_class_key msm_gpio_lock_class;
 
+static inline void msm_gpio_set_irq_handler(struct device *dev)
+{
+	int irq, i;
+
+	if (!dev->of_node) {
+		for (i = 0; i < msm_gpio.gpio_chip.ngpio; ++i) {
+			irq = msm_gpio_to_irq(&msm_gpio.gpio_chip, i);
+			irq_set_lockdep_class(irq, &msm_gpio_lock_class);
+			irq_set_chip_and_handler(irq, &msm_gpio_irq_chip,
+						 handle_level_irq);
+			set_irq_flags(irq, IRQF_VALID);
+		}
+	}
+}
+
 static int __devinit msm_gpio_probe(struct platform_device *pdev)
 {
-	int ret;
-#ifndef CONFIG_OF
-	int irq, i;
-#endif
+	int ret, ngpio = 0;
+	struct msm_gpio_pdata *pdata = pdev->dev.platform_data;
+
+	if (pdev->dev.of_node) {
+		ret = of_property_read_u32(pdev->dev.of_node, "ngpio", &ngpio);
+		if (ret) {
+			pr_err("%s: Failed to find ngpio property\n", __func__);
+			return ret;
+		}
+		ret = of_property_read_u32(pdev->dev.of_node,
+					"qcom,direct-connect-irqs",
+					&nr_direct_connect_irqs);
+		if (ret) {
+			pr_err("%s: Failed to find qcom,direct-connect-irqs property\n"
+				, __func__);
+			return ret;
+		}
+	} else {
+		ngpio = pdata->ngpio;
+		nr_direct_connect_irqs = pdata->direct_connect_irqs;
+	}
+
 	tlmm_msm_summary_irq = platform_get_irq(pdev, 0);
 	if (tlmm_msm_summary_irq < 0) {
 		pr_err("%s: No interrupt defined for msmgpio\n", __func__);
 		return -ENXIO;
 	}
+
 	msm_gpio.gpio_chip.dev = &pdev->dev;
+	msm_gpio.gpio_chip.ngpio = ngpio;
 	spin_lock_init(&tlmm_lock);
-	bitmap_zero(msm_gpio.enabled_irqs, NR_MSM_GPIOS);
-	bitmap_zero(msm_gpio.wake_irqs, NR_MSM_GPIOS);
-	bitmap_zero(msm_gpio.dual_edge_irqs, NR_MSM_GPIOS);
+	msm_gpio.enabled_irqs = devm_kzalloc(&pdev->dev, sizeof(unsigned long)
+					* BITS_TO_LONGS(ngpio), GFP_KERNEL);
+	if (!msm_gpio.enabled_irqs) {
+		dev_err(&pdev->dev, "%s failed to allocated enabled_irqs bitmap\n"
+				, __func__);
+		return -ENOMEM;
+	}
+
+	msm_gpio.wake_irqs = devm_kzalloc(&pdev->dev, sizeof(unsigned long) *
+					BITS_TO_LONGS(ngpio), GFP_KERNEL);
+	if (!msm_gpio.wake_irqs) {
+		dev_err(&pdev->dev, "%s failed to allocated wake_irqs bitmap\n"
+				, __func__);
+		return -ENOMEM;
+	}
+	msm_gpio.dual_edge_irqs = devm_kzalloc(&pdev->dev, sizeof(unsigned long)
+					* BITS_TO_LONGS(ngpio), GFP_KERNEL);
+	if (!msm_gpio.dual_edge_irqs) {
+		dev_err(&pdev->dev, "%s failed to allocated dual_edge_irqs bitmap\n"
+				, __func__);
+		return -ENOMEM;
+	}
+
+	bitmap_zero(msm_gpio.enabled_irqs, ngpio);
+	bitmap_zero(msm_gpio.wake_irqs, ngpio);
+	bitmap_zero(msm_gpio.dual_edge_irqs, ngpio);
 	ret = gpiochip_add(&msm_gpio.gpio_chip);
 	if (ret < 0)
 		return ret;
 
-#ifndef CONFIG_OF
-	for (i = 0; i < msm_gpio.gpio_chip.ngpio; ++i) {
-		irq = msm_gpio_to_irq(&msm_gpio.gpio_chip, i);
-		irq_set_lockdep_class(irq, &msm_gpio_lock_class);
-		irq_set_chip_and_handler(irq, &msm_gpio_irq_chip,
-					 handle_level_irq);
-		set_irq_flags(irq, IRQF_VALID);
-	}
-#endif
-	ret = request_irq(tlmm_msm_summary_irq, msm_summary_irq_handler,
-			IRQF_TRIGGER_HIGH, "msmgpio", NULL);
+	msm_gpio_set_irq_handler(&pdev->dev);
+
+	ret = devm_request_irq(&pdev->dev, tlmm_msm_summary_irq,
+			msm_summary_irq_handler, IRQF_TRIGGER_HIGH,
+			"msmgpio", NULL);
 	if (ret) {
 		pr_err("Request_irq failed for tlmm_msm_summary_irq - %d\n",
 				ret);
@@ -658,7 +717,14 @@
 int __init msm_gpio_of_init(struct device_node *node,
 			    struct device_node *parent)
 {
-	msm_gpio.domain = irq_domain_add_linear(node, NR_MSM_GPIOS,
+	int ngpio, ret;
+
+	ret = of_property_read_u32(node, "ngpio", &ngpio);
+	if (ret) {
+		WARN(1, "Cannot get numgpios from device tree\n");
+		return ret;
+	}
+	msm_gpio.domain = irq_domain_add_linear(node, ngpio,
 			&msm_gpio_irq_domain_ops, &msm_gpio);
 	if (!msm_gpio.domain) {
 		WARN(1, "Cannot allocate irq_domain\n");
diff --git a/drivers/gpu/ion/msm/msm_ion.c b/drivers/gpu/ion/msm/msm_ion.c
index 697587b..229e775 100644
--- a/drivers/gpu/ion/msm/msm_ion.c
+++ b/drivers/gpu/ion/msm/msm_ion.c
@@ -774,10 +774,10 @@
 
 		ion_device_add_heap(idev, heaps[i]);
 	}
+	check_for_heap_overlap(pdata->heaps, num_heaps);
 	if (pdata_needs_to_be_freed)
 		free_pdata(pdata);
 
-	check_for_heap_overlap(pdata->heaps, num_heaps);
 	platform_set_drvdata(pdev, idev);
 	return 0;
 
diff --git a/drivers/gpu/msm/kgsl.c b/drivers/gpu/msm/kgsl.c
index deafa7a..9cde1d7 100644
--- a/drivers/gpu/msm/kgsl.c
+++ b/drivers/gpu/msm/kgsl.c
@@ -592,7 +592,7 @@
 	    device->state == KGSL_STATE_ACTIVE &&
 		device->requested_state == KGSL_STATE_NONE) {
 		kgsl_pwrctrl_request_state(device, KGSL_STATE_NAP);
-		kgsl_pwrscale_idle(device, 1);
+		kgsl_pwrscale_idle(device);
 		if (kgsl_pwrctrl_sleep(device) != 0)
 			mod_timer(&device->idle_timer,
 				  jiffies +
diff --git a/drivers/gpu/msm/kgsl_pwrctrl.c b/drivers/gpu/msm/kgsl_pwrctrl.c
index d33df60..73c8df1 100644
--- a/drivers/gpu/msm/kgsl_pwrctrl.c
+++ b/drivers/gpu/msm/kgsl_pwrctrl.c
@@ -1012,7 +1012,7 @@
 
 	mutex_lock(&device->mutex);
 	if (device->state & (KGSL_STATE_ACTIVE | KGSL_STATE_NAP)) {
-		kgsl_pwrscale_idle(device, 0);
+		kgsl_pwrscale_idle(device);
 
 		if (kgsl_pwrctrl_sleep(device) != 0) {
 			mod_timer(&device->idle_timer,
diff --git a/drivers/gpu/msm/kgsl_pwrscale.c b/drivers/gpu/msm/kgsl_pwrscale.c
index aad1a8d..d46f552 100644
--- a/drivers/gpu/msm/kgsl_pwrscale.c
+++ b/drivers/gpu/msm/kgsl_pwrscale.c
@@ -242,13 +242,13 @@
 					&device->pwrscale);
 }
 
-void kgsl_pwrscale_idle(struct kgsl_device *device, unsigned int ignore_idle)
+void kgsl_pwrscale_idle(struct kgsl_device *device)
 {
 	if (PWRSCALE_ACTIVE(device) && device->pwrscale.policy->idle)
 		if (device->requested_state != KGSL_STATE_SLUMBER &&
 			device->requested_state != KGSL_STATE_SLEEP)
 			device->pwrscale.policy->idle(device,
-					&device->pwrscale, ignore_idle);
+					&device->pwrscale);
 }
 EXPORT_SYMBOL(kgsl_pwrscale_idle);
 
diff --git a/drivers/gpu/msm/kgsl_pwrscale.h b/drivers/gpu/msm/kgsl_pwrscale.h
index ba9b1af..85d5b82 100644
--- a/drivers/gpu/msm/kgsl_pwrscale.h
+++ b/drivers/gpu/msm/kgsl_pwrscale.h
@@ -23,8 +23,7 @@
 	void (*close)(struct kgsl_device *device,
 		struct kgsl_pwrscale *pwrscale);
 	void (*idle)(struct kgsl_device *device,
-		struct kgsl_pwrscale *pwrscale,
-		unsigned int ignore_idle);
+		struct kgsl_pwrscale *pwrscale);
 	void (*busy)(struct kgsl_device *device,
 		struct kgsl_pwrscale *pwrscale);
 	void (*sleep)(struct kgsl_device *device,
@@ -64,8 +63,7 @@
 	struct kgsl_pwrscale_policy *policy);
 void kgsl_pwrscale_detach_policy(struct kgsl_device *device);
 
-void kgsl_pwrscale_idle(struct kgsl_device *device,
-				unsigned int ignore_idle);
+void kgsl_pwrscale_idle(struct kgsl_device *device);
 void kgsl_pwrscale_busy(struct kgsl_device *device);
 void kgsl_pwrscale_sleep(struct kgsl_device *device);
 void kgsl_pwrscale_wake(struct kgsl_device *device);
diff --git a/drivers/gpu/msm/kgsl_pwrscale_idlestats.c b/drivers/gpu/msm/kgsl_pwrscale_idlestats.c
index fc58dd1..cd432c6 100644
--- a/drivers/gpu/msm/kgsl_pwrscale_idlestats.c
+++ b/drivers/gpu/msm/kgsl_pwrscale_idlestats.c
@@ -131,7 +131,7 @@
 }
 
 static void idlestats_idle(struct kgsl_device *device,
-		struct kgsl_pwrscale *pwrscale, unsigned int ignore_idle)
+		struct kgsl_pwrscale *pwrscale)
 {
 	int i, nr_cpu;
 	struct idlestats_priv *priv = pwrscale->priv;
diff --git a/drivers/gpu/msm/kgsl_pwrscale_msm.c b/drivers/gpu/msm/kgsl_pwrscale_msm.c
index c680d57..073e474 100644
--- a/drivers/gpu/msm/kgsl_pwrscale_msm.c
+++ b/drivers/gpu/msm/kgsl_pwrscale_msm.c
@@ -132,7 +132,7 @@
 }
 
 static void msm_idle(struct kgsl_device *device,
-		struct kgsl_pwrscale *pwrscale, unsigned int ignore_idle)
+		struct kgsl_pwrscale *pwrscale)
 {
 	struct msm_priv *priv = pwrscale->priv;
 
diff --git a/drivers/gpu/msm/kgsl_pwrscale_trustzone.c b/drivers/gpu/msm/kgsl_pwrscale_trustzone.c
index e01932b..3e81e56 100644
--- a/drivers/gpu/msm/kgsl_pwrscale_trustzone.c
+++ b/drivers/gpu/msm/kgsl_pwrscale_trustzone.c
@@ -30,9 +30,14 @@
 	int governor;
 	unsigned int no_switch_cnt;
 	unsigned int skip_cnt;
+	struct kgsl_power_stats bin;
 };
 spinlock_t tz_lock;
 
+/* FLOOR is 5msec to capture up to 3 re-draws
+ * per frame for 60fps content.
+ */
+#define FLOOR			5000
 #define SWITCH_OFF		200
 #define SWITCH_OFF_RESET_TH	40
 #define SKIP_COUNTER		500
@@ -119,24 +124,27 @@
 					device->pwrctrl.default_pwrlevel);
 }
 
-static void tz_idle(struct kgsl_device *device, struct kgsl_pwrscale *pwrscale,
-						unsigned int ignore_idle)
+static void tz_idle(struct kgsl_device *device, struct kgsl_pwrscale *pwrscale)
 {
 	struct kgsl_pwrctrl *pwr = &device->pwrctrl;
 	struct tz_priv *priv = pwrscale->priv;
 	struct kgsl_power_stats stats;
 	int val, idle;
 
-	if (ignore_idle)
-		return;
-
 	/* In "performance" mode the clock speed always stays
 	   the same */
 	if (priv->governor == TZ_GOVERNOR_PERFORMANCE)
 		return;
 
 	device->ftbl->power_stats(device, &stats);
-	if (stats.total_time == 0)
+	priv->bin.total_time += stats.total_time;
+	priv->bin.busy_time += stats.busy_time;
+	/* Do not waste CPU cycles running this algorithm if
+	 * the GPU just started, or if less than FLOOR time
+	 * has passed since the last run.
+	 */
+	if ((stats.total_time == 0) ||
+		(priv->bin.total_time < FLOOR))
 		return;
 
 	/* If the GPU has stayed in turbo mode for a while, *
@@ -155,7 +163,9 @@
 		priv->no_switch_cnt = 0;
 	}
 
-	idle = stats.total_time - stats.busy_time;
+	idle = priv->bin.total_time - priv->bin.busy_time;
+	priv->bin.total_time = 0;
+	priv->bin.busy_time = 0;
 	idle = (idle > 0) ? idle : 0;
 	val = __secure_tz_entry(TZ_UPDATE_ID, idle, device->id);
 	if (val)
@@ -176,6 +186,8 @@
 
 	__secure_tz_entry(TZ_RESET_ID, 0, device->id);
 	priv->no_switch_cnt = 0;
+	priv->bin.total_time = 0;
+	priv->bin.busy_time = 0;
 }
 
 #ifdef CONFIG_MSM_SCM
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/hwmon/qpnp-adc-common.c b/drivers/hwmon/qpnp-adc-common.c
index 440dc42..bde18d4 100644
--- a/drivers/hwmon/qpnp-adc-common.c
+++ b/drivers/hwmon/qpnp-adc-common.c
@@ -130,175 +130,6 @@
 	{790,	203}
 };
 
-static const struct qpnp_vadc_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},
-	{886,		102400},
-	{859,		103424},
-	{832,		104448},
-	{807,		105472},
-	{782,		106496},
-	{756,		107520},
-	{735,		108544},
-	{712,		109568},
-	{691,		110592},
-	{670,		111616},
-	{650,		112640},
-	{631,		113664},
-	{612,		114688},
-	{594,		115712},
-	{577,		116736},
-	{560,		117760},
-	{544,		118784},
-	{528,		119808},
-	{513,		120832},
-	{498,		121856},
-	{483,		122880},
-	{470,		123904},
-	{457,		124928},
-	{444,		125952},
-	{431,		126976},
-	{419,		128000}
-};
-
 /* Voltage to temperature */
 static const struct qpnp_vadc_map_pt adcmap_100k_104ef_104fb[] = {
 	{1758,	-40},
@@ -553,9 +384,9 @@
 
 	xo_thm = qpnp_adc_scale_ratiometric_calib(adc_code,
 			adc_properties, chan_properties);
-	xo_thm <<= 4;
-	qpnp_adc_map_voltage_temp(adcmap_ntcg_104ef_104fb,
-		ARRAY_SIZE(adcmap_ntcg_104ef_104fb),
+
+	qpnp_adc_map_voltage_temp(adcmap_100k_104ef_104fb,
+		ARRAY_SIZE(adcmap_100k_104ef_104fb),
 		xo_thm, &adc_chan_result->physical);
 
 	return 0;
diff --git a/drivers/hwmon/qpnp-adc-current.c b/drivers/hwmon/qpnp-adc-current.c
index 8071687e..c28c61d 100644
--- a/drivers/hwmon/qpnp-adc-current.c
+++ b/drivers/hwmon/qpnp-adc-current.c
@@ -171,6 +171,51 @@
 	return 0;
 }
 
+static void trigger_iadc_completion(struct work_struct *work)
+{
+	struct qpnp_iadc_drv *iadc = qpnp_iadc;
+
+	if (!iadc || !iadc->iadc_initialized)
+		return;
+
+	complete(&iadc->adc->adc_rslt_completion);
+
+	return;
+}
+DECLARE_WORK(trigger_iadc_completion_work, trigger_iadc_completion);
+
+static irqreturn_t qpnp_iadc_isr(int irq, void *dev_id)
+{
+	schedule_work(&trigger_iadc_completion_work);
+
+	return IRQ_HANDLED;
+}
+
+static int32_t qpnp_iadc_enable(bool state)
+{
+	int rc = 0;
+	u8 data = 0;
+
+	data = QPNP_IADC_ADC_EN;
+	if (state) {
+		rc = qpnp_iadc_write_reg(QPNP_IADC_EN_CTL1,
+					data);
+		if (rc < 0) {
+			pr_err("IADC enable failed\n");
+			return rc;
+		}
+	} else {
+		rc = qpnp_iadc_write_reg(QPNP_IADC_EN_CTL1,
+					(~data & QPNP_IADC_ADC_EN));
+		if (rc < 0) {
+			pr_err("IADC disable failed\n");
+			return rc;
+		}
+	}
+
+	return 0;
+}
+
 static int32_t qpnp_iadc_status_debug(void)
 {
 	int rc = 0;
@@ -209,46 +254,10 @@
 	pr_err("EOC not set with status:%x, dig:%x, ch:%x, mode:%x, en:%x\n",
 			status1, dig, chan, mode, en);
 
-	return 0;
-}
-
-static void trigger_iadc_completion(struct work_struct *work)
-{
-	struct qpnp_iadc_drv *iadc = qpnp_iadc;
-
-	complete(&iadc->adc->adc_rslt_completion);
-
-	return;
-}
-DECLARE_WORK(trigger_iadc_completion_work, trigger_iadc_completion);
-
-static irqreturn_t qpnp_iadc_isr(int irq, void *dev_id)
-{
-	schedule_work(&trigger_iadc_completion_work);
-
-	return IRQ_HANDLED;
-}
-
-static int32_t qpnp_iadc_enable(bool state)
-{
-	int rc = 0;
-	u8 data = 0;
-
-	data = QPNP_IADC_ADC_EN;
-	if (state) {
-		rc = qpnp_iadc_write_reg(QPNP_IADC_EN_CTL1,
-					data);
-		if (rc < 0) {
-			pr_err("IADC enable failed\n");
-			return rc;
-		}
-	} else {
-		rc = qpnp_iadc_write_reg(QPNP_IADC_EN_CTL1,
-					(~data & QPNP_IADC_ADC_EN));
-		if (rc < 0) {
-			pr_err("IADC disable failed\n");
-			return rc;
-		}
+	rc = qpnp_iadc_enable(false);
+	if (rc < 0) {
+		pr_err("IADC disable failed with %d\n", rc);
+		return rc;
 	}
 
 	return 0;
@@ -721,7 +730,8 @@
 			GFP_KERNEL);
 	if (!adc_qpnp) {
 		dev_err(&spmi->dev, "Unable to allocate memory\n");
-		return -ENOMEM;
+		rc = -ENOMEM;
+		goto fail;
 	}
 
 	iadc->adc = adc_qpnp;
@@ -729,14 +739,14 @@
 	rc = qpnp_adc_get_devicetree_data(spmi, iadc->adc);
 	if (rc) {
 		dev_err(&spmi->dev, "failed to read device tree\n");
-		return rc;
+		goto fail;
 	}
 
 	rc = of_property_read_u32(node, "qcom,rsense",
 			&iadc->rsense);
 	if (rc) {
 		pr_err("Invalid rsens reference property\n");
-		return -EINVAL;
+		goto fail;
 	}
 
 	rc = devm_request_irq(&spmi->dev, iadc->adc->adc_irq_eoc,
@@ -744,7 +754,7 @@
 	IRQF_TRIGGER_RISING, "qpnp_iadc_interrupt", iadc);
 	if (rc) {
 		dev_err(&spmi->dev, "failed to request adc irq\n");
-		return rc;
+		goto fail;
 	} else
 		enable_irq_wake(iadc->adc->adc_irq_eoc);
 
@@ -755,20 +765,20 @@
 	rc = qpnp_iadc_init_hwmon(spmi);
 	if (rc) {
 		dev_err(&spmi->dev, "failed to initialize qpnp hwmon adc\n");
-		return rc;
+		goto fail;
 	}
 	iadc->iadc_hwmon = hwmon_device_register(&iadc->adc->spmi->dev);
 
 	rc = qpnp_iadc_version_check();
 	if (rc) {
 		dev_err(&spmi->dev, "IADC version not supported\n");
-		return rc;
+		goto fail;
 	}
 
 	rc = qpnp_iadc_calibrate_for_trim();
 	if (rc) {
 		dev_err(&spmi->dev, "failed to calibrate for USR trim\n");
-		return rc;
+		goto fail;
 	}
 	iadc->iadc_init_calib = true;
 	INIT_DELAYED_WORK(&iadc->iadc_work, qpnp_iadc_work);
@@ -778,6 +788,9 @@
 	iadc->iadc_initialized = true;
 
 	return 0;
+fail:
+	qpnp_iadc = NULL;
+	return rc;
 }
 
 static int __devexit qpnp_iadc_remove(struct spmi_device *spmi)
diff --git a/drivers/hwmon/qpnp-adc-voltage.c b/drivers/hwmon/qpnp-adc-voltage.c
index d8d5b53..3df19d7 100644
--- a/drivers/hwmon/qpnp-adc-voltage.c
+++ b/drivers/hwmon/qpnp-adc-voltage.c
@@ -170,6 +170,58 @@
 	return 0;
 }
 
+static int32_t qpnp_vadc_status_debug(void)
+{
+	int rc = 0;
+	u8 mode = 0, status1 = 0, chan = 0, dig = 0, en = 0, status2 = 0;
+
+	rc = qpnp_vadc_read_reg(QPNP_VADC_MODE_CTL, &mode);
+	if (rc < 0) {
+		pr_err("mode ctl register read failed with %d\n", rc);
+		return rc;
+	}
+
+	rc = qpnp_vadc_read_reg(QPNP_VADC_ADC_DIG_PARAM, &dig);
+	if (rc < 0) {
+		pr_err("digital param read failed with %d\n", rc);
+		return rc;
+	}
+
+	rc = qpnp_vadc_read_reg(QPNP_VADC_ADC_CH_SEL_CTL, &chan);
+	if (rc < 0) {
+		pr_err("channel read failed with %d\n", rc);
+		return rc;
+	}
+
+	rc = qpnp_vadc_read_reg(QPNP_VADC_STATUS1, &status1);
+	if (rc < 0) {
+		pr_err("status1 read failed with %d\n", rc);
+		return rc;
+	}
+
+	rc = qpnp_vadc_read_reg(QPNP_VADC_STATUS2, &status2);
+	if (rc < 0) {
+		pr_err("status2 read failed with %d\n", rc);
+		return rc;
+	}
+
+	rc = qpnp_vadc_read_reg(QPNP_VADC_EN_CTL1, &en);
+	if (rc < 0) {
+		pr_err("en read failed with %d\n", rc);
+		return rc;
+	}
+
+	pr_err("EOC not set - status1/2:%x/%x, dig:%x, ch:%x, mode:%x, en:%x\n",
+			status1, status2, dig, chan, mode, en);
+
+	rc = qpnp_vadc_enable(false);
+	if (rc < 0) {
+		pr_err("VADC disable failed with %d\n", rc);
+		return rc;
+	}
+
+	return 0;
+}
 static int32_t qpnp_vadc_configure(
 			struct qpnp_adc_amux_properties *chan_prop)
 {
@@ -339,6 +391,9 @@
 {
 	struct qpnp_vadc_drv *vadc = qpnp_vadc;
 
+	if (!vadc || !vadc->vadc_initialized)
+		return;
+
 	complete(&vadc->adc->adc_rslt_completion);
 
 	return;
@@ -563,20 +618,21 @@
 	if (!vadc || !vadc->vadc_initialized)
 		return -EPROBE_DEFER;
 
+	mutex_lock(&vadc->adc->adc_lock);
+
 	if (!vadc->vadc_init_calib) {
 		rc = qpnp_vadc_version_check();
 		if (rc)
-			return rc;
+			goto fail_unlock;
+
 		rc = qpnp_vadc_calib_device();
 		if (rc) {
 			pr_err("Calibration failed\n");
-			return rc;
+			goto fail_unlock;
 		} else
 			vadc->vadc_init_calib = true;
 	}
 
-	mutex_lock(&vadc->adc->adc_lock);
-
 	vadc->adc->amux_prop->amux_channel = channel;
 
 	while ((vadc->adc->adc_channels[dt_index].channel_num
@@ -626,7 +682,9 @@
 		if (status1 == QPNP_VADC_STATUS1_EOC)
 			pr_debug("End of conversion status set\n");
 		else {
-			pr_err("EOC interrupt not received\n");
+			rc = qpnp_vadc_status_debug();
+			if (rc < 0)
+				pr_err("VADC disable failed\n");
 			rc = -EINVAL;
 			goto fail_unlock;
 		}
@@ -765,7 +823,8 @@
 			GFP_KERNEL);
 	if (!adc_qpnp) {
 		dev_err(&spmi->dev, "Unable to allocate memory\n");
-		return -ENOMEM;
+		rc = -ENOMEM;
+		goto fail;
 	}
 
 	vadc->adc = adc_qpnp;
@@ -773,7 +832,7 @@
 	rc = qpnp_adc_get_devicetree_data(spmi, vadc->adc);
 	if (rc) {
 		dev_err(&spmi->dev, "failed to read device tree\n");
-		return rc;
+		goto fail;
 	}
 
 	rc = devm_request_irq(&spmi->dev, vadc->adc->adc_irq_eoc,
@@ -782,7 +841,7 @@
 	if (rc) {
 		dev_err(&spmi->dev,
 			"failed to request adc irq with error %d\n", rc);
-		return rc;
+		goto fail;
 	} else {
 		enable_irq_wake(vadc->adc->adc_irq_eoc);
 	}
@@ -792,7 +851,7 @@
 	rc = qpnp_vadc_init_hwmon(spmi);
 	if (rc) {
 		dev_err(&spmi->dev, "failed to initialize qpnp hwmon adc\n");
-		return rc;
+		goto fail;
 	}
 	vadc->vadc_hwmon = hwmon_device_register(&vadc->adc->spmi->dev);
 	vadc->vadc_init_calib = false;
@@ -800,6 +859,9 @@
 	vadc->vadc_initialized = true;
 
 	return 0;
+fail:
+	qpnp_vadc = NULL;
+	return rc;
 }
 
 static int __devexit qpnp_vadc_remove(struct spmi_device *spmi)
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.c b/drivers/iommu/msm_iommu.c
index 1ce1cf8..38e6fb7 100644
--- a/drivers/iommu/msm_iommu.c
+++ b/drivers/iommu/msm_iommu.c
@@ -428,7 +428,7 @@
 
 	if (!priv || !dev) {
 		ret = -EINVAL;
-		goto fail;
+		goto unlock;
 	}
 
 	iommu_drvdata = dev_get_drvdata(dev->parent);
@@ -436,23 +436,28 @@
 
 	if (!iommu_drvdata || !ctx_drvdata) {
 		ret = -EINVAL;
-		goto fail;
+		goto unlock;
 	}
 
+	++ctx_drvdata->attach_count;
+
+	if (ctx_drvdata->attach_count > 1)
+		goto unlock;
+
 	if (!list_empty(&ctx_drvdata->attached_elm)) {
 		ret = -EBUSY;
-		goto fail;
+		goto unlock;
 	}
 
 	list_for_each_entry(tmp_drvdata, &priv->list_attached, attached_elm)
 		if (tmp_drvdata == ctx_drvdata) {
 			ret = -EBUSY;
-			goto fail;
+			goto unlock;
 		}
 
 	ret = __enable_clocks(iommu_drvdata);
 	if (ret)
-		goto fail;
+		goto unlock;
 
 	__program_context(iommu_drvdata->base, iommu_drvdata->glb_base,
 			  ctx_drvdata->num, iommu_drvdata->ncb,
@@ -463,7 +468,7 @@
 	list_add(&(ctx_drvdata->attached_elm), &priv->list_attached);
 
 	ctx_drvdata->attached_domain = domain;
-fail:
+unlock:
 	mutex_unlock(&msm_iommu_lock);
 	return ret;
 }
@@ -472,7 +477,6 @@
 				 struct device *dev)
 {
 	struct msm_priv *priv;
-	struct msm_iommu_ctx_dev *ctx_dev;
 	struct msm_iommu_drvdata *iommu_drvdata;
 	struct msm_iommu_ctx_drvdata *ctx_drvdata;
 	int ret;
@@ -481,33 +485,38 @@
 	priv = domain->priv;
 
 	if (!priv || !dev)
-		goto fail;
+		goto unlock;
 
 	iommu_drvdata = dev_get_drvdata(dev->parent);
 	ctx_drvdata = dev_get_drvdata(dev);
-	ctx_dev = dev->platform_data;
 
-	if (!iommu_drvdata || !ctx_drvdata || !ctx_dev)
-		goto fail;
+	if (!iommu_drvdata || !ctx_drvdata)
+		goto unlock;
+
+	--ctx_drvdata->attach_count;
+	BUG_ON(ctx_drvdata->attach_count < 0);
+
+	if (ctx_drvdata->attach_count > 0)
+		goto unlock;
 
 	ret = __enable_clocks(iommu_drvdata);
 	if (ret)
-		goto fail;
+		goto unlock;
 
 	msm_iommu_remote_spin_lock();
 
-	SET_TLBIASID(iommu_drvdata->base, ctx_dev->num,
-		     GET_CONTEXTIDR_ASID(iommu_drvdata->base, ctx_dev->num));
+	SET_TLBIASID(iommu_drvdata->base, ctx_drvdata->num,
+		    GET_CONTEXTIDR_ASID(iommu_drvdata->base, ctx_drvdata->num));
 
 	__reset_context(iommu_drvdata->base, iommu_drvdata->glb_base,
-			ctx_dev->num);
+			ctx_drvdata->num);
 
 	msm_iommu_remote_spin_unlock();
 
 	__disable_clocks(iommu_drvdata);
 	list_del_init(&ctx_drvdata->attached_elm);
 	ctx_drvdata->attached_domain = NULL;
-fail:
+unlock:
 	mutex_unlock(&msm_iommu_lock);
 }
 
diff --git a/drivers/iommu/msm_iommu_dev.c b/drivers/iommu/msm_iommu_dev.c
index 44fe454..470d8ce 100644
--- a/drivers/iommu/msm_iommu_dev.c
+++ b/drivers/iommu/msm_iommu_dev.c
@@ -489,6 +489,7 @@
 	ctx_drvdata->pdev = pdev;
 	INIT_LIST_HEAD(&ctx_drvdata->attached_elm);
 	platform_set_drvdata(pdev, ctx_drvdata);
+	ctx_drvdata->attach_count = 0;
 
 	if (pdev->dev.of_node) {
 		ret = msm_iommu_ctx_parse_dt(pdev, ctx_drvdata);
diff --git a/drivers/media/dvb/dvb-core/demux.h b/drivers/media/dvb/dvb-core/demux.h
index ed657d7..042ba37 100644
--- a/drivers/media/dvb/dvb-core/demux.h
+++ b/drivers/media/dvb/dvb-core/demux.h
@@ -64,14 +64,15 @@
 
 enum dmx_success {
 	DMX_OK = 0, /* Received Ok */
-	DMX_OK_PES_END, /* Received ok, data reached end of PES packet */
+	DMX_OK_PES_END, /* Received OK, data reached end of PES packet */
 	DMX_OK_PCR, /* Received OK, data with new PCR/STC pair */
 	DMX_LENGTH_ERROR, /* Incorrect length */
 	DMX_OVERRUN_ERROR, /* Receiver ring buffer overrun */
 	DMX_CRC_ERROR, /* Incorrect CRC */
 	DMX_FRAME_ERROR, /* Frame alignment error */
 	DMX_FIFO_ERROR, /* Receiver FIFO overrun */
-	DMX_MISSED_ERROR /* Receiver missed packet */
+	DMX_MISSED_ERROR, /* Receiver missed packet */
+	DMX_OK_DECODER_BUF /* Received OK, new ES data in decoder buffer */
 } ;
 
 
@@ -106,6 +107,21 @@
 			u64 stc;
 			int disc_indicator_set;
 		} pcr;
+
+		struct {
+			int handle;
+			int cookie;
+			u32 offset;
+			u32 len;
+			int pts_exists;
+			u64 pts;
+			int dts_exists;
+			u64 dts;
+			u32 tei_counter;
+			u32 cont_err_counter;
+			u32 ts_packets_num;
+			u32 ts_dropped_bytes;
+		} buf;
 	};
 };
 
@@ -202,6 +218,9 @@
 	int (*get_decoder_buff_status)(
 			struct dmx_ts_feed *feed,
 			struct dmx_buffer_status *dmx_buffer_status);
+	int (*reuse_decoder_buffer)(
+			struct dmx_ts_feed *feed,
+			int cookie);
 	int (*data_ready_cb)(struct dmx_ts_feed *feed,
 			dmx_ts_data_ready_cb callback);
 	int (*notify_data_read)(struct dmx_ts_feed *feed,
diff --git a/drivers/media/dvb/dvb-core/dmxdev.c b/drivers/media/dvb/dvb-core/dmxdev.c
index e956170..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
@@ -1395,6 +1395,29 @@
 	return 0;
 }
 
+static int dvb_dmxdev_reuse_decoder_buf(struct dmxdev_filter *dmxdevfilter,
+						int cookie)
+{
+	if ((dmxdevfilter->type == DMXDEV_TYPE_PES) &&
+		(dmxdevfilter->params.pes.output == DMX_OUT_DECODER)) {
+		struct dmxdev_feed *feed;
+		int ret = -ENODEV;
+
+		/* Only one feed should be in the list in case of decoder */
+		feed = list_first_entry(&dmxdevfilter->feed.ts,
+					struct dmxdev_feed, next);
+
+		if (feed->ts->reuse_decoder_buffer)
+			ret = feed->ts->reuse_decoder_buffer(
+							feed->ts,
+							cookie);
+
+		return ret;
+	}
+
+	return -EPERM;
+}
+
 static int dvb_dmxdev_ts_fullness_callback(
 				struct dmx_ts_feed *filter,
 				int required_space)
@@ -1535,9 +1558,12 @@
 {
 	struct dvb_ringbuffer *buf = &dmxdevfilter->buffer;
 
-
-	spin_lock_irq(&dmxdevfilter->dev->lock);
-
+	/*
+	 * Note: Taking the dmxdevfilter->dev->lock spinlock is required only
+	 * when getting the status of the Demux-userspace data ringbuffer .
+	 * In case we are getting the status of a decoder buffer, taking this
+	 * spinlock is not required and in fact might lead to a deadlock.
+	 */
 	if ((dmxdevfilter->type == DMXDEV_TYPE_PES) &&
 		(dmxdevfilter->params.pes.output == DMX_OUT_DECODER)) {
 		struct dmxdev_feed *feed;
@@ -1555,10 +1581,11 @@
 		else
 			ret = -ENODEV;
 
-		spin_unlock_irq(&dmxdevfilter->dev->lock);
 		return ret;
 	}
 
+	spin_lock_irq(&dmxdevfilter->dev->lock);
+
 	if (!buf->data) {
 		spin_unlock_irq(&dmxdevfilter->dev->lock);
 		return -EINVAL;
@@ -1629,6 +1656,10 @@
 	spin_lock_irq(&dmxdevfilter->dev->lock);
 
 	res = dvb_dmxdev_remove_event(&dmxdevfilter->events, event);
+	if (res) {
+		spin_unlock_irq(&dmxdevfilter->dev->lock);
+		return res;
+	}
 
 	if (event->type == DMX_EVENT_BUFFER_OVERFLOW) {
 		/*
@@ -1645,6 +1676,15 @@
 		dmxdevfilter->buffer.error = 0;
 	}
 
+	/*
+	 * Decoder filters have no data in the data buffer and their
+	 * events can be removed now from the queue.
+	 */
+	if (dmxdevfilter->params.pes.output == DMX_OUT_DECODER)
+		dmxdevfilter->events.read_index =
+			dvb_dmxdev_advance_event_idx(
+				dmxdevfilter->events.read_index);
+
 	spin_unlock_irq(&dmxdevfilter->dev->lock);
 
 	/*
@@ -1980,7 +2020,7 @@
 		event.params.pcr.stc = dmx_data_ready->pcr.stc;
 		if (dmx_data_ready->pcr.disc_indicator_set)
 			event.params.pcr.flags =
-				DMX_FILTER_DISCONTINUITY_INDEICATOR;
+				DMX_FILTER_DISCONTINUITY_INDICATOR;
 		else
 			event.params.pcr.flags = 0;
 
@@ -1990,6 +2030,30 @@
 		return 0;
 	}
 
+	if (dmx_data_ready->status == DMX_OK_DECODER_BUF) {
+		event.type = DMX_EVENT_NEW_ES_DATA;
+		event.params.es_data.buf_handle = dmx_data_ready->buf.handle;
+		event.params.es_data.cookie = dmx_data_ready->buf.cookie;
+		event.params.es_data.offset = dmx_data_ready->buf.offset;
+		event.params.es_data.data_len = dmx_data_ready->buf.len;
+		event.params.es_data.pts_valid = dmx_data_ready->buf.pts_exists;
+		event.params.es_data.pts = dmx_data_ready->buf.pts;
+		event.params.es_data.dts_valid = dmx_data_ready->buf.dts_exists;
+		event.params.es_data.dts = dmx_data_ready->buf.dts;
+		event.params.es_data.transport_error_indicator_counter =
+				dmx_data_ready->buf.tei_counter;
+		event.params.es_data.continuity_error_counter =
+				dmx_data_ready->buf.cont_err_counter;
+		event.params.es_data.ts_packets_num =
+				dmx_data_ready->buf.ts_packets_num;
+		event.params.es_data.ts_dropped_bytes =
+				dmx_data_ready->buf.ts_dropped_bytes;
+		dvb_dmxdev_add_event(events, &event);
+		spin_unlock(&dmxdevfilter->dev->lock);
+		wake_up_all(&buffer->queue);
+		return 0;
+	}
+
 	if ((dmxdevfilter->params.pes.output == DMX_OUT_DECODER) ||
 		(buffer->error)) {
 		spin_unlock(&dmxdevfilter->dev->lock);
@@ -2038,7 +2102,7 @@
 			event.params.pes.flags = 0;
 			if (dmx_data_ready->pes_end.disc_indicator_set)
 				event.params.pes.flags |=
-					DMX_FILTER_DISCONTINUITY_INDEICATOR;
+					DMX_FILTER_DISCONTINUITY_INDICATOR;
 			if (dmx_data_ready->pes_end.pes_length_mismatch)
 				event.params.pes.flags |=
 					DMX_FILTER_PES_LENGTH_ERROR;
@@ -2191,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);
@@ -2268,6 +2333,7 @@
 			dmxdev->dvr_feed = filter;
 		dmxdev->dvr_feeds_count++;
 	} else if (filter->params.pes.output == DMX_OUT_DECODER) {
+		tsfeed->buffer.ringbuff = &filter->buffer;
 		tsfeed->decoder_buffers = &filter->decoder_buffers;
 		tsfeed->buffer.priv_handle = filter->priv_buff_handle;
 	} else {
@@ -2535,11 +2601,8 @@
 			vfree(mem);
 	}
 
-	/* Decoder filters do not map buffers via priv_buff_handle */
-	if ((DMXDEV_TYPE_PES == dmxdevfilter->type) &&
-		(DMX_OUT_DECODER != dmxdevfilter->params.pes.output) &&
-		(dmxdevfilter->buffer_mode == DMX_BUFFER_MODE_EXTERNAL) &&
-		(dmxdevfilter->priv_buff_handle)) {
+	if ((dmxdevfilter->buffer_mode == DMX_BUFFER_MODE_EXTERNAL) &&
+		dmxdevfilter->priv_buff_handle) {
 		dmxdev->demux->unmap_buffer(dmxdev->demux,
 			dmxdevfilter->priv_buff_handle);
 		dmxdevfilter->priv_buff_handle = NULL;
@@ -3017,6 +3080,15 @@
 		mutex_unlock(&dmxdevfilter->mutex);
 		break;
 
+	case DMX_REUSE_DECODER_BUFFER:
+		if (mutex_lock_interruptible(&dmxdevfilter->mutex)) {
+			mutex_unlock(&dmxdev->mutex);
+			return -ERESTARTSYS;
+		}
+		ret = dvb_dmxdev_reuse_decoder_buf(dmxdevfilter, arg);
+		mutex_unlock(&dmxdevfilter->mutex);
+		break;
+
 	default:
 		ret = -EINVAL;
 		break;
@@ -3283,25 +3355,27 @@
 
 			seq_printf(s, "filter_%02d - ", i);
 
-		    if (filter->type == DMXDEV_TYPE_SEC) {
+			if (filter->type == DMXDEV_TYPE_SEC) {
 				seq_printf(s, "type: SEC, ");
 				seq_printf(s, "PID %04d ",
 						filter->params.sec.pid);
-		    } else {
+			} else {
 				seq_printf(s, "type: %s, ",
 					pes_feeds[filter->params.pes.output]);
 				seq_printf(s, "PID: %04d ",
 						filter->params.pes.pid);
-		    }
+			}
 
 			if (0 == dvb_dmxdev_get_buffer_status(
 						filter, &buffer_status)) {
-				seq_printf(s, "buffer size: %08d, ",
+				seq_printf(s, "size: %08d, ",
 					buffer_status.size);
-				seq_printf(s, "buffer fullness: %08d\n",
+				seq_printf(s, "fullness: %08d, ",
 					buffer_status.fullness);
-				seq_printf(s, "buffer error: %08d\n",
+				seq_printf(s, "error: %d\n",
 					buffer_status.error);
+			} else {
+				seq_printf(s, "\n");
 			}
 		}
 	}
@@ -3309,8 +3383,6 @@
 	if (!active_count)
 		seq_printf(s, "No active filters\n");
 
-	seq_printf(s, "\n");
-
 	return 0;
 }
 
diff --git a/drivers/media/dvb/dvb-core/dvb_demux.c b/drivers/media/dvb/dvb-core/dvb_demux.c
index 978cb38d..eea83c2 100644
--- a/drivers/media/dvb/dvb-core/dvb_demux.c
+++ b/drivers/media/dvb/dvb-core/dvb_demux.c
@@ -1128,21 +1128,47 @@
 	struct dvb_demux *demux = feed->demux;
 	int ret;
 
-	spin_lock_irq(&demux->lock);
+	mutex_lock(&demux->mutex);
 
 	if (feed->state < DMX_STATE_GO) {
-		spin_unlock_irq(&demux->lock);
+		mutex_unlock(&demux->mutex);
 		return -EINVAL;
 	}
 
 	if (!demux->decoder_buffer_status) {
-		spin_unlock_irq(&demux->lock);
+		mutex_unlock(&demux->mutex);
 		return -ENODEV;
 	}
 
 	ret = demux->decoder_buffer_status(feed, dmx_buffer_status);
 
-	spin_unlock_irq(&demux->lock);
+	mutex_unlock(&demux->mutex);
+
+	return ret;
+}
+
+static int dmx_ts_feed_reuse_decoder_buffer(struct dmx_ts_feed *ts_feed,
+						int cookie)
+{
+	struct dvb_demux_feed *feed = (struct dvb_demux_feed *)ts_feed;
+	struct dvb_demux *demux = feed->demux;
+	int ret;
+
+	mutex_lock(&demux->mutex);
+
+	if (feed->state < DMX_STATE_GO) {
+		mutex_unlock(&demux->mutex);
+		return -EINVAL;
+	}
+
+	if (!demux->reuse_decoder_buffer) {
+		mutex_unlock(&demux->mutex);
+		return -ENODEV;
+	}
+
+	ret = demux->reuse_decoder_buffer(feed, cookie);
+
+	mutex_unlock(&demux->mutex);
 
 	return ret;
 }
@@ -1239,6 +1265,7 @@
 	(*ts_feed)->set_indexing_params = dmx_ts_set_indexing_params;
 	(*ts_feed)->set_tsp_out_format = dmx_ts_set_tsp_out_format;
 	(*ts_feed)->get_decoder_buff_status = dmx_ts_feed_decoder_buff_status;
+	(*ts_feed)->reuse_decoder_buffer = dmx_ts_feed_reuse_decoder_buffer;
 	(*ts_feed)->data_ready_cb = dmx_ts_feed_data_ready_cb;
 	(*ts_feed)->notify_data_read = NULL;
 
diff --git a/drivers/media/dvb/dvb-core/dvb_demux.h b/drivers/media/dvb/dvb-core/dvb_demux.h
index f89367b..2e4a468 100644
--- a/drivers/media/dvb/dvb-core/dvb_demux.h
+++ b/drivers/media/dvb/dvb-core/dvb_demux.h
@@ -127,6 +127,8 @@
 	int (*decoder_fullness_abort)(struct dvb_demux_feed *feed);
 	int (*decoder_buffer_status)(struct dvb_demux_feed *feed,
 				struct dmx_buffer_status *dmx_buffer_status);
+	int (*reuse_decoder_buffer)(struct dvb_demux_feed *feed,
+				int cookie);
 	u32 (*check_crc32)(struct dvb_demux_feed *feed,
 			    const u8 *buf, size_t len);
 	void (*memcopy)(struct dvb_demux_feed *feed, u8 *dst,
diff --git a/drivers/media/dvb/mpq/demux/mpq_dmx_plugin_common.c b/drivers/media/dvb/mpq/demux/mpq_dmx_plugin_common.c
index 94fa1b7..4b67477 100644
--- a/drivers/media/dvb/mpq/demux/mpq_dmx_plugin_common.c
+++ b/drivers/media/dvb/mpq/demux/mpq_dmx_plugin_common.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+/* 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
@@ -39,10 +39,18 @@
 static int mpq_demux_device_num = CONFIG_DVB_MPQ_NUM_DMX_DEVICES;
 module_param(mpq_demux_device_num, int, S_IRUGO);
 
-/* ION head ID to be used when calling ion_alloc for video decoder buffer */
-static int video_ion_alloc_heap = ION_CP_MM_HEAP_ID;
-module_param(video_ion_alloc_heap, int, S_IRUGO | S_IWUSR);
-MODULE_PARM_DESC(video_ion_alloc_heap, "ION heap ID for allocation");
+/* ION heap IDs used for allocating video output buffer */
+static int video_secure_ion_heap = ION_CP_MM_HEAP_ID;
+module_param(video_secure_ion_heap , int, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(video_secure_ion_heap, "ION heap for secure video buffer allocation");
+
+static int video_nonsecure_ion_heap = ION_IOMMU_HEAP_ID;
+module_param(video_nonsecure_ion_heap, int, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(video_nonsecure_ion_heap, "ION heap for non-secure video buffer allocation");
+
+static int generate_es_events;
+module_param(generate_es_events, int, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(generate_es_events, "Generate new elementary stream data events");
 
 /**
  * Maximum allowed framing pattern size
@@ -480,7 +488,6 @@
 	mpq_demux->hw_notification_count = 0;
 	mpq_demux->hw_notification_interval = 0;
 	mpq_demux->hw_notification_size = 0;
-	mpq_demux->decoder_drop_count = 0;
 	mpq_demux->hw_notification_min_size = 0xFFFFFFFF;
 
 	if (mpq_demux->demux.dmx.debugfs_demux_dir != NULL) {
@@ -519,6 +526,36 @@
 			S_IRUGO|S_IWUGO,
 			mpq_demux->demux.dmx.debugfs_demux_dir,
 			&mpq_demux->decoder_drop_count);
+
+		debugfs_create_u32(
+			"decoder_out_count",
+			S_IRUGO|S_IWUGO,
+			mpq_demux->demux.dmx.debugfs_demux_dir,
+			&mpq_demux->decoder_out_count);
+
+		debugfs_create_u32(
+			"decoder_out_interval_sum",
+			S_IRUGO|S_IWUGO,
+			mpq_demux->demux.dmx.debugfs_demux_dir,
+			&mpq_demux->decoder_out_interval_sum);
+
+		debugfs_create_u32(
+			"decoder_out_interval_average",
+			S_IRUGO|S_IWUGO,
+			mpq_demux->demux.dmx.debugfs_demux_dir,
+			&mpq_demux->decoder_out_interval_average);
+
+		debugfs_create_u32(
+			"decoder_out_interval_max",
+			S_IRUGO|S_IWUGO,
+			mpq_demux->demux.dmx.debugfs_demux_dir,
+			&mpq_demux->decoder_out_interval_max);
+
+		debugfs_create_u32(
+			"decoder_ts_errors",
+			S_IRUGO|S_IWUGO,
+			mpq_demux->demux.dmx.debugfs_demux_dir,
+			&mpq_demux->decoder_ts_errors);
 	}
 }
 EXPORT_SYMBOL(mpq_dmx_init_hw_statistics);
@@ -923,6 +960,62 @@
 }
 EXPORT_SYMBOL(mpq_dmx_unmap_buffer);
 
+int mpq_dmx_reuse_decoder_buffer(struct dvb_demux_feed *feed, int cookie)
+{
+	struct mpq_demux *mpq_demux = feed->demux->priv;
+
+	if (!generate_es_events) {
+		MPQ_DVB_ERR_PRINT(
+			"%s: Cannot release decoder buffer when not working with new elementary stream data events\n",
+			__func__);
+		return -EPERM;
+	}
+
+	if (cookie < 0) {
+		MPQ_DVB_ERR_PRINT("%s: invalid cookie parameter\n", __func__);
+		return -EINVAL;
+	}
+
+	if (mpq_dmx_is_video_feed(feed)) {
+		struct mpq_video_feed_info *feed_data;
+		struct mpq_streambuffer *stream_buffer;
+		int ret;
+
+		spin_lock(&mpq_demux->feed_lock);
+
+		if (feed->priv == NULL) {
+			MPQ_DVB_ERR_PRINT(
+				"%s: invalid feed, feed->priv is NULL\n",
+				__func__);
+			spin_unlock(&mpq_demux->feed_lock);
+			return -EINVAL;
+		}
+
+		feed_data = feed->priv;
+		stream_buffer = feed_data->video_buffer;
+		if (stream_buffer == NULL) {
+			MPQ_DVB_ERR_PRINT(
+				"%s: invalid feed, feed_data->video_buffer is NULL\n",
+				__func__);
+			spin_unlock(&mpq_demux->feed_lock);
+			return -EINVAL;
+		}
+
+		ret = mpq_streambuffer_pkt_dispose(stream_buffer, cookie, 1);
+
+		spin_unlock(&mpq_demux->feed_lock);
+
+		return ret;
+	}
+
+	/* else */
+	MPQ_DVB_ERR_PRINT("%s: Invalid feed type %d\n",
+			__func__, feed->pes_type);
+
+	return -EINVAL;
+}
+EXPORT_SYMBOL(mpq_dmx_reuse_decoder_buffer);
+
 /**
  * Handles the details of internal decoder buffer allocation via ION.
  * Internal helper function.
@@ -949,7 +1042,9 @@
 	actual_buffer_size &= ~(SZ_4K - 1);
 
 	temp_handle = ion_alloc(client, actual_buffer_size, SZ_4K,
-		ION_HEAP(video_ion_alloc_heap), ION_FLAG_CACHED);
+		ION_HEAP(video_secure_ion_heap) |
+		ION_HEAP(video_nonsecure_ion_heap),
+		ION_FLAG_CACHED);
 
 	if (IS_ERR_OR_NULL(temp_handle)) {
 		ret = PTR_ERR(temp_handle);
@@ -978,9 +1073,7 @@
 	feed_data->buffer_desc.desc[0].read_ptr = 0;
 	feed_data->buffer_desc.desc[0].write_ptr = 0;
 	feed_data->buffer_desc.desc[0].handle =
-		ion_share_dma_buf(
-			client,
-			temp_handle);
+		ion_share_dma_buf(client, temp_handle);
 	if (IS_ERR_VALUE(feed_data->buffer_desc.desc[0].handle)) {
 		MPQ_DVB_ERR_PRINT(
 			"%s: FAILED to share payload buffer %d\n",
@@ -1164,6 +1257,52 @@
 	return ret;
 }
 
+static void mpq_dmx_release_streambuffer(
+	struct dvb_demux_feed *feed,
+	struct mpq_video_feed_info *feed_data,
+	struct ion_client *client)
+{
+	int buf_num = 0;
+	int i;
+	struct dmx_decoder_buffers *dec_buffs = feed->feed.ts.decoder_buffers;
+
+	mpq_adapter_unregister_stream_if(feed_data->stream_interface);
+
+	vfree(feed_data->video_buffer->packet_data.data);
+
+	buf_num = feed_data->buffer_desc.decoder_buffers_num;
+
+	for (i = 0; i < buf_num; i++) {
+		if (feed_data->buffer_desc.ion_handle[i]) {
+			if (feed_data->buffer_desc.desc[i].base) {
+				ion_unmap_kernel(client,
+					feed_data->buffer_desc.ion_handle[i]);
+				feed_data->buffer_desc.desc[i].base = NULL;
+			}
+
+			/*
+			 * Un-share the buffer if kernel it the one that
+			 * shared it.
+			 */
+			if (0 == dec_buffs->buffers_num) {
+				struct file *shared_file = fget(
+					feed_data->buffer_desc.desc[i].handle);
+
+				if (shared_file)
+					fput(shared_file);
+				else
+					MPQ_DVB_ERR_PRINT(
+						"%s: failed to get shared-file handle\n",
+						__func__);
+			}
+
+			ion_free(client, feed_data->buffer_desc.ion_handle[i]);
+			feed_data->buffer_desc.ion_handle[i] = NULL;
+			feed_data->buffer_desc.desc[i].size = 0;
+		}
+	}
+}
+
 int mpq_dmx_init_video_feed(struct dvb_demux_feed *feed)
 {
 	int ret;
@@ -1245,25 +1384,25 @@
 	feed_data->video_buffer =
 		&mpq_dmx_info.decoder_buffers[feed_data->stream_interface];
 
-	ret = mpq_adapter_register_stream_if(
-		feed_data->stream_interface,
-		feed_data->video_buffer);
-
-	if (ret < 0) {
-		MPQ_DVB_ERR_PRINT(
-			"%s: mpq_adapter_register_stream_if failed, "
-			"err = %d\n",
-			__func__, ret);
-		goto init_failed_free_priv_data;
-	}
-
 	ret = mpq_dmx_init_streambuffer(
 		feed, feed_data, feed_data->video_buffer);
 	if (ret) {
 		MPQ_DVB_ERR_PRINT(
 			"%s: mpq_dmx_init_streambuffer failed, err = %d\n",
 			__func__, ret);
-		goto init_failed_unregister_stream_if;
+		goto init_failed_free_priv_data;
+	}
+
+	ret = mpq_adapter_register_stream_if(
+			feed_data->stream_interface,
+			feed_data->video_buffer);
+
+	if (ret < 0) {
+		MPQ_DVB_ERR_PRINT(
+			"%s: mpq_adapter_register_stream_if failed, "
+			"err = %d\n",
+			__func__, ret);
+		goto init_failed_free_stream_buffer;
 	}
 
 	feed_data->pes_payload_address =
@@ -1290,6 +1429,18 @@
 	feed_data->saved_info_used = 1;
 	feed_data->new_info_exists = 0;
 	feed_data->first_pts_dts_copy = 1;
+	feed_data->tei_errs = 0;
+	feed_data->last_continuity = -1;
+	feed_data->continuity_errs = 0;
+	feed_data->ts_packets_num = 0;
+	feed_data->ts_dropped_bytes = 0;
+	feed_data->last_pkt_index = -1;
+
+	mpq_demux->decoder_drop_count = 0;
+	mpq_demux->decoder_out_count = 0;
+	mpq_demux->decoder_out_interval_sum = 0;
+	mpq_demux->decoder_out_interval_max = 0;
+	mpq_demux->decoder_ts_errors = 0;
 
 	spin_lock(&mpq_demux->feed_lock);
 	feed->priv = (void *)feed_data;
@@ -1297,7 +1448,8 @@
 
 	return 0;
 
-init_failed_unregister_stream_if:
+init_failed_free_stream_buffer:
+	mpq_dmx_release_streambuffer(feed, feed_data, mpq_demux->ion_client);
 	mpq_adapter_unregister_stream_if(feed_data->stream_interface);
 init_failed_free_priv_data:
 	vfree(feed_data);
@@ -1308,42 +1460,6 @@
 }
 EXPORT_SYMBOL(mpq_dmx_init_video_feed);
 
-void mpq_dmx_release_streambuffer(
-	struct dvb_demux_feed *feed,
-	struct mpq_video_feed_info *feed_data,
-	struct ion_client *client)
-{
-	int buf_num = 0;
-	struct dmx_decoder_buffers *dec_buffs = feed->feed.ts.decoder_buffers;
-	int i;
-
-	mpq_adapter_unregister_stream_if(feed_data->stream_interface);
-
-	vfree(feed_data->video_buffer->packet_data.data);
-
-	buf_num = feed_data->buffer_desc.decoder_buffers_num;
-	for (i = 0; i < buf_num; i++) {
-		if (feed_data->buffer_desc.ion_handle[i]) {
-			if (feed_data->buffer_desc.desc[i].base) {
-				ion_unmap_kernel(client,
-					feed_data->buffer_desc.ion_handle[i]);
-				feed_data->buffer_desc.desc[i].base = NULL;
-			}
-			ion_free(client, feed_data->buffer_desc.ion_handle[i]);
-			feed_data->buffer_desc.ion_handle[i] = NULL;
-			feed_data->buffer_desc.desc[i].size = 0;
-
-			/*
-			 * Call put_unused_fd only if kernel it the one that
-			 * shared the buffer handle.
-			 */
-			if (0 == dec_buffs->buffers_num)
-				put_unused_fd(
-					feed_data->buffer_desc.desc[i].handle);
-		}
-	}
-}
-
 int mpq_dmx_terminate_video_feed(struct dvb_demux_feed *feed)
 {
 	struct mpq_video_feed_info *feed_data;
@@ -1671,11 +1787,6 @@
 	}
 
 	feed_data->new_info_exists = 1;
-
-	if (feed_data->first_pts_dts_copy) {
-		mpq_dmx_save_pts_dts(feed_data);
-		feed_data->first_pts_dts_copy = 0;
-	}
 }
 
 static inline int mpq_dmx_parse_remaining_pes_header(
@@ -1770,6 +1881,73 @@
 	return 0;
 }
 
+static void mpq_dmx_check_continuity(struct mpq_video_feed_info *feed_data,
+					int current_continuity,
+					int discontinuity_indicator)
+{
+	const int max_continuity = 0x0F; /* 4 bits in the TS packet header */
+
+	/* sanity check */
+	if (unlikely((current_continuity < 0) ||
+			(current_continuity > max_continuity))) {
+		MPQ_DVB_DBG_PRINT(
+			"%s: received invalid continuity counter value %d\n",
+					__func__, current_continuity);
+		return;
+	}
+
+	/* reset last continuity */
+	if ((feed_data->last_continuity == -1) ||
+		(discontinuity_indicator)) {
+		feed_data->last_continuity = current_continuity;
+		return;
+	}
+
+	/* check for continuity errors */
+	if (current_continuity !=
+			((feed_data->last_continuity + 1) & max_continuity))
+		feed_data->continuity_errs++;
+
+	/* save for next time */
+	feed_data->last_continuity = current_continuity;
+}
+
+static inline void mpq_dmx_prepare_es_event_data(
+			struct mpq_streambuffer_packet_header *packet,
+			struct mpq_adapter_video_meta_data *meta_data,
+			struct mpq_video_feed_info *feed_data,
+			struct mpq_streambuffer *stream_buffer,
+			struct dmx_data_ready *data)
+{
+	size_t len = 0;
+
+	data->data_length = 0;
+	data->buf.handle = packet->raw_data_handle;
+	/* this has to succeed when called here, after packet was written */
+	data->buf.cookie = mpq_streambuffer_pkt_next(stream_buffer,
+				feed_data->last_pkt_index, &len);
+	data->buf.offset = packet->raw_data_offset;
+	data->buf.len = packet->raw_data_len;
+	data->buf.pts_exists = meta_data->info.framing.pts_dts_info.pts_exist;
+	data->buf.pts = meta_data->info.framing.pts_dts_info.pts;
+	data->buf.dts_exists = meta_data->info.framing.pts_dts_info.dts_exist;
+	data->buf.dts = meta_data->info.framing.pts_dts_info.dts;
+	data->buf.tei_counter = feed_data->tei_errs;
+	data->buf.cont_err_counter = feed_data->continuity_errs;
+	data->buf.ts_packets_num = feed_data->ts_packets_num;
+	data->buf.ts_dropped_bytes = feed_data->ts_dropped_bytes;
+	data->status = DMX_OK_DECODER_BUF;
+
+	/* save for next time: */
+	feed_data->last_pkt_index = data->buf.cookie;
+
+	/* reset counters */
+	feed_data->ts_packets_num = 0;
+	feed_data->ts_dropped_bytes = 0;
+	feed_data->tei_errs = 0;
+	feed_data->continuity_errs = 0;
+}
+
 static int mpq_dmx_process_video_packet_framing(
 			struct dvb_demux_feed *feed,
 			const u8 *buf)
@@ -1793,6 +1971,8 @@
 	int is_video_frame = 0;
 	int pending_data_len = 0;
 	int ret = 0;
+	int discontinuity_indicator = 0;
+	struct dmx_data_ready data;
 
 	mpq_demux = feed->demux->priv;
 
@@ -1854,9 +2034,18 @@
 
 	ts_payload_offset = sizeof(struct ts_packet_header);
 
-	/* Skip adaptation field if exists */
-	if (ts_header->adaptation_field_control == 3)
+	/*
+	 * Skip adaptation field if exists.
+	 * Save discontinuity indicator if exists.
+	 */
+	if (ts_header->adaptation_field_control == 3) {
+		const struct ts_adaptation_field *adaptation_field;
+		adaptation_field = (const struct ts_adaptation_field *)
+			(buf + ts_payload_offset);
+		discontinuity_indicator =
+			adaptation_field->discontinuity_indicator;
 		ts_payload_offset += buf[ts_payload_offset] + 1;
+	}
 
 	/* 188 bytes: the size of a TS packet including the TS packet header */
 	bytes_avail = 188 - ts_payload_offset;
@@ -1940,6 +2129,29 @@
 		return 0;
 	}
 
+	/* Update error counters based on TS header */
+	feed_data->ts_packets_num++;
+	feed_data->tei_errs += ts_header->transport_error_indicator;
+	mpq_demux->decoder_ts_errors += ts_header->transport_error_indicator;
+	mpq_dmx_check_continuity(feed_data,
+				ts_header->continuity_counter,
+				discontinuity_indicator);
+
+	/* Need to back-up the PTS information of the very first frame */
+	if (feed_data->first_pts_dts_copy) {
+		for (i = first_pattern; i < found_patterns; i++) {
+			is_video_frame = mpq_dmx_is_video_frame(
+					feed->indexing_params.standard,
+					framing_res.info[i].type);
+
+			if (is_video_frame) {
+				mpq_dmx_save_pts_dts(feed_data);
+				feed_data->first_pts_dts_copy = 0;
+				break;
+			}
+		}
+	}
+
 	/*
 	 * write prefix used to find first Sequence pattern, if needed.
 	 * feed_data->patterns[0].pattern always contains the Sequence
@@ -1951,6 +2163,8 @@
 					feed_data->first_prefix_size) < 0) {
 			mpq_demux->decoder_drop_count +=
 				feed_data->first_prefix_size;
+			feed_data->ts_dropped_bytes +=
+				feed_data->first_prefix_size;
 			MPQ_DVB_DBG_PRINT("%s: could not write prefix\n",
 				__func__);
 		} else {
@@ -2003,6 +2217,7 @@
 			(buf + ts_payload_offset + bytes_written),
 			bytes_to_write) < 0) {
 			mpq_demux->decoder_drop_count += bytes_to_write;
+			feed_data->ts_dropped_bytes += bytes_to_write;
 			MPQ_DVB_DBG_PRINT(
 				"%s: Couldn't write %d bytes to data buffer\n",
 				__func__, bytes_to_write);
@@ -2016,6 +2231,9 @@
 				feed->indexing_params.standard,
 				feed_data->last_framing_match_type);
 		if (is_video_frame == 1) {
+			struct timespec curr_time, delta_time;
+			u64 delta_time_ms;
+
 			mpq_dmx_write_pts_dts(feed_data,
 				&(meta_data.info.framing.pts_dts_info));
 			mpq_dmx_save_pts_dts(feed_data);
@@ -2030,6 +2248,34 @@
 				0,	/* current write buffer handle */
 				&packet.raw_data_handle);
 
+			curr_time = current_kernel_time();
+			if (likely(mpq_demux->decoder_out_count)) {
+				/* calculate time-delta between frame */
+				delta_time = timespec_sub(curr_time,
+				mpq_demux->decoder_out_last_time);
+
+				delta_time_ms =
+				  ((u64)delta_time.tv_sec * MSEC_PER_SEC)
+				  + delta_time.tv_nsec / NSEC_PER_MSEC;
+
+				mpq_demux->decoder_out_interval_sum +=
+				  (u32)delta_time_ms;
+
+				mpq_demux->
+				  decoder_out_interval_average =
+				  mpq_demux->decoder_out_interval_sum /
+				  mpq_demux->decoder_out_count;
+
+				if (delta_time_ms >
+				    mpq_demux->decoder_out_interval_max)
+					mpq_demux->
+						decoder_out_interval_max =
+						delta_time_ms;
+			}
+
+			mpq_demux->decoder_out_last_time = curr_time;
+			mpq_demux->decoder_out_count++;
+
 			/*
 			 * writing meta-data that includes
 			 * the framing information
@@ -2043,6 +2289,15 @@
 					"Should never happen\n",
 					__func__);
 			}
+
+			if (generate_es_events) {
+				mpq_dmx_prepare_es_event_data(
+					&packet, &meta_data, feed_data,
+					stream_buffer, &data);
+
+				feed->data_ready_cb.ts(&feed->feed.ts, &data);
+			}
+
 			feed_data->pending_pattern_len = 0;
 			mpq_streambuffer_get_data_rw_offset(
 				feed_data->video_buffer,
@@ -2064,6 +2319,7 @@
 			pending_data_len);
 		if (ret < 0) {
 			mpq_demux->decoder_drop_count += pending_data_len;
+			feed_data->ts_dropped_bytes += pending_data_len;
 			MPQ_DVB_DBG_PRINT(
 				"%s: Couldn't write %d bytes to data buffer\n",
 				__func__, pending_data_len);
@@ -2087,6 +2343,8 @@
 	struct mpq_streambuffer *stream_buffer;
 	struct pes_packet_header *pes_header;
 	struct mpq_demux *mpq_demux;
+	int discontinuity_indicator = 0;
+	struct dmx_data_ready data;
 
 	mpq_demux = feed->demux->priv;
 
@@ -2100,7 +2358,7 @@
 
 	ts_header = (const struct ts_packet_header *)buf;
 
-	stream_buffer =	feed_data->video_buffer;
+	stream_buffer = feed_data->video_buffer;
 
 	pes_header = &feed_data->pes_header;
 
@@ -2153,11 +2411,22 @@
 						"Couldn't write packet. "
 						"Should never happen\n",
 						__func__);
+
 				/* Save write offset where new PES will begin */
 				mpq_streambuffer_get_data_rw_offset(
 					stream_buffer,
 					NULL,
 					&feed_data->frame_offset);
+
+				if (generate_es_events) {
+					mpq_dmx_prepare_es_event_data(
+						&packet, &meta_data,
+						feed_data,
+						stream_buffer, &data);
+
+					feed->data_ready_cb.ts(
+						&feed->feed.ts, &data);
+				}
 			} else {
 				MPQ_DVB_ERR_PRINT(
 					"%s: received PUSI"
@@ -2191,9 +2460,18 @@
 
 	ts_payload_offset = sizeof(struct ts_packet_header);
 
-	/* Skip adaptation field if exists */
-	if (ts_header->adaptation_field_control == 3)
+	/*
+	 * Skip adaptation field if exists.
+	 * Save discontinuity indicator if exists.
+	 */
+	if (ts_header->adaptation_field_control == 3) {
+		const struct ts_adaptation_field *adaptation_field;
+		adaptation_field = (const struct ts_adaptation_field *)
+			(buf + ts_payload_offset);
+		discontinuity_indicator =
+			adaptation_field->discontinuity_indicator;
 		ts_payload_offset += buf[ts_payload_offset] + 1;
+	}
 
 	/* 188 bytes: size of a TS packet including the TS packet header */
 	bytes_avail = 188 - ts_payload_offset;
@@ -2224,13 +2502,32 @@
 		return 0;
 	}
 
+	/*
+	 * Need to back-up the PTS information
+	 * of the very first PES
+	 */
+	if (feed_data->first_pts_dts_copy) {
+		mpq_dmx_save_pts_dts(feed_data);
+		feed_data->first_pts_dts_copy = 0;
+	}
+
+	/* Update error counters based on TS header */
+	feed_data->ts_packets_num++;
+	feed_data->tei_errs += ts_header->transport_error_indicator;
+	mpq_demux->decoder_ts_errors += ts_header->transport_error_indicator;
+	mpq_dmx_check_continuity(feed_data,
+				ts_header->continuity_counter,
+				discontinuity_indicator);
+
 	if (mpq_streambuffer_data_write(
 				stream_buffer,
 				buf+ts_payload_offset,
-				bytes_avail) < 0)
+				bytes_avail) < 0) {
 		mpq_demux->decoder_drop_count += bytes_avail;
-	else
+		feed_data->ts_dropped_bytes += bytes_avail;
+	} else {
 		feed->peslen += bytes_avail;
+	}
 
 	spin_unlock(&mpq_demux->feed_lock);
 
@@ -2261,8 +2558,13 @@
 		spin_unlock(&mpq_demux->feed_lock);
 		return -EINVAL;
 	}
+
 	feed_data = feed->priv;
 	video_buff = feed_data->video_buffer;
+	if (!video_buff) {
+		spin_unlock(&mpq_demux->feed_lock);
+		return -EINVAL;
+	}
 
 	dmx_buffer_status->error = video_buff->raw_data.error;
 
@@ -2318,29 +2620,14 @@
 	const struct ts_packet_header *ts_header;
 	const struct ts_adaptation_field *adaptation_field;
 
-	/*
-	 * When we play from front-end, we configure HW
-	 * to output the extra timestamp, if we are playing
-	 * from DVR, make sure the format is 192 packet.
-	 */
-	if ((mpq_demux->source >= DMX_SOURCE_DVR0) &&
-		(mpq_demux->demux.tsp_format != DMX_TSP_FORMAT_192_TAIL)) {
-		MPQ_DVB_ERR_PRINT(
-			"%s: invalid packet format %d for PCR extraction\n",
-			__func__,
-			mpq_demux->demux.tsp_format);
-
-		 return -EINVAL;
-	}
-
 	ts_header = (const struct ts_packet_header *)buf;
 
 	/* Make sure this TS packet has a adaptation field */
 	if ((ts_header->sync_byte != 0x47) ||
 		(ts_header->adaptation_field_control == 0) ||
-		(ts_header->adaptation_field_control == 1)) {
+		(ts_header->adaptation_field_control == 1) ||
+		ts_header->transport_error_indicator)
 		return 0;
-	}
 
 	adaptation_field = (const struct ts_adaptation_field *)
 			(buf + sizeof(struct ts_packet_header));
@@ -2359,10 +2646,21 @@
 		(((u64)adaptation_field->program_clock_reference_ext_1) << 8) +
 		adaptation_field->program_clock_reference_ext_2;
 
-	stc = buf[190] << 16;
-	stc += buf[189] << 8;
-	stc += buf[188];
-	stc *= 256; /* convert from 105.47 KHZ to 27MHz */
+	/*
+	 * When we play from front-end, we configure HW
+	 * to output the extra timestamp, if we are playing
+	 * from DVR, we don't have a timestamp if the packet
+	 * format is not 192-tail.
+	 */
+	if ((mpq_demux->source >= DMX_SOURCE_DVR0) &&
+		(mpq_demux->demux.tsp_format != DMX_TSP_FORMAT_192_TAIL)) {
+		stc = 0;
+	} else {
+		stc = buf[190] << 16;
+		stc += buf[189] << 8;
+		stc += buf[188];
+		stc *= 256; /* convert from 105.47 KHZ to 27MHz */
+	}
 
 	data.data_length = 0;
 	data.pcr.pcr = pcr;
diff --git a/drivers/media/dvb/mpq/demux/mpq_dmx_plugin_common.h b/drivers/media/dvb/mpq/demux/mpq_dmx_plugin_common.h
index 744900a..c0d5412 100644
--- a/drivers/media/dvb/mpq/demux/mpq_dmx_plugin_common.h
+++ b/drivers/media/dvb/mpq/demux/mpq_dmx_plugin_common.h
@@ -54,6 +54,17 @@
  *                            exposed in debugfs.
  * @decoder_drop_count: Accumulated number of bytes dropped due to decoder
  * buffer fullness, exposed in debugfs.
+ * @decoder_out_count: Counter incremeneted for each video frame output by
+ * demux, exposed in debugfs.
+ * @decoder_out_interval_sum: Sum of intervals (msec) holding the time between
+ * two successive video frames output, exposed in debugfs.
+ * @decoder_out_interval_average: Average interval (msec) between two
+ * successive video frames output, exposed in debugfs.
+ * @decoder_out_interval_max: Max interval (msec) between two
+ * successive video frames output, exposed in debugfs.
+ * @decoder_ts_errors: Counter for number of decoder packets with TEI bit
+ * set, exposed in debugfs.
+ * @decoder_out_last_time: Time of last video frame output.
  * @last_notification_time: Time of last HW notification.
  */
 struct mpq_demux {
@@ -72,6 +83,12 @@
 	u32 hw_notification_size;
 	u32 hw_notification_min_size;
 	u32 decoder_drop_count;
+	u32 decoder_out_count;
+	u32 decoder_out_interval_sum;
+	u32 decoder_out_interval_average;
+	u32 decoder_out_interval_max;
+	u32 decoder_ts_errors;
+	struct timespec decoder_out_last_time;
 	struct timespec last_notification_time;
 };
 
@@ -333,6 +350,15 @@
  * new_pts_dts_info that should be saved to saved_pts_dts_info.
  * @first_pts_dts_copy: a flag used to indicate if PTS/DTS information needs
  * to be copied from the currently parsed PES header to the saved_pts_dts_info.
+ * @tei_errs: Transport stream Transport Error Indicator (TEI) counter.
+ * @last_continuity: last continuity counter value found in TS packet header.
+ * Initialized to -1.
+ * @continuity_errs: Transport stream continuity error counter.
+ * @ts_packets_num: TS packets counter.
+ * @ts_dropped_bytes: counts the number of bytes dropped due to insufficient
+ * buffer space.
+ * @last_pkt_index: used to save the last streambuffer packet index reported in
+ * a new elementary stream data event.
  */
 struct mpq_video_feed_info {
 	void *plugin_data;
@@ -358,6 +384,12 @@
 	int saved_info_used;
 	int new_info_exists;
 	int first_pts_dts_copy;
+	u32 tei_errs;
+	int last_continuity;
+	u32 continuity_errs;
+	u32 ts_packets_num;
+	u32 ts_dropped_bytes;
+	int last_pkt_index;
 };
 
 /**
@@ -500,6 +532,20 @@
 		struct dmx_buffer_status *dmx_buffer_status);
 
 /**
+ * mpq_dmx_reuse_decoder_buffer - release buffer passed to decoder for reuse
+ * by the stream-buffer.
+ *
+ * @feed: The decoder's feed.
+ * @cookie: stream-buffer handle of the buffer.
+ *
+ * Return     error code
+ *
+ * The function releases the buffer provided by the stream-buffer
+ * connected to the decoder back to the stream-buffer for reuse.
+ */
+int mpq_dmx_reuse_decoder_buffer(struct dvb_demux_feed *feed, int cookie);
+
+/**
  * mpq_dmx_process_video_packet - Assemble PES data and output it
  * to the stream-buffer connected to the decoder.
  *
diff --git a/drivers/media/dvb/mpq/demux/mpq_dmx_plugin_tsif.c b/drivers/media/dvb/mpq/demux/mpq_dmx_plugin_tsif.c
index c5c3518..3ad3d21 100644
--- a/drivers/media/dvb/mpq/demux/mpq_dmx_plugin_tsif.c
+++ b/drivers/media/dvb/mpq/demux/mpq_dmx_plugin_tsif.c
@@ -668,6 +668,9 @@
 	mpq_demux->demux.decoder_buffer_status =
 		mpq_dmx_decoder_buffer_status;
 
+	mpq_demux->demux.reuse_decoder_buffer =
+		mpq_dmx_reuse_decoder_buffer;
+
 	/* Initialize dvb_demux object */
 	result = dvb_dmx_init(&mpq_demux->demux);
 	if (result < 0) {
diff --git a/drivers/media/dvb/mpq/demux/mpq_dmx_plugin_tspp_v1.c b/drivers/media/dvb/mpq/demux/mpq_dmx_plugin_tspp_v1.c
index 61c1761..0eee8f3 100644
--- a/drivers/media/dvb/mpq/demux/mpq_dmx_plugin_tspp_v1.c
+++ b/drivers/media/dvb/mpq/demux/mpq_dmx_plugin_tspp_v1.c
@@ -24,14 +24,11 @@
 /* Max number of section filters */
 #define TSPP_MAX_SECTION_FILTER_NUM	64
 
-/* For each TSIF we allocate two pipes, one for PES and one for sections */
-#define TSPP_PES_CHANNEL			0
-#define TSPP_SECTION_CHANNEL			1
-#define TSPP_CHANNEL_COUNT			2
+/* For each TSIF we use a single pipe holding the data after PID filtering */
+#define TSPP_CHANNEL			0
 
 /* the channel_id set to TSPP driver based on TSIF number and channel type */
 #define TSPP_CHANNEL_ID(tsif, ch)		((tsif << 1) + ch)
-#define TSPP_IS_PES_CHANNEL(ch_id)		((ch_id & 0x1) == 0)
 #define TSPP_GET_TSIF_NUM(ch_id)		(ch_id >> 1)
 
 /* mask that set to care for all bits in pid filter */
@@ -47,9 +44,7 @@
 
 #define TSPP_BUFFER_SIZE		(500 * 1024) /* 500KB */
 
-#define TSPP_PES_BUFFER_SIZE		(TSPP_RAW_TTS_SIZE)
-
-#define TSPP_SECTION_BUFFER_SIZE	(TSPP_RAW_TTS_SIZE)
+#define TSPP_DESCRIPTOR_SIZE	(TSPP_RAW_TTS_SIZE)
 
 #define TSPP_BUFFER_COUNT(buffer_size)	\
 	((buffer_size) / TSPP_RAW_TTS_SIZE)
@@ -76,16 +71,18 @@
 static int tsif_mode = 2;
 static int allocation_mode = MPQ_DMX_TSPP_INTERNAL_ALLOC;
 static int tspp_out_buffer_size = TSPP_BUFFER_SIZE;
-static int tspp_notification_size = TSPP_NOTIFICATION_SIZE(TSPP_RAW_TTS_SIZE);
+static int tspp_notification_size =
+	TSPP_NOTIFICATION_SIZE(TSPP_DESCRIPTOR_SIZE);
 static int tspp_channel_timeout = TSPP_CHANNEL_TIMEOUT;
+static int tspp_out_ion_heap = ION_QSECOM_HEAP_ID;
 
 module_param(tsif_mode, int, S_IRUGO | S_IWUSR);
 module_param(clock_inv, int, S_IRUGO | S_IWUSR);
-module_param(allocation_mode, int, S_IRUGO);
+module_param(allocation_mode, int, S_IRUGO | S_IWUSR);
 module_param(tspp_out_buffer_size, int, S_IRUGO);
 module_param(tspp_notification_size, int, S_IRUGO | S_IWUSR);
 module_param(tspp_channel_timeout, int, S_IRUGO | S_IWUSR);
-
+module_param(tspp_out_ion_heap, int, S_IRUGO | S_IWUSR);
 
 /* The following structure hold singelton information
  * required for dmx implementation on top of TSPP.
@@ -95,42 +92,26 @@
 	/* Information for each TSIF input processing */
 	struct {
 		/*
-		 * TSPP pipe holding all TS packets with PES data.
+		 * TSPP pipe holding all TS packets after PID filtering.
 		 * The following is reference count for number of feeds
 		 * allocated on that pipe.
 		 */
-		int pes_channel_ref;
+		int channel_ref;
 
-		/* Counter for data notifications on PES pipe */
-		atomic_t pes_data_cnt;
+		/* Counter for data notifications on the pipe */
+		atomic_t data_cnt;
 
 		/* ION handle used for TSPP data buffer allocation */
-		struct ion_handle *pes_mem_heap_handle;
+		struct ion_handle *ch_mem_heap_handle;
+
 		/* TSPP data buffer heap virtual base address */
-		void *pes_mem_heap_virt_base;
+		void *ch_mem_heap_virt_base;
+
 		/* TSPP data buffer heap physical base address */
-		ion_phys_addr_t pes_mem_heap_phys_base;
+		ion_phys_addr_t ch_mem_heap_phys_base;
+
 		/* buffer allocation index */
-		int pes_index;
-
-		/*
-		 * TSPP pipe holding all TS packets with section data.
-		 * The following is reference count for number of feeds
-		 * allocated on that pipe.
-		 */
-		int section_channel_ref;
-
-		/* Counter for data notifications on section pipe */
-		atomic_t section_data_cnt;
-
-		/* ION handle used for TSPP data buffer allocation */
-		struct ion_handle *section_mem_heap_handle;
-		/* TSPP data buffer heap virtual base address */
-		void *section_mem_heap_virt_base;
-		/* TSPP data buffer heap physical base address */
-		ion_phys_addr_t section_mem_heap_phys_base;
-		/* buffer allocation index */
-		int section_index;
+		int buff_index;
 
 		u32 buffer_count;
 
@@ -167,29 +148,19 @@
 	void *virt_addr = NULL;
 	int i = TSPP_GET_TSIF_NUM(channel_id);
 
-	if (TSPP_IS_PES_CHANNEL(channel_id)) {
-		if (mpq_dmx_tspp_info.tsif[i].pes_index ==
-			mpq_dmx_tspp_info.tsif[i].buffer_count)
-			return NULL;
-		virt_addr =
-			(mpq_dmx_tspp_info.tsif[i].pes_mem_heap_virt_base +
-			(mpq_dmx_tspp_info.tsif[i].pes_index * size));
-		*phys_base =
-			(mpq_dmx_tspp_info.tsif[i].pes_mem_heap_phys_base +
-			(mpq_dmx_tspp_info.tsif[i].pes_index * size));
-		mpq_dmx_tspp_info.tsif[i].pes_index++;
-	} else {
-		if (mpq_dmx_tspp_info.tsif[i].section_index ==
-			mpq_dmx_tspp_info.tsif[i].buffer_count)
-			return NULL;
-		virt_addr =
-			(mpq_dmx_tspp_info.tsif[i].section_mem_heap_virt_base +
-			(mpq_dmx_tspp_info.tsif[i].section_index * size));
-		*phys_base =
-			(mpq_dmx_tspp_info.tsif[i].section_mem_heap_phys_base +
-			(mpq_dmx_tspp_info.tsif[i].section_index * size));
-		mpq_dmx_tspp_info.tsif[i].section_index++;
-	}
+	if (mpq_dmx_tspp_info.tsif[i].buff_index ==
+		mpq_dmx_tspp_info.tsif[i].buffer_count)
+		return NULL;
+
+	virt_addr =
+		(mpq_dmx_tspp_info.tsif[i].ch_mem_heap_virt_base +
+		(mpq_dmx_tspp_info.tsif[i].buff_index * size));
+
+	*phys_base =
+		(mpq_dmx_tspp_info.tsif[i].ch_mem_heap_phys_base +
+		(mpq_dmx_tspp_info.tsif[i].buff_index * size));
+
+	mpq_dmx_tspp_info.tsif[i].buff_index++;
 
 	return virt_addr;
 }
@@ -208,13 +179,8 @@
 	 * a few times, then call tspp_mem_free(), then call
 	 * tspp_mem_allocator() again.
 	 */
-	if (TSPP_IS_PES_CHANNEL(channel_id)) {
-		if (mpq_dmx_tspp_info.tsif[i].pes_index > 0)
-			mpq_dmx_tspp_info.tsif[i].pes_index--;
-	} else {
-		if (mpq_dmx_tspp_info.tsif[i].section_index > 0)
-			mpq_dmx_tspp_info.tsif[i].section_index--;
-	}
+	if (mpq_dmx_tspp_info.tsif[i].buff_index > 0)
+		mpq_dmx_tspp_info.tsif[i].buff_index--;
 }
 
 /**
@@ -224,26 +190,14 @@
  * @channel_id: The channel allocating filter to
  *
  * Return  filter index or -1 if no filters available
- *
- * To give priority to PES data, for pes filters
- * the table is scanned from high to low priority,
- * and sections from low to high priority. This way TSPP
- * would get a match on PES data filters faster as they
- * are scanned first.
  */
 static int mpq_tspp_get_free_filter_slot(int tsif, int channel_id)
 {
 	int i;
 
-	if (TSPP_IS_PES_CHANNEL(channel_id)) {
-		for (i = 0; i < TSPP_MAX_PID_FILTER_NUM; i++)
-			if (mpq_dmx_tspp_info.tsif[tsif].filters[i].pid == -1)
-				return i;
-	} else {
-		for (i = TSPP_MAX_PID_FILTER_NUM-1; i >= 0; i--)
-			if (mpq_dmx_tspp_info.tsif[tsif].filters[i].pid == -1)
-				return i;
-	}
+	for (i = 0; i < TSPP_MAX_PID_FILTER_NUM; i++)
+		if (mpq_dmx_tspp_info.tsif[tsif].filters[i].pid == -1)
+			return i;
 
 	return -ENOMEM;
 }
@@ -279,18 +233,15 @@
 	const struct tspp_data_descriptor *tspp_data_desc;
 	atomic_t *data_cnt;
 	u32 notif_size;
+	int channel_id;
 	int ref_count;
 	int ret;
-	int i;
 	int j;
 
 	do {
 		ret = wait_event_interruptible(
 			mpq_dmx_tspp_info.tsif[tsif].wait_queue,
-			(atomic_read(
-			 &mpq_dmx_tspp_info.tsif[tsif].pes_data_cnt)) ||
-			(atomic_read(
-			 &mpq_dmx_tspp_info.tsif[tsif].section_data_cnt)) ||
+			atomic_read(&mpq_dmx_tspp_info.tsif[tsif].data_cnt) ||
 			kthread_should_stop());
 
 		if ((ret < 0) || kthread_should_stop()) {
@@ -303,66 +254,51 @@
 			&mpq_dmx_tspp_info.tsif[tsif].mutex))
 			return -ERESTARTSYS;
 
-		for (i = 0; i < TSPP_CHANNEL_COUNT; i++) {
-			int channel_id = TSPP_CHANNEL_ID(tsif, i);
+		channel_id = TSPP_CHANNEL_ID(tsif, TSPP_CHANNEL);
 
-			if (TSPP_IS_PES_CHANNEL(channel_id)) {
-				ref_count =
-				 mpq_dmx_tspp_info.tsif[tsif].pes_channel_ref;
-				data_cnt =
-				 &mpq_dmx_tspp_info.tsif[tsif].pes_data_cnt;
-			} else {
-				ref_count =
-				 mpq_dmx_tspp_info.tsif[tsif].
-					section_channel_ref;
-				data_cnt =
-				 &mpq_dmx_tspp_info.tsif[tsif].section_data_cnt;
-			}
+		ref_count = mpq_dmx_tspp_info.tsif[tsif].channel_ref;
+		data_cnt = &mpq_dmx_tspp_info.tsif[tsif].data_cnt;
 
-			/* Make sure channel is still active */
-			if (ref_count == 0)
-				continue;
-
-			atomic_dec(data_cnt);
-
-			mpq_demux = mpq_dmx_tspp_info.tsif[tsif].mpq_demux;
-			mpq_demux->hw_notification_size = 0;
-
-			/*
-			 * Go through all filled descriptors
-			 * and perform demuxing on them
-			 */
-			while ((tspp_data_desc =
-				tspp_get_buffer(0, channel_id)) != NULL) {
-				notif_size =
-					tspp_data_desc->size /
-					TSPP_RAW_TTS_SIZE;
-
-				mpq_demux->hw_notification_size +=
-					notif_size;
-
-				for (j = 0; j < notif_size; j++)
-					dvb_dmx_swfilter_packet(
-					 &mpq_demux->demux,
-					 ((u8 *)tspp_data_desc->virt_base) +
-					 j * TSPP_RAW_TTS_SIZE,
-					 ((u8 *)tspp_data_desc->virt_base) +
-					 j * TSPP_RAW_TTS_SIZE + TSPP_RAW_SIZE);
-				/*
-				 * Notify TSPP that the buffer
-				 * is no longer needed
-				 */
-				tspp_release_buffer(0,
-					channel_id, tspp_data_desc->id);
-			}
-
-			if (mpq_demux->hw_notification_size &&
-				(mpq_demux->hw_notification_size <
-				mpq_demux->hw_notification_min_size))
-				mpq_demux->hw_notification_min_size =
-					mpq_demux->hw_notification_size;
+		/* Make sure channel is still active */
+		if (ref_count == 0) {
+			mutex_unlock(&mpq_dmx_tspp_info.tsif[tsif].mutex);
+			continue;
 		}
 
+		atomic_dec(data_cnt);
+
+		mpq_demux = mpq_dmx_tspp_info.tsif[tsif].mpq_demux;
+		mpq_demux->hw_notification_size = 0;
+
+		/*
+		 * Go through all filled descriptors
+		 * and perform demuxing on them
+		 */
+		while ((tspp_data_desc = tspp_get_buffer(0, channel_id))
+				!= NULL) {
+			notif_size = tspp_data_desc->size / TSPP_RAW_TTS_SIZE;
+			mpq_demux->hw_notification_size += notif_size;
+
+			for (j = 0; j < notif_size; j++)
+				dvb_dmx_swfilter_packet(
+				 &mpq_demux->demux,
+				 ((u8 *)tspp_data_desc->virt_base) +
+				 j * TSPP_RAW_TTS_SIZE,
+				 ((u8 *)tspp_data_desc->virt_base) +
+				 j * TSPP_RAW_TTS_SIZE + TSPP_RAW_SIZE);
+			/*
+			 * Notify TSPP that the buffer
+			 * is no longer needed
+			 */
+			tspp_release_buffer(0, channel_id, tspp_data_desc->id);
+		}
+
+		if (mpq_demux->hw_notification_size &&
+			(mpq_demux->hw_notification_size <
+			mpq_demux->hw_notification_min_size))
+			mpq_demux->hw_notification_min_size =
+				mpq_demux->hw_notification_size;
+
 		mutex_unlock(&mpq_dmx_tspp_info.tsif[tsif].mutex);
 	} while (1);
 
@@ -384,15 +320,89 @@
 	mpq_demux = mpq_dmx_tspp_info.tsif[tsif].mpq_demux;
 	mpq_dmx_update_hw_statistics(mpq_demux);
 
-	if (TSPP_IS_PES_CHANNEL(channel_id))
-		atomic_inc(&mpq_dmx_tspp_info.tsif[tsif].pes_data_cnt);
-	else
-		atomic_inc(&mpq_dmx_tspp_info.tsif[tsif].section_data_cnt);
-
+	atomic_inc(&mpq_dmx_tspp_info.tsif[tsif].data_cnt);
 	wake_up(&mpq_dmx_tspp_info.tsif[tsif].wait_queue);
 }
 
 /**
+ * Free memory of channel output of specific TSIF.
+ *
+ * @tsif: The TSIF id to which memory should be freed.
+ */
+static void mpq_dmx_channel_mem_free(int tsif)
+{
+	MPQ_DVB_DBG_PRINT("%s(%d)\n", __func__, tsif);
+
+	mpq_dmx_tspp_info.tsif[tsif].ch_mem_heap_phys_base = 0;
+
+	if (!IS_ERR_OR_NULL(mpq_dmx_tspp_info.tsif[tsif].ch_mem_heap_handle)) {
+		if (!IS_ERR_OR_NULL(mpq_dmx_tspp_info.tsif[tsif].
+				ch_mem_heap_virt_base))
+			ion_unmap_kernel(mpq_dmx_tspp_info.ion_client,
+				mpq_dmx_tspp_info.tsif[tsif].
+					ch_mem_heap_handle);
+
+		ion_free(mpq_dmx_tspp_info.ion_client,
+			mpq_dmx_tspp_info.tsif[tsif].ch_mem_heap_handle);
+	}
+
+	mpq_dmx_tspp_info.tsif[tsif].ch_mem_heap_virt_base = NULL;
+	mpq_dmx_tspp_info.tsif[tsif].ch_mem_heap_handle = NULL;
+}
+
+/**
+ * Allocate memory for channel output of specific TSIF.
+ *
+ * @tsif: The TSIF id to which memory should be allocated.
+ *
+ * Return  error status
+ */
+static int mpq_dmx_channel_mem_alloc(int tsif)
+{
+	int result;
+	size_t len;
+
+	MPQ_DVB_DBG_PRINT("%s(%d)\n", __func__, tsif);
+
+	mpq_dmx_tspp_info.tsif[tsif].ch_mem_heap_handle =
+		ion_alloc(mpq_dmx_tspp_info.ion_client,
+		 (mpq_dmx_tspp_info.tsif[tsif].buffer_count *
+		  TSPP_DESCRIPTOR_SIZE),
+		 SZ_4K,
+		 ION_HEAP(tspp_out_ion_heap),
+		 0); /* non-cached */
+
+	if (IS_ERR_OR_NULL(mpq_dmx_tspp_info.tsif[tsif].ch_mem_heap_handle)) {
+		MPQ_DVB_ERR_PRINT("%s: ion_alloc() failed\n", __func__);
+		mpq_dmx_channel_mem_free(tsif);
+		return -ENOMEM;
+	}
+
+	/* save virtual base address of heap */
+	mpq_dmx_tspp_info.tsif[tsif].ch_mem_heap_virt_base =
+		ion_map_kernel(mpq_dmx_tspp_info.ion_client,
+			mpq_dmx_tspp_info.tsif[tsif].ch_mem_heap_handle);
+	if (IS_ERR_OR_NULL(mpq_dmx_tspp_info.tsif[tsif].
+				ch_mem_heap_virt_base)) {
+		MPQ_DVB_ERR_PRINT("%s: ion_map_kernel() failed\n", __func__);
+		mpq_dmx_channel_mem_free(tsif);
+		return -ENOMEM;
+	}
+
+	/* save physical base address of heap */
+	result = ion_phys(mpq_dmx_tspp_info.ion_client,
+		mpq_dmx_tspp_info.tsif[tsif].ch_mem_heap_handle,
+		&(mpq_dmx_tspp_info.tsif[tsif].ch_mem_heap_phys_base), &len);
+	if (result < 0) {
+		MPQ_DVB_ERR_PRINT("%s: ion_phys() failed\n", __func__);
+		mpq_dmx_channel_mem_free(tsif);
+		return -ENOMEM;
+	}
+
+	return 0;
+}
+
+/**
  * Configure TSPP channel to filter the PID of new feed.
  *
  * @feed: The feed to configure the channel with
@@ -463,21 +473,25 @@
 		return 0;
 	}
 
-	/* determine to which pipe the feed should be routed: section or pes */
-	if ((feed->type == DMX_TYPE_PES) || (feed->type == DMX_TYPE_TS)) {
-		channel_id = TSPP_CHANNEL_ID(tsif, TSPP_PES_CHANNEL);
-		channel_ref_count =
-			&mpq_dmx_tspp_info.tsif[tsif].pes_channel_ref;
-		buffer_size = TSPP_PES_BUFFER_SIZE;
-	} else {
-		channel_id = TSPP_CHANNEL_ID(tsif, TSPP_SECTION_CHANNEL);
-		channel_ref_count =
-			&mpq_dmx_tspp_info.tsif[tsif].section_channel_ref;
-		buffer_size = TSPP_SECTION_BUFFER_SIZE;
-	}
+	channel_id = TSPP_CHANNEL_ID(tsif, TSPP_CHANNEL);
+	channel_ref_count = &mpq_dmx_tspp_info.tsif[tsif].channel_ref;
+	buffer_size = TSPP_DESCRIPTOR_SIZE;
 
 	/* check if required TSPP pipe is already allocated or not */
 	if (*channel_ref_count == 0) {
+		if (allocation_mode == MPQ_DMX_TSPP_CONTIGUOUS_PHYS_ALLOC) {
+			ret = mpq_dmx_channel_mem_alloc(tsif);
+			if (ret < 0) {
+				MPQ_DVB_ERR_PRINT(
+					"%s: mpq_dmx_channel_mem_alloc(%d) failed (%d)\n",
+					__func__,
+					channel_id,
+					ret);
+
+				goto add_channel_failed;
+			}
+		}
+
 		ret = tspp_open_channel(0, channel_id);
 		if (ret < 0) {
 			MPQ_DVB_ERR_PRINT(
@@ -514,10 +528,6 @@
 		 * big notification size, smallest descriptor, and still provide
 		 * TZ with single big buffer based on notification size.
 		 */
-
-		/* set buffer/descriptor size and count,
-		 * allocate TSPP data buffers
-		 */
 		if (allocation_mode == MPQ_DMX_TSPP_CONTIGUOUS_PHYS_ALLOC) {
 			ret = tspp_allocate_buffers(0, channel_id,
 				   mpq_dmx_tspp_info.tsif[tsif].buffer_count,
@@ -599,6 +609,9 @@
 add_channel_close_ch:
 	tspp_close_channel(0, channel_id);
 add_channel_failed:
+	if (allocation_mode == MPQ_DMX_TSPP_CONTIGUOUS_PHYS_ALLOC)
+		mpq_dmx_channel_mem_free(tsif);
+
 	mutex_unlock(&mpq_dmx_tspp_info.tsif[tsif].mutex);
 	return ret;
 }
@@ -641,18 +654,9 @@
 	if (mutex_lock_interruptible(&mpq_dmx_tspp_info.tsif[tsif].mutex))
 		return -ERESTARTSYS;
 
-	/* determine to which pipe the feed should be routed: section or pes */
-	if ((feed->type == DMX_TYPE_PES) || (feed->type == DMX_TYPE_TS)) {
-		channel_id = TSPP_CHANNEL_ID(tsif, TSPP_PES_CHANNEL);
-		channel_ref_count =
-			&mpq_dmx_tspp_info.tsif[tsif].pes_channel_ref;
-		data_cnt = &mpq_dmx_tspp_info.tsif[tsif].pes_data_cnt;
-	} else {
-		channel_id = TSPP_CHANNEL_ID(tsif, TSPP_SECTION_CHANNEL);
-		channel_ref_count =
-			&mpq_dmx_tspp_info.tsif[tsif].section_channel_ref;
-		data_cnt = &mpq_dmx_tspp_info.tsif[tsif].section_data_cnt;
-	}
+	channel_id = TSPP_CHANNEL_ID(tsif, TSPP_CHANNEL);
+	channel_ref_count = &mpq_dmx_tspp_info.tsif[tsif].channel_ref;
+	data_cnt = &mpq_dmx_tspp_info.tsif[tsif].data_cnt;
 
 	/* check if required TSPP pipe is already allocated or not */
 	if (*channel_ref_count == 0) {
@@ -713,6 +717,9 @@
 		tspp_close_channel(0, channel_id);
 		tspp_close_stream(0, channel_id);
 		atomic_set(data_cnt, 0);
+
+		if (allocation_mode == MPQ_DMX_TSPP_CONTIGUOUS_PHYS_ALLOC)
+			mpq_dmx_channel_mem_free(tsif);
 	}
 
 	mutex_unlock(&mpq_dmx_tspp_info.tsif[tsif].mutex);
@@ -816,7 +823,6 @@
 					const u8 *buf,
 					size_t len)
 {
-
 	/*
 	 * It is assumed that this function is called once for each
 	 * TS packet of the relevant feed.
@@ -919,147 +925,15 @@
 	return 0;
 }
 
-static void mpq_dmx_tsif_ion_cleanup(int i)
-{
-	mpq_dmx_tspp_info.tsif[i].pes_mem_heap_phys_base = 0;
-	mpq_dmx_tspp_info.tsif[i].section_mem_heap_phys_base = 0;
-
-	if (!IS_ERR_OR_NULL(mpq_dmx_tspp_info.tsif[i].pes_mem_heap_handle)) {
-		if (!IS_ERR_OR_NULL(mpq_dmx_tspp_info.tsif[i].
-				pes_mem_heap_virt_base))
-			ion_unmap_kernel(mpq_dmx_tspp_info.ion_client,
-				mpq_dmx_tspp_info.tsif[i].pes_mem_heap_handle);
-
-		ion_free(mpq_dmx_tspp_info.ion_client,
-			mpq_dmx_tspp_info.tsif[i].pes_mem_heap_handle);
-	}
-
-	if (!IS_ERR_OR_NULL(mpq_dmx_tspp_info.tsif[i].
-			section_mem_heap_handle)) {
-		if (!IS_ERR_OR_NULL(mpq_dmx_tspp_info.tsif[i].
-					section_mem_heap_virt_base))
-			ion_unmap_kernel(mpq_dmx_tspp_info.ion_client,
-					mpq_dmx_tspp_info.tsif[i].
-						section_mem_heap_handle);
-
-		ion_free(mpq_dmx_tspp_info.ion_client,
-			mpq_dmx_tspp_info.tsif[i].section_mem_heap_handle);
-	}
-
-	mpq_dmx_tspp_info.tsif[i].pes_mem_heap_virt_base = NULL;
-	mpq_dmx_tspp_info.tsif[i].section_mem_heap_virt_base = NULL;
-	mpq_dmx_tspp_info.tsif[i].pes_mem_heap_handle = NULL;
-	mpq_dmx_tspp_info.tsif[i].section_mem_heap_handle = NULL;
-}
-
-static void mpq_dmx_tspp_ion_cleanup(void)
-{
-	int i;
-
-	for (i = 0; i < TSIF_COUNT; i++)
-		mpq_dmx_tsif_ion_cleanup(i);
-}
-
 static int mpq_tspp_dmx_init(
 			struct dvb_adapter *mpq_adapter,
 			struct mpq_demux *mpq_demux)
 {
-	int i, result;
-	size_t len;
+	int result;
 
 	MPQ_DVB_DBG_PRINT("%s executed\n", __func__);
 
-	if (allocation_mode == MPQ_DMX_TSPP_CONTIGUOUS_PHYS_ALLOC) {
-		/*
-		 * Save ION client, used to allocate memory
-		 * for TSPP's buffers.
-		 */
-		mpq_dmx_tspp_info.ion_client = mpq_demux->ion_client;
-
-		if (IS_ERR_OR_NULL(mpq_dmx_tspp_info.ion_client))
-			return -EINVAL;
-
-		for (i = 0; i < TSIF_COUNT; i++) {
-			mpq_dmx_tspp_info.tsif[i].pes_mem_heap_handle =
-				ion_alloc(mpq_dmx_tspp_info.ion_client,
-				 (mpq_dmx_tspp_info.tsif[i].buffer_count *
-				  TSPP_PES_BUFFER_SIZE),
-				 TSPP_RAW_TTS_SIZE,
-				 ION_HEAP(ION_CP_MM_HEAP_ID),
-				 0); /* non-cached */
-			if (IS_ERR_OR_NULL(mpq_dmx_tspp_info.tsif[i].
-						pes_mem_heap_handle)) {
-				MPQ_DVB_ERR_PRINT("%s: ion_alloc() failed\n",
-						__func__);
-				mpq_dmx_tspp_ion_cleanup();
-				return -ENOMEM;
-			}
-			/* save virtual base address of heap */
-			mpq_dmx_tspp_info.tsif[i].pes_mem_heap_virt_base =
-				ion_map_kernel(mpq_dmx_tspp_info.ion_client,
-					mpq_dmx_tspp_info.tsif[i].
-						pes_mem_heap_handle);
-			if (IS_ERR_OR_NULL(mpq_dmx_tspp_info.tsif[i].
-						pes_mem_heap_virt_base)) {
-				MPQ_DVB_ERR_PRINT(
-					"%s: ion_map_kernel() failed\n",
-					__func__);
-				mpq_dmx_tspp_ion_cleanup();
-				return -ENOMEM;
-			}
-			/* save physical base address of heap */
-			result = ion_phys(mpq_dmx_tspp_info.ion_client,
-				mpq_dmx_tspp_info.tsif[i].pes_mem_heap_handle,
-				&(mpq_dmx_tspp_info.tsif[i].
-					pes_mem_heap_phys_base), &len);
-			if (result < 0) {
-				MPQ_DVB_ERR_PRINT("%s: ion_phys() failed\n",
-						__func__);
-				mpq_dmx_tspp_ion_cleanup();
-				return -ENOMEM;
-			}
-
-			mpq_dmx_tspp_info.tsif[i].section_mem_heap_handle =
-				ion_alloc(mpq_dmx_tspp_info.ion_client,
-				 (mpq_dmx_tspp_info.tsif[i].buffer_count *
-				  TSPP_SECTION_BUFFER_SIZE),
-				 TSPP_RAW_TTS_SIZE,
-				 ION_HEAP(ION_CP_MM_HEAP_ID),
-				 0); /* non-cached */
-			if (IS_ERR_OR_NULL(mpq_dmx_tspp_info.tsif[i].
-						section_mem_heap_handle)) {
-				MPQ_DVB_ERR_PRINT("%s: ion_alloc() failed\n",
-						__func__);
-				mpq_dmx_tspp_ion_cleanup();
-				return -ENOMEM;
-			}
-			/* save virtual base address of heap */
-			mpq_dmx_tspp_info.tsif[i].section_mem_heap_virt_base =
-				ion_map_kernel(mpq_dmx_tspp_info.ion_client,
-				mpq_dmx_tspp_info.tsif[i].
-					section_mem_heap_handle);
-			if (IS_ERR_OR_NULL(mpq_dmx_tspp_info.tsif[i].
-					section_mem_heap_virt_base)) {
-				MPQ_DVB_ERR_PRINT(
-					"%s: ion_map_kernel() failed\n",
-					__func__);
-				mpq_dmx_tspp_ion_cleanup();
-				return -ENOMEM;
-			}
-			/* save physical base address of heap */
-			result = ion_phys(mpq_dmx_tspp_info.ion_client,
-				mpq_dmx_tspp_info.tsif[i].
-					section_mem_heap_handle,
-				&(mpq_dmx_tspp_info.tsif[i].
-					section_mem_heap_phys_base), &len);
-			if (result < 0) {
-				MPQ_DVB_ERR_PRINT("%s: ion_phys() failed\n",
-						__func__);
-				mpq_dmx_tspp_ion_cleanup();
-				return -ENOMEM;
-			}
-		}
-	}
+	mpq_dmx_tspp_info.ion_client = mpq_demux->ion_client;
 
 	/* Set the kernel-demux object capabilities */
 	mpq_demux->demux.dmx.capabilities =
@@ -1090,6 +964,9 @@
 	mpq_demux->demux.decoder_buffer_status =
 		mpq_dmx_decoder_buffer_status;
 
+	mpq_demux->demux.reuse_decoder_buffer =
+		mpq_dmx_reuse_decoder_buffer;
+
 	/* Initialize dvb_demux object */
 	result = dvb_dmx_init(&mpq_demux->demux);
 	if (result < 0) {
@@ -1126,7 +1003,6 @@
 init_failed_dmx_release:
 	dvb_dmx_release(&mpq_demux->demux);
 init_failed:
-	mpq_dmx_tspp_ion_cleanup();
 	return result;
 }
 
@@ -1142,19 +1018,12 @@
 		mpq_dmx_tspp_info.tsif[i].buffer_count =
 				TSPP_BUFFER_COUNT(tspp_out_buffer_size);
 
-		mpq_dmx_tspp_info.tsif[i].pes_channel_ref = 0;
-		mpq_dmx_tspp_info.tsif[i].pes_index = 0;
-		mpq_dmx_tspp_info.tsif[i].pes_mem_heap_handle = NULL;
-		mpq_dmx_tspp_info.tsif[i].pes_mem_heap_virt_base = NULL;
-		mpq_dmx_tspp_info.tsif[i].pes_mem_heap_phys_base = 0;
-		atomic_set(&mpq_dmx_tspp_info.tsif[i].pes_data_cnt, 0);
-
-		mpq_dmx_tspp_info.tsif[i].section_channel_ref = 0;
-		mpq_dmx_tspp_info.tsif[i].section_index = 0;
-		mpq_dmx_tspp_info.tsif[i].section_mem_heap_handle = NULL;
-		mpq_dmx_tspp_info.tsif[i].section_mem_heap_virt_base = NULL;
-		mpq_dmx_tspp_info.tsif[i].section_mem_heap_phys_base = 0;
-		atomic_set(&mpq_dmx_tspp_info.tsif[i].section_data_cnt, 0);
+		mpq_dmx_tspp_info.tsif[i].channel_ref = 0;
+		mpq_dmx_tspp_info.tsif[i].buff_index = 0;
+		mpq_dmx_tspp_info.tsif[i].ch_mem_heap_handle = NULL;
+		mpq_dmx_tspp_info.tsif[i].ch_mem_heap_virt_base = NULL;
+		mpq_dmx_tspp_info.tsif[i].ch_mem_heap_phys_base = 0;
+		atomic_set(&mpq_dmx_tspp_info.tsif[i].data_cnt, 0);
 
 		for (j = 0; j < TSPP_MAX_PID_FILTER_NUM; j++) {
 			mpq_dmx_tspp_info.tsif[i].filters[j].pid = -1;
@@ -1219,24 +1088,17 @@
 		 * even if we allocated them ourselves,
 		 * using our free function.
 		 */
-		if (mpq_dmx_tspp_info.tsif[i].pes_channel_ref) {
-			tspp_unregister_notification(0, TSPP_PES_CHANNEL);
+		if (mpq_dmx_tspp_info.tsif[i].channel_ref) {
+			tspp_unregister_notification(0,
+				TSPP_CHANNEL_ID(i, TSPP_CHANNEL));
 			tspp_close_channel(0,
-				TSPP_CHANNEL_ID(i, TSPP_PES_CHANNEL));
-		}
+				TSPP_CHANNEL_ID(i, TSPP_CHANNEL));
 
-		if (mpq_dmx_tspp_info.tsif[i].section_channel_ref) {
-			tspp_unregister_notification(0, TSPP_SECTION_CHANNEL);
-			tspp_close_channel(0,
-				TSPP_CHANNEL_ID(i, TSPP_SECTION_CHANNEL));
+			if (allocation_mode ==
+				MPQ_DMX_TSPP_CONTIGUOUS_PHYS_ALLOC)
+				mpq_dmx_channel_mem_free(i);
 		}
 
-		/* if we allocated buffer pools
-		 * to TSPP, need to free those as well
-		 */
-		if (allocation_mode == MPQ_DMX_TSPP_CONTIGUOUS_PHYS_ALLOC)
-			mpq_dmx_tsif_ion_cleanup(i);
-
 		mutex_unlock(&mpq_dmx_tspp_info.tsif[i].mutex);
 		kthread_stop(mpq_dmx_tspp_info.tsif[i].thread);
 		mutex_destroy(&mpq_dmx_tspp_info.tsif[i].mutex);
diff --git a/drivers/media/dvb/mpq/demux/mpq_dmx_plugin_tspp_v2.c b/drivers/media/dvb/mpq/demux/mpq_dmx_plugin_tspp_v2.c
index e4858fa..4211d6c 100644
--- a/drivers/media/dvb/mpq/demux/mpq_dmx_plugin_tspp_v2.c
+++ b/drivers/media/dvb/mpq/demux/mpq_dmx_plugin_tspp_v2.c
@@ -125,6 +125,7 @@
 	mpq_demux->demux.decoder_fullness_wait = NULL;
 	mpq_demux->demux.decoder_fullness_abort = NULL;
 	mpq_demux->demux.decoder_buffer_status = NULL;
+	mpq_demux->demux.reuse_decoder_buffer = NULL;
 
 	/* Initialize dvb_demux object */
 	result = dvb_dmx_init(&mpq_demux->demux);
diff --git a/drivers/media/video/msm/msm_v4l2_video.c b/drivers/media/video/msm/msm_v4l2_video.c
index c4e6c62..86a546c 100644
--- a/drivers/media/video/msm/msm_v4l2_video.c
+++ b/drivers/media/video/msm/msm_v4l2_video.c
@@ -140,20 +140,22 @@
 		src_addr = (unsigned long)v4l2_ram_phys
 		+ vout->bufs[buffer->index].offset;
 		src_size = buffer->bytesused;
-		ret = msm_fb_v4l2_update(vout->par, src_addr, src_size,
+		ret = msm_fb_v4l2_update(vout->par, false, src_addr, src_size,
 		0, 0, 0, 0);
 		break;
 	case V4L2_MEMORY_USERPTR:
 		if (copy_from_user(&up_buffer,
 		(void __user *)buffer->m.userptr,
 		sizeof(struct msm_v4l2_overlay_userptr_buffer))) {
+			pr_err("%s:copy_from_user for userptr failed\n",
+				__func__);
 			mutex_unlock(&msmfb_lock);
 			return -EINVAL;
 		}
-		ret = msm_fb_v4l2_update(vout->par,
-		(unsigned long)up_buffer.base[0], up_buffer.length[0],
-		(unsigned long)up_buffer.base[1], up_buffer.length[1],
-		(unsigned long)up_buffer.base[2], up_buffer.length[2]);
+		ret = msm_fb_v4l2_update(vout->par, true,
+		(unsigned long)up_buffer.fd[0], up_buffer.offset[0],
+		(unsigned long)up_buffer.fd[1], up_buffer.offset[1],
+		(unsigned long)up_buffer.fd[2], up_buffer.offset[2]);
 		break;
 	default:
 		mutex_unlock(&msmfb_lock);
@@ -420,6 +422,7 @@
 	struct msm_v4l2_overlay_fh *fh = file->private_data;
 	struct msm_v4l2_overlay_device *vout = fh->vout;
 	int ret;
+	struct v4l2_buffer *buffer = arg;
 
 	switch (cmd) {
 	case VIDIOC_QUERYCAP:
@@ -439,7 +442,14 @@
 
 	case VIDIOC_QBUF:
 		mutex_lock(&vout->update_lock);
-		ret = msm_v4l2_overlay_vidioc_qbuf(file, fh, arg, false);
+		if (buffer->memory == V4L2_MEMORY_USERPTR) {
+			if (!capable(CAP_SYS_RAWIO))
+				return -EPERM;
+			ret = msm_v4l2_overlay_vidioc_qbuf(file, fh, arg, true);
+		} else {
+			ret = msm_v4l2_overlay_vidioc_qbuf(file, fh, arg,
+						false);
+		}
 		mutex_unlock(&vout->update_lock);
 
 		return ret;
diff --git a/drivers/media/video/msm/msm_v4l2_video.h b/drivers/media/video/msm/msm_v4l2_video.h
index a7baa75..9ccfc73 100644
--- a/drivers/media/video/msm/msm_v4l2_video.h
+++ b/drivers/media/video/msm/msm_v4l2_video.h
@@ -52,8 +52,8 @@
 };
 
 struct msm_v4l2_overlay_userptr_buffer {
-	uint base[3];
-	size_t length[3];
+	uint fd[3]; /* ION fd of frame or plane */
+	size_t offset[3]; /* offset of frame or plane in multi buffer case */
 };
 
 #endif
diff --git a/drivers/media/video/msm/server/msm_cam_server.c b/drivers/media/video/msm/server/msm_cam_server.c
index af31748..78d15d9 100644
--- a/drivers/media/video/msm/server/msm_cam_server.c
+++ b/drivers/media/video/msm/server/msm_cam_server.c
@@ -1081,8 +1081,34 @@
 			struct v4l2_event_subscription *sub)
 {
 	int rc = 0;
+	struct v4l2_event ev;
 
 	D("%s: fh = 0x%x\n", __func__, (u32)fh);
+
+	/* Undequeue all pending events and free associated
+	 * msm_isp_event_ctrl  */
+	while (v4l2_event_pending(fh)) {
+		struct msm_isp_event_ctrl *isp_event;
+		rc = v4l2_event_dequeue(fh, &ev, O_NONBLOCK);
+		if (rc) {
+			pr_err("%s: v4l2_event_dequeue failed %d",
+						__func__, rc);
+			break;
+		}
+		isp_event = (struct msm_isp_event_ctrl *)
+			(*((uint32_t *)ev.u.data));
+		if (isp_event) {
+			if (isp_event->isp_data.isp_msg.len != 0 &&
+				isp_event->isp_data.isp_msg.data != NULL) {
+				kfree(isp_event->isp_data.isp_msg.data);
+				isp_event->isp_data.isp_msg.len = 0;
+				isp_event->isp_data.isp_msg.data = NULL;
+			}
+			kfree(isp_event);
+			*((uint32_t *)ev.u.data) = 0;
+		}
+	}
+
 	rc = v4l2_event_unsubscribe(fh, sub);
 	D("%s: rc = %d\n", __func__, rc);
 	return rc;
@@ -1452,7 +1478,7 @@
 			}
 		}
 		sub.type = V4L2_EVENT_ALL;
-		msm_server_v4l2_unsubscribe_event(
+		v4l2_event_unsubscribe(
 			&g_server_dev.server_command_queue.eventHandle, &sub);
 		mutex_unlock(&g_server_dev.server_lock);
 	}
@@ -1645,7 +1671,7 @@
 
 static const struct v4l2_ioctl_ops msm_ioctl_ops_server = {
 	.vidioc_subscribe_event = msm_server_v4l2_subscribe_event,
-	.vidioc_unsubscribe_event = msm_server_v4l2_unsubscribe_event,
+	.vidioc_unsubscribe_event = v4l2_event_unsubscribe,
 	.vidioc_default = msm_ioctl_server,
 };
 
@@ -3103,9 +3129,7 @@
 
 static int msm_close_config(struct inode *node, struct file *f)
 {
-	struct v4l2_event ev;
 	struct v4l2_event_subscription sub;
-	struct msm_isp_event_ctrl *isp_event;
 	struct msm_cam_config_dev *config_cam = f->private_data;
 
 #ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
@@ -3116,20 +3140,6 @@
 	msm_server_v4l2_unsubscribe_event(
 		&config_cam->config_stat_event_queue.eventHandle,
 		&sub);
-	while (v4l2_event_pending(
-		&config_cam->config_stat_event_queue.eventHandle)) {
-		v4l2_event_dequeue(
-			&config_cam->config_stat_event_queue.eventHandle,
-			&ev, O_NONBLOCK);
-		isp_event = (struct msm_isp_event_ctrl *)
-			(*((uint32_t *)ev.u.data));
-		if (isp_event) {
-			if (isp_event->isp_data.isp_msg.len != 0 &&
-				isp_event->isp_data.isp_msg.data != NULL)
-				kfree(isp_event->isp_data.isp_msg.data);
-			kfree(isp_event);
-		}
-	}
 	return 0;
 }
 
diff --git a/drivers/media/video/msm_vidc/Makefile b/drivers/media/video/msm_vidc/Makefile
index 2a1f40f..da829cc 100644
--- a/drivers/media/video/msm_vidc/Makefile
+++ b/drivers/media/video/msm_vidc/Makefile
@@ -5,5 +5,7 @@
 				msm_venc.o \
 				msm_smem.o \
 				msm_vidc_debug.o \
-				vidc_hal.o \
-				vidc_hal_interrupt_handler.o \
+				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
new file mode 100644
index 0000000..509b013
--- /dev/null
+++ b/drivers/media/video/msm_vidc/hfi_packetization.c
@@ -0,0 +1,1101 @@
+/* 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 "hfi_packetization.h"
+#include "msm_vidc_debug.h"
+#include <linux/errno.h>
+#include <mach/ocmem.h>
+
+int create_pkt_cmd_sys_init(struct hfi_cmd_sys_init_packet *pkt,
+			   u32 arch_type)
+{
+	int rc = 0;
+	if (!pkt)
+		return -EINVAL;
+
+	pkt->packet_type = HFI_CMD_SYS_INIT;
+	pkt->size = sizeof(struct hfi_cmd_sys_init_packet);
+	pkt->arch_type = arch_type;
+	return rc;
+}
+
+int create_pkt_cmd_sys_pc_prep(struct hfi_cmd_sys_pc_prep_packet *pkt)
+{
+	int rc = 0;
+	if (!pkt)
+		return -EINVAL;
+
+	pkt->packet_type = HFI_CMD_SYS_PC_PREP;
+	pkt->size = sizeof(struct hfi_cmd_sys_pc_prep_packet);
+	return rc;
+}
+
+int create_pkt_set_cmd_sys_resource(
+		struct hfi_cmd_sys_set_resource_packet *pkt,
+		struct vidc_resource_hdr *resource_hdr,
+		void *resource_value)
+{
+	int rc = 0;
+	if (!pkt || !resource_hdr || !resource_value)
+		return -EINVAL;
+
+	pkt->packet_type = HFI_CMD_SYS_SET_RESOURCE;
+	pkt->size = sizeof(struct hfi_cmd_sys_set_resource_packet);
+	pkt->resource_handle = resource_hdr->resource_handle;
+
+	switch (resource_hdr->resource_id) {
+	case VIDC_RESOURCE_OCMEM:
+	{
+		struct hfi_resource_ocmem *hfioc_mem =
+			(struct hfi_resource_ocmem *)
+			&pkt->rg_resource_data[0];
+		struct ocmem_buf *ocmem =
+			(struct ocmem_buf *) resource_value;
+
+		pkt->resource_type = HFI_RESOURCE_OCMEM;
+		pkt->size += sizeof(struct hfi_resource_ocmem);
+		hfioc_mem->size = (u32) ocmem->len;
+		hfioc_mem->mem = (u8 *) ocmem->addr;
+		break;
+	}
+	default:
+		dprintk(VIDC_ERR, "Invalid resource_id %d",
+					resource_hdr->resource_id);
+		rc = -EINVAL;
+	}
+
+	return rc;
+}
+
+int create_pkt_cmd_sys_release_resource(
+		struct hfi_cmd_sys_release_resource_packet *pkt,
+		struct vidc_resource_hdr *resource_hdr)
+{
+	int rc = 0;
+	if (!pkt)
+		return -EINVAL;
+
+	pkt->size = sizeof(struct hfi_cmd_sys_release_resource_packet);
+	pkt->packet_type = HFI_CMD_SYS_RELEASE_RESOURCE;
+	pkt->resource_type = resource_hdr->resource_id;
+	pkt->resource_handle = resource_hdr->resource_handle;
+
+	return rc;
+}
+
+int create_pkt_cmd_sys_ping(struct hfi_cmd_sys_ping_packet *pkt)
+{
+	int rc = 0;
+	if (!pkt)
+		return -EINVAL;
+
+	pkt->size = sizeof(struct hfi_cmd_sys_ping_packet);
+	pkt->packet_type = HFI_CMD_SYS_PING;
+
+	return rc;
+}
+
+inline int create_pkt_cmd_sys_session_init(
+		struct hfi_cmd_sys_session_init_packet *pkt,
+		u32 session_id, u32 session_domain, u32 session_codec)
+{
+	int rc = 0;
+	if (!pkt)
+		return -EINVAL;
+
+	pkt->size = sizeof(struct hfi_cmd_sys_session_init_packet);
+	pkt->packet_type = HFI_CMD_SYS_SESSION_INIT;
+	pkt->session_id = session_id;
+	pkt->session_domain = session_domain;
+	pkt->session_codec = session_codec;
+
+	return rc;
+}
+
+int create_pkt_cmd_session_cmd(struct vidc_hal_session_cmd_pkt *pkt,
+			int pkt_type, u32 session_id)
+{
+	int rc = 0;
+	if (!pkt)
+		return -EINVAL;
+
+	pkt->size = sizeof(struct vidc_hal_session_cmd_pkt);
+	pkt->packet_type = pkt_type;
+	pkt->session_id = session_id;
+
+	return rc;
+}
+
+static u32 get_hfi_buffer(int hal_buffer)
+{
+	u32 buffer;
+	switch (hal_buffer) {
+	case HAL_BUFFER_INPUT:
+		buffer = HFI_BUFFER_INPUT;
+		break;
+	case HAL_BUFFER_OUTPUT:
+		buffer = HFI_BUFFER_OUTPUT;
+		break;
+	case HAL_BUFFER_OUTPUT2:
+		buffer = HFI_BUFFER_OUTPUT;
+		break;
+	case HAL_BUFFER_EXTRADATA_INPUT:
+		buffer = HFI_BUFFER_EXTRADATA_INPUT;
+		break;
+	case HAL_BUFFER_EXTRADATA_OUTPUT:
+		buffer = HFI_BUFFER_EXTRADATA_OUTPUT;
+		break;
+	case HAL_BUFFER_EXTRADATA_OUTPUT2:
+		buffer = HFI_BUFFER_EXTRADATA_OUTPUT2;
+		break;
+	case HAL_BUFFER_INTERNAL_SCRATCH:
+		buffer = HFI_BUFFER_INTERNAL_SCRATCH;
+		break;
+	case HAL_BUFFER_INTERNAL_PERSIST:
+		buffer = HFI_BUFFER_INTERNAL_PERSIST;
+		break;
+	default:
+		dprintk(VIDC_ERR, "Invalid buffer :0x%x\n",
+				hal_buffer);
+		buffer = 0;
+		break;
+	}
+	return buffer;
+}
+
+static int get_hfi_extradata_index(enum hal_extradata_id index)
+{
+	int ret = 0;
+	switch (index) {
+	case HAL_EXTRADATA_MB_QUANTIZATION:
+		ret = HFI_PROPERTY_PARAM_VDEC_MB_QUANTIZATION;
+		break;
+	case HAL_EXTRADATA_INTERLACE_VIDEO:
+		ret = HFI_PROPERTY_PARAM_VDEC_INTERLACE_VIDEO_EXTRADATA;
+		break;
+	case HAL_EXTRADATA_VC1_FRAMEDISP:
+		ret = HFI_PROPERTY_PARAM_VDEC_VC1_FRAMEDISP_EXTRADATA;
+		break;
+	case HAL_EXTRADATA_VC1_SEQDISP:
+		ret = HFI_PROPERTY_PARAM_VDEC_VC1_SEQDISP_EXTRADATA;
+		break;
+	case HAL_EXTRADATA_TIMESTAMP:
+		ret = HFI_PROPERTY_PARAM_VDEC_TIMESTAMP_EXTRADATA;
+		break;
+	case HAL_EXTRADATA_S3D_FRAME_PACKING:
+		ret = HFI_PROPERTY_PARAM_S3D_FRAME_PACKING_EXTRADATA;
+		break;
+	case HAL_EXTRADATA_FRAME_RATE:
+		ret = HFI_PROPERTY_PARAM_VDEC_FRAME_RATE_EXTRADATA;
+		break;
+	case HAL_EXTRADATA_PANSCAN_WINDOW:
+		ret = HFI_PROPERTY_PARAM_VDEC_PANSCAN_WNDW_EXTRADATA;
+		break;
+	case HAL_EXTRADATA_RECOVERY_POINT_SEI:
+		ret = HFI_PROPERTY_PARAM_VDEC_RECOVERY_POINT_SEI_EXTRADATA;
+		break;
+	case HAL_EXTRADATA_CLOSED_CAPTION_UD:
+		ret = HFI_PROPERTY_PARAM_VDEC_CLOSED_CAPTION_EXTRADATA;
+		break;
+	case HAL_EXTRADATA_AFD_UD:
+		ret = HFI_PROPERTY_PARAM_VDEC_AFD_EXTRADATA;
+		break;
+	case HAL_EXTRADATA_MULTISLICE_INFO:
+		ret = HFI_PROPERTY_PARAM_VENC_MULTI_SLICE_INFO;
+		break;
+	case HAL_EXTRADATA_NUM_CONCEALED_MB:
+		ret = HFI_PROPERTY_PARAM_VDEC_NUM_CONCEALED_MB;
+		break;
+	case HAL_EXTRADATA_INDEX:
+		ret = HFI_PROPERTY_PARAM_EXTRA_DATA_HEADER_CONFIG;
+		break;
+	default:
+		dprintk(VIDC_WARN, "Extradata index not found: %d\n", index);
+		break;
+	}
+	return ret;
+}
+
+int create_pkt_cmd_session_set_buffers(
+		struct hfi_cmd_session_set_buffers_packet *pkt,
+		u32 session_id,
+		struct vidc_buffer_addr_info *buffer_info)
+{
+	int rc = 0;
+	int i = 0;
+	if (!pkt || !session_id)
+		return -EINVAL;
+
+	pkt->packet_type = HFI_CMD_SESSION_SET_BUFFERS;
+	pkt->session_id = session_id;
+	pkt->buffer_size = buffer_info->buffer_size;
+	pkt->min_buffer_size = buffer_info->buffer_size;
+	pkt->num_buffers = buffer_info->num_buffers;
+
+	if ((buffer_info->buffer_type == HAL_BUFFER_OUTPUT) ||
+		(buffer_info->buffer_type == HAL_BUFFER_OUTPUT2)) {
+		struct hfi_buffer_info *buff;
+		pkt->extra_data_size = buffer_info->extradata_size;
+		pkt->size = sizeof(struct hfi_cmd_session_set_buffers_packet) -
+				sizeof(u32) + (buffer_info->num_buffers *
+				sizeof(struct hfi_buffer_info));
+		buff = (struct hfi_buffer_info *) pkt->rg_buffer_info;
+		for (i = 0; i < pkt->num_buffers; i++) {
+			buff->buffer_addr = buffer_info->align_device_addr;
+			buff->extra_data_addr = buffer_info->extradata_addr;
+		}
+	} else {
+		pkt->extra_data_size = 0;
+		pkt->size = sizeof(struct hfi_cmd_session_set_buffers_packet) +
+			((buffer_info->num_buffers - 1) * sizeof(u32));
+		for (i = 0; i < pkt->num_buffers; i++)
+			pkt->rg_buffer_info[i] = buffer_info->align_device_addr;
+	}
+
+	pkt->buffer_type = get_hfi_buffer(buffer_info->buffer_type);
+	if (!pkt->buffer_type)
+		return -EINVAL;
+
+	return rc;
+}
+
+int create_pkt_cmd_session_release_buffers(
+		struct hfi_cmd_session_release_buffer_packet *pkt,
+		u32 session_id, struct vidc_buffer_addr_info *buffer_info)
+{
+	int rc = 0;
+	int i = 0;
+	if (!pkt || !session_id)
+		return -EINVAL;
+
+	pkt->packet_type = HFI_CMD_SESSION_RELEASE_BUFFERS;
+	pkt->session_id = session_id;
+	pkt->buffer_size = buffer_info->buffer_size;
+	pkt->num_buffers = buffer_info->num_buffers;
+
+	if ((buffer_info->buffer_type == HAL_BUFFER_OUTPUT) ||
+		(buffer_info->buffer_type == HAL_BUFFER_OUTPUT2)) {
+		struct hfi_buffer_info *buff;
+		buff = (struct hfi_buffer_info *) pkt->rg_buffer_info;
+		for (i = 0; i < pkt->num_buffers; i++) {
+			buff->buffer_addr = buffer_info->align_device_addr;
+			buff->extra_data_addr = buffer_info->extradata_addr;
+		}
+		pkt->size = sizeof(struct hfi_cmd_session_set_buffers_packet) -
+				sizeof(u32) + (buffer_info->num_buffers *
+				sizeof(struct hfi_buffer_info));
+	} else {
+		for (i = 0; i < pkt->num_buffers; i++)
+			pkt->rg_buffer_info[i] = buffer_info->align_device_addr;
+		pkt->extra_data_size = 0;
+		pkt->size = sizeof(struct hfi_cmd_session_set_buffers_packet) +
+			((buffer_info->num_buffers - 1) * sizeof(u32));
+	}
+	pkt->response_req = buffer_info->response_required;
+	pkt->buffer_type = get_hfi_buffer(buffer_info->buffer_type);
+	if (!pkt->buffer_type)
+		return -EINVAL;
+	return rc;
+}
+
+int create_pkt_cmd_session_etb_decoder(
+	struct hfi_cmd_session_empty_buffer_compressed_packet *pkt,
+	u32 session_id, struct vidc_frame_data *input_frame)
+{
+	int rc = 0;
+	if (!pkt || !session_id)
+		return -EINVAL;
+
+	pkt->size =
+		sizeof(struct hfi_cmd_session_empty_buffer_compressed_packet);
+	pkt->packet_type = HFI_CMD_SESSION_EMPTY_BUFFER;
+	pkt->session_id = session_id;
+	pkt->time_stamp_hi = (int) (((u64)input_frame->timestamp) >> 32);
+	pkt->time_stamp_lo = (int) input_frame->timestamp;
+	pkt->flags = input_frame->flags;
+	pkt->mark_target = input_frame->mark_target;
+	pkt->mark_data = input_frame->mark_data;
+	pkt->offset = input_frame->offset;
+	pkt->alloc_len = input_frame->alloc_len;
+	pkt->filled_len = input_frame->filled_len;
+	pkt->input_tag = input_frame->clnt_data;
+	pkt->packet_buffer = (u8 *) input_frame->device_addr;
+
+	if (!pkt->packet_buffer)
+		return -EINVAL;
+	return rc;
+}
+
+int create_pkt_cmd_session_etb_encoder(
+	struct hfi_cmd_session_empty_buffer_uncompressed_plane0_packet *pkt,
+	u32 session_id, struct vidc_frame_data *input_frame)
+{
+	int rc = 0;
+	if (!pkt || !session_id)
+		return -EINVAL;
+
+	pkt->size = sizeof(struct
+		hfi_cmd_session_empty_buffer_uncompressed_plane0_packet);
+	pkt->packet_type = HFI_CMD_SESSION_EMPTY_BUFFER;
+	pkt->session_id = session_id;
+	pkt->view_id = 0;
+	pkt->time_stamp_hi = (u32)(((u64)input_frame->timestamp) >> 32);
+	pkt->time_stamp_lo = (u32)input_frame->timestamp;
+	pkt->flags = input_frame->flags;
+	pkt->mark_target = input_frame->mark_target;
+	pkt->mark_data = input_frame->mark_data;
+	pkt->offset = input_frame->offset;
+	pkt->alloc_len = input_frame->alloc_len;
+	pkt->filled_len = input_frame->filled_len;
+	pkt->input_tag = input_frame->clnt_data;
+	pkt->packet_buffer = (u8 *) input_frame->device_addr;
+
+	if (!pkt->packet_buffer)
+		return -EINVAL;
+	return rc;
+}
+
+int create_pkt_cmd_session_ftb(struct hfi_cmd_session_fill_buffer_packet *pkt,
+		u32 session_id, struct vidc_frame_data *output_frame)
+{
+	int rc = 0;
+	if (!pkt || !session_id || !output_frame)
+		return -EINVAL;
+
+	pkt->size = sizeof(struct hfi_cmd_session_fill_buffer_packet);
+	pkt->packet_type = HFI_CMD_SESSION_FILL_BUFFER;
+	pkt->session_id = session_id;
+
+	if (output_frame->buffer_type == HAL_BUFFER_OUTPUT)
+		pkt->stream_id = 0;
+	else if (output_frame->buffer_type == HAL_BUFFER_OUTPUT2)
+		pkt->stream_id = 1;
+
+	if (!output_frame->device_addr)
+		return -EINVAL;
+
+	pkt->packet_buffer = (u8 *) output_frame->device_addr;
+	pkt->extra_data_buffer = (u8 *) output_frame->extradata_addr;
+
+	pkt->alloc_len = output_frame->alloc_len;
+	pkt->filled_len = output_frame->filled_len;
+	pkt->offset = output_frame->offset;
+	dprintk(VIDC_DBG, "### Q OUTPUT BUFFER ###: %d, %d, %d\n",
+			pkt->alloc_len, pkt->filled_len, pkt->offset);
+
+	return rc;
+}
+
+int create_pkt_cmd_session_parse_seq_header(
+		struct hfi_cmd_session_parse_sequence_header_packet *pkt,
+		u32 session_id, struct vidc_seq_hdr *seq_hdr)
+{
+	int rc = 0;
+	if (!pkt || !session_id || seq_hdr)
+		return -EINVAL;
+
+	pkt->size = sizeof(struct hfi_cmd_session_parse_sequence_header_packet);
+	pkt->packet_type = HFI_CMD_SESSION_PARSE_SEQUENCE_HEADER;
+	pkt->session_id = session_id;
+	pkt->header_len = seq_hdr->seq_hdr_len;
+	if (!seq_hdr->seq_hdr)
+		return -EINVAL;
+	pkt->packet_buffer = seq_hdr->seq_hdr;
+
+	return rc;
+}
+
+int create_pkt_cmd_session_get_seq_hdr(
+		struct hfi_cmd_session_get_sequence_header_packet *pkt,
+		u32 session_id, struct vidc_seq_hdr *seq_hdr)
+{
+	int rc = 0;
+
+	if (!pkt || !session_id || !seq_hdr)
+		return -EINVAL;
+
+	pkt->size = sizeof(struct hfi_cmd_session_get_sequence_header_packet);
+	pkt->packet_type = HFI_CMD_SESSION_GET_SEQUENCE_HEADER;
+	pkt->session_id = session_id;
+	pkt->buffer_len = seq_hdr->seq_hdr_len;
+	if (!seq_hdr->seq_hdr)
+		return -EINVAL;
+	pkt->packet_buffer = seq_hdr->seq_hdr;
+
+	return rc;
+}
+
+int create_pkt_cmd_session_get_buf_req(
+		struct hfi_cmd_session_get_property_packet *pkt,
+		u32 session_id)
+{
+	int rc = 0;
+
+	if (!pkt || !session_id)
+		return -EINVAL;
+
+	pkt->size = sizeof(struct hfi_cmd_session_get_property_packet);
+	pkt->packet_type = HFI_CMD_SESSION_GET_PROPERTY;
+	pkt->session_id = session_id;
+	pkt->num_properties = 1;
+	pkt->rg_property_data[0] = HFI_PROPERTY_CONFIG_BUFFER_REQUIREMENTS;
+
+	return rc;
+}
+
+int create_pkt_cmd_session_flush(struct hfi_cmd_session_flush_packet *pkt,
+			u32 session_id, enum hal_flush flush_mode)
+{
+	int rc = 0;
+	if (!pkt || !session_id)
+		return -EINVAL;
+
+	pkt->size = sizeof(struct hfi_cmd_session_flush_packet);
+	pkt->packet_type = HFI_CMD_SESSION_FLUSH;
+	pkt->session_id = session_id;
+	switch (flush_mode) {
+	case HAL_FLUSH_INPUT:
+		pkt->flush_type = HFI_FLUSH_INPUT;
+		break;
+	case HAL_FLUSH_OUTPUT:
+		pkt->flush_type = HFI_FLUSH_OUTPUT;
+		break;
+	case HAL_FLUSH_OUTPUT2:
+		pkt->flush_type = HFI_FLUSH_OUTPUT2;
+		break;
+	case HAL_FLUSH_ALL:
+		pkt->flush_type = HFI_FLUSH_ALL;
+		break;
+	default:
+		dprintk(VIDC_ERR, "Invalid flush mode: 0x%x\n", flush_mode);
+		return -EINVAL;
+	}
+	return rc;
+}
+
+int create_pkt_cmd_session_set_property(
+		struct hfi_cmd_session_set_property_packet *pkt,
+		u32 session_id, enum hal_property ptype, void *pdata)
+{
+	int rc = 0;
+	if (!pkt || !session_id)
+		return -EINVAL;
+
+	pkt->size = sizeof(struct hfi_cmd_session_set_property_packet);
+	pkt->packet_type = HFI_CMD_SESSION_SET_PROPERTY;
+	pkt->session_id = session_id;
+	pkt->num_properties = 1;
+
+	switch (ptype) {
+	case HAL_CONFIG_FRAME_RATE:
+	{
+		u32 buffer_type;
+		struct hfi_frame_rate *hfi;
+		struct hal_frame_rate *prop = (struct hal_frame_rate *) pdata;
+
+		pkt->rg_property_data[0] = HFI_PROPERTY_CONFIG_FRAME_RATE;
+		hfi = (struct hfi_frame_rate *) &pkt->rg_property_data[1];
+		buffer_type = get_hfi_buffer(prop->buffer_type);
+		if (buffer_type)
+			hfi->buffer_type = buffer_type;
+		else
+			return -EINVAL;
+
+		hfi->frame_rate = prop->frame_rate;
+		pkt->size += sizeof(u32) + sizeof(struct hfi_frame_rate);
+		break;
+	}
+	case HAL_PARAM_UNCOMPRESSED_FORMAT_SELECT:
+	{
+		u32 buffer_type;
+		struct hfi_uncompressed_format_select *hfi;
+		struct hal_uncompressed_format_select *prop =
+			(struct hal_uncompressed_format_select *) pdata;
+
+		pkt->rg_property_data[0] =
+			HFI_PROPERTY_PARAM_UNCOMPRESSED_FORMAT_SELECT;
+
+		hfi = (struct hfi_uncompressed_format_select *)
+					&pkt->rg_property_data[1];
+		buffer_type = get_hfi_buffer(prop->buffer_type);
+		if (buffer_type)
+			hfi->buffer_type = buffer_type;
+		else
+			return -EINVAL;
+		hfi->format = prop->format;
+		pkt->size += sizeof(u32) +
+			sizeof(struct hfi_uncompressed_format_select);
+		break;
+		}
+	case HAL_PARAM_UNCOMPRESSED_PLANE_ACTUAL_CONSTRAINTS_INFO:
+		break;
+	case HAL_PARAM_UNCOMPRESSED_PLANE_ACTUAL_INFO:
+		break;
+	case HAL_PARAM_EXTRA_DATA_HEADER_CONFIG:
+		break;
+	case HAL_PARAM_FRAME_SIZE:
+	{
+		struct hfi_frame_size *hfi;
+		struct hal_frame_size *prop = (struct hal_frame_size *) pdata;
+		u32 buffer_type;
+
+		pkt->rg_property_data[0] = HFI_PROPERTY_PARAM_FRAME_SIZE;
+		hfi = (struct hfi_frame_size *) &pkt->rg_property_data[1];
+		buffer_type = get_hfi_buffer(prop->buffer_type);
+		if (buffer_type)
+			hfi->buffer_type = buffer_type;
+		else
+			return -EINVAL;
+
+		hfi->height = prop->height;
+		hfi->width = prop->width;
+		pkt->size += sizeof(u32) + sizeof(struct hfi_frame_size);
+		break;
+	}
+	case HAL_CONFIG_REALTIME:
+	{
+		struct hfi_enable *hfi;
+		pkt->rg_property_data[0] = HFI_PROPERTY_CONFIG_REALTIME;
+		hfi = (struct hfi_enable *) &pkt->rg_property_data[1];
+		hfi->enable = ((struct hfi_enable *) pdata)->enable;
+		pkt->size += sizeof(u32) * 2;
+		break;
+	}
+	case HAL_PARAM_BUFFER_COUNT_ACTUAL:
+	{
+		struct hfi_buffer_count_actual *hfi;
+		struct hal_buffer_count_actual *prop =
+			(struct hal_buffer_count_actual *) pdata;
+		u32 buffer_type;
+		pkt->rg_property_data[0] =
+			HFI_PROPERTY_PARAM_BUFFER_COUNT_ACTUAL;
+		hfi = (struct hfi_buffer_count_actual *)
+			&pkt->rg_property_data[1];
+		hfi->buffer_count_actual = prop->buffer_count_actual;
+
+		buffer_type = get_hfi_buffer(prop->buffer_type);
+		if (buffer_type)
+			hfi->buffer_type = buffer_type;
+		else
+			return -EINVAL;
+
+		pkt->size += sizeof(u32) + sizeof(struct
+				hfi_buffer_count_actual);
+
+		break;
+	}
+	case HAL_PARAM_NAL_STREAM_FORMAT_SELECT:
+	{
+		struct hal_nal_stream_format_supported *prop =
+			(struct hal_nal_stream_format_supported *)pdata;
+		pkt->rg_property_data[0] =
+			HFI_PROPERTY_PARAM_NAL_STREAM_FORMAT_SELECT;
+		dprintk(VIDC_DBG, "data is :%d",
+				prop->nal_stream_format_supported);
+
+		switch (prop->nal_stream_format_supported) {
+		case HAL_NAL_FORMAT_STARTCODES:
+			pkt->rg_property_data[1] =
+				HFI_NAL_FORMAT_STARTCODES;
+			break;
+		case HAL_NAL_FORMAT_ONE_NAL_PER_BUFFER:
+			pkt->rg_property_data[1] =
+				HFI_NAL_FORMAT_ONE_NAL_PER_BUFFER;
+			break;
+		case HAL_NAL_FORMAT_ONE_BYTE_LENGTH:
+			pkt->rg_property_data[1] =
+				HFI_NAL_FORMAT_ONE_BYTE_LENGTH;
+			break;
+		case HAL_NAL_FORMAT_TWO_BYTE_LENGTH:
+			pkt->rg_property_data[1] =
+				HFI_NAL_FORMAT_TWO_BYTE_LENGTH;
+			break;
+		case HAL_NAL_FORMAT_FOUR_BYTE_LENGTH:
+			pkt->rg_property_data[1] =
+				HFI_NAL_FORMAT_FOUR_BYTE_LENGTH;
+			break;
+		default:
+			dprintk(VIDC_ERR, "Invalid nal format: 0x%x",
+				  prop->nal_stream_format_supported);
+			break;
+		}
+		pkt->size += sizeof(u32) * 2;
+		break;
+	}
+	case HAL_PARAM_VDEC_OUTPUT_ORDER:
+	{
+		int *data = (int *) pdata;
+		pkt->rg_property_data[0] =
+				HFI_PROPERTY_PARAM_VDEC_OUTPUT_ORDER;
+		switch (*data) {
+		case HAL_OUTPUT_ORDER_DECODE:
+			pkt->rg_property_data[1] = HFI_OUTPUT_ORDER_DECODE;
+			break;
+		case HAL_OUTPUT_ORDER_DISPLAY:
+			pkt->rg_property_data[1] = HFI_OUTPUT_ORDER_DISPLAY;
+			break;
+		default:
+			dprintk(VIDC_ERR, "invalid output order: 0x%x",
+						  *data);
+			break;
+		}
+		pkt->size += sizeof(u32) * 2;
+		break;
+	}
+	case HAL_PARAM_VDEC_PICTURE_TYPE_DECODE:
+	{
+		struct hfi_enable_picture *hfi;
+		pkt->rg_property_data[0] =
+			HFI_PROPERTY_PARAM_VDEC_PICTURE_TYPE_DECODE;
+		hfi = (struct hfi_enable_picture *) &pkt->rg_property_data[1];
+		hfi->picture_type = (u32) pdata;
+		pkt->size += sizeof(u32) * 2;
+		break;
+	}
+	case HAL_PARAM_VDEC_OUTPUT2_KEEP_ASPECT_RATIO:
+	{
+		struct hfi_enable *hfi;
+		pkt->rg_property_data[0] =
+			HFI_PROPERTY_PARAM_VDEC_OUTPUT2_KEEP_ASPECT_RATIO;
+		hfi = (struct hfi_enable *) &pkt->rg_property_data[1];
+		hfi->enable = ((struct hfi_enable *) pdata)->enable;
+		pkt->size += sizeof(u32) * 2;
+		break;
+	}
+	case HAL_CONFIG_VDEC_POST_LOOP_DEBLOCKER:
+	{
+		struct hfi_enable *hfi;
+		pkt->rg_property_data[0] =
+			HFI_PROPERTY_CONFIG_VDEC_POST_LOOP_DEBLOCKER;
+		hfi = (struct hfi_enable *) &pkt->rg_property_data[1];
+		hfi->enable = ((struct hfi_enable *) pdata)->enable;
+		pkt->size += sizeof(u32) * 2;
+		break;
+	}
+	case HAL_PARAM_VDEC_MULTI_STREAM:
+	{
+		struct hfi_multi_stream *hfi;
+		struct hal_multi_stream *prop =
+			(struct hal_multi_stream *) pdata;
+		u32 buffer_type;
+		pkt->rg_property_data[0] =
+			HFI_PROPERTY_PARAM_VDEC_MULTI_STREAM;
+		hfi = (struct hfi_multi_stream *) &pkt->rg_property_data[1];
+
+		buffer_type = get_hfi_buffer(prop->buffer_type);
+		if (buffer_type)
+			hfi->buffer_type = buffer_type;
+		else
+			return -EINVAL;
+		hfi->enable = prop->enable;
+		hfi->width = prop->width;
+		hfi->height = prop->height;
+		pkt->size += sizeof(u32) + sizeof(struct hfi_multi_stream);
+		break;
+	}
+	case HAL_PARAM_VDEC_DISPLAY_PICTURE_BUFFER_COUNT:
+	{
+		struct hfi_display_picture_buffer_count *hfi;
+		struct hal_display_picture_buffer_count *prop =
+			(struct hal_display_picture_buffer_count *) pdata;
+		pkt->rg_property_data[0] =
+			HFI_PROPERTY_PARAM_VDEC_DISPLAY_PICTURE_BUFFER_COUNT;
+		hfi = (struct hfi_display_picture_buffer_count *)
+			&pkt->rg_property_data[1];
+		hfi->count = prop->count;
+		hfi->enable = prop->enable;
+		pkt->size += sizeof(u32) +
+			sizeof(struct hfi_display_picture_buffer_count);
+		break;
+	}
+	case HAL_PARAM_DIVX_FORMAT:
+	{
+		int *data = pdata;
+		pkt->rg_property_data[0] = HFI_PROPERTY_PARAM_DIVX_FORMAT;
+		switch (*data) {
+		case HAL_DIVX_FORMAT_4:
+			pkt->rg_property_data[1] = HFI_DIVX_FORMAT_4;
+			break;
+		case HAL_DIVX_FORMAT_5:
+			pkt->rg_property_data[1] = HFI_DIVX_FORMAT_5;
+			break;
+		case HAL_DIVX_FORMAT_6:
+			pkt->rg_property_data[1] = HFI_DIVX_FORMAT_6;
+			break;
+		default:
+			dprintk(VIDC_ERR, "Invalid divx format: 0x%x", *data);
+			break;
+		}
+		pkt->size += sizeof(u32) * 2;
+		break;
+	}
+	case HAL_CONFIG_VDEC_MB_ERROR_MAP_REPORTING:
+	{
+		struct hfi_enable *hfi;
+		pkt->rg_property_data[0] =
+			HFI_PROPERTY_CONFIG_VDEC_MB_ERROR_MAP_REPORTING;
+		hfi = (struct hfi_enable *) &pkt->rg_property_data[1];
+		hfi->enable = ((struct hfi_enable *) pdata)->enable;
+		pkt->size += sizeof(u32) * 2;
+		break;
+	}
+	case HAL_PARAM_VDEC_CONTINUE_DATA_TRANSFER:
+	{
+		struct hfi_enable *hfi;
+		pkt->rg_property_data[0] =
+			HFI_PROPERTY_PARAM_VDEC_CONTINUE_DATA_TRANSFER;
+		hfi = (struct hfi_enable *) &pkt->rg_property_data[1];
+		hfi->enable = ((struct hfi_enable *) pdata)->enable;
+		pkt->size += sizeof(u32) * 2;
+		break;
+	}
+	case HAL_PARAM_VDEC_SYNC_FRAME_DECODE:
+	{
+		struct hfi_enable *hfi;
+		pkt->rg_property_data[0] =
+			HFI_PROPERTY_PARAM_VDEC_THUMBNAIL_MODE;
+		hfi = (struct hfi_enable *) &pkt->rg_property_data[1];
+		hfi->enable = ((struct hfi_enable *) pdata)->enable;
+		pkt->size += sizeof(u32) * 2;
+		break;
+	}
+	case HAL_PARAM_VENC_SYNC_FRAME_SEQUENCE_HEADER:
+	{
+		struct hfi_enable *hfi;
+		pkt->rg_property_data[0] =
+			HFI_PROPERTY_CONFIG_VENC_SYNC_FRAME_SEQUENCE_HEADER;
+		hfi = (struct hfi_enable *) &pkt->rg_property_data[1];
+		hfi->enable = ((struct hfi_enable *) pdata)->enable;
+		pkt->size += sizeof(u32) * 2;
+		break;
+	}
+	case HAL_CONFIG_VENC_REQUEST_IFRAME:
+		pkt->rg_property_data[0] =
+			HFI_PROPERTY_CONFIG_VENC_REQUEST_SYNC_FRAME;
+		pkt->size += sizeof(u32);
+		break;
+	case HAL_PARAM_VENC_MPEG4_SHORT_HEADER:
+		break;
+	case HAL_PARAM_VENC_MPEG4_AC_PREDICTION:
+		break;
+	case HAL_CONFIG_VENC_TARGET_BITRATE:
+	{
+		struct hfi_bitrate *hfi;
+		pkt->rg_property_data[0] =
+			HFI_PROPERTY_CONFIG_VENC_TARGET_BITRATE;
+		hfi = (struct hfi_bitrate *) &pkt->rg_property_data[1];
+		hfi->bit_rate = ((struct hal_bitrate *)pdata)->bit_rate;
+		pkt->size += sizeof(u32) * 2;
+		break;
+	}
+	case HAL_PARAM_PROFILE_LEVEL_CURRENT:
+	{
+		struct hfi_profile_level *hfi;
+		struct hal_profile_level *prop =
+			(struct hal_profile_level *) pdata;
+		pkt->rg_property_data[0] =
+			HFI_PROPERTY_PARAM_PROFILE_LEVEL_CURRENT;
+		hfi = (struct hfi_profile_level *)
+			&pkt->rg_property_data[1];
+		hfi->level = (u32) prop->level;
+		hfi->profile = prop->profile;
+		if (!hfi->profile)
+			hfi->profile = HFI_H264_PROFILE_HIGH;
+		if (!hfi->level)
+			hfi->level = 1;
+		pkt->size += sizeof(u32) + sizeof(struct hfi_profile_level);
+		break;
+	}
+	case HAL_PARAM_VENC_H264_ENTROPY_CONTROL:
+	{
+		struct hfi_h264_entropy_control *hfi;
+		struct hal_h264_entropy_control *prop =
+			(struct hal_h264_entropy_control *) pdata;
+		pkt->rg_property_data[0] =
+			HFI_PROPERTY_PARAM_VENC_H264_ENTROPY_CONTROL;
+		hfi = (struct hfi_h264_entropy_control *)
+			&pkt->rg_property_data[1];
+		switch (prop->entropy_mode) {
+		case HAL_H264_ENTROPY_CAVLC:
+			hfi->cabac_model = HFI_H264_ENTROPY_CAVLC;
+			break;
+		case HAL_H264_ENTROPY_CABAC:
+			hfi->cabac_model = HFI_H264_ENTROPY_CABAC;
+			switch (prop->cabac_model) {
+			case HAL_H264_CABAC_MODEL_0:
+				hfi->cabac_model = HFI_H264_CABAC_MODEL_0;
+				break;
+			case HAL_H264_CABAC_MODEL_1:
+				hfi->cabac_model = HFI_H264_CABAC_MODEL_1;
+				break;
+			case HAL_H264_CABAC_MODEL_2:
+				hfi->cabac_model = HFI_H264_CABAC_MODEL_2;
+				break;
+			default:
+				dprintk(VIDC_ERR,
+					"Invalid cabac model 0x%x",
+					prop->entropy_mode);
+				break;
+			}
+		break;
+		default:
+			dprintk(VIDC_ERR,
+				"Invalid entropy selected: 0x%x",
+				prop->cabac_model);
+			break;
+		}
+		pkt->size += sizeof(u32) + sizeof(
+			struct hfi_h264_entropy_control);
+		break;
+	}
+	case HAL_PARAM_VENC_RATE_CONTROL:
+	{
+		u32 *rc;
+		pkt->rg_property_data[0] =
+			HFI_PROPERTY_PARAM_VENC_RATE_CONTROL;
+		rc = (u32 *)pdata;
+		switch ((enum hal_rate_control) *rc) {
+		case HAL_RATE_CONTROL_OFF:
+			pkt->rg_property_data[1] = HFI_RATE_CONTROL_OFF;
+			break;
+		case HAL_RATE_CONTROL_CBR_CFR:
+			pkt->rg_property_data[1] = HFI_RATE_CONTROL_CBR_CFR;
+			break;
+		case HAL_RATE_CONTROL_CBR_VFR:
+			pkt->rg_property_data[1] = HFI_RATE_CONTROL_CBR_VFR;
+			break;
+		case HAL_RATE_CONTROL_VBR_CFR:
+			pkt->rg_property_data[1] = HFI_RATE_CONTROL_VBR_CFR;
+			break;
+		case HAL_RATE_CONTROL_VBR_VFR:
+			pkt->rg_property_data[1] = HFI_RATE_CONTROL_VBR_VFR;
+			break;
+		default:
+			dprintk(VIDC_ERR, "Invalid Rate control setting: 0x%x",
+						  (int) pdata);
+			break;
+		}
+		pkt->size += sizeof(u32) * 2;
+		break;
+	}
+	case HAL_PARAM_VENC_MPEG4_TIME_RESOLUTION:
+	{
+		struct hfi_mpeg4_time_resolution *hfi;
+		pkt->rg_property_data[0] =
+			HFI_PROPERTY_PARAM_VENC_MPEG4_TIME_RESOLUTION;
+		hfi = (struct hfi_mpeg4_time_resolution *)
+			&pkt->rg_property_data[1];
+		hfi->time_increment_resolution =
+			((struct hal_mpeg4_time_resolution *)pdata)->
+					time_increment_resolution;
+		pkt->size += sizeof(u32) * 2;
+		break;
+	}
+	case HAL_PARAM_VENC_MPEG4_HEADER_EXTENSION:
+	{
+		struct hfi_mpeg4_header_extension *hfi;
+		pkt->rg_property_data[0] =
+			HFI_PROPERTY_PARAM_VENC_MPEG4_HEADER_EXTENSION;
+		hfi = (struct hfi_mpeg4_header_extension *)
+			&pkt->rg_property_data[1];
+		hfi->header_extension = (u32) pdata;
+		pkt->size += sizeof(u32) * 2;
+		break;
+	}
+	case HAL_PARAM_VENC_H264_DEBLOCK_CONTROL:
+	{
+		struct hfi_h264_db_control *hfi;
+		struct hal_h264_db_control *prop =
+			(struct hal_h264_db_control *) pdata;
+		pkt->rg_property_data[0] =
+			HFI_PROPERTY_PARAM_VENC_H264_DEBLOCK_CONTROL;
+		hfi = (struct hfi_h264_db_control *) &pkt->rg_property_data[1];
+		switch (prop->mode) {
+		case HAL_H264_DB_MODE_DISABLE:
+			hfi->mode = HFI_H264_DB_MODE_DISABLE;
+			break;
+		case HAL_H264_DB_MODE_SKIP_SLICE_BOUNDARY:
+			hfi->mode = HFI_H264_DB_MODE_SKIP_SLICE_BOUNDARY;
+			break;
+		case HAL_H264_DB_MODE_ALL_BOUNDARY:
+			hfi->mode = HFI_H264_DB_MODE_ALL_BOUNDARY;
+			break;
+		default:
+			dprintk(VIDC_ERR, "Invalid deblocking mode: 0x%x",
+						  prop->mode);
+			break;
+		}
+		hfi->slice_alpha_offset = prop->slice_alpha_offset;
+		hfi->slice_beta_offset = prop->slice_beta_offset;
+		pkt->size += sizeof(u32) +
+			sizeof(struct hfi_h264_db_control);
+		break;
+	}
+	case HAL_PARAM_VENC_SESSION_QP:
+	{
+		struct hfi_quantization *hfi;
+		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));
+		pkt->size += sizeof(u32) + sizeof(struct hfi_quantization);
+		break;
+	}
+	case HAL_CONFIG_VENC_INTRA_PERIOD:
+	{
+		struct hfi_intra_period *hfi;
+		pkt->rg_property_data[0] =
+			HFI_PROPERTY_CONFIG_VENC_INTRA_PERIOD;
+		hfi = (struct hfi_intra_period *) &pkt->rg_property_data[1];
+		memcpy(hfi, (struct hfi_intra_period *) pdata,
+				sizeof(struct hfi_intra_period));
+		pkt->size += sizeof(u32) + sizeof(struct hfi_intra_period);
+		break;
+	}
+	case HAL_CONFIG_VENC_IDR_PERIOD:
+	{
+		struct hfi_idr_period *hfi;
+		pkt->rg_property_data[0] = HFI_PROPERTY_CONFIG_VENC_IDR_PERIOD;
+		hfi = (struct hfi_idr_period *) &pkt->rg_property_data[1];
+		hfi->idr_period = ((struct hfi_idr_period *) pdata)->idr_period;
+		pkt->size += sizeof(u32) * 2;
+		break;
+	}
+	case HAL_CONFIG_VPE_OPERATIONS:
+		break;
+	case HAL_PARAM_VENC_INTRA_REFRESH:
+	{
+		struct hfi_intra_refresh *hfi;
+		struct hal_intra_refresh *prop =
+			(struct hal_intra_refresh *) pdata;
+		pkt->rg_property_data[0] =
+			HFI_PROPERTY_PARAM_VENC_INTRA_REFRESH;
+		hfi = (struct hfi_intra_refresh *) &pkt->rg_property_data[1];
+		switch (prop->mode) {
+		case HAL_INTRA_REFRESH_NONE:
+			hfi->mode = HFI_INTRA_REFRESH_NONE;
+			break;
+		case HAL_INTRA_REFRESH_ADAPTIVE:
+			hfi->mode = HFI_INTRA_REFRESH_ADAPTIVE;
+			break;
+		case HAL_INTRA_REFRESH_CYCLIC:
+			hfi->mode = HFI_INTRA_REFRESH_CYCLIC;
+			break;
+		case HAL_INTRA_REFRESH_CYCLIC_ADAPTIVE:
+			hfi->mode = HFI_INTRA_REFRESH_CYCLIC_ADAPTIVE;
+			break;
+		case HAL_INTRA_REFRESH_RANDOM:
+			hfi->mode = HFI_INTRA_REFRESH_RANDOM;
+			break;
+		default:
+			dprintk(VIDC_ERR, "Invalid intra refresh setting: 0x%x",
+				prop->mode);
+			break;
+		}
+		hfi->air_mbs = prop->air_mbs;
+		hfi->air_ref = prop->air_ref;
+		hfi->cir_mbs = prop->cir_mbs;
+		pkt->size += sizeof(u32) + sizeof(struct hfi_intra_refresh);
+		break;
+	}
+	case HAL_PARAM_VENC_MULTI_SLICE_CONTROL:
+	{
+		struct hfi_multi_slice_control *hfi;
+		struct hal_multi_slice_control *prop =
+			(struct hal_multi_slice_control *) pdata;
+		pkt->rg_property_data[0] =
+			HFI_PROPERTY_PARAM_VENC_MULTI_SLICE_CONTROL;
+		hfi = (struct hfi_multi_slice_control *)
+			&pkt->rg_property_data[1];
+		switch (prop->multi_slice) {
+		case HAL_MULTI_SLICE_OFF:
+			hfi->multi_slice = HFI_MULTI_SLICE_OFF;
+			break;
+		case HAL_MULTI_SLICE_GOB:
+			hfi->multi_slice = HFI_MULTI_SLICE_GOB;
+			break;
+		case HAL_MULTI_SLICE_BY_MB_COUNT:
+			hfi->multi_slice = HFI_MULTI_SLICE_BY_MB_COUNT;
+			break;
+		case HAL_MULTI_SLICE_BY_BYTE_COUNT:
+			hfi->multi_slice = HFI_MULTI_SLICE_BY_BYTE_COUNT;
+			break;
+		default:
+			dprintk(VIDC_ERR, "Invalid slice settings: 0x%x",
+				prop->multi_slice);
+			break;
+		}
+		hfi->slice_size = prop->slice_size;
+		pkt->size += sizeof(u32) + sizeof(struct
+					hfi_multi_slice_control);
+		break;
+	}
+	case HAL_PARAM_INDEX_EXTRADATA:
+	{
+		struct hfi_index_extradata_config *hfi;
+		struct hal_extradata_enable *extra = pdata;
+		int index = 0;
+		pkt->rg_property_data[0] =
+			get_hfi_extradata_index(extra->index);
+		hfi =
+			(struct hfi_index_extradata_config *)
+			&pkt->rg_property_data[1];
+		hfi->enable = extra->enable;
+		index = get_hfi_extradata_index(extra->index);
+		if (index)
+			hfi->index_extra_data_id = index;
+		else {
+			dprintk(VIDC_WARN,
+				"Failed to find extradata index: %d\n",
+				index);
+			rc = -EINVAL;
+		}
+		pkt->size += sizeof(u32) +
+			sizeof(struct hfi_index_extradata_config);
+		break;
+	}
+	case HAL_CONFIG_VPE_DEINTERLACE:
+		break;
+	/* FOLLOWING PROPERTIES ARE NOT IMPLEMENTED IN CORE YET */
+	case HAL_CONFIG_BUFFER_REQUIREMENTS:
+	case HAL_CONFIG_PRIORITY:
+	case HAL_CONFIG_BATCH_INFO:
+	case HAL_PARAM_METADATA_PASS_THROUGH:
+	case HAL_SYS_IDLE_INDICATOR:
+	case HAL_PARAM_UNCOMPRESSED_FORMAT_SUPPORTED:
+	case HAL_PARAM_INTERLACE_FORMAT_SUPPORTED:
+	case HAL_PARAM_CHROMA_SITE:
+	case HAL_PARAM_PROPERTIES_SUPPORTED:
+	case HAL_PARAM_PROFILE_LEVEL_SUPPORTED:
+	case HAL_PARAM_CAPABILITY_SUPPORTED:
+	case HAL_PARAM_NAL_STREAM_FORMAT_SUPPORTED:
+	case HAL_PARAM_MULTI_VIEW_FORMAT:
+	case HAL_PARAM_MAX_SEQUENCE_HEADER_SIZE:
+	case HAL_PARAM_CODEC_SUPPORTED:
+	case HAL_PARAM_VDEC_MULTI_VIEW_SELECT:
+	case HAL_PARAM_VDEC_MB_QUANTIZATION:
+	case HAL_PARAM_VDEC_NUM_CONCEALED_MB:
+	case HAL_PARAM_VDEC_H264_ENTROPY_SWITCHING:
+	case HAL_PARAM_VENC_SLICE_DELIVERY_MODE:
+	case HAL_PARAM_VENC_MPEG4_DATA_PARTITIONING:
+	case HAL_CONFIG_BUFFER_COUNT_ACTUAL:
+	case HAL_CONFIG_VDEC_MULTI_STREAM:
+	case HAL_PARAM_VENC_MULTI_SLICE_INFO:
+	case HAL_CONFIG_VENC_TIMESTAMP_SCALE:
+	case HAL_PARAM_VENC_LOW_LATENCY:
+	default:
+		dprintk(VIDC_ERR, "DEFAULT: Calling 0x%x", ptype);
+		break;
+	}
+	return rc;
+}
diff --git a/drivers/media/video/msm_vidc/hfi_packetization.h b/drivers/media/video/msm_vidc/hfi_packetization.h
new file mode 100644
index 0000000..a3edc7c
--- /dev/null
+++ b/drivers/media/video/msm_vidc/hfi_packetization.h
@@ -0,0 +1,83 @@
+/* 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 __HFI_PACKETIZATION__
+#define __HFI_PACKETIZATION__
+
+#include <linux/types.h>
+#include "vidc_hfi_helper.h"
+#include "vidc_hfi.h"
+#include "vidc_hfi_api.h"
+
+int create_pkt_cmd_sys_init(struct hfi_cmd_sys_init_packet *pkt,
+							   u32 arch_type);
+int create_pkt_cmd_sys_pc_prep(struct hfi_cmd_sys_pc_prep_packet *pkt);
+
+int create_pkt_set_cmd_sys_resource(
+		struct hfi_cmd_sys_set_resource_packet *pkt,
+		struct vidc_resource_hdr *resource_hdr,
+		void *resource_value);
+
+int create_pkt_cmd_sys_release_resource(
+		struct hfi_cmd_sys_release_resource_packet *pkt,
+		struct vidc_resource_hdr *resource_hdr);
+
+int create_pkt_cmd_sys_ping(struct hfi_cmd_sys_ping_packet *pkt);
+
+int create_pkt_cmd_sys_session_init(
+	struct hfi_cmd_sys_session_init_packet *pkt,
+	u32 session_id, u32 session_domain, u32 session_codec);
+
+int create_pkt_cmd_session_cmd(struct vidc_hal_session_cmd_pkt *pkt,
+			int pkt_type, u32 session_id);
+
+int create_pkt_cmd_session_set_buffers(
+		struct hfi_cmd_session_set_buffers_packet *pkt,
+		u32 session_id,
+		struct vidc_buffer_addr_info *buffer_info);
+
+int create_pkt_cmd_session_release_buffers(
+		struct hfi_cmd_session_release_buffer_packet *pkt,
+		u32 session_id, struct vidc_buffer_addr_info *buffer_info);
+
+int create_pkt_cmd_session_etb_decoder(
+	struct hfi_cmd_session_empty_buffer_compressed_packet *pkt,
+	u32 session_id, struct vidc_frame_data *input_frame);
+
+int create_pkt_cmd_session_etb_encoder(
+	struct hfi_cmd_session_empty_buffer_uncompressed_plane0_packet *pkt,
+	u32 session_id, struct vidc_frame_data *input_frame);
+
+int create_pkt_cmd_session_ftb(struct hfi_cmd_session_fill_buffer_packet *pkt,
+		u32 session_id, struct vidc_frame_data *output_frame);
+
+int create_pkt_cmd_session_parse_seq_header(
+		struct hfi_cmd_session_parse_sequence_header_packet *pkt,
+		u32 session_id, struct vidc_seq_hdr *seq_hdr);
+
+int create_pkt_cmd_session_get_seq_hdr(
+		struct hfi_cmd_session_get_sequence_header_packet *pkt,
+		u32 session_id, struct vidc_seq_hdr *seq_hdr);
+
+int create_pkt_cmd_session_get_buf_req(
+		struct hfi_cmd_session_get_property_packet *pkt,
+		u32 session_id);
+
+int create_pkt_cmd_session_flush(struct hfi_cmd_session_flush_packet *pkt,
+			u32 session_id, enum hal_flush flush_mode);
+
+int create_pkt_cmd_session_set_property(
+		struct hfi_cmd_session_set_property_packet *pkt,
+		u32 session_id, enum hal_property ptype, void *pdata);
+
+#endif
+
diff --git a/drivers/media/video/msm_vidc/vidc_hal_interrupt_handler.c b/drivers/media/video/msm_vidc/hfi_response_handler.c
similarity index 76%
rename from drivers/media/video/msm_vidc/vidc_hal_interrupt_handler.c
rename to drivers/media/video/msm_vidc/hfi_response_handler.c
index 8201b0e..23829e5 100644
--- a/drivers/media/video/msm_vidc/vidc_hal_interrupt_handler.c
+++ b/drivers/media/video/msm_vidc/hfi_response_handler.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
@@ -14,11 +14,12 @@
 #include <linux/slab.h>
 #include <linux/list.h>
 #include <linux/interrupt.h>
-#include "vidc_hal.h"
-#include "vidc_hal_io.h"
+#include "vidc_hfi_helper.h"
+#include "vidc_hfi_io.h"
 #include "msm_vidc_debug.h"
+#include "vidc_hfi.h"
 
-static enum vidc_status vidc_map_hal_err_status(int hfi_err)
+static enum vidc_status hfi_map_err_status(int hfi_err)
 {
 	enum vidc_status vidc_err;
 	switch (hfi_err) {
@@ -75,8 +76,9 @@
 	return vidc_err;
 }
 
-void hal_process_sess_evt_seq_changed(struct hal_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 hal_process_sys_watchdog_timeout(struct hal_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 hal_process_sys_error(struct hal_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 hal_process_session_error(struct hal_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 hal_process_event_notify(struct hal_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);
-		hal_process_sys_error(device);
+		hfi_process_sys_error(callback, device_id);
 		break;
 	case HFI_EVENT_SESSION_ERROR:
 		dprintk(VIDC_ERR, "HFI_EVENT_SESSION_ERROR");
-		hal_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");
-		hal_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 hal_process_sys_init_done(struct hal_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;
@@ -213,7 +212,7 @@
 		return;
 	}
 
-	status = vidc_map_hal_err_status((u32)pkt->error_type);
+	status = hfi_map_err_status((u32)pkt->error_type);
 
 	if (!status) {
 		if (pkt->num_properties == 0) {
@@ -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 hal_process_sys_rel_resource_done(struct hal_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;
@@ -296,23 +296,23 @@
 			pkt->size);
 		return;
 	}
-	status = vidc_map_hal_err_status((u32)pkt->error_type);
-	cmd_done.device_id = device->device_id;
+	status = hfi_map_err_status((u32)pkt->error_type);
+	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 vidc_hal_process_sess_init_done_prop_read(
+enum vidc_status hfi_process_sess_init_done_prop_read(
 	struct hfi_msg_sys_session_init_done_packet *pkt,
 	struct msm_vidc_cb_cmd_done *cmddone)
 {
 	return VIDC_ERR_NONE;
 }
 
-static void hal_process_sess_get_prop_buf_req(
+static void hfi_process_sess_get_prop_buf_req(
 	struct hfi_msg_session_property_info_packet *prop,
 	struct buffer_requirements *buffreq)
 {
@@ -408,8 +408,9 @@
 	}
 }
 
-static void hal_process_session_prop_info(struct hal_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;
@@ -432,14 +433,14 @@
 
 	switch (pkt->rg_property_data[0]) {
 	case HFI_PROPERTY_CONFIG_BUFFER_REQUIREMENTS:
-		hal_process_sess_get_prop_buf_req(pkt, &buff_req);
-		cmd_done.device_id = device->device_id;
+		hfi_process_sess_get_prop_buf_req(pkt, &buff_req);
+		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 hal_process_session_init_done(struct hal_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,21 +468,22 @@
 	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 = vidc_map_hal_err_status((u32)pkt->error_type);
+	cmd_done.status = hfi_map_err_status((u32)pkt->error_type);
 	cmd_done.data = &session_init_done;
 	if (!cmd_done.status) {
-		cmd_done.status = vidc_hal_process_sess_init_done_prop_read(
+		cmd_done.status = hfi_process_sess_init_done_prop_read(
 			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 hal_process_session_load_res_done(struct hal_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 = vidc_map_hal_err_status((u32)pkt->error_type);
+	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 hal_process_session_flush_done(struct hal_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 = vidc_map_hal_err_status((u32)pkt->error_type);
+	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 hal_process_session_etb_done(struct hal_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,20 +546,21 @@
 
 	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 = vidc_map_hal_err_status((u32) pkt->error_type);
+	data_done.status = hfi_map_err_status((u32) pkt->error_type);
 	data_done.size = sizeof(struct msm_vidc_cb_data_done);
 	data_done.clnt_data = (void *)pkt->input_tag;
 	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 hal_process_session_ftb_done(struct hal_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,9 +596,9 @@
 			/* 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 = vidc_map_hal_err_status((u32)
+		data_done.status = hfi_map_err_status((u32)
 							pkt->error_type);
 		data_done.size = sizeof(struct msm_vidc_cb_data_done);
 		data_done.clnt_data = (void *) pkt->input_tag;
@@ -624,9 +630,9 @@
 			return;
 		}
 
-		data_done.device_id = device->device_id;
+		data_done.device_id = device_id;
 		data_done.session_id = (u32) session;
-		data_done.status = vidc_map_hal_err_status((u32)
+		data_done.status = hfi_map_err_status((u32)
 			pkt->error_type);
 		data_done.size = sizeof(struct msm_vidc_cb_data_done);
 		data_done.clnt_data = (void *)pkt->input_tag;
@@ -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 hal_process_session_start_done(struct hal_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 = vidc_map_hal_err_status((u32)pkt->error_type);
+	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 hal_process_session_stop_done(struct hal_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 = vidc_map_hal_err_status((u32)pkt->error_type);
+	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 hal_process_session_rel_res_done(struct hal_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 = vidc_map_hal_err_status((u32)pkt->error_type);
+	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 hal_process_session_rel_buf_done(struct hal_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,22 +753,23 @@
 		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;
-	cmd_done.status = vidc_map_hal_err_status((u32)pkt->error_type);
+	cmd_done.status = hfi_map_err_status((u32)pkt->error_type);
 	if (pkt->rg_buffer_info) {
 		cmd_done.data = (void *) &pkt->rg_buffer_info;
 		cmd_done.size = sizeof(struct hfi_buffer_info);
 	} 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 hal_process_session_end_done(struct hal_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,16 +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 = vidc_map_hal_err_status((u32)pkt->error_type);
+	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 hal_process_session_get_seq_hdr_done(struct hal_device *device,
+static void hfi_process_session_get_seq_hdr_done(
+	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;
@@ -799,130 +811,108 @@
 		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;
-	data_done.status = vidc_map_hal_err_status((u32)pkt->error_type);
+	data_done.status = hfi_map_err_status((u32)pkt->error_type);
 	data_done.output_done.packet_buffer1 = pkt->sequence_header;
 	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 hal_process_msg_packet(struct hal_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__);
-		hal_process_sys_watchdog_timeout(device);
-		return;
-	}
 
 	switch (msg_hdr->packet) {
 	case HFI_MSG_EVENT_NOTIFY:
-		hal_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:
-		hal_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:
-		hal_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:
-		hal_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:
-		hal_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:
-		hal_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:
-		hal_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:
-		hal_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:
-		hal_process_session_ftb_done(device, msg_hdr);
+		hfi_process_session_ftb_done(callback, device_id, msg_hdr);
 		break;
 	case HFI_MSG_SESSION_FLUSH_DONE:
-		hal_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:
-		hal_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:
-		hal_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:
-		hal_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:
-		hal_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:
-		hal_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 vidc_hal_response_handler(struct hal_device *device)
-{
-	u8 packet[VIDC_IFACEQ_MED_PKT_SIZE];
-
-	dprintk(VIDC_INFO, "#####vidc_hal_response_handler#####\n");
-	if (device) {
-		while (!vidc_hal_iface_msgq_read(device, packet)) {
-			hal_process_msg_packet(device,
-				(struct vidc_hal_msg_pkt_hdr *) packet);
-		}
-		while (!vidc_hal_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_smem.c b/drivers/media/video/msm_vidc/msm_smem.c
index eae18c4..8e2aa30 100644
--- a/drivers/media/video/msm_vidc/msm_smem.c
+++ b/drivers/media/video/msm_vidc/msm_smem.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+/* 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
diff --git a/drivers/media/video/msm_vidc/msm_smem.h b/drivers/media/video/msm_vidc/msm_smem.h
index 8241fdd..6e40bef 100644
--- a/drivers/media/video/msm_vidc/msm_smem.h
+++ b/drivers/media/video/msm_vidc/msm_smem.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+/* 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
diff --git a/drivers/media/video/msm_vidc/msm_v4l2_vidc.c b/drivers/media/video/msm_vidc/msm_v4l2_vidc.c
index 0979e99..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, 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,413 +27,11 @@
 #include <media/msm_vidc.h>
 #include "msm_vidc_internal.h"
 #include "msm_vidc_debug.h"
-#include "vidc_hal_api.h"
+#include "vidc_hfi_api.h"
 #include "msm_smem.h"
+#include "vidc_hfi_api.h"
 
 #define BASE_DEVICE_NUMBER 32
-#define SHARED_QSIZE 0x1000000
-
-static struct msm_bus_vectors enc_ocmem_init_vectors[]  = {
-	{
-		.src = MSM_BUS_MASTER_VIDEO_P0_OCMEM,
-		.dst = MSM_BUS_SLAVE_OCMEM,
-		.ab = 0,
-		.ib = 0,
-	},
-};
-
-static struct msm_bus_vectors enc_ocmem_perf1_vectors[]  = {
-	{
-		.src = MSM_BUS_MASTER_VIDEO_P0_OCMEM,
-		.dst = MSM_BUS_SLAVE_OCMEM,
-		.ab = 138200000,
-		.ib = 1222000000,
-	},
-};
-
-static struct msm_bus_vectors enc_ocmem_perf2_vectors[]  = {
-	{
-		.src = MSM_BUS_MASTER_VIDEO_P0_OCMEM,
-		.dst = MSM_BUS_SLAVE_OCMEM,
-		.ab = 414700000,
-		.ib = 1222000000,
-	},
-};
-
-static struct msm_bus_vectors enc_ocmem_perf3_vectors[]  = {
-	{
-		.src = MSM_BUS_MASTER_VIDEO_P0_OCMEM,
-		.dst = MSM_BUS_SLAVE_OCMEM,
-		.ab = 940000000,
-		.ib = 2444000000U,
-	},
-};
-
-static struct msm_bus_vectors enc_ocmem_perf4_vectors[]  = {
-	{
-		.src = MSM_BUS_MASTER_VIDEO_P0_OCMEM,
-		.dst = MSM_BUS_SLAVE_OCMEM,
-		.ab = 1880000000,
-		.ib = 2444000000U,
-	},
-};
-
-static struct msm_bus_vectors enc_ocmem_perf5_vectors[]  = {
-	{
-		.src = MSM_BUS_MASTER_VIDEO_P0_OCMEM,
-		.dst = MSM_BUS_SLAVE_OCMEM,
-		.ab = 3008000000U,
-		.ib = 3910400000U,
-	},
-};
-
-static struct msm_bus_vectors enc_ocmem_perf6_vectors[]  = {
-	{
-		.src = MSM_BUS_MASTER_VIDEO_P0_OCMEM,
-		.dst = MSM_BUS_SLAVE_OCMEM,
-		.ab = 3760000000U,
-		.ib = 4888000000ULL,
-	},
-};
-
-static struct msm_bus_vectors dec_ocmem_init_vectors[]  = {
-	{
-		.src = MSM_BUS_MASTER_VIDEO_P0_OCMEM,
-		.dst = MSM_BUS_SLAVE_OCMEM,
-		.ab = 0,
-		.ib = 0,
-	},
-};
-
-static struct msm_bus_vectors dec_ocmem_perf1_vectors[]  = {
-	{
-		.src = MSM_BUS_MASTER_VIDEO_P0_OCMEM,
-		.dst = MSM_BUS_SLAVE_OCMEM,
-		.ab = 176900000,
-		.ib = 1556640000,
-	},
-};
-
-static struct msm_bus_vectors dec_ocmem_perf2_vectors[]  = {
-	{
-		.src = MSM_BUS_MASTER_VIDEO_P0_OCMEM,
-		.dst = MSM_BUS_SLAVE_OCMEM,
-		.ab = 456200000,
-		.ib = 1556640000,
-	},
-};
-
-static struct msm_bus_vectors dec_ocmem_perf3_vectors[]  = {
-	{
-		.src = MSM_BUS_MASTER_VIDEO_P0_OCMEM,
-		.dst = MSM_BUS_SLAVE_OCMEM,
-		.ab = 864800000,
-		.ib = 1556640000,
-	},
-};
-
-static struct msm_bus_vectors dec_ocmem_perf4_vectors[]  = {
-	{
-		.src = MSM_BUS_MASTER_VIDEO_P0_OCMEM,
-		.dst = MSM_BUS_SLAVE_OCMEM,
-		.ab = 1729600000,
-		.ib = 3113280000U,
-	},
-};
-
-static struct msm_bus_vectors dec_ocmem_perf5_vectors[]  = {
-	{
-		.src = MSM_BUS_MASTER_VIDEO_P0_OCMEM,
-		.dst = MSM_BUS_SLAVE_OCMEM,
-		.ab = 2767360000U,
-		.ib = 4981248000ULL,
-	},
-};
-
-static struct msm_bus_vectors dec_ocmem_perf6_vectors[]  = {
-	{
-		.src = MSM_BUS_MASTER_VIDEO_P0_OCMEM,
-		.dst = MSM_BUS_SLAVE_OCMEM,
-		.ab = 3459200000U,
-		.ib = 6226560000ULL,
-	},
-};
-
-static struct msm_bus_paths enc_ocmem_perf_vectors[]  = {
-	{
-		ARRAY_SIZE(enc_ocmem_init_vectors),
-		enc_ocmem_init_vectors,
-	},
-	{
-		ARRAY_SIZE(enc_ocmem_perf1_vectors),
-		enc_ocmem_perf1_vectors,
-	},
-	{
-		ARRAY_SIZE(enc_ocmem_perf2_vectors),
-		enc_ocmem_perf2_vectors,
-	},
-	{
-		ARRAY_SIZE(enc_ocmem_perf3_vectors),
-		enc_ocmem_perf3_vectors,
-	},
-	{
-		ARRAY_SIZE(enc_ocmem_perf4_vectors),
-		enc_ocmem_perf4_vectors,
-	},
-	{
-		ARRAY_SIZE(enc_ocmem_perf5_vectors),
-		enc_ocmem_perf5_vectors,
-	},
-	{
-		ARRAY_SIZE(enc_ocmem_perf6_vectors),
-		enc_ocmem_perf6_vectors,
-	},
-};
-
-static struct msm_bus_paths dec_ocmem_perf_vectors[]  = {
-	{
-		ARRAY_SIZE(dec_ocmem_init_vectors),
-		dec_ocmem_init_vectors,
-	},
-	{
-		ARRAY_SIZE(dec_ocmem_perf1_vectors),
-		dec_ocmem_perf1_vectors,
-	},
-	{
-		ARRAY_SIZE(dec_ocmem_perf2_vectors),
-		dec_ocmem_perf2_vectors,
-	},
-	{
-		ARRAY_SIZE(dec_ocmem_perf3_vectors),
-		dec_ocmem_perf3_vectors,
-	},
-	{
-		ARRAY_SIZE(dec_ocmem_perf4_vectors),
-		dec_ocmem_perf4_vectors,
-	},
-	{
-		ARRAY_SIZE(dec_ocmem_perf5_vectors),
-		dec_ocmem_perf5_vectors,
-	},
-	{
-		ARRAY_SIZE(dec_ocmem_perf6_vectors),
-		dec_ocmem_perf6_vectors,
-	},
-};
-
-
-static struct msm_bus_scale_pdata enc_ocmem_bus_data = {
-	.usecase = enc_ocmem_perf_vectors,
-	.num_usecases = ARRAY_SIZE(enc_ocmem_perf_vectors),
-	.name = "msm_vidc_enc_ocmem",
-};
-
-static struct msm_bus_scale_pdata dec_ocmem_bus_data = {
-	.usecase = dec_ocmem_perf_vectors,
-	.num_usecases = ARRAY_SIZE(dec_ocmem_perf_vectors),
-	.name = "msm_vidc_dec_ocmem",
-};
-
-static struct msm_bus_vectors enc_ddr_init_vectors[]  = {
-	{
-		.src = MSM_BUS_MASTER_VIDEO_P0,
-		.dst = MSM_BUS_SLAVE_EBI_CH0,
-		.ab = 0,
-		.ib = 0,
-	},
-};
-
-
-static struct msm_bus_vectors enc_ddr_perf1_vectors[]  = {
-	{
-		.src = MSM_BUS_MASTER_VIDEO_P0,
-		.dst = MSM_BUS_SLAVE_EBI_CH0,
-		.ab = 60000000,
-		.ib = 664950000,
-	},
-};
-
-static struct msm_bus_vectors enc_ddr_perf2_vectors[]  = {
-	{
-		.src = MSM_BUS_MASTER_VIDEO_P0,
-		.dst = MSM_BUS_SLAVE_EBI_CH0,
-		.ab = 181000000,
-		.ib = 664950000,
-	},
-};
-
-static struct msm_bus_vectors enc_ddr_perf3_vectors[]  = {
-	{
-		.src = MSM_BUS_MASTER_VIDEO_P0,
-		.dst = MSM_BUS_SLAVE_EBI_CH0,
-		.ab = 403000000,
-		.ib = 664950000,
-	},
-};
-
-static struct msm_bus_vectors enc_ddr_perf4_vectors[]  = {
-	{
-		.src = MSM_BUS_MASTER_VIDEO_P0,
-		.dst = MSM_BUS_SLAVE_EBI_CH0,
-		.ab = 806000000,
-		.ib = 1329900000,
-	},
-};
-
-static struct msm_bus_vectors enc_ddr_perf5_vectors[]  = {
-	{
-		.src = MSM_BUS_MASTER_VIDEO_P0,
-		.dst = MSM_BUS_SLAVE_EBI_CH0,
-		.ab = 1289600000,
-		.ib = 2127840000U,
-	},
-};
-
-static struct msm_bus_vectors enc_ddr_perf6_vectors[]  = {
-	{
-		.src = MSM_BUS_MASTER_VIDEO_P0,
-		.dst = MSM_BUS_SLAVE_EBI_CH0,
-		.ab = 161200000,
-		.ib = 6400000000ULL,
-	},
-};
-
-static struct msm_bus_vectors dec_ddr_init_vectors[]  = {
-	{
-		.src = MSM_BUS_MASTER_VIDEO_P0,
-		.dst = MSM_BUS_SLAVE_EBI_CH0,
-		.ab = 0,
-		.ib = 0,
-	},
-};
-
-static struct msm_bus_vectors dec_ddr_perf1_vectors[]  = {
-	{
-		.src = MSM_BUS_MASTER_VIDEO_P0,
-		.dst = MSM_BUS_SLAVE_EBI_CH0,
-		.ab = 110000000,
-		.ib = 909000000,
-	},
-};
-
-static struct msm_bus_vectors dec_ddr_perf2_vectors[]  = {
-	{
-		.src = MSM_BUS_MASTER_VIDEO_P0,
-		.dst = MSM_BUS_SLAVE_EBI_CH0,
-		.ab = 268000000,
-		.ib = 909000000,
-	},
-};
-
-static struct msm_bus_vectors dec_ddr_perf3_vectors[]  = {
-	{
-		.src = MSM_BUS_MASTER_VIDEO_P0,
-		.dst = MSM_BUS_SLAVE_EBI_CH0,
-		.ab = 505000000,
-		.ib = 909000000,
-	},
-};
-
-static struct msm_bus_vectors dec_ddr_perf4_vectors[]  = {
-	{
-		.src = MSM_BUS_MASTER_VIDEO_P0,
-		.dst = MSM_BUS_SLAVE_EBI_CH0,
-		.ab = 1010000000,
-		.ib = 1818000000,
-	},
-};
-
-static struct msm_bus_vectors dec_ddr_perf5_vectors[]  = {
-	{
-		.src = MSM_BUS_MASTER_VIDEO_P0,
-		.dst = MSM_BUS_SLAVE_EBI_CH0,
-		.ab = 1616000000,
-		.ib = 2908800000U,
-	},
-};
-
-static struct msm_bus_vectors dec_ddr_perf6_vectors[]  = {
-	{
-		.src = MSM_BUS_MASTER_VIDEO_P0,
-		.dst = MSM_BUS_SLAVE_EBI_CH0,
-		.ab = 2020000000U,
-		.ib = 6400000000ULL,
-	},
-};
-
-static struct msm_bus_paths enc_ddr_perf_vectors[]  = {
-	{
-		ARRAY_SIZE(enc_ddr_init_vectors),
-		enc_ddr_init_vectors,
-	},
-	{
-		ARRAY_SIZE(enc_ddr_perf1_vectors),
-		enc_ddr_perf1_vectors,
-	},
-	{
-		ARRAY_SIZE(enc_ddr_perf2_vectors),
-		enc_ddr_perf2_vectors,
-	},
-	{
-		ARRAY_SIZE(enc_ddr_perf3_vectors),
-		enc_ddr_perf3_vectors,
-	},
-	{
-		ARRAY_SIZE(enc_ddr_perf4_vectors),
-		enc_ddr_perf4_vectors,
-	},
-	{
-		ARRAY_SIZE(enc_ddr_perf5_vectors),
-		enc_ddr_perf5_vectors,
-	},
-	{
-		ARRAY_SIZE(enc_ddr_perf6_vectors),
-		enc_ddr_perf6_vectors,
-	},
-};
-
-static struct msm_bus_paths dec_ddr_perf_vectors[]  = {
-	{
-		ARRAY_SIZE(dec_ddr_init_vectors),
-		dec_ddr_init_vectors,
-	},
-	{
-		ARRAY_SIZE(dec_ddr_perf1_vectors),
-		dec_ddr_perf1_vectors,
-	},
-	{
-		ARRAY_SIZE(dec_ddr_perf2_vectors),
-		dec_ddr_perf2_vectors,
-	},
-	{
-		ARRAY_SIZE(dec_ddr_perf3_vectors),
-		dec_ddr_perf3_vectors,
-	},
-	{
-		ARRAY_SIZE(dec_ddr_perf4_vectors),
-		dec_ddr_perf4_vectors,
-	},
-	{
-		ARRAY_SIZE(dec_ddr_perf5_vectors),
-		dec_ddr_perf5_vectors,
-	},
-	{
-		ARRAY_SIZE(dec_ddr_perf6_vectors),
-		dec_ddr_perf6_vectors,
-	},
-};
-
-static struct msm_bus_scale_pdata enc_ddr_bus_data = {
-	.usecase = enc_ddr_perf_vectors,
-	.num_usecases = ARRAY_SIZE(enc_ddr_perf_vectors),
-	.name = "msm_vidc_enc_ddr",
-};
-
-static struct msm_bus_scale_pdata dec_ddr_bus_data = {
-	.usecase = dec_ddr_perf_vectors,
-	.num_usecases = ARRAY_SIZE(dec_ddr_perf_vectors),
-	.name = "msm_vidc_dec_ddr",
-};
 
 struct msm_vidc_drv *vidc_driver;
 
@@ -757,8 +355,18 @@
 	int i, rc = 0;
 	int smem_flags = 0;
 	int domain;
+	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
+		|| !vidc_inst->core->device) {
+		rc = -EINVAL;
+		goto exit;
+	}
+
+	hdev = vidc_inst->core->device;
+
 	if (!v4l2_inst->mem_client) {
 		dprintk(VIDC_ERR, "Failed to get memory client\n");
 		rc = -ENOMEM;
@@ -798,11 +406,11 @@
 				&& (!EXTRADATA_IDX(b->length)
 					|| (i != EXTRADATA_IDX(b->length)))) {
 			smem_flags |= SMEM_SECURE;
-			domain =
-			vidc_inst->core->resources.io_map[CP_MAP].domain;
+			domain = hdev->get_domain(hdev->hfi_device_data,
+						CP_MAP);
 		} else
-			domain =
-			vidc_inst->core->resources.io_map[NS_MAP].domain;
+			domain = hdev->get_domain(hdev->hfi_device_data,
+						NS_MAP);
 
 		if (b->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)
 			smem_flags |= SMEM_INPUT;
@@ -1063,270 +671,53 @@
 {
 }
 
-static size_t read_u32_array(struct platform_device *pdev,
-		char *name, u32 *arr, size_t size)
+static int msm_vidc_get_hfi(struct platform_device *pdev,
+			struct msm_vidc_core *core)
 {
-	int len;
-	size_t sz = 0;
 	struct device_node *np = pdev->dev.of_node;
-	if (!of_get_property(np, name, &len)) {
-		dprintk(VIDC_ERR, "Failed to read %s from device tree\n",
-			name);
-		goto fail_read;
-	}
-	sz = len / sizeof(u32);
-	if (sz <= 0) {
-		dprintk(VIDC_ERR, "%s not specified in device tree\n",
-			name);
-		goto fail_read;
-	}
-	if (sz > size) {
-		dprintk(VIDC_ERR, "Not enough memory to store %s values\n",
-			name);
-		goto fail_read;
-	}
-	if (of_property_read_u32_array(np, name, arr, sz)) {
-		dprintk(VIDC_ERR,
-			"error while reading %s from device tree\n",
-			name);
-		goto fail_read;
-	}
-	return sz;
-fail_read:
-	sz = 0;
-	return sz;
-}
-
-static int register_iommu_domains(struct platform_device *pdev,
-	struct msm_vidc_core *core)
-{
-	size_t len;
-	struct msm_iova_partition partition[2];
-	struct msm_iova_layout layout;
 	int rc = 0;
-	int i;
-	struct msm_vidc_iommu_info *io_map = core->resources.io_map;
-	strlcpy(io_map[CP_MAP].name, "vidc-cp-map",
-			sizeof(io_map[CP_MAP].name));
-	strlcpy(io_map[CP_MAP].ctx, "venus_cp",
-			sizeof(io_map[CP_MAP].ctx));
-	strlcpy(io_map[NS_MAP].name, "vidc-ns-map",
-			sizeof(io_map[NS_MAP].name));
-	strlcpy(io_map[NS_MAP].ctx, "venus_ns",
-			sizeof(io_map[NS_MAP].ctx));
+	const char *hfi_name = NULL;
 
-	for (i = 0; i < MAX_MAP; i++) {
-		len = read_u32_array(pdev, io_map[i].name,
-				io_map[i].addr_range,
-				(sizeof(io_map[i].addr_range)/sizeof(u32)));
-		if (!len) {
-			dprintk(VIDC_ERR,
-				"Error in reading cp address range\n");
-			rc = -EINVAL;
-			break;
-		}
-		partition[0].start = io_map[i].addr_range[0];
-		if (i == NS_MAP) {
-			partition[0].size =
-				io_map[i].addr_range[1] - SHARED_QSIZE;
-			partition[1].start =
-				partition[0].start + io_map[i].addr_range[1]
-					- SHARED_QSIZE;
-			partition[1].size = SHARED_QSIZE;
-			layout.npartitions = 2;
-			layout.is_secure = 0;
-		} else {
-			partition[0].size = io_map[i].addr_range[1];
-			layout.npartitions = 1;
-			layout.is_secure = 1;
-		}
-		layout.partitions = &partition[0];
-		layout.client_name = io_map[i].name;
-		layout.domain_flags = 0;
-		dprintk(VIDC_DBG, "Registering domain 1 with: %lx, %lx, %s\n",
-			partition[0].start, partition[0].size,
-			layout.client_name);
-		dprintk(VIDC_DBG, "Registering domain 2 with: %lx, %lx, %s\n",
-			partition[1].start, partition[1].size,
-			layout.client_name);
-		io_map[i].domain = msm_register_domain(&layout);
-		if (io_map[i].domain < 0) {
-			dprintk(VIDC_ERR, "Failed to register cp domain\n");
-			rc = -EINVAL;
-			break;
-		}
+	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;
 	}
-	/* There is no api provided as msm_unregister_domain, so
-	 * we are not able to unregister the previously
-	 * registered domains if any domain registration fails.*/
-	BUG_ON(i < MAX_MAP);
+
+	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 inline int msm_vidc_init_clocks(struct platform_device *pdev,
-		struct msm_vidc_core *core)
-{
-	struct core_clock *cl;
-	int i;
-	int rc = 0;
-	struct core_clock *clock;
-	if (!core) {
-		dprintk(VIDC_ERR, "Invalid params: %p\n", core);
-		return -EINVAL;
-	}
-	clock = core->resources.clock;
-	strlcpy(clock[VCODEC_CLK].name, "core_clk",
-		sizeof(clock[VCODEC_CLK].name));
-	strlcpy(clock[VCODEC_AHB_CLK].name, "iface_clk",
-		sizeof(clock[VCODEC_AHB_CLK].name));
-	strlcpy(clock[VCODEC_AXI_CLK].name, "bus_clk",
-		sizeof(clock[VCODEC_AXI_CLK].name));
-	strlcpy(clock[VCODEC_OCMEM_CLK].name, "mem_clk",
-		sizeof(clock[VCODEC_OCMEM_CLK].name));
-
-	clock[VCODEC_CLK].count = read_u32_array(pdev,
-		"load-freq-tbl", (u32 *)clock[VCODEC_CLK].load_freq_tbl,
-		(sizeof(clock[VCODEC_CLK].load_freq_tbl)/sizeof(u32)));
-	clock[VCODEC_CLK].count /= 2;
-	dprintk(VIDC_DBG, "count = %d\n", clock[VCODEC_CLK].count);
-	if (!clock[VCODEC_CLK].count) {
-		dprintk(VIDC_ERR, "Failed to read clock frequency\n");
-		goto fail_init_clocks;
-	}
-	for (i = 0; i <	clock[VCODEC_CLK].count; i++) {
-		dprintk(VIDC_DBG,
-				"load = %d, freq = %d\n",
-				clock[VCODEC_CLK].load_freq_tbl[i].load,
-				clock[VCODEC_CLK].load_freq_tbl[i].freq
-			  );
-	}
-
-	for (i = 0; i < VCODEC_MAX_CLKS; i++) {
-		cl = &core->resources.clock[i];
-		if (!cl->clk) {
-			cl->clk = devm_clk_get(&pdev->dev, cl->name);
-			if (IS_ERR_OR_NULL(cl->clk)) {
-				dprintk(VIDC_ERR,
-					"Failed to get clock: %s\n", cl->name);
-				rc = PTR_ERR(cl->clk);
-				break;
-			}
-		}
-	}
-
-	if (i < VCODEC_MAX_CLKS) {
-		for (--i; i >= 0; i--) {
-			cl = &core->resources.clock[i];
-			clk_put(cl->clk);
-		}
-	}
-fail_init_clocks:
-	return rc;
-}
-
-static inline void msm_vidc_deinit_clocks(struct msm_vidc_core *core)
-{
-	int i;
-	if (!core) {
-		dprintk(VIDC_ERR, "Invalid args\n");
-		return;
-	}
-	for (i = 0; i < VCODEC_MAX_CLKS; i++)
-		clk_put(core->resources.clock[i].clk);
-}
-
 static int msm_vidc_initialize_core(struct platform_device *pdev,
 				struct msm_vidc_core *core)
 {
-	struct resource *res;
 	int i = 0;
 	int rc = 0;
-	struct on_chip_mem *ocmem;
 	if (!core)
 		return -EINVAL;
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (!res) {
-		dprintk(VIDC_ERR, "Failed to get IORESOURCE_MEM\n");
-		rc = -ENODEV;
-		goto core_init_failed;
-	}
-	core->register_base = res->start;
-	core->register_size = resource_size(res);
-	res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
-	if (!res) {
-		dprintk(VIDC_ERR, "Failed to get IORESOURCE_IRQ\n");
-		rc = -ENODEV;
-		goto core_init_failed;
-	}
-	core->irq = res->start;
+
 	INIT_LIST_HEAD(&core->instances);
 	mutex_init(&core->sync_lock);
 	spin_lock_init(&core->lock);
-	core->base_addr = 0x0;
+
 	core->state = VIDC_CORE_UNINIT;
 	for (i = SYS_MSG_INDEX(SYS_MSG_START);
 		i <= SYS_MSG_INDEX(SYS_MSG_END); i++) {
 		init_completion(&core->completions[i]);
 	}
-	rc = msm_vidc_init_clocks(pdev, core);
-	if (rc) {
-		dprintk(VIDC_ERR, "Failed to init clocks\n");
-		rc = -ENODEV;
-		goto core_init_failed;
-	}
-	core->resources.bus_info.ddr_handle[MSM_VIDC_ENCODER] =
-		msm_bus_scale_register_client(&enc_ddr_bus_data);
-	if (!core->resources.bus_info.ddr_handle[MSM_VIDC_ENCODER]) {
-		dprintk(VIDC_ERR, "Failed to register bus scale client\n");
-		goto fail_register_enc_ddr_bus;
-	}
-	core->resources.bus_info.ddr_handle[MSM_VIDC_DECODER] =
-		msm_bus_scale_register_client(&dec_ddr_bus_data);
-	if (!core->resources.bus_info.ddr_handle[MSM_VIDC_DECODER]) {
-		dprintk(VIDC_ERR, "Failed to register bus scale client\n");
-		goto fail_register_dec_ddr_bus;
-	}
-	core->resources.bus_info.ocmem_handle[MSM_VIDC_ENCODER] =
-		msm_bus_scale_register_client(&enc_ocmem_bus_data);
-	if (!core->resources.bus_info.ocmem_handle[MSM_VIDC_ENCODER]) {
-		dprintk(VIDC_ERR, "Failed to register bus scale client\n");
-		goto fail_register_enc_ocmem;
-	}
-	core->resources.bus_info.ocmem_handle[MSM_VIDC_DECODER] =
-		msm_bus_scale_register_client(&dec_ocmem_bus_data);
-	if (!core->resources.bus_info.ocmem_handle[MSM_VIDC_DECODER]) {
-		dprintk(VIDC_ERR, "Failed to register bus scale client\n");
-		goto fail_register_dec_ocmem;
-	}
-	rc = register_iommu_domains(pdev, core);
-	if (rc) {
-		dprintk(VIDC_ERR, "Failed to register iommu domains: %d\n", rc);
-		goto fail_register_domains;
-	}
-	ocmem = &core->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");
-	}
-	return rc;
-fail_register_domains:
-	msm_bus_scale_unregister_client(
-		core->resources.bus_info.ocmem_handle[MSM_VIDC_DECODER]);
-fail_register_dec_ocmem:
-	msm_bus_scale_unregister_client(
-		core->resources.bus_info.ocmem_handle[MSM_VIDC_ENCODER]);
-fail_register_enc_ocmem:
-	msm_bus_scale_unregister_client(
-		core->resources.bus_info.ddr_handle[MSM_VIDC_DECODER]);
-fail_register_dec_ddr_bus:
-	msm_bus_scale_unregister_client(
-		core->resources.bus_info.ddr_handle[MSM_VIDC_ENCODER]);
-fail_register_enc_ddr_bus:
-	msm_vidc_deinit_clocks(core);
-core_init_failed:
+
+	rc = msm_vidc_get_hfi(pdev, core);
+	if (rc)
+		dprintk(VIDC_ERR,
+			"Failed to read Host-Firmware Interface rc: %d\n", rc);
+
 	return rc;
 }
 
@@ -1377,11 +768,11 @@
 		goto err_enc_register;
 	}
 	video_set_drvdata(&core->vdev[MSM_VIDC_ENCODER].vdev, core);
-	core->device = vidc_hal_add_device(core->id, core->base_addr,
-			core->register_base, core->register_size, core->irq,
-			&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 interrupt handler");
+		dprintk(VIDC_ERR, "Failed to create HFI device\n");
 		goto err_cores_exceeded;
 	}
 
@@ -1416,21 +807,24 @@
 static int __devexit msm_vidc_remove(struct platform_device *pdev)
 {
 	int rc = 0;
-	struct msm_vidc_core *core = pdev->dev.platform_data;
-	int i;
-	for (i = 0; i < MSM_VIDC_MAX_DEVICES; ++i) {
-		msm_bus_scale_unregister_client(
-			core->resources.bus_info.ddr_handle[i]);
-		msm_bus_scale_unregister_client(
-			core->resources.bus_info.ocmem_handle[i]);
+	struct msm_vidc_core *core;
+
+	if (!pdev) {
+		dprintk(VIDC_ERR, "%s invalid input %p", __func__, pdev);
+		return -EINVAL;
 	}
-	vidc_hal_delete_device(core->device);
+	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);
-	if (core->resources.ocmem.handle)
-		ocmem_notifier_unregister(core->resources.ocmem.handle,
-				&core->resources.ocmem.vidc_ocmem_nb);
+
 	kfree(core);
 	return rc;
 }
diff --git a/drivers/media/video/msm_vidc/msm_vdec.c b/drivers/media/video/msm_vidc/msm_vdec.c
index 440c704..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
@@ -15,7 +15,7 @@
 
 #include "msm_vidc_internal.h"
 #include "msm_vidc_common.h"
-#include "vidc_hal_api.h"
+#include "vidc_hfi_api.h"
 #include "msm_smem.h"
 #include "msm_vidc_debug.h"
 
@@ -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,8 +423,8 @@
 				buffer_info.extradata_addr = 0;
 				buffer_info.extradata_size = 0;
 			}
-			rc = vidc_hal_session_set_buffers((void *)inst->session,
-					&buffer_info);
+			rc = hdev->session_set_buffers(
+				(void *)inst->session, &buffer_info);
 			if (rc)
 				dprintk(VIDC_ERR,
 				"vidc_hal_session_set_buffers failed");
@@ -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 = vidc_hal_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 = vidc_hal_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 = vidc_hal_session_set_property((void *)
+			rc = hdev->session_set_property((void *)
 				inst->session, property_id,
 					pdata);
 	}
diff --git a/drivers/media/video/msm_vidc/msm_vdec.h b/drivers/media/video/msm_vidc/msm_vdec.h
index 73a516e..c7f8427 100644
--- a/drivers/media/video/msm_vidc/msm_vdec.h
+++ b/drivers/media/video/msm_vidc/msm_vdec.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+/* 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
diff --git a/drivers/media/video/msm_vidc/msm_venc.c b/drivers/media/video/msm_vidc/msm_venc.c
index 0fa56b7..080f4c4 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
@@ -14,7 +14,7 @@
 
 #include "msm_vidc_internal.h"
 #include "msm_vidc_common.h"
-#include "vidc_hal_api.h"
+#include "vidc_hfi_api.h"
 #include "msm_smem.h"
 #include "msm_vidc_debug.h"
 
@@ -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 = vidc_hal_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) ({ \
@@ -1405,7 +1420,7 @@
 		dprintk(VIDC_DBG, "Control: HAL property=%d,ctrl_value=%d\n",
 				property_id,
 				ctrl->val);
-		rc = vidc_hal_session_set_property((void *)inst->session,
+		rc = hdev->session_set_property((void *)inst->session,
 				property_id, pdata);
 	}
 
@@ -1570,6 +1585,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 +1620,7 @@
 		frame_rate.frame_rate = inst->prop.fps * (0x1<<16);
 		frame_rate.buffer_type = HAL_BUFFER_OUTPUT;
 		pdata = &frame_rate;
-		rc = vidc_hal_session_set_property((void *)inst->session,
+		rc = hdev->session_set_property((void *)inst->session,
 				property_id, pdata);
 		if (rc) {
 			dprintk(VIDC_WARN,
@@ -1614,11 +1637,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 +1669,7 @@
 		frame_sz.height = inst->prop.height;
 		dprintk(VIDC_DBG, "width = %d, height = %d\n",
 				frame_sz.width, frame_sz.height);
-		rc = vidc_hal_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 +1677,7 @@
 			goto exit;
 		}
 		frame_sz.buffer_type = HAL_BUFFER_OUTPUT;
-		rc = vidc_hal_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 +1783,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,8 +1808,8 @@
 				b->m.planes[i].m.userptr;
 			buffer_info.extradata_size = 0;
 			buffer_info.extradata_addr = 0;
-			rc = vidc_hal_session_set_buffers((void *)inst->session,
-					&buffer_info);
+			rc = hdev->session_set_buffers(
+				(void *)inst->session, &buffer_info);
 			if (rc)
 				dprintk(VIDC_ERR,
 					"vidc_hal_session_set_buffers failed");
@@ -1790,6 +1829,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 +1862,7 @@
 			buffer_info.extradata_size = 0;
 			buffer_info.extradata_addr = 0;
 			buffer_info.response_required = false;
-			rc = vidc_hal_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_venc.h b/drivers/media/video/msm_vidc/msm_venc.h
index c098773..9020167 100644
--- a/drivers/media/video/msm_vidc/msm_venc.h
+++ b/drivers/media/video/msm_vidc/msm_venc.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+/* 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
diff --git a/drivers/media/video/msm_vidc/msm_vidc.c b/drivers/media/video/msm_vidc/msm_vidc.c
index 13180c5..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, 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
@@ -21,6 +21,7 @@
 #include "msm_vidc_common.h"
 #include "msm_smem.h"
 #include <linux/delay.h>
+#include "vidc_hfi_api.h"
 
 #define MAX_EVENTS 30
 
@@ -85,15 +86,14 @@
 		struct msm_vidc_iommu_info maps[MAX_MAP])
 {
 	struct msm_vidc_inst *inst = instance;
-	int c = 0;
+	struct hfi_device *hdev;
 
-	if (!inst || !maps)
+	if (!inst || !maps || !inst->core || !inst->core->device)
 		return -EINVAL;
 
-	for (c = 0; c < MAX_MAP; ++c)
-		maps[c] = inst->core->resources.io_map[c];
+	hdev = inst->core->device;
 
-	return 0;
+	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 e00528f..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, 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,15 +13,11 @@
 
 #include <linux/sched.h>
 #include <linux/slab.h>
-#include <linux/iommu.h>
 #include <asm/div64.h>
-#include <mach/iommu.h>
-#include <mach/iommu_domains.h>
 #include <mach/subsystem_restart.h>
-#include <mach/scm.h>
 
 #include "msm_vidc_common.h"
-#include "vidc_hal_api.h"
+#include "vidc_hfi_api.h"
 #include "msm_smem.h"
 #include "msm_vidc_debug.h"
 
@@ -50,42 +46,8 @@
 	__mbs;\
 })
 
-#define TZBSP_MEM_PROTECT_VIDEO_VAR 0x8
-struct tzbsp_memprot {
-	u32 cp_start;
-	u32 cp_size;
-	u32 cp_nonpixel_start;
-	u32 cp_nonpixel_size;
-};
-
-struct tzbsp_resp {
-	int ret;
-};
-
 #define TIME_DIFF_THRESHOLD 200
 
-static const u32 bus_table[] = {
-	36000,
-	110400,
-	244800,
-	489000,
-	783360,
-	979200,
-};
-
-static int get_bus_vector(int load)
-{
-	int num_rows = sizeof(bus_table)/(sizeof(u32));
-	int i;
-	for (i = 0; i < num_rows; i++) {
-		if (load <= bus_table[i])
-			break;
-	}
-	i++;
-	dprintk(VIDC_DBG, "Required bus = %d\n", i);
-	return i;
-}
-
 static int msm_comm_get_load(struct msm_vidc_core *core,
 	enum session_type type)
 {
@@ -109,47 +71,30 @@
 	return num_mbs_per_sec;
 }
 
-static unsigned long get_clock_rate(struct core_clock *clock,
-	int num_mbs_per_sec)
-{
-	int num_rows = clock->count;
-	struct load_freq_table *table = clock->load_freq_tbl;
-	unsigned long ret = table[num_rows-1].freq;
-	int i;
-	for (i = 0; i < num_rows; i++) {
-		if (num_mbs_per_sec > table[i].load)
-			break;
-		ret = table[i].freq;
-	}
-	dprintk(VIDC_DBG, "Required clock rate = %lu\n", ret);
-	return ret;
-}
-
 static int msm_comm_scale_bus(struct msm_vidc_core *core,
 	enum session_type type, enum mem_type mtype)
 {
 	int load;
 	int rc = 0;
-	u32 handle = 0;
+	struct hfi_device *hdev;
+
 	if (!core || type >= MSM_VIDC_MAX_DEVICES) {
 		dprintk(VIDC_ERR, "Invalid args: %p, %d\n", core, type);
 		return -EINVAL;
 	}
-	load = msm_comm_get_load(core, type);
-	if (mtype & DDR_MEM)
-		handle = core->resources.bus_info.ddr_handle[type];
-	if (mtype & OCMEM_MEM)
-		handle = core->resources.bus_info.ocmem_handle[type];
-	if (handle) {
-		rc = msm_bus_scale_client_update_request(
-				handle, get_bus_vector(load));
-		if (rc)
-			dprintk(VIDC_ERR, "Failed to scale bus: %d\n", rc);
-	} else {
-		dprintk(VIDC_ERR, "Failed to scale bus, mtype: %d\n",
-				mtype);
-		rc = -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 = hdev->scale_bus(hdev->hfi_device_data, load, type, mtype);
+	if (rc)
+		dprintk(VIDC_ERR, "Failed to scale bus: %d\n", rc);
+
 	return rc;
 }
 
@@ -157,49 +102,29 @@
 	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) &&
-			msm_bus_scale_client_update_request(
-				core->resources.bus_info.ddr_handle[i],
-				0)) {
+			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) &&
-			msm_bus_scale_client_update_request(
-				core->resources.bus_info.ocmem_handle[i],
-				0)) {
+			hdev->scale_bus(hdev->hfi_device_data, 0, i,
+					OCMEM_MEM)) {
 			dprintk(VIDC_WARN,
 				"Failed to unvote for OCMEM accesses\n");
 		}
 	}
 }
 
-static int protect_cp_mem(struct msm_vidc_core *core)
-{
-	struct tzbsp_memprot memprot;
-	unsigned int resp = 0;
-	int rc = 0;
-	struct msm_vidc_iommu_info *io_map = core->resources.io_map;
-	if (!io_map) {
-		dprintk(VIDC_ERR, "invalid params: %p\n", io_map);
-		return -EINVAL;
-	}
-	memprot.cp_start = 0x0;
-	memprot.cp_size = io_map[CP_MAP].addr_range[0] +
-			io_map[CP_MAP].addr_range[1];
-	memprot.cp_nonpixel_start = 0;
-	memprot.cp_nonpixel_size = 0;
-
-	rc = scm_call(SCM_SVC_CP, TZBSP_MEM_PROTECT_VIDEO_VAR, &memprot,
-			sizeof(memprot), &resp, sizeof(resp));
-	if (rc)
-		dprintk(VIDC_ERR,
-		"Failed to protect memory , rc is :%d, response : %d\n",
-		rc, resp);
-	return rc;
-}
-
 struct msm_vidc_core *get_vidc_core(int core_id)
 {
 	struct msm_vidc_core *core;
@@ -222,62 +147,6 @@
 	return NULL;
 }
 
-static int msm_comm_iommu_attach(struct msm_vidc_core *core)
-{
-	int rc;
-	struct iommu_domain *domain;
-	int i;
-	struct msm_vidc_iommu_info *io_map;
-	struct device *dev;
-	for (i = 0; i < MAX_MAP; i++) {
-		io_map = &core->resources.io_map[i];
-		dev = msm_iommu_get_ctx(io_map->ctx);
-		domain = msm_get_iommu_domain(io_map->domain);
-		if (IS_ERR_OR_NULL(domain)) {
-			dprintk(VIDC_ERR,
-				"Failed to get domain: %s\n", io_map->name);
-			rc = PTR_ERR(domain);
-			break;
-		}
-		rc = iommu_attach_device(domain, dev);
-		if (rc) {
-			dprintk(VIDC_ERR,
-				"IOMMU attach failed: %s\n", io_map->name);
-			break;
-		}
-	}
-	if (i < MAX_MAP) {
-		i--;
-		for (; i >= 0; i--) {
-			io_map = &core->resources.io_map[i];
-			dev = msm_iommu_get_ctx(io_map->ctx);
-			domain = msm_get_iommu_domain(io_map->domain);
-			if (dev && domain)
-				iommu_detach_device(domain, dev);
-		}
-	}
-	return rc;
-}
-
-static void msm_comm_iommu_detach(struct msm_vidc_core *core)
-{
-	struct device *dev;
-	struct iommu_domain *domain;
-	struct msm_vidc_iommu_info *io_map;
-	int i;
-	if (!core) {
-		dprintk(VIDC_ERR, "Invalid paramter: %p\n", core);
-		return;
-	}
-	for (i = 0; i < MAX_MAP; i++) {
-		io_map = &core->resources.io_map[i];
-		dev = msm_iommu_get_ctx(io_map->ctx);
-		domain = msm_get_iommu_domain(io_map->domain);
-		if (dev && domain)
-			iommu_detach_device(domain, dev);
-	}
-}
-
 const struct msm_vidc_format *msm_comm_get_pixel_fmt_index(
 	const struct msm_vidc_format fmt[], int size, int index, int fmt_type)
 {
@@ -1023,70 +892,40 @@
 {
 	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 = clk_set_rate(core->resources.clock[VCODEC_CLK].clk,
-			get_clock_rate(&core->resources.clock[VCODEC_CLK],
-				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;
 }
 
-static inline int msm_comm_enable_clks(struct msm_vidc_core *core)
-{
-	int i;
-	struct core_clock *cl;
-	int rc = 0;
-	if (!core) {
-		dprintk(VIDC_ERR, "Invalid params: %p\n", core);
-		return -EINVAL;
-	}
-	for (i = 0; i < VCODEC_MAX_CLKS; i++) {
-		cl = &core->resources.clock[i];
-		rc = clk_prepare_enable(cl->clk);
-		if (rc) {
-			dprintk(VIDC_ERR, "Failed to enable clocks\n");
-			goto fail_clk_enable;
-		} else {
-			dprintk(VIDC_DBG, "Clock: %s enabled\n", cl->name);
-		}
-	}
-	return rc;
-fail_clk_enable:
-	for (; i >= 0; i--) {
-		cl = &core->resources.clock[i];
-		clk_disable_unprepare(cl->clk);
-	}
-	return rc;
-}
-
-static inline void msm_comm_disable_clks(struct msm_vidc_core *core)
-{
-	int i;
-	struct core_clock *cl;
-	if (!core) {
-		dprintk(VIDC_ERR, "Invalid params: %p\n", core);
-		return;
-	}
-	for (i = 0; i < VCODEC_MAX_CLKS; i++) {
-		cl = &core->resources.clock[i];
-		clk_disable_unprepare(cl->clk);
-	}
-}
-
 void msm_comm_scale_clocks_and_bus(struct msm_vidc_inst *inst)
 {
-	struct msm_vidc_core *core = inst->core;
-	if (!inst) {
-		dprintk(VIDC_WARN, "Invalid params\n");
+	struct msm_vidc_core *core;
+	struct hfi_device *hdev;
+
+	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");
@@ -1095,7 +934,7 @@
 		dprintk(VIDC_WARN,
 				"Failed to scale DDR bus. Performance might be impacted\n");
 	}
-	if (core->resources.ocmem.buf) {
+	if (hdev->is_ocmem_present(hdev->hfi_device_data)) {
 		if (msm_comm_scale_bus(core, inst->session_type,
 					OCMEM_MEM))
 			dprintk(VIDC_WARN,
@@ -1103,64 +942,6 @@
 	}
 }
 
-static int msm_comm_load_fw(struct msm_vidc_core *core)
-{
-	int rc = 0;
-	if (!core) {
-		dprintk(VIDC_ERR, "Invalid paramter: %p\n", core);
-		return -EINVAL;
-	}
-	if (!core->resources.fw.cookie)
-		core->resources.fw.cookie = subsystem_get("venus");
-
-	if (IS_ERR_OR_NULL(core->resources.fw.cookie)) {
-		dprintk(VIDC_ERR, "Failed to download firmware\n");
-		rc = -ENOMEM;
-		goto fail_load_fw;
-	}
-	/*Clocks can be enabled only after pil_get since
-	 * gdsc is turned-on in pil_get*/
-	rc = msm_comm_enable_clks(core);
-	if (rc) {
-		dprintk(VIDC_ERR, "Failed to enable clocks: %d\n", rc);
-		goto fail_enable_clks;
-	}
-
-	rc = protect_cp_mem(core);
-	if (rc) {
-		dprintk(VIDC_ERR, "Failed to protect memory\n");
-		goto fail_iommu_attach;
-	}
-
-	rc = msm_comm_iommu_attach(core);
-	if (rc) {
-		dprintk(VIDC_ERR, "Failed to attach iommu");
-		goto fail_iommu_attach;
-	}
-	return rc;
-fail_iommu_attach:
-	msm_comm_disable_clks(core);
-fail_enable_clks:
-	subsystem_put(core->resources.fw.cookie);
-	core->resources.fw.cookie = NULL;
-fail_load_fw:
-	return rc;
-}
-
-static void msm_comm_unload_fw(struct msm_vidc_core *core)
-{
-	if (!core) {
-		dprintk(VIDC_ERR, "Invalid paramter: %p\n", core);
-		return;
-	}
-	if (core->resources.fw.cookie) {
-		msm_comm_iommu_detach(core);
-		msm_comm_disable_clks(core);
-		subsystem_put(core->resources.fw.cookie);
-		core->resources.fw.cookie = NULL;
-	}
-}
-
 static inline unsigned long get_ocmem_requirement(u32 height, u32 width)
 {
 	int num_mbs = 0;
@@ -1170,48 +951,27 @@
 	return 512 * 1024;
 }
 
-static int msm_comm_set_ocmem(struct msm_vidc_core *core,
-	struct ocmem_buf *ocmem)
-{
-	struct vidc_resource_hdr rhdr;
-	int rc = 0;
-	if (!core || !ocmem) {
-		dprintk(VIDC_ERR, "Invalid params, core:%p, ocmem: %p\n",
-			core, ocmem);
-		return -EINVAL;
-	}
-	rhdr.resource_id = VIDC_RESOURCE_OCMEM;
-	rhdr.resource_handle = (u32) &core->resources.ocmem;
-	rhdr.size =	ocmem->len;
-	rc = vidc_hal_core_set_resource(core->device, &rhdr, ocmem);
-	if (rc) {
-		dprintk(VIDC_ERR, "Failed to set OCMEM on driver\n");
-		goto ocmem_set_failed;
-	}
-	dprintk(VIDC_DBG, "OCMEM set, addr = %lx, size: %ld\n",
-		ocmem->addr, ocmem->len);
-ocmem_set_failed:
-	return rc;
-}
-
 static int msm_comm_unset_ocmem(struct msm_vidc_core *core)
 {
-	struct vidc_resource_hdr rhdr;
 	int rc = 0;
-	if (!core || !core->resources.ocmem.buf) {
-		dprintk(VIDC_ERR, "Invalid params, core:%p\n",	core);
+	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");
 		return -EIO;
 	}
-	rhdr.resource_id = VIDC_RESOURCE_OCMEM;
-	rhdr.resource_handle = (u32) &core->resources.ocmem;
+
 	init_completion(
 		&core->completions[SYS_MSG_INDEX(RELEASE_RESOURCE_DONE)]);
-	rc = vidc_hal_core_release_resource(core->device, &rhdr);
+
+	rc = hdev->unset_ocmem(hdev->hfi_device_data);
 	if (rc) {
 		dprintk(VIDC_ERR, "Failed to set OCMEM on driver\n");
 		goto release_ocmem_failed;
@@ -1222,91 +982,11 @@
 	if (!rc) {
 		dprintk(VIDC_ERR, "Wait interrupted or timeout: %d\n", rc);
 		rc = -EIO;
-		goto release_ocmem_failed;
 	}
 release_ocmem_failed:
 	return rc;
 }
 
-static int msm_comm_alloc_ocmem(struct msm_vidc_core *core,
-		unsigned long size)
-{
-	int rc = 0;
-	struct ocmem_buf *ocmem_buffer;
-	mutex_lock(&core->sync_lock);
-	if (!core || !size) {
-		dprintk(VIDC_ERR,
-			"Invalid param, core: %p, size: %lu\n", core, size);
-		return -EINVAL;
-	}
-	ocmem_buffer = core->resources.ocmem.buf;
-	if (!ocmem_buffer ||
-		ocmem_buffer->len < size) {
-		ocmem_buffer = ocmem_allocate_nb(OCMEM_VIDEO, size);
-		if (IS_ERR_OR_NULL(ocmem_buffer)) {
-			dprintk(VIDC_ERR,
-				"ocmem_allocate_nb failed: %d\n",
-				(u32) ocmem_buffer);
-			rc = -ENOMEM;
-		}
-		core->resources.ocmem.buf = ocmem_buffer;
-		rc = msm_comm_set_ocmem(core, ocmem_buffer);
-		if (rc) {
-			dprintk(VIDC_ERR, "Failed to set ocmem: %d\n", rc);
-			goto ocmem_set_failed;
-		}
-	} else
-		dprintk(VIDC_DBG,
-			"OCMEM is enough. reqd: %lu, available: %lu\n",
-			size, ocmem_buffer->len);
-
-ocmem_set_failed:
-	mutex_unlock(&core->sync_lock);
-	return rc;
-}
-
-static int msm_comm_free_ocmem(struct msm_vidc_core *core)
-{
-	int rc = 0;
-	if (core->resources.ocmem.buf) {
-		rc = ocmem_free(OCMEM_VIDEO, core->resources.ocmem.buf);
-		if (rc)
-			dprintk(VIDC_ERR, "Failed to free ocmem\n");
-	}
-	core->resources.ocmem.buf = NULL;
-	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 msm_vidc_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 msm_vidc_resources, ocmem);
-		core = container_of(resources,
-			struct msm_vidc_core, resources);
-		if (msm_comm_set_ocmem(core, 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;
@@ -1345,6 +1025,12 @@
 	int rc = 0;
 	struct msm_vidc_core *core = inst->core;
 	unsigned long flags;
+	struct hfi_device *hdev;
+
+	if (!core || !core->device)
+		return -EINVAL;
+	hdev = core->device;
+
 	mutex_lock(&core->sync_lock);
 	if (core->state >= VIDC_CORE_INIT) {
 		dprintk(VIDC_INFO, "Video core: %d is already in state: %d\n",
@@ -1358,7 +1044,7 @@
 		goto fail_scale_bus;
 	}
 
-	rc = msm_comm_load_fw(core);
+	rc = hdev->load_fw(hdev->hfi_device_data);
 	if (rc) {
 		dprintk(VIDC_ERR, "Failed to load video firmware\n");
 		goto fail_load_fw;
@@ -1370,8 +1056,7 @@
 	}
 
 	init_completion(&core->completions[SYS_MSG_INDEX(SYS_INIT_DONE)]);
-	rc = vidc_hal_core_init(core->device,
-		core->resources.io_map[NS_MAP].domain);
+	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;
@@ -1384,7 +1069,7 @@
 	mutex_unlock(&core->sync_lock);
 	return rc;
 fail_core_init:
-	msm_comm_unload_fw(core);
+	hdev->unload_fw(hdev->hfi_device_data);
 fail_load_fw:
 	msm_comm_unvote_buses(core, DDR_MEM);
 fail_scale_bus:
@@ -1395,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",
@@ -1406,9 +1101,9 @@
 	msm_comm_scale_clocks_and_bus(inst);
 	if (list_empty(&core->instances)) {
 		msm_comm_unset_ocmem(core);
-		msm_comm_free_ocmem(core);
+		hdev->free_ocmem(hdev->hfi_device_data);
 		dprintk(VIDC_DBG, "Calling vidc_hal_core_release\n");
-		rc = vidc_hal_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);
@@ -1417,7 +1112,7 @@
 		spin_lock_irqsave(&core->lock, flags);
 		core->state = VIDC_CORE_UNINIT;
 		spin_unlock_irqrestore(&core->lock, flags);
-		msm_comm_unload_fw(core);
+		hdev->unload_fw(hdev->hfi_device_data);
 		msm_comm_unvote_buses(core, DDR_MEM|OCMEM_MEM);
 	}
 core_already_uninited:
@@ -1500,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);
@@ -1515,7 +1218,7 @@
 	}
 	init_completion(
 		&inst->completions[SESSION_MSG_INDEX(SESSION_INIT_DONE)]);
-	inst->session = vidc_hal_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) {
@@ -1536,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);
@@ -1544,7 +1255,9 @@
 	ocmem_sz = get_ocmem_requirement(inst->prop.height, inst->prop.width);
 	rc = msm_comm_scale_bus(inst->core, inst->session_type, OCMEM_MEM);
 	if (!rc) {
-		rc = msm_comm_alloc_ocmem(inst->core, ocmem_sz);
+		mutex_lock(&inst->core->sync_lock);
+		rc = hdev->alloc_ocmem(hdev->hfi_device_data, ocmem_sz);
+		mutex_unlock(&inst->core->sync_lock);
 		if (rc) {
 			dprintk(VIDC_WARN,
 			"Failed to allocate OCMEM. Performance will be impacted\n");
@@ -1554,7 +1267,7 @@
 		dprintk(VIDC_WARN,
 		"Failed to vote for OCMEM BW. Performance will be impacted\n");
 	}
-	rc = vidc_hal_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");
@@ -1568,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",
@@ -1576,7 +1298,7 @@
 	}
 	init_completion(
 		&inst->completions[SESSION_MSG_INDEX(SESSION_START_DONE)]);
-	rc = vidc_hal_session_start((void *) inst->session);
+	rc = hdev->session_start((void *) inst->session);
 	if (rc) {
 		dprintk(VIDC_ERR,
 			"Failed to send start\n");
@@ -1590,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",
@@ -1599,7 +1329,7 @@
 	dprintk(VIDC_DBG, "Send Stop to hal\n");
 	init_completion(
 		&inst->completions[SESSION_MSG_INDEX(SESSION_STOP_DONE)]);
-	rc = vidc_hal_session_stop((void *) inst->session);
+	rc = hdev->session_stop((void *) inst->session);
 	if (rc) {
 		dprintk(VIDC_ERR, "Failed to send stop\n");
 		goto exit;
@@ -1612,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",
@@ -1622,7 +1360,7 @@
 		"Send release res to hal\n");
 	init_completion(
 	&inst->completions[SESSION_MSG_INDEX(SESSION_RELEASE_RESOURCE_DONE)]);
-	rc = vidc_hal_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");
@@ -1633,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",
@@ -1646,7 +1392,7 @@
 		"Send session close to hal\n");
 	init_completion(
 		&inst->completions[SESSION_MSG_INDEX(SESSION_END_DONE)]);
-	rc = vidc_hal_session_end((void *) inst->session);
+	rc = hdev->session_end((void *) inst->session);
 	if (rc) {
 		dprintk(VIDC_ERR,
 			"Failed to send close\n");
@@ -1795,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) {
@@ -1807,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) {
@@ -1850,7 +1602,7 @@
 			dprintk(VIDC_DBG,
 				"Sending etb to hal: Alloc: %d :filled: %d\n",
 				frame_data.alloc_len, frame_data.filled_len);
-			rc = vidc_hal_session_etb((void *) inst->session,
+			rc = hdev->session_etb((void *) inst->session,
 					&frame_data);
 			if (!rc)
 				msm_vidc_debugfs_update(inst,
@@ -1880,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 = vidc_hal_session_get_seq_hdr((void *)
+				rc = hdev->session_get_seq_hdr((void *)
 						inst->session, &seq_hdr);
 				if (!rc) {
 					inst->vb2_seq_hdr = vb;
@@ -1888,7 +1640,7 @@
 						inst->vb2_seq_hdr);
 				}
 			} else {
-				rc = vidc_hal_session_ftb((void *)
+				rc = hdev->session_ftb((void *)
 					inst->session, &frame_data);
 			if (!rc)
 				msm_vidc_debugfs_update(inst,
@@ -1911,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,
@@ -1920,7 +1680,7 @@
 	}
 	init_completion(
 		&inst->completions[SESSION_MSG_INDEX(SESSION_PROPERTY_INFO)]);
-	rc = vidc_hal_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;
@@ -1948,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);
@@ -1959,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) {
@@ -1975,7 +1741,7 @@
 				init_completion(
 				   &inst->completions[SESSION_MSG_INDEX
 				   (SESSION_RELEASE_BUFFER_DONE)]);
-				rc = vidc_hal_session_release_buffers(
+				rc = hdev->session_release_buffers(
 						(void *) inst->session,
 							&buffer_info);
 				if (rc)
@@ -2008,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);
@@ -2019,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) {
@@ -2035,7 +1807,7 @@
 				init_completion(
 				   &inst->completions[SESSION_MSG_INDEX
 				   (SESSION_RELEASE_BUFFER_DONE)]);
-				rc = vidc_hal_session_release_buffers(
+				rc = hdev->session_release_buffers(
 						(void *) inst->session,
 							&buffer_info);
 				if (rc)
@@ -2063,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 = vidc_hal_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");
@@ -2091,9 +1871,19 @@
 	unsigned long flags;
 	int domain;
 	unsigned long smem_flags = 0;
-	struct hal_buffer_requirements *scratch_buf =
-		&inst->buff_req.buffer[HAL_BUFFER_INTERNAL_SCRATCH];
+	struct hal_buffer_requirements *scratch_buf;
 	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;
+
+	scratch_buf =
+		&inst->buff_req.buffer[HAL_BUFFER_INTERNAL_SCRATCH];
 	dprintk(VIDC_DBG,
 		"scratch: num = %d, size = %d\n",
 		scratch_buf->buffer_count_actual,
@@ -2101,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 = inst->core->resources.io_map[CP_MAP].domain;
+		domain = hdev->get_domain(hdev->hfi_device_data, CP_MAP);
 		smem_flags |= SMEM_SECURE;
 	} else
-		domain = inst->core->resources.io_map[NS_MAP].domain;
+		domain = hdev->get_domain(hdev->hfi_device_data, NS_MAP);
 
 	if (scratch_buf->buffer_size) {
 		for (i = 0; i < scratch_buf->buffer_count_actual;
@@ -2131,7 +1921,7 @@
 			buffer_info.align_device_addr = handle->device_addr;
 			dprintk(VIDC_DBG, "Scratch buffer address: %x",
 					buffer_info.align_device_addr);
-			rc = vidc_hal_session_set_buffers(
+			rc = hdev->session_set_buffers(
 					(void *) inst->session,	&buffer_info);
 			if (rc) {
 				dprintk(VIDC_ERR,
@@ -2161,9 +1951,19 @@
 	unsigned long flags;
 	unsigned long smem_flags = 0;
 	int domain;
-	struct hal_buffer_requirements *persist_buf =
-		&inst->buff_req.buffer[HAL_BUFFER_INTERNAL_PERSIST];
+	struct hal_buffer_requirements *persist_buf;
 	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;
+
+	persist_buf =
+		&inst->buff_req.buffer[HAL_BUFFER_INTERNAL_PERSIST];
 	dprintk(VIDC_DBG,
 		"persist: num = %d, size = %d\n",
 		persist_buf->buffer_count_actual,
@@ -2175,10 +1975,10 @@
 	}
 
 	if (inst->mode == VIDC_SECURE) {
-		domain = inst->core->resources.io_map[CP_MAP].domain;
+		domain = hdev->get_domain(hdev->hfi_device_data, CP_MAP);
 		flags |= SMEM_SECURE;
 	} else
-		domain = inst->core->resources.io_map[NS_MAP].domain;
+		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++) {
@@ -2204,7 +2004,7 @@
 			buffer_info.align_device_addr = handle->device_addr;
 			dprintk(VIDC_DBG, "Persist buffer address: %x",
 					buffer_info.align_device_addr);
-			rc = vidc_hal_session_set_buffers(
+			rc = hdev->session_set_buffers(
 				(void *) inst->session, &buffer_info);
 			if (rc) {
 				dprintk(VIDC_ERR,
@@ -2278,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);
@@ -2289,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;
@@ -2315,7 +2121,7 @@
 			dprintk(VIDC_WARN,
 			"FLUSH BUG: Pending q not empty! It should be empty\n");
 		}
-		rc = vidc_hal_session_flush(inst->session,
+		rc = hdev->session_flush(inst->session,
 				HAL_FLUSH_OUTPUT);
 	} else {
 		if (!list_empty(&inst->pendingq)) {
@@ -2336,7 +2142,7 @@
 				kfree(temp);
 			}
 		}
-		rc = vidc_hal_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_common.h b/drivers/media/video/msm_vidc/msm_vidc_common.h
index 27eab6f..69f41c7 100644
--- a/drivers/media/video/msm_vidc/msm_vidc_common.h
+++ b/drivers/media/video/msm_vidc/msm_vidc_common.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+/* 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
diff --git a/drivers/media/video/msm_vidc/msm_vidc_debug.c b/drivers/media/video/msm_vidc/msm_vidc_debug.c
index f91d0dd..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, 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
@@ -12,10 +12,11 @@
  */
 
 #include "msm_vidc_debug.h"
+#include "vidc_hfi_api.h"
 
 #define MAX_DBG_BUF_SIZE 4096
-int msm_vidc_debug;
-int msm_fw_debug;
+int msm_vidc_debug = 0x3;
+int msm_fw_debug = 0x18;
 
 struct debug_buffer {
 	char ptr[MAX_DBG_BUF_SIZE];
@@ -52,20 +53,26 @@
 		size_t count, loff_t *ppos)
 {
 	struct msm_vidc_core *core = file->private_data;
+	struct hfi_device *hdev;
 	int i = 0;
-	if (!core) {
+	if (!core || !core->device) {
 		dprintk(VIDC_ERR, "Invalid params, core: %p\n", core);
 		return 0;
 	}
+	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", core->base_addr);
-	write_str(&dbg_buf, "register_base: 0x%x\n", core->register_base);
-	write_str(&dbg_buf, "register_size: %u\n", core->register_size);
-	write_str(&dbg_buf, "irq: %u\n", core->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)]) ?
@@ -89,8 +96,7 @@
 		dprintk(VIDC_ERR, "Invalid params, core: %p\n", core);
 		goto failed_create_dir;
 	}
-	msm_vidc_debug = 0;
-	msm_fw_debug = 0;
+
 	snprintf(debugfs_name, MAX_DEBUGFS_NAME, "core%d", core->id);
 	dir = debugfs_create_dir(debugfs_name, parent);
 	if (!dir) {
@@ -106,13 +112,11 @@
 		dprintk(VIDC_ERR, "debugfs_create_file: fail\n");
 		goto failed_create_dir;
 	}
-	msm_vidc_debug = 0x3;
 	if (!debugfs_create_u32("fw_level", S_IRUGO | S_IWUSR,
 			parent, &msm_fw_debug)) {
 		dprintk(VIDC_ERR, "debugfs_create_file: fail\n");
 		goto failed_create_dir;
 	}
-	msm_fw_debug = 0x18;
 failed_create_dir:
 	return dir;
 }
diff --git a/drivers/media/video/msm_vidc/msm_vidc_debug.h b/drivers/media/video/msm_vidc/msm_vidc_debug.h
index 995daf0..b3bb6e1 100644
--- a/drivers/media/video/msm_vidc/msm_vidc_debug.h
+++ b/drivers/media/video/msm_vidc/msm_vidc_debug.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+/* 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
diff --git a/drivers/media/video/msm_vidc/msm_vidc_internal.h b/drivers/media/video/msm_vidc/msm_vidc_internal.h
index aadb4c2..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
@@ -18,7 +18,6 @@
 #include <linux/spinlock.h>
 #include <linux/types.h>
 #include <linux/completion.h>
-#include <linux/clk.h>
 #include <linux/wait.h>
 #include <mach/msm_bus.h>
 #include <mach/msm_bus_board.h>
@@ -32,7 +31,8 @@
 #include <media/msm_vidc.h>
 #include <media/msm_media_info.h>
 
-#include "vidc_hal_api.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);
@@ -117,54 +117,6 @@
 	struct video_device vdev;
 };
 
-struct msm_vidc_fw {
-	void *cookie;
-};
-
-enum vidc_clocks {
-	VCODEC_CLK,
-	VCODEC_AHB_CLK,
-	VCODEC_AXI_CLK,
-	VCODEC_OCMEM_CLK,
-	VCODEC_MAX_CLKS
-};
-
-struct load_freq_table {
-	u32 load;
-	u32 freq;
-};
-
-enum mem_type {
-	DDR_MEM = 0x1,
-	OCMEM_MEM = 0x2,
-};
-
-struct core_clock {
-	char name[MAX_NAME_LENGTH];
-	struct clk *clk;
-	u32 count;
-	struct load_freq_table load_freq_tbl[8];
-};
-
-struct vidc_bus_info {
-	u32 ddr_handle[MSM_VIDC_MAX_DEVICES];
-	u32 ocmem_handle[MSM_VIDC_MAX_DEVICES];
-};
-
-struct on_chip_mem {
-	struct ocmem_buf *buf;
-	struct notifier_block vidc_ocmem_nb;
-	void *handle;
-};
-
-struct msm_vidc_resources {
-	struct msm_vidc_fw fw;
-	struct msm_vidc_iommu_info io_map[MAX_MAP];
-	struct core_clock clock[VCODEC_MAX_CLKS];
-	struct vidc_bus_info bus_info;
-	struct on_chip_mem ocmem;
-};
-
 struct session_prop {
 	u32 width;
 	u32 height;
@@ -224,13 +176,9 @@
 	spinlock_t lock;
 	struct list_head instances;
 	struct dentry *debugfs_root;
-	u32 base_addr;
-	u32 register_base;
-	u32 register_size;
-	u32 irq;
 	enum vidc_core_state state;
-	struct msm_vidc_resources resources;
 	struct completion completions[SYS_MSG_END - SYS_MSG_START + 1];
+	enum msm_vidc_hfi_type hfi_type;
 };
 
 struct msm_vidc_inst {
@@ -289,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
new file mode 100644
index 0000000..015ed11
--- /dev/null
+++ b/drivers/media/video/msm_vidc/venus_hfi.c
@@ -0,0 +1,3027 @@
+/* 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 <linux/workqueue.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/delay.h>
+#include <linux/of.h>
+#include <linux/iommu.h>
+#include <mach/iommu.h>
+#include <mach/iommu_domains.h>
+#include <mach/ocmem.h>
+#include <mach/scm.h>
+#include <mach/subsystem_restart.h>
+#include <asm/memory.h>
+#include "hfi_packetization.h"
+#include "venus_hfi.h"
+#include "vidc_hfi_io.h"
+#include "msm_vidc_debug.h"
+
+#define FIRMWARE_SIZE			0X00A00000
+#define REG_ADDR_OFFSET_BITMASK	0x000FFFFF
+
+/*Workaround for simulator */
+#define HFI_SIM_FW_BIAS		0x0
+
+#define SHARED_QSIZE 0x1000000
+
+static struct msm_bus_vectors enc_ocmem_init_vectors[]  = {
+	{
+		.src = MSM_BUS_MASTER_VIDEO_P0_OCMEM,
+		.dst = MSM_BUS_SLAVE_OCMEM,
+		.ab = 0,
+		.ib = 0,
+	},
+};
+
+static struct msm_bus_vectors enc_ocmem_perf1_vectors[]  = {
+	{
+		.src = MSM_BUS_MASTER_VIDEO_P0_OCMEM,
+		.dst = MSM_BUS_SLAVE_OCMEM,
+		.ab = 138200000,
+		.ib = 1222000000,
+	},
+};
+
+static struct msm_bus_vectors enc_ocmem_perf2_vectors[]  = {
+	{
+		.src = MSM_BUS_MASTER_VIDEO_P0_OCMEM,
+		.dst = MSM_BUS_SLAVE_OCMEM,
+		.ab = 414700000,
+		.ib = 1222000000,
+	},
+};
+
+static struct msm_bus_vectors enc_ocmem_perf3_vectors[]  = {
+	{
+		.src = MSM_BUS_MASTER_VIDEO_P0_OCMEM,
+		.dst = MSM_BUS_SLAVE_OCMEM,
+		.ab = 940000000,
+		.ib = 2444000000U,
+	},
+};
+
+static struct msm_bus_vectors enc_ocmem_perf4_vectors[]  = {
+	{
+		.src = MSM_BUS_MASTER_VIDEO_P0_OCMEM,
+		.dst = MSM_BUS_SLAVE_OCMEM,
+		.ab = 1880000000,
+		.ib = 2444000000U,
+	},
+};
+
+static struct msm_bus_vectors enc_ocmem_perf5_vectors[]  = {
+	{
+		.src = MSM_BUS_MASTER_VIDEO_P0_OCMEM,
+		.dst = MSM_BUS_SLAVE_OCMEM,
+		.ab = 3008000000U,
+		.ib = 3910400000U,
+	},
+};
+
+static struct msm_bus_vectors enc_ocmem_perf6_vectors[]  = {
+	{
+		.src = MSM_BUS_MASTER_VIDEO_P0_OCMEM,
+		.dst = MSM_BUS_SLAVE_OCMEM,
+		.ab = 3760000000U,
+		.ib = 4888000000ULL,
+	},
+};
+
+static struct msm_bus_vectors dec_ocmem_init_vectors[]  = {
+	{
+		.src = MSM_BUS_MASTER_VIDEO_P0_OCMEM,
+		.dst = MSM_BUS_SLAVE_OCMEM,
+		.ab = 0,
+		.ib = 0,
+	},
+};
+
+static struct msm_bus_vectors dec_ocmem_perf1_vectors[]  = {
+	{
+		.src = MSM_BUS_MASTER_VIDEO_P0_OCMEM,
+		.dst = MSM_BUS_SLAVE_OCMEM,
+		.ab = 176900000,
+		.ib = 1556640000,
+	},
+};
+
+static struct msm_bus_vectors dec_ocmem_perf2_vectors[]  = {
+	{
+		.src = MSM_BUS_MASTER_VIDEO_P0_OCMEM,
+		.dst = MSM_BUS_SLAVE_OCMEM,
+		.ab = 456200000,
+		.ib = 1556640000,
+	},
+};
+
+static struct msm_bus_vectors dec_ocmem_perf3_vectors[]  = {
+	{
+		.src = MSM_BUS_MASTER_VIDEO_P0_OCMEM,
+		.dst = MSM_BUS_SLAVE_OCMEM,
+		.ab = 864800000,
+		.ib = 1556640000,
+	},
+};
+
+static struct msm_bus_vectors dec_ocmem_perf4_vectors[]  = {
+	{
+		.src = MSM_BUS_MASTER_VIDEO_P0_OCMEM,
+		.dst = MSM_BUS_SLAVE_OCMEM,
+		.ab = 1729600000,
+		.ib = 3113280000U,
+	},
+};
+
+static struct msm_bus_vectors dec_ocmem_perf5_vectors[]  = {
+	{
+		.src = MSM_BUS_MASTER_VIDEO_P0_OCMEM,
+		.dst = MSM_BUS_SLAVE_OCMEM,
+		.ab = 2767360000U,
+		.ib = 4981248000ULL,
+	},
+};
+
+static struct msm_bus_vectors dec_ocmem_perf6_vectors[]  = {
+	{
+		.src = MSM_BUS_MASTER_VIDEO_P0_OCMEM,
+		.dst = MSM_BUS_SLAVE_OCMEM,
+		.ab = 3459200000U,
+		.ib = 6226560000ULL,
+	},
+};
+
+static struct msm_bus_paths enc_ocmem_perf_vectors[]  = {
+	{
+		ARRAY_SIZE(enc_ocmem_init_vectors),
+		enc_ocmem_init_vectors,
+	},
+	{
+		ARRAY_SIZE(enc_ocmem_perf1_vectors),
+		enc_ocmem_perf1_vectors,
+	},
+	{
+		ARRAY_SIZE(enc_ocmem_perf2_vectors),
+		enc_ocmem_perf2_vectors,
+	},
+	{
+		ARRAY_SIZE(enc_ocmem_perf3_vectors),
+		enc_ocmem_perf3_vectors,
+	},
+	{
+		ARRAY_SIZE(enc_ocmem_perf4_vectors),
+		enc_ocmem_perf4_vectors,
+	},
+	{
+		ARRAY_SIZE(enc_ocmem_perf5_vectors),
+		enc_ocmem_perf5_vectors,
+	},
+	{
+		ARRAY_SIZE(enc_ocmem_perf6_vectors),
+		enc_ocmem_perf6_vectors,
+	},
+};
+
+static struct msm_bus_paths dec_ocmem_perf_vectors[]  = {
+	{
+		ARRAY_SIZE(dec_ocmem_init_vectors),
+		dec_ocmem_init_vectors,
+	},
+	{
+		ARRAY_SIZE(dec_ocmem_perf1_vectors),
+		dec_ocmem_perf1_vectors,
+	},
+	{
+		ARRAY_SIZE(dec_ocmem_perf2_vectors),
+		dec_ocmem_perf2_vectors,
+	},
+	{
+		ARRAY_SIZE(dec_ocmem_perf3_vectors),
+		dec_ocmem_perf3_vectors,
+	},
+	{
+		ARRAY_SIZE(dec_ocmem_perf4_vectors),
+		dec_ocmem_perf4_vectors,
+	},
+	{
+		ARRAY_SIZE(dec_ocmem_perf5_vectors),
+		dec_ocmem_perf5_vectors,
+	},
+	{
+		ARRAY_SIZE(dec_ocmem_perf6_vectors),
+		dec_ocmem_perf6_vectors,
+	},
+};
+
+
+static struct msm_bus_scale_pdata enc_ocmem_bus_data = {
+	.usecase = enc_ocmem_perf_vectors,
+	.num_usecases = ARRAY_SIZE(enc_ocmem_perf_vectors),
+	.name = "msm_vidc_enc_ocmem",
+};
+
+static struct msm_bus_scale_pdata dec_ocmem_bus_data = {
+	.usecase = dec_ocmem_perf_vectors,
+	.num_usecases = ARRAY_SIZE(dec_ocmem_perf_vectors),
+	.name = "msm_vidc_dec_ocmem",
+};
+
+static struct msm_bus_vectors enc_ddr_init_vectors[]  = {
+	{
+		.src = MSM_BUS_MASTER_VIDEO_P0,
+		.dst = MSM_BUS_SLAVE_EBI_CH0,
+		.ab = 0,
+		.ib = 0,
+	},
+};
+
+
+static struct msm_bus_vectors enc_ddr_perf1_vectors[]  = {
+	{
+		.src = MSM_BUS_MASTER_VIDEO_P0,
+		.dst = MSM_BUS_SLAVE_EBI_CH0,
+		.ab = 60000000,
+		.ib = 664950000,
+	},
+};
+
+static struct msm_bus_vectors enc_ddr_perf2_vectors[]  = {
+	{
+		.src = MSM_BUS_MASTER_VIDEO_P0,
+		.dst = MSM_BUS_SLAVE_EBI_CH0,
+		.ab = 181000000,
+		.ib = 664950000,
+	},
+};
+
+static struct msm_bus_vectors enc_ddr_perf3_vectors[]  = {
+	{
+		.src = MSM_BUS_MASTER_VIDEO_P0,
+		.dst = MSM_BUS_SLAVE_EBI_CH0,
+		.ab = 403000000,
+		.ib = 664950000,
+	},
+};
+
+static struct msm_bus_vectors enc_ddr_perf4_vectors[]  = {
+	{
+		.src = MSM_BUS_MASTER_VIDEO_P0,
+		.dst = MSM_BUS_SLAVE_EBI_CH0,
+		.ab = 806000000,
+		.ib = 1329900000,
+	},
+};
+
+static struct msm_bus_vectors enc_ddr_perf5_vectors[]  = {
+	{
+		.src = MSM_BUS_MASTER_VIDEO_P0,
+		.dst = MSM_BUS_SLAVE_EBI_CH0,
+		.ab = 1289600000,
+		.ib = 2127840000U,
+	},
+};
+
+static struct msm_bus_vectors enc_ddr_perf6_vectors[]  = {
+	{
+		.src = MSM_BUS_MASTER_VIDEO_P0,
+		.dst = MSM_BUS_SLAVE_EBI_CH0,
+		.ab = 161200000,
+		.ib = 6400000000ULL,
+	},
+};
+
+static struct msm_bus_vectors dec_ddr_init_vectors[]  = {
+	{
+		.src = MSM_BUS_MASTER_VIDEO_P0,
+		.dst = MSM_BUS_SLAVE_EBI_CH0,
+		.ab = 0,
+		.ib = 0,
+	},
+};
+
+static struct msm_bus_vectors dec_ddr_perf1_vectors[]  = {
+	{
+		.src = MSM_BUS_MASTER_VIDEO_P0,
+		.dst = MSM_BUS_SLAVE_EBI_CH0,
+		.ab = 110000000,
+		.ib = 909000000,
+	},
+};
+
+static struct msm_bus_vectors dec_ddr_perf2_vectors[]  = {
+	{
+		.src = MSM_BUS_MASTER_VIDEO_P0,
+		.dst = MSM_BUS_SLAVE_EBI_CH0,
+		.ab = 268000000,
+		.ib = 909000000,
+	},
+};
+
+static struct msm_bus_vectors dec_ddr_perf3_vectors[]  = {
+	{
+		.src = MSM_BUS_MASTER_VIDEO_P0,
+		.dst = MSM_BUS_SLAVE_EBI_CH0,
+		.ab = 505000000,
+		.ib = 909000000,
+	},
+};
+
+static struct msm_bus_vectors dec_ddr_perf4_vectors[]  = {
+	{
+		.src = MSM_BUS_MASTER_VIDEO_P0,
+		.dst = MSM_BUS_SLAVE_EBI_CH0,
+		.ab = 1010000000,
+		.ib = 1818000000,
+	},
+};
+
+static struct msm_bus_vectors dec_ddr_perf5_vectors[]  = {
+	{
+		.src = MSM_BUS_MASTER_VIDEO_P0,
+		.dst = MSM_BUS_SLAVE_EBI_CH0,
+		.ab = 1616000000,
+		.ib = 2908800000U,
+	},
+};
+
+static struct msm_bus_vectors dec_ddr_perf6_vectors[]  = {
+	{
+		.src = MSM_BUS_MASTER_VIDEO_P0,
+		.dst = MSM_BUS_SLAVE_EBI_CH0,
+		.ab = 2020000000U,
+		.ib = 6400000000ULL,
+	},
+};
+
+static struct msm_bus_paths enc_ddr_perf_vectors[]  = {
+	{
+		ARRAY_SIZE(enc_ddr_init_vectors),
+		enc_ddr_init_vectors,
+	},
+	{
+		ARRAY_SIZE(enc_ddr_perf1_vectors),
+		enc_ddr_perf1_vectors,
+	},
+	{
+		ARRAY_SIZE(enc_ddr_perf2_vectors),
+		enc_ddr_perf2_vectors,
+	},
+	{
+		ARRAY_SIZE(enc_ddr_perf3_vectors),
+		enc_ddr_perf3_vectors,
+	},
+	{
+		ARRAY_SIZE(enc_ddr_perf4_vectors),
+		enc_ddr_perf4_vectors,
+	},
+	{
+		ARRAY_SIZE(enc_ddr_perf5_vectors),
+		enc_ddr_perf5_vectors,
+	},
+	{
+		ARRAY_SIZE(enc_ddr_perf6_vectors),
+		enc_ddr_perf6_vectors,
+	},
+};
+
+static struct msm_bus_paths dec_ddr_perf_vectors[]  = {
+	{
+		ARRAY_SIZE(dec_ddr_init_vectors),
+		dec_ddr_init_vectors,
+	},
+	{
+		ARRAY_SIZE(dec_ddr_perf1_vectors),
+		dec_ddr_perf1_vectors,
+	},
+	{
+		ARRAY_SIZE(dec_ddr_perf2_vectors),
+		dec_ddr_perf2_vectors,
+	},
+	{
+		ARRAY_SIZE(dec_ddr_perf3_vectors),
+		dec_ddr_perf3_vectors,
+	},
+	{
+		ARRAY_SIZE(dec_ddr_perf4_vectors),
+		dec_ddr_perf4_vectors,
+	},
+	{
+		ARRAY_SIZE(dec_ddr_perf5_vectors),
+		dec_ddr_perf5_vectors,
+	},
+	{
+		ARRAY_SIZE(dec_ddr_perf6_vectors),
+		dec_ddr_perf6_vectors,
+	},
+};
+
+static struct msm_bus_scale_pdata enc_ddr_bus_data = {
+	.usecase = enc_ddr_perf_vectors,
+	.num_usecases = ARRAY_SIZE(enc_ddr_perf_vectors),
+	.name = "msm_vidc_enc_ddr",
+};
+
+static struct msm_bus_scale_pdata dec_ddr_bus_data = {
+	.usecase = dec_ddr_perf_vectors,
+	.num_usecases = ARRAY_SIZE(dec_ddr_perf_vectors),
+	.name = "msm_vidc_dec_ddr",
+};
+
+#define TZBSP_MEM_PROTECT_VIDEO_VAR 0x8
+struct tzbsp_memprot {
+	u32 cp_start;
+	u32 cp_size;
+	u32 cp_nonpixel_start;
+	u32 cp_nonpixel_size;
+};
+
+struct tzbsp_resp {
+	int ret;
+};
+
+static void venus_hfi_sim_modify_cmd_packet(u8 *packet)
+{
+	struct hfi_cmd_sys_session_init_packet *sys_init;
+	struct hal_session *sess;
+	u8 i;
+
+	if (!packet) {
+		dprintk(VIDC_ERR, "Invalid Param");
+		return;
+	}
+
+	sys_init = (struct hfi_cmd_sys_session_init_packet *)packet;
+	sess = (struct hal_session *) sys_init->session_id;
+	switch (sys_init->packet_type) {
+	case HFI_CMD_SESSION_EMPTY_BUFFER:
+		if (sess->is_decoder) {
+			struct hfi_cmd_session_empty_buffer_compressed_packet
+			*pkt = (struct
+			hfi_cmd_session_empty_buffer_compressed_packet
+			*) packet;
+			pkt->packet_buffer -= HFI_SIM_FW_BIAS;
+		} else {
+			struct
+			hfi_cmd_session_empty_buffer_uncompressed_plane0_packet
+			*pkt = (struct
+			hfi_cmd_session_empty_buffer_uncompressed_plane0_packet
+			*) packet;
+			pkt->packet_buffer -= HFI_SIM_FW_BIAS;
+		}
+		break;
+	case HFI_CMD_SESSION_FILL_BUFFER:
+	{
+		struct hfi_cmd_session_fill_buffer_packet *pkt =
+			(struct hfi_cmd_session_fill_buffer_packet *)packet;
+		pkt->packet_buffer -= HFI_SIM_FW_BIAS;
+		break;
+	}
+	case HFI_CMD_SESSION_SET_BUFFERS:
+	{
+		struct hfi_cmd_session_set_buffers_packet *pkt =
+			(struct hfi_cmd_session_set_buffers_packet *)packet;
+		if ((pkt->buffer_type == HFI_BUFFER_OUTPUT) ||
+			(pkt->buffer_type == HFI_BUFFER_OUTPUT2)) {
+			struct hfi_buffer_info *buff;
+			buff = (struct hfi_buffer_info *) pkt->rg_buffer_info;
+			buff->buffer_addr -= HFI_SIM_FW_BIAS;
+			buff->extra_data_addr -= HFI_SIM_FW_BIAS;
+		} else {
+			for (i = 0; i < pkt->num_buffers; i++)
+				pkt->rg_buffer_info[i] -= HFI_SIM_FW_BIAS;
+		}
+		break;
+	}
+	case HFI_CMD_SESSION_RELEASE_BUFFERS:
+	{
+		struct hfi_cmd_session_release_buffer_packet *pkt =
+			(struct hfi_cmd_session_release_buffer_packet *)packet;
+		if ((pkt->buffer_type == HFI_BUFFER_OUTPUT) ||
+			(pkt->buffer_type == HFI_BUFFER_OUTPUT2)) {
+			struct hfi_buffer_info *buff;
+			buff = (struct hfi_buffer_info *) pkt->rg_buffer_info;
+			buff->buffer_addr -= HFI_SIM_FW_BIAS;
+			buff->extra_data_addr -= HFI_SIM_FW_BIAS;
+		} else {
+			for (i = 0; i < pkt->num_buffers; i++)
+				pkt->rg_buffer_info[i] -= HFI_SIM_FW_BIAS;
+		}
+		break;
+	}
+	case HFI_CMD_SESSION_PARSE_SEQUENCE_HEADER:
+	{
+		struct hfi_cmd_session_parse_sequence_header_packet *pkt =
+			(struct hfi_cmd_session_parse_sequence_header_packet *)
+		packet;
+		pkt->packet_buffer -= HFI_SIM_FW_BIAS;
+		break;
+	}
+	case HFI_CMD_SESSION_GET_SEQUENCE_HEADER:
+	{
+		struct hfi_cmd_session_get_sequence_header_packet *pkt =
+			(struct hfi_cmd_session_get_sequence_header_packet *)
+		packet;
+		pkt->packet_buffer -= HFI_SIM_FW_BIAS;
+		break;
+	}
+	default:
+		break;
+	}
+}
+
+static int venus_hfi_write_queue(void *info, u8 *packet, u32 *rx_req_is_set)
+{
+	struct hfi_queue_header *queue;
+	u32 packet_size_in_words, new_write_idx;
+	struct vidc_iface_q_info *qinfo;
+	u32 empty_space, read_idx;
+	u32 *write_ptr;
+
+	if (!info || !packet || !rx_req_is_set) {
+		dprintk(VIDC_ERR, "Invalid Params");
+		return -EINVAL;
+	}
+
+	qinfo =	(struct vidc_iface_q_info *) info;
+	venus_hfi_sim_modify_cmd_packet(packet);
+
+	queue = (struct hfi_queue_header *) qinfo->q_hdr;
+
+	if (!queue) {
+		dprintk(VIDC_ERR, "queue not present");
+		return -ENOENT;
+	}
+
+	packet_size_in_words = (*(u32 *)packet) >> 2;
+	dprintk(VIDC_DBG, "Packet_size in words: %d", packet_size_in_words);
+
+	if (packet_size_in_words == 0) {
+		dprintk(VIDC_ERR, "Zero packet size");
+		return -ENODATA;
+	}
+
+	read_idx = queue->qhdr_read_idx;
+
+	empty_space = (queue->qhdr_write_idx >=  read_idx) ?
+		(queue->qhdr_q_size - (queue->qhdr_write_idx -  read_idx)) :
+		(read_idx - queue->qhdr_write_idx);
+	dprintk(VIDC_DBG, "Empty_space: %d", empty_space);
+	if (empty_space <= packet_size_in_words) {
+		queue->qhdr_tx_req =  1;
+		dprintk(VIDC_ERR, "Insufficient size (%d) to write (%d)",
+					  empty_space, packet_size_in_words);
+		return -ENOTEMPTY;
+	}
+
+	queue->qhdr_tx_req =  0;
+
+	new_write_idx = (queue->qhdr_write_idx + packet_size_in_words);
+	write_ptr = (u32 *)((qinfo->q_array.align_virtual_addr) +
+		(queue->qhdr_write_idx << 2));
+	dprintk(VIDC_DBG, "Write Ptr: %d", (u32) write_ptr);
+	if (new_write_idx < queue->qhdr_q_size) {
+		memcpy(write_ptr, packet, packet_size_in_words << 2);
+	} else {
+		new_write_idx -= queue->qhdr_q_size;
+		memcpy(write_ptr, packet, (packet_size_in_words -
+			new_write_idx) << 2);
+		memcpy((void *)qinfo->q_array.align_virtual_addr,
+			packet + ((packet_size_in_words - new_write_idx) << 2),
+			new_write_idx  << 2);
+	}
+	queue->qhdr_write_idx = new_write_idx;
+	*rx_req_is_set = (1 == queue->qhdr_rx_req) ? 1 : 0;
+	dprintk(VIDC_DBG, "Out : ");
+	return 0;
+}
+
+static void venus_hfi_hal_sim_modify_msg_packet(u8 *packet)
+{
+	struct hfi_msg_sys_session_init_done_packet *sys_idle;
+	struct hal_session *sess;
+
+	if (!packet) {
+		dprintk(VIDC_ERR, "Invalid Param: ");
+		return;
+	}
+
+	sys_idle = (struct hfi_msg_sys_session_init_done_packet *)packet;
+	sess = (struct hal_session *) sys_idle->session_id;
+
+	switch (sys_idle->packet_type) {
+	case HFI_MSG_SESSION_FILL_BUFFER_DONE:
+		if (sess->is_decoder) {
+			struct
+			hfi_msg_session_fbd_uncompressed_plane0_packet
+			*pkt_uc = (struct
+			hfi_msg_session_fbd_uncompressed_plane0_packet
+			*) packet;
+			pkt_uc->packet_buffer += HFI_SIM_FW_BIAS;
+		} else {
+			struct
+			hfi_msg_session_fill_buffer_done_compressed_packet
+			*pkt = (struct
+			hfi_msg_session_fill_buffer_done_compressed_packet
+			*) packet;
+			pkt->packet_buffer += HFI_SIM_FW_BIAS;
+		}
+		break;
+	case HFI_MSG_SESSION_EMPTY_BUFFER_DONE:
+	{
+		struct hfi_msg_session_empty_buffer_done_packet *pkt =
+		(struct hfi_msg_session_empty_buffer_done_packet *)packet;
+		pkt->packet_buffer += HFI_SIM_FW_BIAS;
+		break;
+	}
+	case HFI_MSG_SESSION_GET_SEQUENCE_HEADER_DONE:
+	{
+		struct
+		hfi_msg_session_get_sequence_header_done_packet
+		*pkt =
+		(struct hfi_msg_session_get_sequence_header_done_packet *)
+		packet;
+		pkt->sequence_header += HFI_SIM_FW_BIAS;
+		break;
+	}
+	default:
+		break;
+	}
+}
+
+static int venus_hfi_read_queue(void *info, u8 *packet, u32 *pb_tx_req_is_set)
+{
+	struct hfi_queue_header *queue;
+	u32 packet_size_in_words, new_read_idx;
+	u32 *read_ptr;
+	struct vidc_iface_q_info *qinfo;
+
+	if (!info || !packet || !pb_tx_req_is_set) {
+		dprintk(VIDC_ERR, "Invalid Params");
+		return -EINVAL;
+	}
+
+	qinfo =	(struct vidc_iface_q_info *) info;
+	queue = (struct hfi_queue_header *) qinfo->q_hdr;
+
+	if (!queue) {
+		dprintk(VIDC_ERR, "Queue memory is not allocated\n");
+		return -ENOMEM;
+	}
+
+	if (queue->qhdr_read_idx == queue->qhdr_write_idx) {
+		queue->qhdr_rx_req = 1;
+		*pb_tx_req_is_set = 0;
+		return -EPERM;
+	}
+
+	read_ptr = (u32 *)((qinfo->q_array.align_virtual_addr) +
+				(queue->qhdr_read_idx << 2));
+	packet_size_in_words = (*read_ptr) >> 2;
+	dprintk(VIDC_DBG, "packet_size_in_words: %d", packet_size_in_words);
+	if (packet_size_in_words == 0) {
+		dprintk(VIDC_ERR, "Zero packet size");
+		return -ENODATA;
+	}
+
+	new_read_idx = queue->qhdr_read_idx + packet_size_in_words;
+	dprintk(VIDC_DBG, "Read Ptr: %d", (u32) new_read_idx);
+	if (new_read_idx < queue->qhdr_q_size) {
+		memcpy(packet, read_ptr,
+			packet_size_in_words << 2);
+	} else {
+		new_read_idx -= queue->qhdr_q_size;
+		memcpy(packet, read_ptr,
+			(packet_size_in_words - new_read_idx) << 2);
+		memcpy(packet + ((packet_size_in_words -
+			new_read_idx) << 2),
+			(u8 *)qinfo->q_array.align_virtual_addr,
+			new_read_idx << 2);
+	}
+
+	queue->qhdr_read_idx = new_read_idx;
+
+	if (queue->qhdr_read_idx != queue->qhdr_write_idx)
+		queue->qhdr_rx_req = 0;
+	else
+		queue->qhdr_rx_req = 1;
+
+	*pb_tx_req_is_set = (1 == queue->qhdr_tx_req) ? 1 : 0;
+	venus_hfi_hal_sim_modify_msg_packet(packet);
+	dprintk(VIDC_DBG, "Out : ");
+	return 0;
+}
+
+static int venus_hfi_alloc(void *mem, void *clnt, u32 size, u32 align,
+						   u32 flags, int domain)
+{
+	struct vidc_mem_addr *vmem;
+	struct msm_smem *alloc;
+	int rc = 0;
+
+	if (!mem || !clnt || !size) {
+		dprintk(VIDC_ERR, "Invalid Params");
+		return -EINVAL;
+	}
+	vmem = (struct vidc_mem_addr *)mem;
+	dprintk(VIDC_INFO, "start to alloc: size:%d, Flags: %d", size, flags);
+
+	alloc  = msm_smem_alloc(clnt, size, align, flags, domain, 1, 1);
+	dprintk(VIDC_DBG, "Alloc done");
+	if (!alloc) {
+		dprintk(VIDC_ERR, "Alloc failed\n");
+		rc = -ENOMEM;
+		goto fail_smem_alloc;
+	}
+	rc = msm_smem_clean_invalidate(clnt, alloc);
+	if (rc) {
+		dprintk(VIDC_ERR, "NOTE: Failed to clean caches\n");
+		goto fail_clean_cache;
+	}
+	dprintk(VIDC_DBG, "venus_hfi_alloc:ptr=%p,size=%d",
+			alloc->kvaddr, size);
+	vmem->mem_size = alloc->size;
+	vmem->mem_data = alloc;
+	vmem->align_virtual_addr = (u8 *) alloc->kvaddr;
+	vmem->align_device_addr = (u8 *)alloc->device_addr;
+	return rc;
+fail_clean_cache:
+	msm_smem_free(clnt, alloc);
+fail_smem_alloc:
+	return rc;
+}
+
+static void venus_hfi_free(struct smem_client *clnt, struct msm_smem *mem)
+{
+	msm_smem_free(clnt, mem);
+}
+
+static void venus_hfi_write_register(u8 *base_addr, u32 reg,
+				u32 value, u8 *vaddr)
+{
+	u32 hwiosymaddr = reg;
+
+	reg &= REG_ADDR_OFFSET_BITMASK;
+	if (reg == (u32)VIDC_CPU_CS_SCIACMDARG2) {
+		/* workaround to offset of FW bias */
+		struct hfi_queue_header *qhdr;
+		struct hfi_queue_table_header *qtbl_hdr =
+			(struct hfi_queue_table_header *)vaddr;
+
+		qhdr = VIDC_IFACEQ_GET_QHDR_START_ADDR(qtbl_hdr, 0);
+		qhdr->qhdr_start_addr -= HFI_SIM_FW_BIAS;
+
+		qhdr = VIDC_IFACEQ_GET_QHDR_START_ADDR(qtbl_hdr, 1);
+		qhdr->qhdr_start_addr -= HFI_SIM_FW_BIAS;
+
+		qhdr = VIDC_IFACEQ_GET_QHDR_START_ADDR(qtbl_hdr, 2);
+		qhdr->qhdr_start_addr -= HFI_SIM_FW_BIAS;
+		value -= HFI_SIM_FW_BIAS;
+	}
+
+	hwiosymaddr = ((u32)base_addr + (hwiosymaddr));
+	dprintk(VIDC_DBG, "Base addr: 0x%x, written to: 0x%x, Value: 0x%x...",
+			(u32)base_addr, hwiosymaddr, value);
+	writel_relaxed(value, hwiosymaddr);
+	wmb();
+}
+
+static int venus_hfi_read_register(u8 *base_addr, u32 reg)
+{
+	int rc = readl_relaxed((u32)base_addr + reg);
+	rmb();
+	return rc;
+}
+
+static int venus_hfi_iface_cmdq_write(struct venus_hfi_device *device,
+					void *pkt)
+{
+	u32 rx_req_is_set = 0;
+	struct vidc_iface_q_info *q_info;
+	int result = -EPERM;
+
+	if (!device || !pkt) {
+		dprintk(VIDC_ERR, "Invalid Params");
+		return -EINVAL;
+	}
+
+	spin_lock(&device->write_lock);
+	q_info = &device->iface_queues[VIDC_IFACEQ_CMDQ_IDX];
+	if (!q_info) {
+		dprintk(VIDC_ERR, "cannot write to shared Q's");
+		goto err_q_write;
+	}
+
+	if (!venus_hfi_write_queue(q_info, (u8 *)pkt, &rx_req_is_set)) {
+		if (rx_req_is_set)
+			venus_hfi_write_register(
+				device->hal_data->register_base_addr,
+				VIDC_CPU_IC_SOFTINT,
+				1 << VIDC_CPU_IC_SOFTINT_H2A_SHFT, 0);
+		result = 0;
+	} else {
+		dprintk(VIDC_ERR, "venus_hfi_iface_cmdq_write:queue_full");
+	}
+err_q_write:
+	spin_unlock(&device->write_lock);
+	return result;
+}
+
+static int venus_hfi_iface_msgq_read(struct venus_hfi_device *device, void *pkt)
+{
+	u32 tx_req_is_set = 0;
+	int rc = 0;
+	struct vidc_iface_q_info *q_info;
+
+	if (!pkt) {
+		dprintk(VIDC_ERR, "Invalid Params");
+		return -EINVAL;
+	}
+	spin_lock(&device->read_lock);
+	if (device->iface_queues[VIDC_IFACEQ_MSGQ_IDX].
+		q_array.align_virtual_addr == 0) {
+		dprintk(VIDC_ERR, "cannot read from shared MSG Q's");
+		rc = -ENODATA;
+		goto read_error;
+	}
+	q_info = &device->iface_queues[VIDC_IFACEQ_MSGQ_IDX];
+
+	if (!venus_hfi_read_queue(q_info, (u8 *)pkt, &tx_req_is_set)) {
+		if (tx_req_is_set)
+			venus_hfi_write_register(
+				device->hal_data->register_base_addr,
+				VIDC_CPU_IC_SOFTINT,
+				1 << VIDC_CPU_IC_SOFTINT_H2A_SHFT, 0);
+		rc = 0;
+	} else {
+		dprintk(VIDC_INFO, "venus_hfi_iface_msgq_read:queue_empty");
+		rc = -ENODATA;
+	}
+read_error:
+	spin_unlock(&device->read_lock);
+	return rc;
+}
+
+static int venus_hfi_iface_dbgq_read(struct venus_hfi_device *device, void *pkt)
+{
+	u32 tx_req_is_set = 0;
+	int rc = 0;
+	struct vidc_iface_q_info *q_info;
+
+	if (!pkt) {
+		dprintk(VIDC_ERR, "Invalid Params");
+		return -EINVAL;
+	}
+	spin_lock(&device->read_lock);
+	if (device->iface_queues[VIDC_IFACEQ_DBGQ_IDX].
+		q_array.align_virtual_addr == 0) {
+		dprintk(VIDC_ERR, "cannot read from shared DBG Q's");
+		rc = -ENODATA;
+		goto dbg_error;
+	}
+	q_info = &device->iface_queues[VIDC_IFACEQ_DBGQ_IDX];
+	if (!venus_hfi_read_queue(q_info, (u8 *)pkt, &tx_req_is_set)) {
+		if (tx_req_is_set)
+			venus_hfi_write_register(
+				device->hal_data->register_base_addr,
+				VIDC_CPU_IC_SOFTINT,
+				1 << VIDC_CPU_IC_SOFTINT_H2A_SHFT, 0);
+		rc = 0;
+	} else {
+		dprintk(VIDC_INFO, "venus_hfi_iface_dbgq_read:queue_empty");
+		rc = -ENODATA;
+	}
+dbg_error:
+	spin_unlock(&device->read_lock);
+	return rc;
+}
+
+static void venus_hfi_set_queue_hdr_defaults(struct hfi_queue_header *q_hdr)
+{
+	q_hdr->qhdr_status = 0x1;
+	q_hdr->qhdr_type = VIDC_IFACEQ_DFLT_QHDR;
+	q_hdr->qhdr_q_size = VIDC_IFACEQ_QUEUE_SIZE / 4;
+	q_hdr->qhdr_pkt_size = 0;
+	q_hdr->qhdr_rx_wm = 0x1;
+	q_hdr->qhdr_tx_wm = 0x1;
+	q_hdr->qhdr_rx_req = 0x1;
+	q_hdr->qhdr_tx_req = 0x0;
+	q_hdr->qhdr_rx_irq_status = 0x0;
+	q_hdr->qhdr_tx_irq_status = 0x0;
+	q_hdr->qhdr_read_idx = 0x0;
+	q_hdr->qhdr_write_idx = 0x0;
+}
+
+static void venus_hfi_interface_queues_release(struct venus_hfi_device *device)
+{
+	int i;
+
+	venus_hfi_free(device->hal_client, device->mem_addr.mem_data);
+
+	for (i = 0; i < VIDC_IFACEQ_NUMQ; i++) {
+		device->iface_queues[i].q_hdr = NULL;
+		device->iface_queues[i].q_array.mem_data = NULL;
+		device->iface_queues[i].q_array.align_virtual_addr = NULL;
+		device->iface_queues[i].q_array.align_device_addr = NULL;
+	}
+	device->iface_q_table.align_virtual_addr = NULL;
+	device->iface_q_table.align_device_addr = NULL;
+
+	device->qdss.align_virtual_addr = NULL;
+	device->qdss.align_device_addr = NULL;
+
+	device->sfr.align_virtual_addr = NULL;
+	device->sfr.align_device_addr = NULL;
+
+	device->mem_addr.align_virtual_addr = NULL;
+	device->mem_addr.align_device_addr = NULL;
+
+	msm_smem_delete_client(device->hal_client);
+	device->hal_client = NULL;
+}
+
+static int venus_hfi_interface_queues_init(struct venus_hfi_device *dev,
+					int domain)
+{
+	struct hfi_queue_table_header *q_tbl_hdr;
+	struct hfi_queue_header *q_hdr;
+	u8 i;
+	int rc = 0;
+	struct vidc_iface_q_info *iface_q;
+	struct hfi_sfr_struct *vsfr;
+	struct vidc_mem_addr *mem_addr;
+	int offset = 0;
+	int size_1m = 1024 * 1024;
+	int uc_size = (UC_SIZE + size_1m - 1) & (~(size_1m - 1));
+	mem_addr = &dev->mem_addr;
+	rc = venus_hfi_alloc((void *) mem_addr,
+			dev->hal_client, uc_size, 1,
+			0, domain);
+	if (rc) {
+		dprintk(VIDC_ERR, "iface_q_table_alloc_fail");
+		return -ENOMEM;
+	}
+	dev->iface_q_table.align_virtual_addr = mem_addr->align_virtual_addr;
+	dev->iface_q_table.align_device_addr = mem_addr->align_device_addr;
+	dev->iface_q_table.mem_size = VIDC_IFACEQ_TABLE_SIZE;
+	dev->iface_q_table.mem_data = NULL;
+	offset += dev->iface_q_table.mem_size;
+
+	for (i = 0; i < VIDC_IFACEQ_NUMQ; i++) {
+		iface_q = &dev->iface_queues[i];
+		iface_q->q_array.align_device_addr =
+			mem_addr->align_device_addr + offset;
+		iface_q->q_array.align_virtual_addr =
+			mem_addr->align_virtual_addr + offset;
+		iface_q->q_array.mem_size = VIDC_IFACEQ_QUEUE_SIZE;
+		iface_q->q_array.mem_data = NULL;
+		offset += iface_q->q_array.mem_size;
+		iface_q->q_hdr = VIDC_IFACEQ_GET_QHDR_START_ADDR(
+				dev->iface_q_table.align_virtual_addr, i);
+		venus_hfi_set_queue_hdr_defaults(iface_q->q_hdr);
+	}
+
+	dev->qdss.align_device_addr = mem_addr->align_device_addr + offset;
+	dev->qdss.align_virtual_addr = mem_addr->align_virtual_addr + offset;
+	dev->qdss.mem_size = QDSS_SIZE;
+	dev->qdss.mem_data = NULL;
+	offset += dev->qdss.mem_size;
+
+	dev->sfr.align_device_addr = mem_addr->align_device_addr + offset;
+	dev->sfr.align_virtual_addr = mem_addr->align_virtual_addr + offset;
+	dev->sfr.mem_size = SFR_SIZE;
+	dev->sfr.mem_data = NULL;
+	offset += dev->sfr.mem_size;
+
+	q_tbl_hdr = (struct hfi_queue_table_header *)
+			dev->iface_q_table.align_virtual_addr;
+	q_tbl_hdr->qtbl_version = 0;
+	q_tbl_hdr->qtbl_size = VIDC_IFACEQ_TABLE_SIZE;
+	q_tbl_hdr->qtbl_qhdr0_offset = sizeof(
+		struct hfi_queue_table_header);
+	q_tbl_hdr->qtbl_qhdr_size = sizeof(
+		struct hfi_queue_header);
+	q_tbl_hdr->qtbl_num_q = VIDC_IFACEQ_NUMQ;
+	q_tbl_hdr->qtbl_num_active_q = VIDC_IFACEQ_NUMQ;
+
+	iface_q = &dev->iface_queues[VIDC_IFACEQ_CMDQ_IDX];
+	q_hdr = iface_q->q_hdr;
+	q_hdr->qhdr_start_addr = (u32)
+		iface_q->q_array.align_device_addr;
+	q_hdr->qhdr_type |= HFI_Q_ID_HOST_TO_CTRL_CMD_Q;
+
+	iface_q = &dev->iface_queues[VIDC_IFACEQ_MSGQ_IDX];
+	q_hdr = iface_q->q_hdr;
+	q_hdr->qhdr_start_addr = (u32)
+		iface_q->q_array.align_device_addr;
+	q_hdr->qhdr_type |= HFI_Q_ID_CTRL_TO_HOST_MSG_Q;
+
+	iface_q = &dev->iface_queues[VIDC_IFACEQ_DBGQ_IDX];
+	q_hdr = iface_q->q_hdr;
+	q_hdr->qhdr_start_addr = (u32)
+		iface_q->q_array.align_device_addr;
+	q_hdr->qhdr_type |= HFI_Q_ID_CTRL_TO_HOST_DEBUG_Q;
+
+	venus_hfi_write_register(dev->hal_data->register_base_addr,
+			VIDC_UC_REGION_ADDR,
+			(u32) mem_addr->align_device_addr, 0);
+	venus_hfi_write_register(dev->hal_data->register_base_addr,
+			VIDC_UC_REGION_SIZE, mem_addr->mem_size, 0);
+	venus_hfi_write_register(dev->hal_data->register_base_addr,
+		VIDC_CPU_CS_SCIACMDARG2,
+		(u32) dev->iface_q_table.align_device_addr,
+		dev->iface_q_table.align_virtual_addr);
+	venus_hfi_write_register(dev->hal_data->register_base_addr,
+		VIDC_CPU_CS_SCIACMDARG1, 0x01,
+		dev->iface_q_table.align_virtual_addr);
+	venus_hfi_write_register(dev->hal_data->register_base_addr,
+			VIDC_MMAP_ADDR,
+			(u32) dev->qdss.align_device_addr, 0);
+
+	vsfr = (struct hfi_sfr_struct *) dev->sfr.align_virtual_addr;
+	vsfr->bufSize = SFR_SIZE;
+
+	venus_hfi_write_register(dev->hal_data->register_base_addr,
+			VIDC_SFR_ADDR, (u32)dev->sfr.align_device_addr , 0);
+	return 0;
+}
+
+static int venus_hfi_core_start_cpu(struct venus_hfi_device *device)
+{
+	u32 ctrl_status = 0, count = 0, rc = 0;
+	int max_tries = 100;
+	venus_hfi_write_register(device->hal_data->register_base_addr,
+			VIDC_WRAPPER_INTR_MASK, 0x8, 0);
+	venus_hfi_write_register(device->hal_data->register_base_addr,
+			VIDC_CPU_CS_SCIACMDARG3, 1, 0);
+
+	while (!ctrl_status && count < max_tries) {
+		ctrl_status = venus_hfi_read_register(
+				device->hal_data->register_base_addr,
+				VIDC_CPU_CS_SCIACMDARG0);
+		if ((ctrl_status & 0xFE) == 0x4) {
+			dprintk(VIDC_ERR, "invalid setting for UC_REGION\n");
+			break;
+		}
+		usleep_range(500, 1000);
+		count++;
+	}
+	if (count >= max_tries)
+		rc = -ETIME;
+	return rc;
+}
+
+static void venus_hfi_set_vbif_registers(struct venus_hfi_device *device)
+{
+	/*Disable Dynamic clock gating for Venus VBIF*/
+	venus_hfi_write_register(device->hal_data->register_base_addr,
+				   VIDC_VENUS_VBIF_CLK_ON, 1, 0);
+	venus_hfi_write_register(device->hal_data->register_base_addr,
+			VIDC_VBIF_OUT_AXI_AOOO_EN, 0x00001FFF, 0);
+	venus_hfi_write_register(device->hal_data->register_base_addr,
+			VIDC_VBIF_OUT_AXI_AOOO, 0x1FFF1FFF, 0);
+	venus_hfi_write_register(device->hal_data->register_base_addr,
+			VIDC_VBIF_IN_RD_LIM_CONF0, 0x10101001, 0);
+	venus_hfi_write_register(device->hal_data->register_base_addr,
+			VIDC_VBIF_IN_RD_LIM_CONF1, 0x10101010, 0);
+	venus_hfi_write_register(device->hal_data->register_base_addr,
+			VIDC_VBIF_IN_RD_LIM_CONF2, 0x10101010, 0);
+	venus_hfi_write_register(device->hal_data->register_base_addr,
+			VIDC_VBIF_IN_RD_LIM_CONF3, 0x00000010, 0);
+	venus_hfi_write_register(device->hal_data->register_base_addr,
+			VIDC_VBIF_IN_WR_LIM_CONF0, 0x1010100f, 0);
+	venus_hfi_write_register(device->hal_data->register_base_addr,
+			VIDC_VBIF_IN_WR_LIM_CONF1, 0x10101010, 0);
+	venus_hfi_write_register(device->hal_data->register_base_addr,
+			VIDC_VBIF_IN_WR_LIM_CONF2, 0x10101010, 0);
+	venus_hfi_write_register(device->hal_data->register_base_addr,
+			VIDC_VBIF_IN_WR_LIM_CONF3, 0x00000010, 0);
+	venus_hfi_write_register(device->hal_data->register_base_addr,
+			VIDC_VBIF_OUT_RD_LIM_CONF0, 0x00001010, 0);
+	venus_hfi_write_register(device->hal_data->register_base_addr,
+			VIDC_VBIF_OUT_WR_LIM_CONF0, 0x00001010, 0);
+	venus_hfi_write_register(device->hal_data->register_base_addr,
+			VIDC_VBIF_ARB_CTL, 0x00000030, 0);
+	venus_hfi_write_register(device->hal_data->register_base_addr,
+			VIDC_VENUS_VBIF_DDR_OUT_MAX_BURST, 0x00000707, 0);
+	venus_hfi_write_register(device->hal_data->register_base_addr,
+			VIDC_VENUS_VBIF_OCMEM_OUT_MAX_BURST, 0x00000707, 0);
+	venus_hfi_write_register(device->hal_data->register_base_addr,
+			VIDC_VENUS_VBIF_ROUND_ROBIN_QOS_ARB, 0x00000001, 0);
+	venus_hfi_write_register(device->hal_data->register_base_addr,
+			VIDC_VENUS0_WRAPPER_VBIF_REQ_PRIORITY, 0x5555556, 0);
+	venus_hfi_write_register(device->hal_data->register_base_addr,
+			VIDC_VENUS0_WRAPPER_VBIF_PRIORITY_LEVEL, 0, 0);
+}
+
+static int venus_hfi_sys_set_debug(struct venus_hfi_device *device, int debug)
+{
+	struct hfi_debug_config *hfi;
+	u8 packet[VIDC_IFACEQ_VAR_SMALL_PKT_SIZE];
+	struct hfi_cmd_sys_set_property_packet *pkt =
+		(struct hfi_cmd_sys_set_property_packet *) &packet;
+	pkt->size = sizeof(struct hfi_cmd_sys_set_property_packet) +
+		sizeof(struct hfi_debug_config) + sizeof(u32);
+	pkt->packet_type = HFI_CMD_SYS_SET_PROPERTY;
+	pkt->num_properties = 1;
+	pkt->rg_property_data[0] = HFI_PROPERTY_SYS_DEBUG_CONFIG;
+	hfi = (struct hfi_debug_config *) &pkt->rg_property_data[1];
+	hfi->debug_config = debug;
+	hfi->debug_mode = HFI_DEBUG_MODE_QUEUE;
+	if (venus_hfi_iface_cmdq_write(device, pkt))
+		return -ENOTEMPTY;
+	return 0;
+}
+
+static int venus_hfi_core_init(void *device)
+{
+	struct hfi_cmd_sys_init_packet pkt;
+	int rc = 0;
+	struct venus_hfi_device *dev;
+
+	if (device) {
+		dev = device;
+	} else {
+		dprintk(VIDC_ERR, "Invalid device");
+		return -ENODEV;
+	}
+
+	dev->intr_status = 0;
+	enable_irq(dev->hal_data->irq);
+	INIT_LIST_HEAD(&dev->sess_head);
+	spin_lock_init(&dev->read_lock);
+	spin_lock_init(&dev->write_lock);
+	venus_hfi_set_vbif_registers(dev);
+
+	if (!dev->hal_client) {
+		dev->hal_client = msm_smem_new_client(SMEM_ION);
+		if (dev->hal_client == NULL) {
+			dprintk(VIDC_ERR, "Failed to alloc ION_Client");
+			rc = -ENODEV;
+			goto err_core_init;
+		}
+
+		dprintk(VIDC_DBG, "Dev_Virt: 0x%x, Reg_Virt: 0x%x",
+		dev->hal_data->device_base_addr,
+		(u32) dev->hal_data->register_base_addr);
+
+		rc = venus_hfi_interface_queues_init(dev,
+				dev->resources.io_map[NS_MAP].domain);
+		if (rc) {
+			dprintk(VIDC_ERR, "failed to init queues");
+			rc = -ENOMEM;
+			goto err_core_init;
+		}
+	} else {
+		dprintk(VIDC_ERR, "hal_client exists");
+		rc = -EEXIST;
+		goto err_core_init;
+	}
+	venus_hfi_write_register(dev->hal_data->register_base_addr,
+		VIDC_CTRL_INIT, 0x1, 0);
+	rc = venus_hfi_core_start_cpu(dev);
+	if (rc) {
+		dprintk(VIDC_ERR, "Failed to start core");
+		rc = -ENODEV;
+		goto err_core_init;
+	}
+
+	rc = create_pkt_cmd_sys_init(&pkt, HFI_ARCH_OX_OFFSET);
+	if (rc) {
+		dprintk(VIDC_ERR, "Failed to create sys init pkt");
+		goto err_core_init;
+	}
+	if (venus_hfi_iface_cmdq_write(dev, &pkt)) {
+		rc = -ENOTEMPTY;
+		goto err_core_init;
+	}
+	return rc;
+err_core_init:
+	disable_irq_nosync(dev->hal_data->irq);
+	return rc;
+}
+
+static int venus_hfi_core_release(void *device)
+{
+	struct venus_hfi_device *dev;
+	if (device) {
+		dev = device;
+	} else {
+		dprintk(VIDC_ERR, "invalid device");
+		return -ENODEV;
+	}
+	if (dev->hal_client) {
+		venus_hfi_write_register(dev->hal_data->register_base_addr,
+				VIDC_CPU_CS_SCIACMDARG3, 0, 0);
+		disable_irq_nosync(dev->hal_data->irq);
+		venus_hfi_interface_queues_release(dev);
+	}
+	dprintk(VIDC_INFO, "HAL exited\n");
+	return 0;
+}
+
+int venus_hfi_core_pc_prep(void *device)
+{
+	struct hfi_cmd_sys_pc_prep_packet pkt;
+	int rc = 0;
+	struct venus_hfi_device *dev;
+
+	if (device) {
+		dev = device;
+	} else {
+		dprintk(VIDC_ERR, "invalid device");
+		return -ENODEV;
+	}
+
+	rc = create_pkt_cmd_sys_pc_prep(&pkt);
+	if (rc) {
+		dprintk(VIDC_ERR, "Failed to create sys pc prep pkt");
+		goto err_create_pkt;
+	}
+
+	if (venus_hfi_iface_cmdq_write(dev, &pkt))
+		rc = -ENOTEMPTY;
+
+err_create_pkt:
+	return rc;
+}
+
+static void venus_hfi_core_clear_interrupt(struct venus_hfi_device *device)
+{
+	u32 intr_status = 0;
+
+	if (!device->callback)
+		return;
+
+	intr_status = venus_hfi_read_register(
+			device->hal_data->register_base_addr,
+			VIDC_WRAPPER_INTR_STATUS);
+
+	if ((intr_status & VIDC_WRAPPER_INTR_STATUS_A2H_BMSK) ||
+		(intr_status & VIDC_WRAPPER_INTR_STATUS_A2HWD_BMSK)) {
+		device->intr_status |= intr_status;
+		dprintk(VIDC_DBG, "INTERRUPT for device: 0x%x: "
+			"times: %d interrupt_status: %d",
+			(u32) device, ++device->reg_count, intr_status);
+	} else {
+		dprintk(VIDC_INFO, "SPURIOUS_INTR for device: 0x%x: "
+			"times: %d interrupt_status: %d",
+			(u32) device, ++device->spur_count, intr_status);
+	}
+	venus_hfi_write_register(device->hal_data->register_base_addr,
+			VIDC_CPU_CS_A2HSOFTINTCLR, 1, 0);
+	venus_hfi_write_register(device->hal_data->register_base_addr,
+			VIDC_WRAPPER_INTR_CLEAR, intr_status, 0);
+	dprintk(VIDC_DBG, "Cleared WRAPPER/A2H interrupt");
+}
+
+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;
+	u8 packet[VIDC_IFACEQ_VAR_SMALL_PKT_SIZE];
+	int rc = 0;
+	struct venus_hfi_device *dev;
+
+	if (!device || !resource_hdr || !resource_value) {
+		dprintk(VIDC_ERR, "set_res: Invalid Params");
+		return -EINVAL;
+	} else {
+		dev = device;
+	}
+
+	pkt = (struct hfi_cmd_sys_set_resource_packet *) packet;
+
+	rc = create_pkt_set_cmd_sys_resource(pkt, resource_hdr,
+						resource_value);
+	if (rc) {
+		dprintk(VIDC_ERR, "set_res: failed to create packet");
+		goto err_create_pkt;
+	}
+	if (venus_hfi_iface_cmdq_write(dev, pkt))
+		rc = -ENOTEMPTY;
+
+err_create_pkt:
+	return rc;
+}
+
+static int venus_hfi_core_release_resource(void *device,
+			struct vidc_resource_hdr *resource_hdr)
+{
+	struct hfi_cmd_sys_release_resource_packet pkt;
+	int rc = 0;
+	struct venus_hfi_device *dev;
+
+	if (!device || !resource_hdr) {
+		dprintk(VIDC_ERR, "Inv-Params in rel_res");
+		return -EINVAL;
+	} else {
+		dev = device;
+	}
+
+	rc = create_pkt_cmd_sys_release_resource(&pkt, resource_hdr);
+	if (rc) {
+		dprintk(VIDC_ERR, "release_res: failed to create packet");
+		goto err_create_pkt;
+	}
+
+	if (venus_hfi_iface_cmdq_write(dev, &pkt))
+		rc = -ENOTEMPTY;
+
+err_create_pkt:
+	return rc;
+}
+
+static int venus_hfi_core_ping(void *device)
+{
+	struct hfi_cmd_sys_ping_packet pkt;
+	int rc = 0;
+	struct venus_hfi_device *dev;
+
+	if (device) {
+		dev = device;
+	} else {
+		dprintk(VIDC_ERR, "invalid device");
+		return -ENODEV;
+	}
+
+	rc = create_pkt_cmd_sys_ping(&pkt);
+	if (rc) {
+		dprintk(VIDC_ERR, "core_ping: failed to create packet");
+		goto err_create_pkt;
+	}
+
+	if (venus_hfi_iface_cmdq_write(dev, &pkt))
+		rc = -ENOTEMPTY;
+
+err_create_pkt:
+	return rc;
+}
+
+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 =
+		(struct hfi_cmd_session_set_property_packet *) &packet;
+	struct hal_session *session;
+	int rc = 0;
+
+	if (!sess || !pdata) {
+		dprintk(VIDC_ERR, "Invalid Params");
+		return -EINVAL;
+	} else {
+		session = sess;
+	}
+
+	dprintk(VIDC_INFO, "in set_prop,with prop id: 0x%x", ptype);
+
+	if (create_pkt_cmd_session_set_property(pkt, (u32)session, ptype,
+				pdata)) {
+		dprintk(VIDC_ERR, "set property: failed to create packet");
+		return -EINVAL;
+	}
+
+	if (venus_hfi_iface_cmdq_write(session->device, pkt))
+		return -ENOTEMPTY;
+
+	return rc;
+}
+
+static int venus_hfi_session_get_property(void *sess,
+				enum hal_property ptype, void *pdata)
+{
+	struct hal_session *session;
+
+	if (!sess || !pdata) {
+		dprintk(VIDC_ERR, "Invalid Params in ");
+		return -EINVAL;
+	} else {
+		session = sess;
+	}
+	dprintk(VIDC_INFO, "IN func: , with property id: %d", ptype);
+
+	switch (ptype) {
+	case HAL_CONFIG_FRAME_RATE:
+		break;
+	case HAL_PARAM_UNCOMPRESSED_FORMAT_SELECT:
+		break;
+	case HAL_PARAM_UNCOMPRESSED_PLANE_ACTUAL_CONSTRAINTS_INFO:
+		break;
+	case HAL_PARAM_UNCOMPRESSED_PLANE_ACTUAL_INFO:
+		break;
+	case HAL_PARAM_EXTRA_DATA_HEADER_CONFIG:
+		break;
+	case HAL_PARAM_FRAME_SIZE:
+		break;
+	case HAL_CONFIG_REALTIME:
+		break;
+	case HAL_PARAM_BUFFER_COUNT_ACTUAL:
+		break;
+	case HAL_PARAM_NAL_STREAM_FORMAT_SELECT:
+		break;
+	case HAL_PARAM_VDEC_OUTPUT_ORDER:
+		break;
+	case HAL_PARAM_VDEC_PICTURE_TYPE_DECODE:
+		break;
+	case HAL_PARAM_VDEC_OUTPUT2_KEEP_ASPECT_RATIO:
+		break;
+	case HAL_CONFIG_VDEC_POST_LOOP_DEBLOCKER:
+		break;
+	case HAL_PARAM_VDEC_MULTI_STREAM:
+		break;
+	case HAL_PARAM_VDEC_DISPLAY_PICTURE_BUFFER_COUNT:
+		break;
+	case HAL_PARAM_DIVX_FORMAT:
+		break;
+	case HAL_CONFIG_VDEC_MB_ERROR_MAP_REPORTING:
+		break;
+	case HAL_PARAM_VDEC_CONTINUE_DATA_TRANSFER:
+		break;
+	case HAL_CONFIG_VDEC_MB_ERROR_MAP:
+		break;
+	case HAL_CONFIG_VENC_REQUEST_IFRAME:
+		break;
+	case HAL_PARAM_VENC_MPEG4_SHORT_HEADER:
+		break;
+	case HAL_PARAM_VENC_MPEG4_AC_PREDICTION:
+		break;
+	case HAL_CONFIG_VENC_TARGET_BITRATE:
+		break;
+	case HAL_PARAM_PROFILE_LEVEL_CURRENT:
+		break;
+	case HAL_PARAM_VENC_H264_ENTROPY_CONTROL:
+		break;
+	case HAL_PARAM_VENC_RATE_CONTROL:
+		break;
+	case HAL_PARAM_VENC_MPEG4_TIME_RESOLUTION:
+		break;
+	case HAL_PARAM_VENC_MPEG4_HEADER_EXTENSION:
+		break;
+	case HAL_PARAM_VENC_H264_DEBLOCK_CONTROL:
+		break;
+	case HAL_PARAM_VENC_SESSION_QP:
+		break;
+	case HAL_CONFIG_VENC_INTRA_PERIOD:
+		break;
+	case HAL_CONFIG_VENC_IDR_PERIOD:
+		break;
+	case HAL_CONFIG_VPE_OPERATIONS:
+		break;
+	case HAL_PARAM_VENC_INTRA_REFRESH:
+		break;
+	case HAL_PARAM_VENC_MULTI_SLICE_CONTROL:
+		break;
+	case HAL_CONFIG_VPE_DEINTERLACE:
+		break;
+	case HAL_SYS_DEBUG_CONFIG:
+		break;
+	/*FOLLOWING PROPERTIES ARE NOT IMPLEMENTED IN CORE YET*/
+	case HAL_CONFIG_BUFFER_REQUIREMENTS:
+	case HAL_CONFIG_PRIORITY:
+	case HAL_CONFIG_BATCH_INFO:
+	case HAL_PARAM_METADATA_PASS_THROUGH:
+	case HAL_SYS_IDLE_INDICATOR:
+	case HAL_PARAM_UNCOMPRESSED_FORMAT_SUPPORTED:
+	case HAL_PARAM_INTERLACE_FORMAT_SUPPORTED:
+	case HAL_PARAM_CHROMA_SITE:
+	case HAL_PARAM_PROPERTIES_SUPPORTED:
+	case HAL_PARAM_PROFILE_LEVEL_SUPPORTED:
+	case HAL_PARAM_CAPABILITY_SUPPORTED:
+	case HAL_PARAM_NAL_STREAM_FORMAT_SUPPORTED:
+	case HAL_PARAM_MULTI_VIEW_FORMAT:
+	case HAL_PARAM_MAX_SEQUENCE_HEADER_SIZE:
+	case HAL_PARAM_CODEC_SUPPORTED:
+	case HAL_PARAM_VDEC_MULTI_VIEW_SELECT:
+	case HAL_PARAM_VDEC_MB_QUANTIZATION:
+	case HAL_PARAM_VDEC_NUM_CONCEALED_MB:
+	case HAL_PARAM_VDEC_H264_ENTROPY_SWITCHING:
+	case HAL_PARAM_VENC_SLICE_DELIVERY_MODE:
+	case HAL_PARAM_VENC_MPEG4_DATA_PARTITIONING:
+
+	case HAL_CONFIG_BUFFER_COUNT_ACTUAL:
+	case HAL_CONFIG_VDEC_MULTI_STREAM:
+	case HAL_PARAM_VENC_MULTI_SLICE_INFO:
+	case HAL_CONFIG_VENC_TIMESTAMP_SCALE:
+	case HAL_PARAM_VENC_LOW_LATENCY:
+	default:
+		dprintk(VIDC_INFO, "DEFAULT: Calling 0x%x", ptype);
+		break;
+	}
+	return 0;
+}
+
+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;
+	struct venus_hfi_device *dev;
+
+	if (device) {
+		dev = device;
+	} else {
+		dprintk(VIDC_ERR, "invalid device");
+		return NULL;
+	}
+
+	new_session = (struct hal_session *)
+		kzalloc(sizeof(struct hal_session), GFP_KERNEL);
+	new_session->session_id = (u32) session_id;
+	if (session_type == 1)
+		new_session->is_decoder = 0;
+	else if (session_type == 2)
+		new_session->is_decoder = 1;
+	new_session->device = dev;
+	list_add_tail(&new_session->list, &dev->sess_head);
+
+	if (create_pkt_cmd_sys_session_init(&pkt, (u32)new_session,
+			session_type, codec_type)) {
+		dprintk(VIDC_ERR, "session_init: failed to create packet");
+		goto err_session_init_fail;
+	}
+
+	if (venus_hfi_iface_cmdq_write(dev, &pkt))
+		goto err_session_init_fail;
+	if (venus_hfi_sys_set_debug(dev, msm_fw_debug))
+		dprintk(VIDC_ERR, "Setting fw_debug msg ON failed");
+	return (void *) new_session;
+
+err_session_init_fail:
+	kfree(new_session);
+	return NULL;
+}
+
+static int venus_hfi_send_session_cmd(void *session_id,
+	 int pkt_type)
+{
+	struct vidc_hal_session_cmd_pkt pkt;
+	int rc = 0;
+	struct hal_session *session;
+
+	if (session_id) {
+		session = session_id;
+	} else {
+		dprintk(VIDC_ERR, "invalid session");
+		return -ENODEV;
+	}
+
+	rc = create_pkt_cmd_session_cmd(&pkt, pkt_type, (u32)session);
+	if (rc) {
+		dprintk(VIDC_ERR, "send session cmd: create pkt failed");
+		goto err_create_pkt;
+	}
+
+	if (venus_hfi_iface_cmdq_write(session->device, &pkt))
+		rc = -ENOTEMPTY;
+
+err_create_pkt:
+	return rc;
+}
+
+static int venus_hfi_session_end(void *session)
+{
+	return venus_hfi_send_session_cmd(session,
+		HFI_CMD_SYS_SESSION_END);
+}
+
+static int venus_hfi_session_abort(void *session)
+{
+	return venus_hfi_send_session_cmd(session,
+		HFI_CMD_SYS_SESSION_ABORT);
+}
+
+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];
+	int rc = 0;
+	struct hal_session *session;
+
+	if (!sess || !buffer_info) {
+		dprintk(VIDC_ERR, "Invalid Params");
+		return -EINVAL;
+	} else {
+		session = sess;
+	}
+
+	if (buffer_info->buffer_type == HAL_BUFFER_INPUT)
+		return 0;
+
+	pkt = (struct hfi_cmd_session_set_buffers_packet *)packet;
+
+	rc = create_pkt_cmd_session_set_buffers(pkt,
+			(u32)session, buffer_info);
+	if (rc) {
+		dprintk(VIDC_ERR, "set buffers: failed to create packet");
+		goto err_create_pkt;
+	}
+
+	dprintk(VIDC_INFO, "set buffers: 0x%x", buffer_info->buffer_type);
+	if (venus_hfi_iface_cmdq_write(session->device, pkt))
+		rc = -ENOTEMPTY;
+err_create_pkt:
+	return rc;
+}
+
+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];
+	int rc = 0;
+	struct hal_session *session;
+
+	if (!sess || !buffer_info) {
+		dprintk(VIDC_ERR, "Invalid Params");
+		return -EINVAL;
+	} else {
+		session = sess;
+	}
+
+	if (buffer_info->buffer_type == HAL_BUFFER_INPUT)
+		return 0;
+
+	pkt = (struct hfi_cmd_session_release_buffer_packet *) packet;
+
+	rc = create_pkt_cmd_session_release_buffers(pkt,
+					(u32)session, buffer_info);
+	if (rc) {
+		dprintk(VIDC_ERR, "release buffers: failed to create packet");
+		goto err_create_pkt;
+	}
+
+	dprintk(VIDC_INFO, "Release buffers: 0x%x", buffer_info->buffer_type);
+	if (venus_hfi_iface_cmdq_write(session->device, pkt))
+		rc = -ENOTEMPTY;
+err_create_pkt:
+	return rc;
+}
+
+static int venus_hfi_session_load_res(void *sess)
+{
+	return venus_hfi_send_session_cmd(sess,
+		HFI_CMD_SESSION_LOAD_RESOURCES);
+}
+
+static int venus_hfi_session_release_res(void *sess)
+{
+	return venus_hfi_send_session_cmd(sess,
+		HFI_CMD_SESSION_RELEASE_RESOURCES);
+}
+
+static int venus_hfi_session_start(void *sess)
+{
+	return venus_hfi_send_session_cmd(sess,
+		HFI_CMD_SESSION_START);
+}
+
+static int venus_hfi_session_stop(void *sess)
+{
+	return venus_hfi_send_session_cmd(sess,
+		HFI_CMD_SESSION_STOP);
+}
+
+static int venus_hfi_session_suspend(void *sess)
+{
+	return venus_hfi_send_session_cmd(sess,
+		HFI_CMD_SESSION_SUSPEND);
+}
+
+static int venus_hfi_session_resume(void *sess)
+{
+	return venus_hfi_send_session_cmd(sess,
+		HFI_CMD_SESSION_RESUME);
+}
+
+static int venus_hfi_session_etb(void *sess,
+				struct vidc_frame_data *input_frame)
+{
+	int rc = 0;
+	struct hal_session *session;
+
+	if (!sess || !input_frame) {
+		dprintk(VIDC_ERR, "Invalid Params");
+		return -EINVAL;
+	} else {
+		session = sess;
+	}
+
+	if (session->is_decoder) {
+		struct hfi_cmd_session_empty_buffer_compressed_packet pkt;
+
+		rc = create_pkt_cmd_session_etb_decoder(&pkt,
+					(u32)session, input_frame);
+		if (rc) {
+			dprintk(VIDC_ERR,
+			"Session etb decoder: failed to create pkt");
+			goto err_create_pkt;
+		}
+		dprintk(VIDC_DBG, "Q DECODER INPUT BUFFER");
+		if (venus_hfi_iface_cmdq_write(session->device, &pkt))
+			rc = -ENOTEMPTY;
+	} else {
+		struct hfi_cmd_session_empty_buffer_uncompressed_plane0_packet
+			pkt;
+
+		rc =  create_pkt_cmd_session_etb_encoder(&pkt,
+					(u32)session, input_frame);
+		if (rc) {
+			dprintk(VIDC_ERR,
+			"Session etb encoder: failed to create pkt");
+			goto err_create_pkt;
+		}
+		dprintk(VIDC_DBG, "Q ENCODER INPUT BUFFER");
+		if (venus_hfi_iface_cmdq_write(session->device, &pkt))
+			rc = -ENOTEMPTY;
+	}
+err_create_pkt:
+	return rc;
+}
+
+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;
+	struct hal_session *session;
+
+	if (!sess || !output_frame) {
+		dprintk(VIDC_ERR, "Invalid Params");
+		return -EINVAL;
+	} else {
+		session = sess;
+	}
+
+	rc = create_pkt_cmd_session_ftb(&pkt, (u32)session, output_frame);
+	if (rc) {
+		dprintk(VIDC_ERR, "Session ftb: failed to create pkt");
+		goto err_create_pkt;
+	}
+
+	if (venus_hfi_iface_cmdq_write(session->device, &pkt))
+		rc = -ENOTEMPTY;
+err_create_pkt:
+	return rc;
+}
+
+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;
+	u8 packet[VIDC_IFACEQ_VAR_SMALL_PKT_SIZE];
+	struct hal_session *session;
+
+	if (!sess || !seq_hdr) {
+		dprintk(VIDC_ERR, "Invalid Params");
+		return -EINVAL;
+	} else {
+		session = sess;
+	}
+
+	pkt = (struct hfi_cmd_session_parse_sequence_header_packet *) packet;
+
+	rc = create_pkt_cmd_session_parse_seq_header(pkt, (u32)session,
+							seq_hdr);
+	if (rc) {
+		dprintk(VIDC_ERR,
+		"Session parse seq hdr: failed to create pkt");
+		goto err_create_pkt;
+	}
+
+	if (venus_hfi_iface_cmdq_write(session->device, pkt))
+		rc = -ENOTEMPTY;
+err_create_pkt:
+	return rc;
+}
+
+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;
+	u8 packet[VIDC_IFACEQ_VAR_SMALL_PKT_SIZE];
+	struct hal_session *session;
+
+	if (!sess || !seq_hdr) {
+		dprintk(VIDC_ERR, "Invalid Params");
+		return -EINVAL;
+	} else {
+		session = sess;
+	}
+
+	pkt = (struct hfi_cmd_session_get_sequence_header_packet *) packet;
+	rc = create_pkt_cmd_session_get_seq_hdr(pkt, (u32)session, seq_hdr);
+	if (rc) {
+		dprintk(VIDC_ERR, "Session get seq hdr: failed to create pkt");
+		goto err_create_pkt;
+	}
+
+	if (venus_hfi_iface_cmdq_write(session->device, pkt))
+		rc = -ENOTEMPTY;
+err_create_pkt:
+	return rc;
+}
+
+static int venus_hfi_session_get_buf_req(void *sess)
+{
+	struct hfi_cmd_session_get_property_packet pkt;
+	int rc = 0;
+	struct hal_session *session;
+
+	if (sess) {
+		session = sess;
+	} else {
+		dprintk(VIDC_ERR, "invalid session");
+		return -ENODEV;
+	}
+
+	rc = create_pkt_cmd_session_get_buf_req(&pkt, (u32)session);
+	if (rc) {
+		dprintk(VIDC_ERR, "Session get buf req: failed to create pkt");
+		goto err_create_pkt;
+	}
+
+	if (venus_hfi_iface_cmdq_write(session->device, &pkt))
+		rc = -ENOTEMPTY;
+err_create_pkt:
+	return rc;
+}
+
+static int venus_hfi_session_flush(void *sess, enum hal_flush flush_mode)
+{
+	struct hfi_cmd_session_flush_packet pkt;
+	int rc = 0;
+	struct hal_session *session;
+
+	if (sess) {
+		session = sess;
+	} else {
+		dprintk(VIDC_ERR, "invalid session");
+		return -ENODEV;
+	}
+
+	rc = create_pkt_cmd_session_flush(&pkt, (u32)session, flush_mode);
+	if (rc) {
+		dprintk(VIDC_ERR, "Session flush: failed to create pkt");
+		goto err_create_pkt;
+	}
+
+	if (venus_hfi_iface_cmdq_write(session->device, &pkt))
+		rc = -ENOTEMPTY;
+err_create_pkt:
+	return rc;
+}
+
+static int venus_hfi_check_core_registered(
+	struct hal_device_data core, u32 fw_addr,
+	u32 reg_addr, u32 reg_size, u32 irq)
+{
+	struct venus_hfi_device *device;
+	struct list_head *curr, *next;
+
+	if (core.dev_count) {
+		list_for_each_safe(curr, next, &core.dev_head) {
+			device = list_entry(curr,
+				struct venus_hfi_device, list);
+			if (device && device->hal_data->irq == irq &&
+				(CONTAINS(device->hal_data->
+						device_base_addr,
+						FIRMWARE_SIZE, fw_addr) ||
+				CONTAINS(fw_addr, FIRMWARE_SIZE,
+						device->hal_data->
+						device_base_addr) ||
+				CONTAINS((u32)device->hal_data->
+						register_base_addr,
+						reg_size, reg_addr) ||
+				CONTAINS(reg_addr, reg_size,
+						(u32)device->hal_data->
+						register_base_addr) ||
+				OVERLAPS((u32)device->hal_data->
+						register_base_addr,
+						reg_size, reg_addr, reg_size) ||
+				OVERLAPS(reg_addr, reg_size,
+						(u32)device->hal_data->
+						register_base_addr, reg_size) ||
+				OVERLAPS(device->hal_data->
+						device_base_addr,
+						FIRMWARE_SIZE, fw_addr,
+						FIRMWARE_SIZE) ||
+				OVERLAPS(fw_addr, FIRMWARE_SIZE,
+						device->hal_data->
+						device_base_addr,
+						FIRMWARE_SIZE))) {
+				return 0;
+			} else {
+				dprintk(VIDC_INFO, "Device not registered");
+				return -EINVAL;
+			}
+		}
+	} else {
+		dprintk(VIDC_INFO, "no device Registered");
+	}
+	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(
+		&hal_ctxt.dev_head, struct venus_hfi_device, list);
+
+	dprintk(VIDC_INFO, " GOT INTERRUPT () ");
+	if (!device->callback) {
+		dprintk(VIDC_ERR, "No interrupt callback function: %p\n",
+				device);
+		return;
+	}
+	venus_hfi_core_clear_interrupt(device);
+	venus_hfi_response_handler(device);
+	enable_irq(device->hal_data->irq);
+}
+static DECLARE_WORK(venus_hfi_work, venus_hfi_core_work_handler);
+
+static irqreturn_t venus_hfi_isr(int irq, void *dev)
+{
+	struct venus_hfi_device *device = dev;
+	dprintk(VIDC_INFO, "vidc_hal_isr() %d ", irq);
+	disable_irq_nosync(irq);
+	queue_work(device->vidc_workq, &venus_hfi_work);
+	dprintk(VIDC_INFO, "vidc_hal_isr() %d ", irq);
+	return IRQ_HANDLED;
+}
+
+static int venus_hfi_init_regs_and_interrupts(
+		struct venus_hfi_device *device, struct platform_device *pdev)
+{
+	struct hal_data *hal = NULL;
+	int rc = 0;
+	struct resource *res;
+
+	device->base_addr = 0x0;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res) {
+		dprintk(VIDC_ERR, "Failed to get IORESOURCE_MEM\n");
+		rc = -ENODEV;
+		goto err_core_init;
+	}
+	device->register_base = res->start;
+	device->register_size = resource_size(res);
+
+	res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+	if (!res) {
+		dprintk(VIDC_ERR, "Failed to get IORESOURCE_IRQ\n");
+		rc = -ENODEV;
+		goto err_core_init;
+	}
+	device->irq = res->start;
+
+	rc = venus_hfi_check_core_registered(hal_ctxt, device->base_addr,
+			device->register_base, device->register_size,
+			device->irq);
+	if (!rc) {
+		dprintk(VIDC_ERR, "Core present/Already added");
+		rc = -EEXIST;
+		goto err_core_init;
+	}
+
+	dprintk(VIDC_DBG, "HAL_DATA will be assigned now");
+	hal = (struct hal_data *)
+		kzalloc(sizeof(struct hal_data), GFP_KERNEL);
+	if (!hal) {
+		dprintk(VIDC_ERR, "Failed to alloc");
+		rc = -ENOMEM;
+		goto err_core_init;
+	}
+	hal->irq = device->irq;
+	hal->device_base_addr = device->base_addr;
+	hal->register_base_addr =
+		ioremap_nocache(device->register_base, device->register_size);
+	if (!hal->register_base_addr) {
+		dprintk(VIDC_ERR,
+			"could not map reg addr %d of size %d",
+			device->register_base, device->register_size);
+		goto error_irq_fail;
+	}
+
+	device->hal_data = hal;
+	rc = request_irq(device->irq, venus_hfi_isr, IRQF_TRIGGER_HIGH,
+			"msm_vidc", device);
+	if (unlikely(rc)) {
+		dprintk(VIDC_ERR, "() :request_irq failed\n");
+		goto error_irq_fail;
+	}
+	disable_irq_nosync(device->irq);
+	return rc;
+
+error_irq_fail:
+	kfree(hal);
+err_core_init:
+	return rc;
+
+}
+
+static size_t read_u32_array(struct platform_device *pdev,
+		char *name, u32 *arr, size_t size)
+{
+	int len;
+	size_t sz = 0;
+	struct device_node *np = pdev->dev.of_node;
+	if (!of_get_property(np, name, &len)) {
+		dprintk(VIDC_ERR, "Failed to read %s from device tree\n",
+			name);
+		goto fail_read;
+	}
+	sz = len / sizeof(u32);
+	if (sz <= 0) {
+		dprintk(VIDC_ERR, "%s not specified in device tree\n",
+			name);
+		goto fail_read;
+	}
+	if (sz > size) {
+		dprintk(VIDC_ERR, "Not enough memory to store %s values\n",
+			name);
+		goto fail_read;
+	}
+	if (of_property_read_u32_array(np, name, arr, sz)) {
+		dprintk(VIDC_ERR,
+			"error while reading %s from device tree\n",
+			name);
+		goto fail_read;
+	}
+	return sz;
+fail_read:
+	sz = 0;
+	return sz;
+}
+
+static inline int venus_hfi_init_clocks(struct platform_device *pdev,
+		struct venus_hfi_device *device)
+{
+	struct venus_core_clock *cl;
+	int i;
+	int rc = 0;
+	struct venus_core_clock *clock;
+	if (!device) {
+		dprintk(VIDC_ERR, "Invalid params: %p\n", device);
+		return -EINVAL;
+	}
+	clock = device->resources.clock;
+	strlcpy(clock[VCODEC_CLK].name, "core_clk",
+		sizeof(clock[VCODEC_CLK].name));
+	strlcpy(clock[VCODEC_AHB_CLK].name, "iface_clk",
+		sizeof(clock[VCODEC_AHB_CLK].name));
+	strlcpy(clock[VCODEC_AXI_CLK].name, "bus_clk",
+		sizeof(clock[VCODEC_AXI_CLK].name));
+	strlcpy(clock[VCODEC_OCMEM_CLK].name, "mem_clk",
+		sizeof(clock[VCODEC_OCMEM_CLK].name));
+
+	clock[VCODEC_CLK].count = read_u32_array(pdev,
+		"load-freq-tbl", (u32 *)clock[VCODEC_CLK].load_freq_tbl,
+		(sizeof(clock[VCODEC_CLK].load_freq_tbl)/sizeof(u32)));
+	clock[VCODEC_CLK].count /= 2;
+	dprintk(VIDC_DBG, "count = %d\n", clock[VCODEC_CLK].count);
+	if (!clock[VCODEC_CLK].count) {
+		dprintk(VIDC_ERR, "Failed to read clock frequency\n");
+		goto fail_init_clocks;
+	}
+	for (i = 0; i <	clock[VCODEC_CLK].count; i++) {
+		dprintk(VIDC_DBG,
+				"load = %d, freq = %d\n",
+				clock[VCODEC_CLK].load_freq_tbl[i].load,
+				clock[VCODEC_CLK].load_freq_tbl[i].freq
+			  );
+	}
+
+	for (i = 0; i < VCODEC_MAX_CLKS; i++) {
+		cl = &device->resources.clock[i];
+		if (!cl->clk) {
+			cl->clk = devm_clk_get(&pdev->dev, cl->name);
+			if (IS_ERR_OR_NULL(cl->clk)) {
+				dprintk(VIDC_ERR,
+					"Failed to get clock: %s\n", cl->name);
+				rc = PTR_ERR(cl->clk);
+				break;
+			}
+		}
+	}
+
+	if (i < VCODEC_MAX_CLKS) {
+		for (--i; i >= 0; i--) {
+			cl = &device->resources.clock[i];
+			clk_put(cl->clk);
+		}
+	}
+fail_init_clocks:
+	return rc;
+}
+
+static inline void venus_hfi_deinit_clocks(struct venus_hfi_device *device)
+{
+	int i;
+	if (!device) {
+		dprintk(VIDC_ERR, "Invalid args\n");
+		return;
+	}
+	for (i = 0; i < VCODEC_MAX_CLKS; i++)
+		clk_put(device->resources.clock[i].clk);
+}
+
+static unsigned long venus_hfi_get_clock_rate(struct venus_core_clock *clock,
+	int num_mbs_per_sec)
+{
+	int num_rows = clock->count;
+	struct load_freq_table *table = clock->load_freq_tbl;
+	unsigned long ret = table[num_rows-1].freq;
+	int i;
+	for (i = 0; i < num_rows; i++) {
+		if (num_mbs_per_sec > table[i].load)
+			break;
+		ret = table[i].freq;
+	}
+	dprintk(VIDC_DBG, "Required clock rate = %lu\n", ret);
+	return ret;
+}
+
+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;
+	}
+
+	rc = clk_set_rate(device->resources.clock[VCODEC_CLK].clk,
+		venus_hfi_get_clock_rate(&device->resources.clock[VCODEC_CLK],
+		load));
+	if (rc)
+		dprintk(VIDC_ERR, "Failed to set clock rate: %d\n", rc);
+	return rc;
+}
+
+static inline int venus_hfi_enable_clks(struct venus_hfi_device *device)
+{
+	int i;
+	struct venus_core_clock *cl;
+	int rc = 0;
+	if (!device) {
+		dprintk(VIDC_ERR, "Invalid params: %p\n", device);
+		return -EINVAL;
+	}
+	for (i = 0; i < VCODEC_MAX_CLKS; i++) {
+		cl = &device->resources.clock[i];
+		rc = clk_prepare_enable(cl->clk);
+		if (rc) {
+			dprintk(VIDC_ERR, "Failed to enable clocks\n");
+			goto fail_clk_enable;
+		} else {
+			dprintk(VIDC_DBG, "Clock: %s enabled\n", cl->name);
+		}
+	}
+	return rc;
+fail_clk_enable:
+	for (; i >= 0; i--) {
+		cl = &device->resources.clock[i];
+		clk_disable_unprepare(cl->clk);
+	}
+	return rc;
+}
+
+static inline void venus_hfi_disable_clks(struct venus_hfi_device *device)
+{
+	int i;
+	struct venus_core_clock *cl;
+	if (!device) {
+		dprintk(VIDC_ERR, "Invalid params: %p\n", device);
+		return;
+	}
+	for (i = 0; i < VCODEC_MAX_CLKS; i++) {
+		cl = &device->resources.clock[i];
+		clk_disable_unprepare(cl->clk);
+	}
+}
+
+static int venus_hfi_register_iommu_domains(struct venus_hfi_device *device,
+					struct platform_device *pdev)
+{
+	size_t len;
+	struct msm_iova_partition partition[2];
+	struct msm_iova_layout layout;
+	int rc = 0;
+	int i;
+	struct msm_vidc_iommu_info *io_map;
+
+	if (!device)
+		return -EINVAL;
+
+	io_map = device->resources.io_map;
+
+	strlcpy(io_map[CP_MAP].name, "vidc-cp-map",
+			sizeof(io_map[CP_MAP].name));
+	strlcpy(io_map[CP_MAP].ctx, "venus_cp",
+			sizeof(io_map[CP_MAP].ctx));
+	strlcpy(io_map[NS_MAP].name, "vidc-ns-map",
+			sizeof(io_map[NS_MAP].name));
+	strlcpy(io_map[NS_MAP].ctx, "venus_ns",
+			sizeof(io_map[NS_MAP].ctx));
+
+	for (i = 0; i < MAX_MAP; i++) {
+		len = read_u32_array(pdev, io_map[i].name,
+				io_map[i].addr_range,
+				(sizeof(io_map[i].addr_range)/sizeof(u32)));
+		if (!len) {
+			dprintk(VIDC_ERR,
+				"Error in reading cp address range\n");
+			rc = -EINVAL;
+			break;
+		}
+		partition[0].start = io_map[i].addr_range[0];
+		if (i == NS_MAP) {
+			partition[0].size =
+				io_map[i].addr_range[1] - SHARED_QSIZE;
+			partition[1].start =
+				partition[0].start + io_map[i].addr_range[1]
+					- SHARED_QSIZE;
+			partition[1].size = SHARED_QSIZE;
+			layout.npartitions = 2;
+			layout.is_secure = 0;
+		} else {
+			partition[0].size = io_map[i].addr_range[1];
+			layout.npartitions = 1;
+			layout.is_secure = 1;
+		}
+		layout.partitions = &partition[0];
+		layout.client_name = io_map[i].name;
+		layout.domain_flags = 0;
+		dprintk(VIDC_DBG, "Registering domain 1 with: %lx, %lx, %s\n",
+			partition[0].start, partition[0].size,
+			layout.client_name);
+		dprintk(VIDC_DBG, "Registering domain 2 with: %lx, %lx, %s\n",
+			partition[1].start, partition[1].size,
+			layout.client_name);
+		io_map[i].domain = msm_register_domain(&layout);
+		if (io_map[i].domain < 0) {
+			dprintk(VIDC_ERR, "Failed to register cp domain\n");
+			rc = -EINVAL;
+			break;
+		}
+	}
+	/* There is no api provided as msm_unregister_domain, so
+	 * we are not able to unregister the previously
+	 * registered domains if any domain registration fails.*/
+	BUG_ON(i < MAX_MAP);
+	return rc;
+}
+
+static void venus_hfi_deinit_bus(struct venus_hfi_device *device)
+{
+	struct venus_bus_info *bus_info;
+	int i = 0;
+
+	if (!device)
+		return;
+
+	bus_info = &device->resources.bus_info;
+
+	for (i = 0; i < MSM_VIDC_MAX_DEVICES; i++) {
+		if (bus_info->ddr_handle[i]) {
+			msm_bus_scale_unregister_client(
+			   bus_info->ddr_handle[i]);
+			bus_info->ddr_handle[i] = 0;
+		}
+
+		if (bus_info->ocmem_handle[i]) {
+			msm_bus_scale_unregister_client(
+			   bus_info->ocmem_handle[i]);
+			bus_info->ocmem_handle[i] = 0;
+		}
+	}
+}
+
+static int venus_hfi_init_bus(struct venus_hfi_device *device)
+{
+	struct venus_bus_info *bus_info;
+	int rc = 0;
+	if (!device)
+		return -EINVAL;
+
+	bus_info = &device->resources.bus_info;
+
+	bus_info->ddr_handle[MSM_VIDC_ENCODER] =
+		msm_bus_scale_register_client(&enc_ddr_bus_data);
+	if (!bus_info->ddr_handle[MSM_VIDC_ENCODER]) {
+		dprintk(VIDC_ERR, "Failed to register bus scale client\n");
+		goto err_init_bus;
+	}
+	bus_info->ddr_handle[MSM_VIDC_DECODER] =
+		msm_bus_scale_register_client(&dec_ddr_bus_data);
+	if (!bus_info->ddr_handle[MSM_VIDC_DECODER]) {
+		dprintk(VIDC_ERR, "Failed to register bus scale client\n");
+		goto err_init_bus;
+	}
+	bus_info->ocmem_handle[MSM_VIDC_ENCODER] =
+		msm_bus_scale_register_client(&enc_ocmem_bus_data);
+	if (!bus_info->ocmem_handle[MSM_VIDC_ENCODER]) {
+		dprintk(VIDC_ERR, "Failed to register bus scale client\n");
+		goto err_init_bus;
+	}
+	bus_info->ocmem_handle[MSM_VIDC_DECODER] =
+		msm_bus_scale_register_client(&dec_ocmem_bus_data);
+	if (!bus_info->ocmem_handle[MSM_VIDC_DECODER]) {
+		dprintk(VIDC_ERR, "Failed to register bus scale client\n");
+		goto err_init_bus;
+	}
+	return rc;
+err_init_bus:
+	venus_hfi_deinit_bus(device);
+	return -EINVAL;
+}
+
+
+static const u32 venus_hfi_bus_table[] = {
+	36000,
+	110400,
+	244800,
+	489000,
+	783360,
+	979200,
+};
+
+static int venus_hfi_get_bus_vector(int load)
+{
+	int num_rows = sizeof(venus_hfi_bus_table)/(sizeof(u32));
+	int i;
+	for (i = 0; i < num_rows; i++) {
+		if (load <= venus_hfi_bus_table[i])
+			break;
+	}
+	i++;
+	dprintk(VIDC_DBG, "Required bus = %d\n", i);
+	return i;
+}
+
+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];
+	if (mtype & OCMEM_MEM)
+		handle = device->resources.bus_info.ocmem_handle[type];
+
+	if (handle) {
+		rc = msm_bus_scale_client_update_request(
+				handle, venus_hfi_get_bus_vector(load));
+		if (rc)
+			dprintk(VIDC_ERR, "Failed to scale bus: %d\n", rc);
+	} else {
+		dprintk(VIDC_ERR, "Failed to scale bus, mtype: %d\n",
+				mtype);
+		rc = -EINVAL;
+	}
+
+	return rc;
+}
+
+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",
+			device, ocmem);
+		return -EINVAL;
+	}
+	rhdr.resource_id = VIDC_RESOURCE_OCMEM;
+	rhdr.resource_handle = (u32) &device->resources.ocmem;
+	rhdr.size =	ocmem->len;
+	rc = venus_hfi_core_set_resource(device, &rhdr, ocmem);
+	if (rc) {
+		dprintk(VIDC_ERR, "Failed to set OCMEM on driver\n");
+		goto ocmem_set_failed;
+	}
+	dprintk(VIDC_DBG, "OCMEM set, addr = %lx, size: %ld\n",
+		ocmem->addr, ocmem->len);
+ocmem_set_failed:
+	return rc;
+}
+
+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, "%s Invalid params, device:%p\n",
+			__func__, device);
+		return -EINVAL;
+	}
+	rhdr.resource_id = VIDC_RESOURCE_OCMEM;
+	rhdr.resource_handle = (u32) &device->resources.ocmem;
+	rc = venus_hfi_core_release_resource(device, &rhdr);
+	if (rc)
+		dprintk(VIDC_ERR, "Failed to set OCMEM on driver\n");
+
+	return rc;
+}
+
+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, "%s Invalid param, core: %p, size: %lu\n",
+			__func__, device, size);
+		return -EINVAL;
+	}
+	ocmem_buffer = device->resources.ocmem.buf;
+	if (!ocmem_buffer ||
+		ocmem_buffer->len < size) {
+		ocmem_buffer = ocmem_allocate_nb(OCMEM_VIDEO, size);
+		if (IS_ERR_OR_NULL(ocmem_buffer)) {
+			dprintk(VIDC_ERR,
+				"ocmem_allocate_nb failed: %d\n",
+				(u32) ocmem_buffer);
+			rc = -ENOMEM;
+		}
+		device->resources.ocmem.buf = ocmem_buffer;
+		rc = venus_hfi_set_ocmem(device, ocmem_buffer);
+		if (rc) {
+			dprintk(VIDC_ERR, "Failed to set ocmem: %d\n", rc);
+			goto ocmem_set_failed;
+		}
+	} else
+		dprintk(VIDC_DBG,
+			"OCMEM is enough. reqd: %lu, available: %lu\n",
+			size, ocmem_buffer->len);
+
+ocmem_set_failed:
+	return rc;
+}
+
+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;
+	}
+	return rc;
+}
+
+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;
+}
+
+static void venus_hfi_deinit_ocmem(struct venus_hfi_device *device)
+{
+	if (device->resources.ocmem.handle)
+		ocmem_notifier_unregister(device->resources.ocmem.handle,
+				&device->resources.ocmem.vidc_ocmem_nb);
+}
+
+
+static int venus_hfi_init_resources(struct venus_hfi_device *device,
+				struct platform_device *pdev)
+{
+	int rc = 0;
+
+	rc = venus_hfi_init_clocks(pdev, device);
+	if (rc) {
+		dprintk(VIDC_ERR, "Failed to init clocks\n");
+		rc = -ENODEV;
+		goto err_init_clocks;
+	}
+
+	rc = venus_hfi_init_bus(device);
+	if (rc) {
+		dprintk(VIDC_ERR, "Failed to init bus: %d\n", rc);
+		goto err_init_bus;
+	}
+
+	rc = venus_hfi_register_iommu_domains(device, pdev);
+	if (rc) {
+		dprintk(VIDC_ERR, "Failed to register iommu domains: %d\n", rc);
+		goto err_register_iommu_domain;
+	}
+
+	venus_hfi_ocmem_init(device);
+	return rc;
+
+err_register_iommu_domain:
+	venus_hfi_deinit_bus(device);
+err_init_bus:
+	venus_hfi_deinit_clocks(device);
+err_init_clocks:
+	return rc;
+}
+
+static void venus_hfi_deinit_resources(struct venus_hfi_device *device)
+{
+	venus_hfi_deinit_ocmem(device);
+	venus_hfi_deinit_bus(device);
+	venus_hfi_deinit_clocks(device);
+}
+
+static int venus_hfi_iommu_attach(struct venus_hfi_device *device)
+{
+	int rc;
+	struct iommu_domain *domain;
+	int i;
+	struct msm_vidc_iommu_info *io_map;
+	struct device *dev;
+
+	if (!device)
+		return -EINVAL;
+
+	for (i = 0; i < MAX_MAP; i++) {
+		io_map = &device->resources.io_map[i];
+		dev = msm_iommu_get_ctx(io_map->ctx);
+		domain = msm_get_iommu_domain(io_map->domain);
+		if (IS_ERR_OR_NULL(domain)) {
+			dprintk(VIDC_ERR,
+				"Failed to get domain: %s\n", io_map->name);
+			rc = PTR_ERR(domain);
+			break;
+		}
+		rc = iommu_attach_device(domain, dev);
+		if (rc) {
+			dprintk(VIDC_ERR,
+				"IOMMU attach failed: %s\n", io_map->name);
+			break;
+		}
+	}
+	if (i < MAX_MAP) {
+		i--;
+		for (; i >= 0; i--) {
+			io_map = &device->resources.io_map[i];
+			dev = msm_iommu_get_ctx(io_map->ctx);
+			domain = msm_get_iommu_domain(io_map->domain);
+			if (dev && domain)
+				iommu_detach_device(domain, dev);
+		}
+	}
+	return rc;
+}
+
+static void venus_hfi_iommu_detach(struct venus_hfi_device *device)
+{
+	struct device *dev;
+	struct iommu_domain *domain;
+	struct msm_vidc_iommu_info *io_map;
+	int i;
+
+	if (!device) {
+		dprintk(VIDC_ERR, "Invalid paramter: %p\n", device);
+		return;
+	}
+
+	for (i = 0; i < MAX_MAP; i++) {
+		io_map = &device->resources.io_map[i];
+		dev = msm_iommu_get_ctx(io_map->ctx);
+		domain = msm_get_iommu_domain(io_map->domain);
+		if (dev && domain)
+			iommu_detach_device(domain, dev);
+	}
+}
+
+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);
+		return -EINVAL;
+	}
+	return device->resources.io_map[iomap].domain;
+}
+
+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",
+		 __func__, device, maps);
+		return -EINVAL;
+	}
+
+	for (i = 0; i < MAX_MAP; i++)
+		maps[i] = device->resources.io_map[i];
+
+	return 0;
+}
+
+static int protect_cp_mem(struct venus_hfi_device *device)
+{
+	struct tzbsp_memprot memprot;
+	unsigned int resp = 0;
+	int rc = 0;
+	struct msm_vidc_iommu_info *io_map;
+
+	if (!device)
+		return -EINVAL;
+
+	io_map = device->resources.io_map;
+	if (!io_map) {
+		dprintk(VIDC_ERR, "invalid params: %p\n", io_map);
+		return -EINVAL;
+	}
+	memprot.cp_start = 0x0;
+	memprot.cp_size = io_map[CP_MAP].addr_range[0] +
+			io_map[CP_MAP].addr_range[1];
+	memprot.cp_nonpixel_start = 0;
+	memprot.cp_nonpixel_size = 0;
+
+	rc = scm_call(SCM_SVC_CP, TZBSP_MEM_PROTECT_VIDEO_VAR, &memprot,
+			sizeof(memprot), &resp, sizeof(resp));
+	if (rc)
+		dprintk(VIDC_ERR,
+		"Failed to protect memory , rc is :%d, response : %d\n",
+		rc, resp);
+	return rc;
+}
+
+static int venus_hfi_load_fw(void *dev)
+{
+	int rc = 0;
+	struct venus_hfi_device *device = dev;
+
+	if (!device) {
+		dprintk(VIDC_ERR, "%s Invalid paramter: %p\n",
+			__func__, device);
+		return -EINVAL;
+	}
+
+	if (!device->resources.fw.cookie)
+		device->resources.fw.cookie = subsystem_get("venus");
+
+	if (IS_ERR_OR_NULL(device->resources.fw.cookie)) {
+		dprintk(VIDC_ERR, "Failed to download firmware\n");
+		rc = -ENOMEM;
+		goto fail_load_fw;
+	}
+	/*Clocks can be enabled only after pil_get since
+	 * gdsc is turned-on in pil_get*/
+	rc = venus_hfi_enable_clks(device);
+	if (rc) {
+		dprintk(VIDC_ERR, "Failed to enable clocks: %d\n", rc);
+		goto fail_enable_clks;
+	}
+
+	rc = protect_cp_mem(device);
+	if (rc) {
+		dprintk(VIDC_ERR, "Failed to protect memory\n");
+		goto fail_iommu_attach;
+	}
+
+	rc = venus_hfi_iommu_attach(device);
+	if (rc) {
+		dprintk(VIDC_ERR, "Failed to attach iommu");
+		goto fail_iommu_attach;
+	}
+	return rc;
+fail_iommu_attach:
+	venus_hfi_disable_clks(device);
+fail_enable_clks:
+	subsystem_put(device->resources.fw.cookie);
+	device->resources.fw.cookie = NULL;
+fail_load_fw:
+	return rc;
+}
+
+static void venus_hfi_unload_fw(void *dev)
+{
+	struct venus_hfi_device *device = dev;
+	if (!device) {
+		dprintk(VIDC_ERR, "%s Invalid paramter: %p\n",
+			__func__, device);
+		return;
+	}
+	if (device->resources.fw.cookie) {
+		venus_hfi_iommu_detach(device);
+		venus_hfi_disable_clks(device);
+		subsystem_put(device->resources.fw.cookie);
+		device->resources.fw.cookie = NULL;
+	}
+}
+
+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))
+{
+	struct venus_hfi_device *hdevice = NULL;
+	int rc = 0;
+
+	if (device_id || !pdev || !callback) {
+		dprintk(VIDC_ERR, "Invalid Paramters");
+		return NULL;
+	}
+
+	dprintk(VIDC_INFO, "entered , device_id: %d", device_id);
+
+	hdevice = (struct venus_hfi_device *)
+			kzalloc(sizeof(struct venus_hfi_device), GFP_KERNEL);
+	if (!hdevice) {
+		dprintk(VIDC_ERR, "failed to allocate new device");
+		goto err_alloc;
+	}
+
+	rc = venus_hfi_init_regs_and_interrupts(hdevice, pdev);
+	if (rc)
+		goto err_init_regs;
+
+	INIT_LIST_HEAD(&hal_ctxt.dev_head);
+	INIT_LIST_HEAD(&hdevice->list);
+	list_add_tail(&hdevice->list, &hal_ctxt.dev_head);
+	hal_ctxt.dev_count++;
+	hdevice->device_id = device_id;
+
+	hdevice->callback = callback;
+
+	hdevice->vidc_workq = create_singlethread_workqueue(
+		"msm_vidc_workerq");
+	if (!hdevice->vidc_workq) {
+		dprintk(VIDC_ERR, ": create workq failed\n");
+		goto error_createq;
+	}
+
+	return (void *) hdevice;
+error_createq:
+	hal_ctxt.dev_count--;
+	list_del(&hal_ctxt.dev_head);
+err_init_regs:
+	kfree(hdevice);
+err_alloc:
+	return NULL;
+}
+
+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;
+
+	if (!pdev || !callback) {
+		dprintk(VIDC_ERR, "Invalid params: %p %p\n", pdev, callback);
+		return NULL;
+	}
+
+	device = venus_hfi_add_device(device_id, pdev, &handle_cmd_response);
+	if (!device) {
+		dprintk(VIDC_ERR, "Failed to create HFI device\n");
+		return NULL;
+	}
+
+	rc = venus_hfi_init_resources(device, pdev);
+	if (rc) {
+		dprintk(VIDC_ERR, "Failed to init resources: %d\n", rc);
+		goto err_fail_init_res;
+	}
+	return device;
+
+err_fail_init_res:
+	venus_hfi_delete_device(device);
+	return NULL;
+}
+
+void venus_hfi_delete_device(void *device)
+{
+	struct venus_hfi_device *close, *dev;
+
+	if (device) {
+		venus_hfi_deinit_resources(device);
+		dev = (struct venus_hfi_device *) device;
+		list_for_each_entry(close, &hal_ctxt.dev_head, list) {
+			if (close->hal_data->irq == dev->hal_data->irq) {
+				hal_ctxt.dev_count--;
+				free_irq(dev->hal_data->irq, close);
+				list_del(&close->list);
+				destroy_workqueue(close->vidc_workq);
+				kfree(close->hal_data);
+				kfree(close);
+				break;
+			}
+		}
+
+	}
+}
+
+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
new file mode 100644
index 0000000..f825c20
--- /dev/null
+++ b/drivers/media/video/msm_vidc/venus_hfi.h
@@ -0,0 +1,202 @@
+/* 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_VENUS_HFI_H__
+#define __H_VENUS_HFI_H__
+
+#include <linux/clk.h>
+#include <linux/mutex.h>
+#include <linux/platform_device.h>
+#include <linux/spinlock.h>
+#include <mach/ocmem.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
+#define HFI_MASK_QHDR_PRI_TYPE			0x0000FF00
+#define HFI_MASK_QHDR_Q_ID_TYPE			0x000000FF
+#define HFI_Q_ID_HOST_TO_CTRL_CMD_Q		0x00
+#define HFI_Q_ID_CTRL_TO_HOST_MSG_Q		0x01
+#define HFI_Q_ID_CTRL_TO_HOST_DEBUG_Q	0x02
+#define HFI_MASK_QHDR_STATUS			0x000000FF
+
+#define VIDC_MAX_UNCOMPRESSED_FMT_PLANES	3
+
+#define VIDC_IFACEQ_NUMQ					3
+#define VIDC_IFACEQ_CMDQ_IDX				0
+#define VIDC_IFACEQ_MSGQ_IDX				1
+#define VIDC_IFACEQ_DBGQ_IDX				2
+
+#define VIDC_IFACEQ_MAX_PKT_SIZE			1024
+#define VIDC_IFACEQ_MED_PKT_SIZE			768
+#define VIDC_IFACEQ_MIN_PKT_SIZE			8
+#define VIDC_IFACEQ_VAR_SMALL_PKT_SIZE		100
+#define VIDC_IFACEQ_VAR_LARGE_PKT_SIZE		512
+#define VIDC_IFACEQ_MAX_BUF_COUNT			50
+#define VIDC_IFACE_MAX_PARALLEL_CLNTS		16
+#define VIDC_IFACEQ_DFLT_QHDR				0x01010000
+
+#define VIDC_MAX_NAME_LENGTH 64
+
+struct hfi_queue_table_header {
+	u32 qtbl_version;
+	u32 qtbl_size;
+	u32 qtbl_qhdr0_offset;
+	u32 qtbl_qhdr_size;
+	u32 qtbl_num_q;
+	u32 qtbl_num_active_q;
+};
+
+struct hfi_queue_header {
+	u32 qhdr_status;
+	u32 qhdr_start_addr;
+	u32 qhdr_type;
+	u32 qhdr_q_size;
+	u32 qhdr_pkt_size;
+	u32 qhdr_pkt_drop_cnt;
+	u32 qhdr_rx_wm;
+	u32 qhdr_tx_wm;
+	u32 qhdr_rx_req;
+	u32 qhdr_tx_req;
+	u32 qhdr_rx_irq_status;
+	u32 qhdr_tx_irq_status;
+	u32 qhdr_read_idx;
+	u32 qhdr_write_idx;
+};
+
+#define VIDC_IFACEQ_TABLE_SIZE (sizeof(struct hfi_queue_table_header) \
+	+ sizeof(struct hfi_queue_header) * VIDC_IFACEQ_NUMQ)
+
+#define VIDC_IFACEQ_QUEUE_SIZE	(VIDC_IFACEQ_MAX_PKT_SIZE *  \
+	VIDC_IFACEQ_MAX_BUF_COUNT * VIDC_IFACE_MAX_PARALLEL_CLNTS)
+
+#define VIDC_IFACEQ_GET_QHDR_START_ADDR(ptr, i)     \
+	(void *)((((u32)ptr) + sizeof(struct hfi_queue_table_header)) + \
+		(i * sizeof(struct hfi_queue_header)))
+
+#define QDSS_SIZE 4096
+#define SFR_SIZE 4096
+
+#define UC_SIZE (VIDC_IFACEQ_TABLE_SIZE + \
+	(VIDC_IFACEQ_QUEUE_SIZE * VIDC_IFACEQ_NUMQ) + QDSS_SIZE + SFR_SIZE)
+
+enum vidc_hw_reg {
+	VIDC_HWREG_CTRL_STATUS =  0x1,
+	VIDC_HWREG_QTBL_INFO =  0x2,
+	VIDC_HWREG_QTBL_ADDR =  0x3,
+	VIDC_HWREG_CTRLR_RESET =  0x4,
+	VIDC_HWREG_IFACEQ_FWRXREQ =  0x5,
+	VIDC_HWREG_IFACEQ_FWTXREQ =  0x6,
+	VIDC_HWREG_VHI_SOFTINTEN =  0x7,
+	VIDC_HWREG_VHI_SOFTINTSTATUS =  0x8,
+	VIDC_HWREG_VHI_SOFTINTCLR =  0x9,
+	VIDC_HWREG_HVI_SOFTINTEN =  0xA,
+};
+
+struct vidc_mem_addr {
+	u8 *align_device_addr;
+	u8 *align_virtual_addr;
+	u32 mem_size;
+	struct msm_smem *mem_data;
+};
+
+struct vidc_iface_q_info {
+	void *q_hdr;
+	struct vidc_mem_addr q_array;
+};
+
+/* Internal data used in vidc_hal not exposed to msm_vidc*/
+
+struct hal_data {
+	u32 irq;
+	u32 device_base_addr;
+	u8 *register_base_addr;
+};
+
+enum vidc_clocks {
+	VCODEC_CLK,
+	VCODEC_AHB_CLK,
+	VCODEC_AXI_CLK,
+	VCODEC_OCMEM_CLK,
+	VCODEC_MAX_CLKS
+};
+
+struct load_freq_table {
+	u32 load;
+	u32 freq;
+};
+
+struct msm_vidc_fw {
+	void *cookie;
+};
+
+struct venus_core_clock {
+	char name[VIDC_MAX_NAME_LENGTH];
+	struct clk *clk;
+	u32 count;
+	struct load_freq_table load_freq_tbl[8];
+};
+
+struct venus_bus_info {
+	u32 ddr_handle[MSM_VIDC_MAX_DEVICES];
+	u32 ocmem_handle[MSM_VIDC_MAX_DEVICES];
+};
+
+struct on_chip_mem {
+	struct ocmem_buf *buf;
+	struct notifier_block vidc_ocmem_nb;
+	void *handle;
+};
+
+struct venus_resources {
+	struct msm_vidc_fw fw;
+	struct msm_vidc_iommu_info io_map[MAX_MAP];
+	struct venus_core_clock clock[VCODEC_MAX_CLKS];
+	struct venus_bus_info bus_info;
+	struct on_chip_mem ocmem;
+};
+
+struct venus_hfi_device {
+	struct list_head list;
+	struct list_head sess_head;
+	u32 intr_status;
+	u32 device_id;
+	spinlock_t read_lock;
+	spinlock_t write_lock;
+	msm_vidc_callback callback;
+	struct vidc_mem_addr iface_q_table;
+	struct vidc_mem_addr qdss;
+	struct vidc_mem_addr sfr;
+	struct vidc_mem_addr mem_addr;
+	struct vidc_iface_q_info iface_queues[VIDC_IFACEQ_NUMQ];
+	struct smem_client *hal_client;
+	struct hal_data *hal_data;
+	struct workqueue_struct *vidc_workq;
+	int spur_count;
+	int reg_count;
+	u32 base_addr;
+	u32 register_base;
+	u32 register_size;
+	u32 irq;
+	struct venus_resources resources;
+};
+
+void venus_hfi_delete_device(void *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_hal.c b/drivers/media/video/msm_vidc/vidc_hal.c
deleted file mode 100644
index 8283fac..0000000
--- a/drivers/media/video/msm_vidc/vidc_hal.c
+++ /dev/null
@@ -1,2389 +0,0 @@
-/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- */
-
-#include <linux/slab.h>
-#include <linux/workqueue.h>
-#include <linux/interrupt.h>
-#include <linux/io.h>
-#include <linux/delay.h>
-#include <mach/ocmem.h>
-
-#include <asm/memory.h>
-#include "vidc_hal.h"
-#include "vidc_hal_io.h"
-#include "msm_vidc_debug.h"
-
-#define FIRMWARE_SIZE			0X00A00000
-#define REG_ADDR_OFFSET_BITMASK	0x000FFFFF
-
-/*Workaround for virtio */
-#define HFI_VIRTIO_FW_BIAS		0x0
-
-struct hal_device_data hal_ctxt;
-
-static void hal_virtio_modify_cmd_packet(u8 *packet)
-{
-	struct hfi_cmd_sys_session_init_packet *sys_init;
-	struct hal_session *sess;
-	u8 i;
-
-	if (!packet) {
-		dprintk(VIDC_ERR, "Invalid Param");
-		return;
-	}
-
-	sys_init = (struct hfi_cmd_sys_session_init_packet *)packet;
-	sess = (struct hal_session *) sys_init->session_id;
-	switch (sys_init->packet_type) {
-	case HFI_CMD_SESSION_EMPTY_BUFFER:
-		if (sess->is_decoder) {
-			struct hfi_cmd_session_empty_buffer_compressed_packet
-			*pkt = (struct
-			hfi_cmd_session_empty_buffer_compressed_packet
-			*) packet;
-			pkt->packet_buffer -= HFI_VIRTIO_FW_BIAS;
-		} else {
-			struct
-			hfi_cmd_session_empty_buffer_uncompressed_plane0_packet
-			*pkt = (struct
-			hfi_cmd_session_empty_buffer_uncompressed_plane0_packet
-			*) packet;
-			pkt->packet_buffer -= HFI_VIRTIO_FW_BIAS;
-		}
-		break;
-	case HFI_CMD_SESSION_FILL_BUFFER:
-	{
-		struct hfi_cmd_session_fill_buffer_packet *pkt =
-			(struct hfi_cmd_session_fill_buffer_packet *)packet;
-		pkt->packet_buffer -= HFI_VIRTIO_FW_BIAS;
-		break;
-	}
-	case HFI_CMD_SESSION_SET_BUFFERS:
-	{
-		struct hfi_cmd_session_set_buffers_packet *pkt =
-			(struct hfi_cmd_session_set_buffers_packet *)packet;
-		if ((pkt->buffer_type == HFI_BUFFER_OUTPUT) ||
-			(pkt->buffer_type == HFI_BUFFER_OUTPUT2)) {
-			struct hfi_buffer_info *buff;
-			buff = (struct hfi_buffer_info *) pkt->rg_buffer_info;
-			buff->buffer_addr -= HFI_VIRTIO_FW_BIAS;
-			buff->extra_data_addr -= HFI_VIRTIO_FW_BIAS;
-		} else {
-			for (i = 0; i < pkt->num_buffers; i++)
-				pkt->rg_buffer_info[i] -= HFI_VIRTIO_FW_BIAS;
-		}
-		break;
-	}
-	case HFI_CMD_SESSION_RELEASE_BUFFERS:
-	{
-		struct hfi_cmd_session_release_buffer_packet *pkt =
-			(struct hfi_cmd_session_release_buffer_packet *)packet;
-		if ((pkt->buffer_type == HFI_BUFFER_OUTPUT) ||
-			(pkt->buffer_type == HFI_BUFFER_OUTPUT2)) {
-			struct hfi_buffer_info *buff;
-			buff = (struct hfi_buffer_info *) pkt->rg_buffer_info;
-			buff->buffer_addr -= HFI_VIRTIO_FW_BIAS;
-			buff->extra_data_addr -= HFI_VIRTIO_FW_BIAS;
-		} else {
-			for (i = 0; i < pkt->num_buffers; i++)
-				pkt->rg_buffer_info[i] -= HFI_VIRTIO_FW_BIAS;
-		}
-		break;
-	}
-	case HFI_CMD_SESSION_PARSE_SEQUENCE_HEADER:
-	{
-		struct hfi_cmd_session_parse_sequence_header_packet *pkt =
-			(struct hfi_cmd_session_parse_sequence_header_packet *)
-		packet;
-		pkt->packet_buffer -= HFI_VIRTIO_FW_BIAS;
-		break;
-	}
-	case HFI_CMD_SESSION_GET_SEQUENCE_HEADER:
-	{
-		struct hfi_cmd_session_get_sequence_header_packet *pkt =
-			(struct hfi_cmd_session_get_sequence_header_packet *)
-		packet;
-		pkt->packet_buffer -= HFI_VIRTIO_FW_BIAS;
-		break;
-	}
-	default:
-		break;
-	}
-}
-
-static int write_queue(void *info, u8 *packet, u32 *rx_req_is_set)
-{
-	struct hfi_queue_header *queue;
-	u32 packet_size_in_words, new_write_idx;
-	struct vidc_iface_q_info *qinfo;
-	u32 empty_space, read_idx;
-	u32 *write_ptr;
-
-	if (!info || !packet || !rx_req_is_set) {
-		dprintk(VIDC_ERR, "Invalid Params");
-		return -EINVAL;
-	}
-
-	qinfo =	(struct vidc_iface_q_info *) info;
-	hal_virtio_modify_cmd_packet(packet);
-
-	queue = (struct hfi_queue_header *) qinfo->q_hdr;
-
-	if (!queue) {
-		dprintk(VIDC_ERR, "queue not present");
-		return -ENOENT;
-	}
-
-	packet_size_in_words = (*(u32 *)packet) >> 2;
-	dprintk(VIDC_DBG, "Packet_size in words: %d", packet_size_in_words);
-
-	if (packet_size_in_words == 0) {
-		dprintk(VIDC_ERR, "Zero packet size");
-		return -ENODATA;
-	}
-
-	read_idx = queue->qhdr_read_idx;
-
-	empty_space = (queue->qhdr_write_idx >=  read_idx) ?
-		(queue->qhdr_q_size - (queue->qhdr_write_idx -  read_idx)) :
-		(read_idx - queue->qhdr_write_idx);
-	dprintk(VIDC_DBG, "Empty_space: %d", empty_space);
-	if (empty_space <= packet_size_in_words) {
-		queue->qhdr_tx_req =  1;
-		dprintk(VIDC_ERR, "Insufficient size (%d) to write (%d)",
-					  empty_space, packet_size_in_words);
-		return -ENOTEMPTY;
-	}
-
-	queue->qhdr_tx_req =  0;
-
-	new_write_idx = (queue->qhdr_write_idx + packet_size_in_words);
-	write_ptr = (u32 *)((qinfo->q_array.align_virtual_addr) +
-		(queue->qhdr_write_idx << 2));
-	dprintk(VIDC_DBG, "Write Ptr: %d", (u32) write_ptr);
-	if (new_write_idx < queue->qhdr_q_size) {
-		memcpy(write_ptr, packet, packet_size_in_words << 2);
-	} else {
-		new_write_idx -= queue->qhdr_q_size;
-		memcpy(write_ptr, packet, (packet_size_in_words -
-			new_write_idx) << 2);
-		memcpy((void *)qinfo->q_array.align_virtual_addr,
-			packet + ((packet_size_in_words - new_write_idx) << 2),
-			new_write_idx  << 2);
-	}
-	queue->qhdr_write_idx = new_write_idx;
-	*rx_req_is_set = (1 == queue->qhdr_rx_req) ? 1 : 0;
-	dprintk(VIDC_DBG, "Out : ");
-	return 0;
-}
-
-static void hal_virtio_modify_msg_packet(u8 *packet)
-{
-	struct hfi_msg_sys_session_init_done_packet *sys_idle;
-	struct hal_session *sess;
-
-	if (!packet) {
-		dprintk(VIDC_ERR, "Invalid Param: ");
-		return;
-	}
-
-	sys_idle = (struct hfi_msg_sys_session_init_done_packet *)packet;
-	sess = (struct hal_session *) sys_idle->session_id;
-
-	switch (sys_idle->packet_type) {
-	case HFI_MSG_SESSION_FILL_BUFFER_DONE:
-		if (sess->is_decoder) {
-			struct
-			hfi_msg_session_fbd_uncompressed_plane0_packet
-			*pkt_uc = (struct
-			hfi_msg_session_fbd_uncompressed_plane0_packet
-			*) packet;
-			pkt_uc->packet_buffer += HFI_VIRTIO_FW_BIAS;
-		} else {
-			struct
-			hfi_msg_session_fill_buffer_done_compressed_packet
-			*pkt = (struct
-			hfi_msg_session_fill_buffer_done_compressed_packet
-			*) packet;
-			pkt->packet_buffer += HFI_VIRTIO_FW_BIAS;
-		}
-		break;
-	case HFI_MSG_SESSION_EMPTY_BUFFER_DONE:
-	{
-		struct hfi_msg_session_empty_buffer_done_packet *pkt =
-		(struct hfi_msg_session_empty_buffer_done_packet *)packet;
-		pkt->packet_buffer += HFI_VIRTIO_FW_BIAS;
-		break;
-	}
-	case HFI_MSG_SESSION_GET_SEQUENCE_HEADER_DONE:
-	{
-		struct
-		hfi_msg_session_get_sequence_header_done_packet
-		*pkt =
-		(struct hfi_msg_session_get_sequence_header_done_packet *)
-		packet;
-		pkt->sequence_header += HFI_VIRTIO_FW_BIAS;
-		break;
-	}
-	default:
-		break;
-	}
-}
-
-static int read_queue(void *info, u8 *packet, u32 *pb_tx_req_is_set)
-{
-	struct hfi_queue_header *queue;
-	u32 packet_size_in_words, new_read_idx;
-	u32 *read_ptr;
-	struct vidc_iface_q_info *qinfo;
-
-	if (!info || !packet || !pb_tx_req_is_set) {
-		dprintk(VIDC_ERR, "Invalid Params");
-		return -EINVAL;
-	}
-
-	qinfo =	(struct vidc_iface_q_info *) info;
-	queue = (struct hfi_queue_header *) qinfo->q_hdr;
-
-	if (!queue) {
-		dprintk(VIDC_ERR, "Queue memory is not allocated\n");
-		return -ENOMEM;
-	}
-
-	if (queue->qhdr_read_idx == queue->qhdr_write_idx) {
-		queue->qhdr_rx_req = 1;
-		*pb_tx_req_is_set = 0;
-		return -EPERM;
-	}
-
-	read_ptr = (u32 *)((qinfo->q_array.align_virtual_addr) +
-				(queue->qhdr_read_idx << 2));
-	packet_size_in_words = (*read_ptr) >> 2;
-	dprintk(VIDC_DBG, "packet_size_in_words: %d", packet_size_in_words);
-	if (packet_size_in_words == 0) {
-		dprintk(VIDC_ERR, "Zero packet size");
-		return -ENODATA;
-	}
-
-	new_read_idx = queue->qhdr_read_idx + packet_size_in_words;
-	dprintk(VIDC_DBG, "Read Ptr: %d", (u32) new_read_idx);
-	if (new_read_idx < queue->qhdr_q_size) {
-		memcpy(packet, read_ptr,
-			packet_size_in_words << 2);
-	} else {
-		new_read_idx -= queue->qhdr_q_size;
-		memcpy(packet, read_ptr,
-			(packet_size_in_words - new_read_idx) << 2);
-		memcpy(packet + ((packet_size_in_words -
-			new_read_idx) << 2),
-			(u8 *)qinfo->q_array.align_virtual_addr,
-			new_read_idx << 2);
-	}
-
-	queue->qhdr_read_idx = new_read_idx;
-
-	if (queue->qhdr_read_idx != queue->qhdr_write_idx)
-		queue->qhdr_rx_req = 0;
-	else
-		queue->qhdr_rx_req = 1;
-
-	*pb_tx_req_is_set = (1 == queue->qhdr_tx_req) ? 1 : 0;
-	hal_virtio_modify_msg_packet(packet);
-	dprintk(VIDC_DBG, "Out : ");
-	return 0;
-}
-
-static int vidc_hal_alloc(void *mem, void *clnt, u32 size, u32 align, u32 flags,
-		int domain)
-{
-	struct vidc_mem_addr *vmem;
-	struct msm_smem *alloc;
-	int rc = 0;
-
-	if (!mem || !clnt || !size) {
-		dprintk(VIDC_ERR, "Invalid Params");
-		return -EINVAL;
-	}
-	vmem = (struct vidc_mem_addr *)mem;
-	dprintk(VIDC_INFO, "start to alloc: size:%d, Flags: %d", size, flags);
-
-	alloc  = msm_smem_alloc(clnt, size, align, flags, domain, 1, 1);
-	dprintk(VIDC_DBG, "Alloc done");
-	if (!alloc) {
-		dprintk(VIDC_ERR, "Alloc failed\n");
-		rc = -ENOMEM;
-		goto fail_smem_alloc;
-	}
-	rc = msm_smem_clean_invalidate(clnt, alloc);
-	if (rc) {
-		dprintk(VIDC_ERR, "NOTE: Failed to clean caches\n");
-		goto fail_clean_cache;
-	}
-	dprintk(VIDC_DBG, "vidc_hal_alloc:ptr=%p,size=%d",
-			alloc->kvaddr, size);
-	vmem->mem_size = alloc->size;
-	vmem->mem_data = alloc;
-	vmem->align_virtual_addr = (u8 *) alloc->kvaddr;
-	vmem->align_device_addr = (u8 *)alloc->device_addr;
-	return rc;
-fail_clean_cache:
-	msm_smem_free(clnt, alloc);
-fail_smem_alloc:
-	return rc;
-}
-
-static void vidc_hal_free(struct smem_client *clnt, struct msm_smem *mem)
-{
-	msm_smem_free(clnt, mem);
-}
-
-static void write_register(u8 *base_addr, u32 reg, u32 value, u8 *vaddr)
-{
-	u32 hwiosymaddr = reg;
-
-	reg &= REG_ADDR_OFFSET_BITMASK;
-	if (reg == (u32)VIDC_CPU_CS_SCIACMDARG2) {
-		/* workaround to offset of FW bias */
-		struct hfi_queue_header *qhdr;
-		struct hfi_queue_table_header *qtbl_hdr =
-			(struct hfi_queue_table_header *)vaddr;
-
-		qhdr = VIDC_IFACEQ_GET_QHDR_START_ADDR(qtbl_hdr, 0);
-		qhdr->qhdr_start_addr -= HFI_VIRTIO_FW_BIAS;
-
-		qhdr = VIDC_IFACEQ_GET_QHDR_START_ADDR(qtbl_hdr, 1);
-		qhdr->qhdr_start_addr -= HFI_VIRTIO_FW_BIAS;
-
-		qhdr = VIDC_IFACEQ_GET_QHDR_START_ADDR(qtbl_hdr, 2);
-		qhdr->qhdr_start_addr -= HFI_VIRTIO_FW_BIAS;
-		value -= HFI_VIRTIO_FW_BIAS;
-	}
-
-	hwiosymaddr = ((u32)base_addr + (hwiosymaddr));
-	dprintk(VIDC_DBG, "Base addr: 0x%x, written to: 0x%x, Value: 0x%x...",
-			(u32)base_addr, hwiosymaddr, value);
-	writel_relaxed(value, hwiosymaddr);
-	wmb();
-}
-
-static int read_register(u8 *base_addr, u32 reg)
-{
-	int rc = readl_relaxed((u32)base_addr + reg);
-	rmb();
-	return rc;
-}
-
-static int vidc_hal_iface_cmdq_write(struct hal_device *device, void *pkt)
-{
-	u32 rx_req_is_set = 0;
-	struct vidc_iface_q_info *q_info;
-	int result = -EPERM;
-
-	if (!device || !pkt) {
-		dprintk(VIDC_ERR, "Invalid Params");
-		return -EINVAL;
-	}
-
-	spin_lock(&device->write_lock);
-	q_info = &device->iface_queues[VIDC_IFACEQ_CMDQ_IDX];
-	if (!q_info) {
-		dprintk(VIDC_ERR, "cannot write to shared Q's");
-		goto err_q_write;
-	}
-
-	if (!write_queue(q_info, (u8 *)pkt, &rx_req_is_set)) {
-		if (rx_req_is_set)
-			write_register(device->hal_data->register_base_addr,
-				VIDC_CPU_IC_SOFTINT,
-				1 << VIDC_CPU_IC_SOFTINT_H2A_SHFT, 0);
-		result = 0;
-	} else {
-		dprintk(VIDC_ERR, "vidc_hal_iface_cmdq_write:queue_full");
-	}
-err_q_write:
-	spin_unlock(&device->write_lock);
-	return result;
-}
-
-int vidc_hal_iface_msgq_read(struct hal_device *device, void *pkt)
-{
-	u32 tx_req_is_set = 0;
-	int rc = 0;
-	struct vidc_iface_q_info *q_info;
-
-	if (!pkt) {
-		dprintk(VIDC_ERR, "Invalid Params");
-		return -EINVAL;
-	}
-	spin_lock(&device->read_lock);
-	if (device->iface_queues[VIDC_IFACEQ_MSGQ_IDX].
-		q_array.align_virtual_addr == 0) {
-		dprintk(VIDC_ERR, "cannot read from shared MSG Q's");
-		rc = -ENODATA;
-		goto read_error;
-	}
-	q_info = &device->iface_queues[VIDC_IFACEQ_MSGQ_IDX];
-
-	if (!read_queue(q_info, (u8 *)pkt, &tx_req_is_set)) {
-		if (tx_req_is_set)
-			write_register(device->hal_data->register_base_addr,
-				VIDC_CPU_IC_SOFTINT,
-				1 << VIDC_CPU_IC_SOFTINT_H2A_SHFT, 0);
-		rc = 0;
-	} else {
-		dprintk(VIDC_INFO, "vidc_hal_iface_msgq_read:queue_empty");
-		rc = -ENODATA;
-	}
-read_error:
-	spin_unlock(&device->read_lock);
-	return rc;
-}
-
-int vidc_hal_iface_dbgq_read(struct hal_device *device, void *pkt)
-{
-	u32 tx_req_is_set = 0;
-	int rc = 0;
-	struct vidc_iface_q_info *q_info;
-
-	if (!pkt) {
-		dprintk(VIDC_ERR, "Invalid Params");
-		return -EINVAL;
-	}
-	spin_lock(&device->read_lock);
-	if (device->iface_queues[VIDC_IFACEQ_DBGQ_IDX].
-		q_array.align_virtual_addr == 0) {
-		dprintk(VIDC_ERR, "cannot read from shared DBG Q's");
-		rc = -ENODATA;
-		goto dbg_error;
-	}
-	q_info = &device->iface_queues[VIDC_IFACEQ_DBGQ_IDX];
-	if (!read_queue(q_info, (u8 *)pkt, &tx_req_is_set)) {
-		if (tx_req_is_set)
-			write_register(device->hal_data->register_base_addr,
-			VIDC_CPU_IC_SOFTINT,
-			1 << VIDC_CPU_IC_SOFTINT_H2A_SHFT, 0);
-		rc = 0;
-	} else {
-		dprintk(VIDC_INFO, "vidc_hal_iface_dbgq_read:queue_empty");
-		rc = -ENODATA;
-	}
-dbg_error:
-	spin_unlock(&device->read_lock);
-	return rc;
-}
-
-static void vidc_hal_set_queue_hdr_defaults(struct hfi_queue_header *q_hdr)
-{
-	q_hdr->qhdr_status = 0x1;
-	q_hdr->qhdr_type = VIDC_IFACEQ_DFLT_QHDR;
-	q_hdr->qhdr_q_size = VIDC_IFACEQ_QUEUE_SIZE / 4;
-	q_hdr->qhdr_pkt_size = 0;
-	q_hdr->qhdr_rx_wm = 0x1;
-	q_hdr->qhdr_tx_wm = 0x1;
-	q_hdr->qhdr_rx_req = 0x1;
-	q_hdr->qhdr_tx_req = 0x0;
-	q_hdr->qhdr_rx_irq_status = 0x0;
-	q_hdr->qhdr_tx_irq_status = 0x0;
-	q_hdr->qhdr_read_idx = 0x0;
-	q_hdr->qhdr_write_idx = 0x0;
-}
-
-static void vidc_hal_interface_queues_release(struct hal_device *device)
-{
-	int i;
-
-	vidc_hal_free(device->hal_client, device->mem_addr.mem_data);
-
-	for (i = 0; i < VIDC_IFACEQ_NUMQ; i++) {
-		device->iface_queues[i].q_hdr = NULL;
-		device->iface_queues[i].q_array.mem_data = NULL;
-		device->iface_queues[i].q_array.align_virtual_addr = NULL;
-		device->iface_queues[i].q_array.align_device_addr = NULL;
-	}
-	device->iface_q_table.align_virtual_addr = NULL;
-	device->iface_q_table.align_device_addr = NULL;
-
-	device->qdss.align_virtual_addr = NULL;
-	device->qdss.align_device_addr = NULL;
-
-	device->sfr.align_virtual_addr = NULL;
-	device->sfr.align_device_addr = NULL;
-
-	device->mem_addr.align_virtual_addr = NULL;
-	device->mem_addr.align_device_addr = NULL;
-
-	msm_smem_delete_client(device->hal_client);
-	device->hal_client = NULL;
-}
-
-static int vidc_hal_interface_queues_init(struct hal_device *dev, int domain)
-{
-	struct hfi_queue_table_header *q_tbl_hdr;
-	struct hfi_queue_header *q_hdr;
-	u8 i;
-	int rc = 0;
-	struct vidc_iface_q_info *iface_q;
-	struct hfi_sfr_struct *vsfr;
-	struct vidc_mem_addr *mem_addr;
-	int offset = 0;
-	int size_1m = 1024 * 1024;
-	int uc_size = (UC_SIZE + size_1m - 1) & (~(size_1m - 1));
-	mem_addr = &dev->mem_addr;
-	rc = vidc_hal_alloc((void *) mem_addr,
-			dev->hal_client, uc_size, 1,
-			0, domain);
-	if (rc) {
-		dprintk(VIDC_ERR, "iface_q_table_alloc_fail");
-		return -ENOMEM;
-	}
-	dev->iface_q_table.align_virtual_addr = mem_addr->align_virtual_addr;
-	dev->iface_q_table.align_device_addr = mem_addr->align_device_addr;
-	dev->iface_q_table.mem_size = VIDC_IFACEQ_TABLE_SIZE;
-	dev->iface_q_table.mem_data = NULL;
-	offset += dev->iface_q_table.mem_size;
-
-	for (i = 0; i < VIDC_IFACEQ_NUMQ; i++) {
-		iface_q = &dev->iface_queues[i];
-		iface_q->q_array.align_device_addr =
-			mem_addr->align_device_addr + offset;
-		iface_q->q_array.align_virtual_addr =
-			mem_addr->align_virtual_addr + offset;
-		iface_q->q_array.mem_size = VIDC_IFACEQ_QUEUE_SIZE;
-		iface_q->q_array.mem_data = NULL;
-		offset += iface_q->q_array.mem_size;
-		iface_q->q_hdr = VIDC_IFACEQ_GET_QHDR_START_ADDR(
-				dev->iface_q_table.align_virtual_addr, i);
-		vidc_hal_set_queue_hdr_defaults(iface_q->q_hdr);
-	}
-
-	dev->qdss.align_device_addr = mem_addr->align_device_addr + offset;
-	dev->qdss.align_virtual_addr = mem_addr->align_virtual_addr + offset;
-	dev->qdss.mem_size = QDSS_SIZE;
-	dev->qdss.mem_data = NULL;
-	offset += dev->qdss.mem_size;
-
-	dev->sfr.align_device_addr = mem_addr->align_device_addr + offset;
-	dev->sfr.align_virtual_addr = mem_addr->align_virtual_addr + offset;
-	dev->sfr.mem_size = SFR_SIZE;
-	dev->sfr.mem_data = NULL;
-	offset += dev->sfr.mem_size;
-
-	q_tbl_hdr = (struct hfi_queue_table_header *)
-			dev->iface_q_table.align_virtual_addr;
-	q_tbl_hdr->qtbl_version = 0;
-	q_tbl_hdr->qtbl_size = VIDC_IFACEQ_TABLE_SIZE;
-	q_tbl_hdr->qtbl_qhdr0_offset = sizeof(
-		struct hfi_queue_table_header);
-	q_tbl_hdr->qtbl_qhdr_size = sizeof(
-		struct hfi_queue_header);
-	q_tbl_hdr->qtbl_num_q = VIDC_IFACEQ_NUMQ;
-	q_tbl_hdr->qtbl_num_active_q = VIDC_IFACEQ_NUMQ;
-
-	iface_q = &dev->iface_queues[VIDC_IFACEQ_CMDQ_IDX];
-	q_hdr = iface_q->q_hdr;
-	q_hdr->qhdr_start_addr = (u32)
-		iface_q->q_array.align_device_addr;
-	q_hdr->qhdr_type |= HFI_Q_ID_HOST_TO_CTRL_CMD_Q;
-
-	iface_q = &dev->iface_queues[VIDC_IFACEQ_MSGQ_IDX];
-	q_hdr = iface_q->q_hdr;
-	q_hdr->qhdr_start_addr = (u32)
-		iface_q->q_array.align_device_addr;
-	q_hdr->qhdr_type |= HFI_Q_ID_CTRL_TO_HOST_MSG_Q;
-
-	iface_q = &dev->iface_queues[VIDC_IFACEQ_DBGQ_IDX];
-	q_hdr = iface_q->q_hdr;
-	q_hdr->qhdr_start_addr = (u32)
-		iface_q->q_array.align_device_addr;
-	q_hdr->qhdr_type |= HFI_Q_ID_CTRL_TO_HOST_DEBUG_Q;
-
-	write_register(dev->hal_data->register_base_addr,
-			VIDC_UC_REGION_ADDR,
-			(u32) mem_addr->align_device_addr, 0);
-	write_register(dev->hal_data->register_base_addr,
-			VIDC_UC_REGION_SIZE, mem_addr->mem_size, 0);
-	write_register(dev->hal_data->register_base_addr,
-		VIDC_CPU_CS_SCIACMDARG2,
-		(u32) dev->iface_q_table.align_device_addr,
-		dev->iface_q_table.align_virtual_addr);
-	write_register(dev->hal_data->register_base_addr,
-		VIDC_CPU_CS_SCIACMDARG1, 0x01,
-		dev->iface_q_table.align_virtual_addr);
-	write_register(dev->hal_data->register_base_addr,
-			VIDC_MMAP_ADDR,
-			(u32) dev->qdss.align_device_addr, 0);
-
-	vsfr = (struct hfi_sfr_struct *) dev->sfr.align_virtual_addr;
-	vsfr->bufSize = SFR_SIZE;
-
-	write_register(dev->hal_data->register_base_addr,
-			VIDC_SFR_ADDR, (u32)dev->sfr.align_device_addr , 0);
-	return 0;
-}
-
-static int vidc_hal_core_start_cpu(struct hal_device *device)
-{
-	u32 ctrl_status = 0, count = 0, rc = 0;
-	int max_tries = 100;
-	write_register(device->hal_data->register_base_addr,
-			VIDC_WRAPPER_INTR_MASK, 0x8, 0);
-	write_register(device->hal_data->register_base_addr,
-			VIDC_CPU_CS_SCIACMDARG3, 1, 0);
-
-	while (!ctrl_status && count < max_tries) {
-		ctrl_status = read_register(
-		device->hal_data->register_base_addr,
-		VIDC_CPU_CS_SCIACMDARG0);
-		if ((ctrl_status & 0xFE) == 0x4) {
-			dprintk(VIDC_ERR, "invalid setting for UC_REGION\n");
-			break;
-		}
-		usleep_range(500, 1000);
-		count++;
-	}
-	if (count >= max_tries)
-		rc = -ETIME;
-	return rc;
-}
-
-static void set_vbif_registers(struct hal_device *device)
-{
-	/*Disable Dynamic clock gating for Venus VBIF*/
-	write_register(device->hal_data->register_base_addr,
-				   VIDC_VENUS_VBIF_CLK_ON, 1, 0);
-	write_register(device->hal_data->register_base_addr,
-			VIDC_VBIF_OUT_AXI_AOOO_EN, 0x00001FFF, 0);
-	write_register(device->hal_data->register_base_addr,
-			VIDC_VBIF_OUT_AXI_AOOO, 0x1FFF1FFF, 0);
-	write_register(device->hal_data->register_base_addr,
-			VIDC_VBIF_IN_RD_LIM_CONF0, 0x10101001, 0);
-	write_register(device->hal_data->register_base_addr,
-			VIDC_VBIF_IN_RD_LIM_CONF1, 0x10101010, 0);
-	write_register(device->hal_data->register_base_addr,
-			VIDC_VBIF_IN_RD_LIM_CONF2, 0x10101010, 0);
-	write_register(device->hal_data->register_base_addr,
-			VIDC_VBIF_IN_RD_LIM_CONF3, 0x00000010, 0);
-	write_register(device->hal_data->register_base_addr,
-			VIDC_VBIF_IN_WR_LIM_CONF0, 0x1010100f, 0);
-	write_register(device->hal_data->register_base_addr,
-			VIDC_VBIF_IN_WR_LIM_CONF1, 0x10101010, 0);
-	write_register(device->hal_data->register_base_addr,
-			VIDC_VBIF_IN_WR_LIM_CONF2, 0x10101010, 0);
-	write_register(device->hal_data->register_base_addr,
-			VIDC_VBIF_IN_WR_LIM_CONF3, 0x00000010, 0);
-	write_register(device->hal_data->register_base_addr,
-			VIDC_VBIF_OUT_RD_LIM_CONF0, 0x00001010, 0);
-	write_register(device->hal_data->register_base_addr,
-			VIDC_VBIF_OUT_WR_LIM_CONF0, 0x00001010, 0);
-	write_register(device->hal_data->register_base_addr,
-			VIDC_VBIF_ARB_CTL, 0x00000030, 0);
-	write_register(device->hal_data->register_base_addr,
-			VIDC_VENUS_VBIF_DDR_OUT_MAX_BURST, 0x00000707, 0);
-	write_register(device->hal_data->register_base_addr,
-			VIDC_VENUS_VBIF_OCMEM_OUT_MAX_BURST, 0x00000707, 0);
-	write_register(device->hal_data->register_base_addr,
-			VIDC_VENUS_VBIF_ROUND_ROBIN_QOS_ARB, 0x00000001, 0);
-	write_register(device->hal_data->register_base_addr,
-			VIDC_VENUS0_WRAPPER_VBIF_REQ_PRIORITY, 0x5555556, 0);
-	write_register(device->hal_data->register_base_addr,
-			VIDC_VENUS0_WRAPPER_VBIF_PRIORITY_LEVEL, 0, 0);
-}
-
-static int vidc_hal_sys_set_debug(struct hal_device *device, int debug)
-{
-	struct hfi_debug_config *hfi;
-	u8 packet[VIDC_IFACEQ_VAR_SMALL_PKT_SIZE];
-	struct hfi_cmd_sys_set_property_packet *pkt =
-		(struct hfi_cmd_sys_set_property_packet *) &packet;
-	pkt->size = sizeof(struct hfi_cmd_sys_set_property_packet) +
-		sizeof(struct hfi_debug_config) + sizeof(u32);
-	pkt->packet_type = HFI_CMD_SYS_SET_PROPERTY;
-	pkt->num_properties = 1;
-	pkt->rg_property_data[0] = HFI_PROPERTY_SYS_DEBUG_CONFIG;
-	hfi = (struct hfi_debug_config *) &pkt->rg_property_data[1];
-	hfi->debug_config = debug;
-	hfi->debug_mode = HFI_DEBUG_MODE_QUEUE;
-	if (vidc_hal_iface_cmdq_write(device, pkt))
-		return -ENOTEMPTY;
-	return 0;
-}
-
-int vidc_hal_core_init(void *device, int domain)
-{
-	struct hfi_cmd_sys_init_packet pkt;
-	int rc = 0;
-	struct hal_device *dev;
-
-	if (device) {
-		dev = device;
-	} else {
-		dprintk(VIDC_ERR, "Invalid device");
-		return -ENODEV;
-	}
-	dev->intr_status = 0;
-	enable_irq(dev->hal_data->irq);
-	INIT_LIST_HEAD(&dev->sess_head);
-	spin_lock_init(&dev->read_lock);
-	spin_lock_init(&dev->write_lock);
-	set_vbif_registers(dev);
-
-	if (!dev->hal_client) {
-		dev->hal_client = msm_smem_new_client(SMEM_ION);
-		if (dev->hal_client == NULL) {
-			dprintk(VIDC_ERR, "Failed to alloc ION_Client");
-			rc = -ENODEV;
-			goto err_no_mem;
-		}
-
-		dprintk(VIDC_DBG, "Dev_Virt: 0x%x, Reg_Virt: 0x%x",
-		dev->hal_data->device_base_addr,
-		(u32) dev->hal_data->register_base_addr);
-
-		rc = vidc_hal_interface_queues_init(dev, domain);
-		if (rc) {
-			dprintk(VIDC_ERR, "failed to init queues");
-			rc = -ENOMEM;
-			goto err_no_mem;
-		}
-	} else {
-		dprintk(VIDC_ERR, "hal_client exists");
-		rc = -EEXIST;
-		goto err_no_mem;
-	}
-	write_register(dev->hal_data->register_base_addr,
-		VIDC_CTRL_INIT, 0x1, 0);
-	rc = vidc_hal_core_start_cpu(dev);
-	if (rc) {
-		dprintk(VIDC_ERR, "Failed to start core");
-		rc = -ENODEV;
-		goto err_no_dev;
-	}
-
-	pkt.size = sizeof(struct hfi_cmd_sys_init_packet);
-	pkt.packet_type = HFI_CMD_SYS_INIT;
-	pkt.arch_type = HFI_ARCH_OX_OFFSET;
-	if (vidc_hal_iface_cmdq_write(dev, &pkt)) {
-		rc = -ENOTEMPTY;
-		goto err_write_fail;
-	}
-	return rc;
-err_no_dev:
-err_write_fail:
-err_no_mem:
-	disable_irq_nosync(dev->hal_data->irq);
-	return rc;
-}
-
-int vidc_hal_core_release(void *device)
-{
-	struct hal_device *dev;
-	if (device) {
-		dev = device;
-	} else {
-		dprintk(VIDC_ERR, "invalid device");
-		return -ENODEV;
-	}
-	if (dev->hal_client) {
-		write_register(dev->hal_data->register_base_addr,
-				VIDC_CPU_CS_SCIACMDARG3, 0, 0);
-		disable_irq_nosync(dev->hal_data->irq);
-		vidc_hal_interface_queues_release(dev);
-	}
-	dprintk(VIDC_INFO, "HAL exited\n");
-	return 0;
-}
-
-int vidc_hal_core_pc_prep(void *device)
-{
-	struct hfi_cmd_sys_pc_prep_packet pkt;
-	int rc = 0;
-	struct hal_device *dev;
-
-	if (device) {
-		dev = device;
-	} else {
-		dprintk(VIDC_ERR, "invalid device");
-		return -ENODEV;
-	}
-	pkt.size = sizeof(struct hfi_cmd_sys_pc_prep_packet);
-	pkt.packet_type = HFI_CMD_SYS_PC_PREP;
-	if (vidc_hal_iface_cmdq_write(dev, &pkt))
-		rc = -ENOTEMPTY;
-	return rc;
-}
-
-static void vidc_hal_core_clear_interrupt(struct hal_device *device)
-{
-	u32 intr_status = 0;
-
-	if (!device->callback)
-		return;
-
-	intr_status = read_register(
-		device->hal_data->register_base_addr,
-		VIDC_WRAPPER_INTR_STATUS);
-
-	if ((intr_status & VIDC_WRAPPER_INTR_STATUS_A2H_BMSK) ||
-		(intr_status & VIDC_WRAPPER_INTR_STATUS_A2HWD_BMSK)) {
-		device->intr_status |= intr_status;
-		dprintk(VIDC_DBG, "INTERRUPT for device: 0x%x: "
-			"times: %d interrupt_status: %d",
-			(u32) device, ++device->reg_count, intr_status);
-	} else {
-		dprintk(VIDC_INFO, "SPURIOUS_INTR for device: 0x%x: "
-			"times: %d interrupt_status: %d",
-			(u32) device, ++device->spur_count, intr_status);
-	}
-	write_register(device->hal_data->register_base_addr,
-			VIDC_CPU_CS_A2HSOFTINTCLR, 1, 0);
-	write_register(device->hal_data->register_base_addr,
-			VIDC_WRAPPER_INTR_CLEAR, intr_status, 0);
-	dprintk(VIDC_DBG, "Cleared WRAPPER/A2H interrupt");
-}
-
-int vidc_hal_core_set_resource(void *device,
-		struct vidc_resource_hdr *resource_hdr, void *resource_value)
-{
-	struct hfi_cmd_sys_set_resource_packet *pkt;
-	u8 packet[VIDC_IFACEQ_VAR_SMALL_PKT_SIZE];
-	int rc = 0;
-	struct hal_device *dev;
-
-	if (!device || !resource_hdr || !resource_value) {
-		dprintk(VIDC_ERR, "set_res: Invalid Params");
-		return -EINVAL;
-	} else {
-		dev = device;
-	}
-
-	pkt = (struct hfi_cmd_sys_set_resource_packet *) packet;
-
-	pkt->size = sizeof(struct hfi_cmd_sys_set_resource_packet);
-	pkt->packet_type = HFI_CMD_SYS_SET_RESOURCE;
-	pkt->resource_handle = resource_hdr->resource_handle;
-
-	switch (resource_hdr->resource_id) {
-	case VIDC_RESOURCE_OCMEM:
-	{
-		struct hfi_resource_ocmem *hfioc_mem =
-			(struct hfi_resource_ocmem *)
-			&pkt->rg_resource_data[0];
-		struct ocmem_buf *ocmem =
-			(struct ocmem_buf *) resource_value;
-
-		pkt->resource_type = HFI_RESOURCE_OCMEM;
-		hfioc_mem->size = (u32) ocmem->len;
-		hfioc_mem->mem = (u8 *) ocmem->addr;
-		pkt->size += sizeof(struct hfi_resource_ocmem);
-		if (vidc_hal_iface_cmdq_write(dev, pkt))
-			rc = -ENOTEMPTY;
-		break;
-	}
-	default:
-		dprintk(VIDC_INFO, "Invalid res_id in set_res %d",
-						resource_hdr->resource_id);
-		break;
-	}
-	return rc;
-}
-
-int vidc_hal_core_release_resource(void *device,
-			struct vidc_resource_hdr *resource_hdr)
-{
-	struct hfi_cmd_sys_release_resource_packet pkt;
-	int rc = 0;
-	struct hal_device *dev;
-
-	if (!device || !resource_hdr) {
-		dprintk(VIDC_ERR, "Inv-Params in rel_res");
-		return -EINVAL;
-	} else {
-		dev = device;
-	}
-
-	pkt.size = sizeof(struct hfi_cmd_sys_release_resource_packet);
-	pkt.packet_type = HFI_CMD_SYS_RELEASE_RESOURCE;
-	pkt.resource_type = resource_hdr->resource_id;
-	pkt.resource_handle = resource_hdr->resource_handle;
-
-	if (vidc_hal_iface_cmdq_write(dev, &pkt))
-		rc = -ENOTEMPTY;
-	return rc;
-}
-
-int vidc_hal_core_ping(void *device)
-{
-	struct hfi_cmd_sys_ping_packet pkt;
-	int rc = 0;
-	struct hal_device *dev;
-
-	if (device) {
-		dev = device;
-	} else {
-		dprintk(VIDC_ERR, "invalid device");
-		return -ENODEV;
-	}
-	pkt.size = sizeof(struct hfi_cmd_sys_ping_packet);
-	pkt.packet_type = HFI_CMD_SYS_PING;
-
-	if (vidc_hal_iface_cmdq_write(dev, &pkt))
-		rc = -ENOTEMPTY;
-	return rc;
-}
-static u32 get_hfi_buffer(int hal_buffer)
-{
-	u32 buffer;
-	switch (hal_buffer) {
-	case HAL_BUFFER_INPUT:
-		buffer = HFI_BUFFER_INPUT;
-		break;
-	case HAL_BUFFER_OUTPUT:
-		buffer = HFI_BUFFER_OUTPUT;
-		break;
-	case HAL_BUFFER_OUTPUT2:
-		buffer = HFI_BUFFER_OUTPUT;
-		break;
-	case HAL_BUFFER_EXTRADATA_INPUT:
-		buffer = HFI_BUFFER_EXTRADATA_INPUT;
-		break;
-	case HAL_BUFFER_EXTRADATA_OUTPUT:
-		buffer = HFI_BUFFER_EXTRADATA_OUTPUT;
-		break;
-	case HAL_BUFFER_EXTRADATA_OUTPUT2:
-		buffer = HFI_BUFFER_EXTRADATA_OUTPUT2;
-		break;
-	case HAL_BUFFER_INTERNAL_SCRATCH:
-		buffer = HFI_BUFFER_INTERNAL_SCRATCH;
-		break;
-	case HAL_BUFFER_INTERNAL_PERSIST:
-		buffer = HFI_BUFFER_INTERNAL_PERSIST;
-		break;
-	default:
-		dprintk(VIDC_ERR, "Invalid buffer :0x%x\n",
-				hal_buffer);
-		buffer = 0;
-		break;
-	}
-	return buffer;
-}
-
-
-static int get_hfi_extradata_index(enum hal_extradata_id index)
-{
-	int ret = 0;
-	switch (index) {
-	case HAL_EXTRADATA_MB_QUANTIZATION:
-		ret = HFI_PROPERTY_PARAM_VDEC_MB_QUANTIZATION;
-		break;
-	case HAL_EXTRADATA_INTERLACE_VIDEO:
-		ret = HFI_PROPERTY_PARAM_VDEC_INTERLACE_VIDEO_EXTRADATA;
-		break;
-	case HAL_EXTRADATA_VC1_FRAMEDISP:
-		ret = HFI_PROPERTY_PARAM_VDEC_VC1_FRAMEDISP_EXTRADATA;
-		break;
-	case HAL_EXTRADATA_VC1_SEQDISP:
-		ret = HFI_PROPERTY_PARAM_VDEC_VC1_SEQDISP_EXTRADATA;
-		break;
-	case HAL_EXTRADATA_TIMESTAMP:
-		ret = HFI_PROPERTY_PARAM_VDEC_TIMESTAMP_EXTRADATA;
-		break;
-	case HAL_EXTRADATA_S3D_FRAME_PACKING:
-		ret = HFI_PROPERTY_PARAM_S3D_FRAME_PACKING_EXTRADATA;
-		break;
-	case HAL_EXTRADATA_FRAME_RATE:
-		ret = HFI_PROPERTY_PARAM_VDEC_FRAME_RATE_EXTRADATA;
-		break;
-	case HAL_EXTRADATA_PANSCAN_WINDOW:
-		ret = HFI_PROPERTY_PARAM_VDEC_PANSCAN_WNDW_EXTRADATA;
-		break;
-	case HAL_EXTRADATA_RECOVERY_POINT_SEI:
-		ret = HFI_PROPERTY_PARAM_VDEC_RECOVERY_POINT_SEI_EXTRADATA;
-		break;
-	case HAL_EXTRADATA_CLOSED_CAPTION_UD:
-		ret = HFI_PROPERTY_PARAM_VDEC_CLOSED_CAPTION_EXTRADATA;
-		break;
-	case HAL_EXTRADATA_AFD_UD:
-		ret = HFI_PROPERTY_PARAM_VDEC_AFD_EXTRADATA;
-		break;
-	case HAL_EXTRADATA_MULTISLICE_INFO:
-		ret = HFI_PROPERTY_PARAM_VENC_MULTI_SLICE_INFO;
-		break;
-	case HAL_EXTRADATA_NUM_CONCEALED_MB:
-		ret = HFI_PROPERTY_PARAM_VDEC_NUM_CONCEALED_MB;
-		break;
-	case HAL_EXTRADATA_INDEX:
-		ret = HFI_PROPERTY_PARAM_EXTRA_DATA_HEADER_CONFIG;
-		break;
-	default:
-		dprintk(VIDC_WARN, "Extradata index not found: %d\n", index);
-		break;
-	}
-	return ret;
-}
-
-int vidc_hal_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 =
-		(struct hfi_cmd_session_set_property_packet *) &packet;
-	struct hal_session *session;
-	int rc = 0;
-
-	if (!sess || !pdata) {
-		dprintk(VIDC_ERR, "Invalid Params");
-		return -EINVAL;
-	} else {
-		session = sess;
-	}
-
-	dprintk(VIDC_INFO, "in set_prop,with prop id: 0x%x", ptype);
-	pkt->size = sizeof(struct hfi_cmd_session_set_property_packet);
-	pkt->packet_type = HFI_CMD_SESSION_SET_PROPERTY;
-	pkt->session_id = (u32) session;
-	pkt->num_properties = 1;
-
-	switch (ptype) {
-	case HAL_CONFIG_FRAME_RATE:
-	{
-		struct hfi_frame_rate *hfi;
-		u32 buffer;
-		struct hal_frame_rate *prop =
-			(struct hal_frame_rate *) pdata;
-		pkt->rg_property_data[0] = HFI_PROPERTY_CONFIG_FRAME_RATE;
-		hfi = (struct hfi_frame_rate *) &pkt->rg_property_data[1];
-		buffer = get_hfi_buffer(prop->buffer_type);
-		if (buffer)
-			hfi->buffer_type = buffer;
-		else
-			return -EINVAL;
-		hfi->frame_rate = prop->frame_rate;
-		pkt->size += sizeof(u32) + sizeof(struct hfi_frame_rate);
-		break;
-	}
-	case HAL_PARAM_UNCOMPRESSED_FORMAT_SELECT:
-	{
-		u32 buffer;
-		struct hfi_uncompressed_format_select *hfi;
-		struct hal_uncompressed_format_select *prop =
-			(struct hal_uncompressed_format_select *) pdata;
-		pkt->rg_property_data[0] =
-			HFI_PROPERTY_PARAM_UNCOMPRESSED_FORMAT_SELECT;
-		hfi = (struct hfi_uncompressed_format_select *)
-			&pkt->rg_property_data[1];
-		buffer = get_hfi_buffer(prop->buffer_type);
-		if (buffer)
-			hfi->buffer_type = buffer;
-		else
-			return -EINVAL;
-		hfi->format = prop->format;
-		pkt->size += sizeof(u32) + sizeof(struct
-			hfi_uncompressed_format_select);
-		break;
-	}
-	case HAL_PARAM_UNCOMPRESSED_PLANE_ACTUAL_CONSTRAINTS_INFO:
-		break;
-	case HAL_PARAM_UNCOMPRESSED_PLANE_ACTUAL_INFO:
-		break;
-	case HAL_PARAM_EXTRA_DATA_HEADER_CONFIG:
-		break;
-	case HAL_PARAM_FRAME_SIZE:
-	{
-		u32 buffer;
-		struct hfi_frame_size *hfi;
-		struct hal_frame_size *prop = (struct hal_frame_size *) pdata;
-		pkt->rg_property_data[0] = HFI_PROPERTY_PARAM_FRAME_SIZE;
-		hfi = (struct hfi_frame_size *) &pkt->rg_property_data[1];
-		buffer = get_hfi_buffer(prop->buffer_type);
-		if (buffer)
-			hfi->buffer_type = buffer;
-		else
-			return -EINVAL;
-		hfi->height = prop->height;
-		hfi->width = prop->width;
-		pkt->size += sizeof(u32) + sizeof(struct hfi_frame_size);
-		break;
-	}
-	case HAL_CONFIG_REALTIME:
-	{
-		struct hfi_enable *hfi;
-		pkt->rg_property_data[0] = HFI_PROPERTY_CONFIG_REALTIME;
-		hfi = (struct hfi_enable *) &pkt->rg_property_data[1];
-		hfi->enable = ((struct hfi_enable *) pdata)->enable;
-		pkt->size += sizeof(u32) * 2;
-		break;
-	}
-	case HAL_PARAM_BUFFER_COUNT_ACTUAL:
-	{
-		u32 buffer;
-		struct hfi_buffer_count_actual *hfi;
-		struct hal_buffer_count_actual *prop =
-			(struct hal_buffer_count_actual *) pdata;
-		pkt->rg_property_data[0] =
-			HFI_PROPERTY_PARAM_BUFFER_COUNT_ACTUAL;
-		hfi = (struct hfi_buffer_count_actual *)
-				&pkt->rg_property_data[1];
-		hfi->buffer_count_actual = prop->buffer_count_actual;
-		buffer = get_hfi_buffer(prop->buffer_type);
-		if (buffer)
-			hfi->buffer_type = buffer;
-		else
-			return -EINVAL;
-		pkt->size += sizeof(u32) + sizeof(struct
-					hfi_buffer_count_actual);
-		break;
-	}
-	case HAL_PARAM_NAL_STREAM_FORMAT_SELECT:
-	{
-		struct hal_nal_stream_format_supported *prop =
-			(struct hal_nal_stream_format_supported *)pdata;
-		pkt->rg_property_data[0] =
-			HFI_PROPERTY_PARAM_NAL_STREAM_FORMAT_SELECT;
-		dprintk(VIDC_DBG, "data is :%d",
-				prop->nal_stream_format_supported);
-		switch (prop->nal_stream_format_supported) {
-		case HAL_NAL_FORMAT_STARTCODES:
-			pkt->rg_property_data[1] =
-				HFI_NAL_FORMAT_STARTCODES;
-			break;
-		case HAL_NAL_FORMAT_ONE_NAL_PER_BUFFER:
-			pkt->rg_property_data[1] =
-				HFI_NAL_FORMAT_ONE_NAL_PER_BUFFER;
-			break;
-		case HAL_NAL_FORMAT_ONE_BYTE_LENGTH:
-			pkt->rg_property_data[1] =
-				HFI_NAL_FORMAT_ONE_BYTE_LENGTH;
-			break;
-		case HAL_NAL_FORMAT_TWO_BYTE_LENGTH:
-			pkt->rg_property_data[1] =
-				HFI_NAL_FORMAT_TWO_BYTE_LENGTH;
-			break;
-		case HAL_NAL_FORMAT_FOUR_BYTE_LENGTH:
-			pkt->rg_property_data[1] =
-				HFI_NAL_FORMAT_FOUR_BYTE_LENGTH;
-			break;
-		default:
-			dprintk(VIDC_ERR, "Invalid nal format: 0x%x",
-				  prop->nal_stream_format_supported);
-			break;
-		}
-		pkt->size += sizeof(u32) * 2;
-		break;
-	}
-	case HAL_PARAM_VDEC_OUTPUT_ORDER:
-	{
-		int *data = (int *) pdata;
-		pkt->rg_property_data[0] =
-			HFI_PROPERTY_PARAM_VDEC_OUTPUT_ORDER;
-		switch (*data) {
-		case HAL_OUTPUT_ORDER_DECODE:
-			pkt->rg_property_data[1] = HFI_OUTPUT_ORDER_DECODE;
-			break;
-		case HAL_OUTPUT_ORDER_DISPLAY:
-			pkt->rg_property_data[1] = HFI_OUTPUT_ORDER_DISPLAY;
-			break;
-		default:
-			dprintk(VIDC_ERR, "invalid output order: 0x%x",
-						  *data);
-			break;
-		}
-		pkt->size += sizeof(u32) * 2;
-		break;
-	}
-	case HAL_PARAM_VDEC_PICTURE_TYPE_DECODE:
-	{
-		struct hfi_enable_picture *hfi;
-		pkt->rg_property_data[0] =
-			HFI_PROPERTY_PARAM_VDEC_PICTURE_TYPE_DECODE;
-		hfi = (struct hfi_enable_picture *) &pkt->rg_property_data[1];
-		hfi->picture_type = (u32) pdata;
-		pkt->size += sizeof(u32) * 2;
-		break;
-	}
-	case HAL_PARAM_VDEC_OUTPUT2_KEEP_ASPECT_RATIO:
-	{
-		struct hfi_enable *hfi;
-		pkt->rg_property_data[0] =
-			HFI_PROPERTY_PARAM_VDEC_OUTPUT2_KEEP_ASPECT_RATIO;
-		hfi = (struct hfi_enable *) &pkt->rg_property_data[1];
-		hfi->enable = ((struct hfi_enable *) pdata)->enable;
-		pkt->size += sizeof(u32) * 2;
-		break;
-	}
-	case HAL_CONFIG_VDEC_POST_LOOP_DEBLOCKER:
-	{
-		struct hfi_enable *hfi;
-		pkt->rg_property_data[0] =
-			HFI_PROPERTY_CONFIG_VDEC_POST_LOOP_DEBLOCKER;
-		hfi = (struct hfi_enable *) &pkt->rg_property_data[1];
-		hfi->enable = ((struct hfi_enable *) pdata)->enable;
-		pkt->size += sizeof(u32) * 2;
-		break;
-	}
-	case HAL_PARAM_VDEC_MULTI_STREAM:
-	{
-		u32 buffer;
-		struct hfi_multi_stream *hfi;
-		struct hal_multi_stream *prop =
-			(struct hal_multi_stream *) pdata;
-		pkt->rg_property_data[0] =
-			HFI_PROPERTY_PARAM_VDEC_MULTI_STREAM;
-		hfi = (struct hfi_multi_stream *) &pkt->rg_property_data[1];
-		buffer = get_hfi_buffer(prop->buffer_type);
-		if (buffer)
-			hfi->buffer_type = buffer;
-		else
-			return -EINVAL;
-		hfi->enable = prop->enable;
-		hfi->width = prop->width;
-		hfi->height = prop->height;
-		pkt->size += sizeof(u32) + sizeof(struct hfi_multi_stream);
-		break;
-	}
-	case HAL_PARAM_VDEC_DISPLAY_PICTURE_BUFFER_COUNT:
-	{
-		struct hfi_display_picture_buffer_count *hfi;
-		struct hal_display_picture_buffer_count *prop =
-			(struct hal_display_picture_buffer_count *) pdata;
-		pkt->rg_property_data[0] =
-			HFI_PROPERTY_PARAM_VDEC_DISPLAY_PICTURE_BUFFER_COUNT;
-		hfi = (struct hfi_display_picture_buffer_count *)
-			&pkt->rg_property_data[1];
-		hfi->count = prop->count;
-		hfi->enable = prop->enable;
-		pkt->size += sizeof(u32) +
-			sizeof(struct hfi_display_picture_buffer_count);
-		break;
-	}
-	case HAL_PARAM_DIVX_FORMAT:
-	{
-		int *data = pdata;
-		pkt->rg_property_data[0] = HFI_PROPERTY_PARAM_DIVX_FORMAT;
-		switch (*data) {
-		case HAL_DIVX_FORMAT_4:
-			pkt->rg_property_data[1] = HFI_DIVX_FORMAT_4;
-			break;
-		case HAL_DIVX_FORMAT_5:
-			pkt->rg_property_data[1] = HFI_DIVX_FORMAT_5;
-			break;
-		case HAL_DIVX_FORMAT_6:
-			pkt->rg_property_data[1] = HFI_DIVX_FORMAT_6;
-			break;
-		default:
-			dprintk(VIDC_ERR, "Invalid divx format: 0x%x", *data);
-			break;
-		}
-		pkt->size += sizeof(u32) * 2;
-		break;
-	}
-	case HAL_CONFIG_VDEC_MB_ERROR_MAP_REPORTING:
-	{
-		struct hfi_enable *hfi;
-		pkt->rg_property_data[0] =
-			HFI_PROPERTY_CONFIG_VDEC_MB_ERROR_MAP_REPORTING;
-		hfi = (struct hfi_enable *) &pkt->rg_property_data[1];
-		hfi->enable = ((struct hfi_enable *) pdata)->enable;
-		pkt->size += sizeof(u32) * 2;
-		break;
-	}
-	case HAL_PARAM_VDEC_CONTINUE_DATA_TRANSFER:
-	{
-		struct hfi_enable *hfi;
-		pkt->rg_property_data[0] =
-			HFI_PROPERTY_PARAM_VDEC_CONTINUE_DATA_TRANSFER;
-		hfi = (struct hfi_enable *) &pkt->rg_property_data[1];
-		hfi->enable = ((struct hfi_enable *) pdata)->enable;
-		pkt->size += sizeof(u32) * 2;
-		break;
-	}
-	case HAL_PARAM_VDEC_SYNC_FRAME_DECODE:
-	{
-		struct hfi_enable *hfi;
-		pkt->rg_property_data[0] =
-			HFI_PROPERTY_PARAM_VDEC_THUMBNAIL_MODE;
-		hfi = (struct hfi_enable *) &pkt->rg_property_data[1];
-		hfi->enable = ((struct hfi_enable *) pdata)->enable;
-		pkt->size += sizeof(u32) * 2;
-		break;
-	}
-	case HAL_PARAM_VENC_SYNC_FRAME_SEQUENCE_HEADER:
-	{
-		struct hfi_enable *hfi;
-		pkt->rg_property_data[0] =
-			HFI_PROPERTY_CONFIG_VENC_SYNC_FRAME_SEQUENCE_HEADER;
-		hfi = (struct hfi_enable *) &pkt->rg_property_data[1];
-		hfi->enable = ((struct hfi_enable *) pdata)->enable;
-		pkt->size += sizeof(u32) * 2;
-		break;
-	}
-	case HAL_CONFIG_VENC_REQUEST_IFRAME:
-		pkt->rg_property_data[0] =
-			HFI_PROPERTY_CONFIG_VENC_REQUEST_SYNC_FRAME;
-		pkt->size += sizeof(u32);
-		break;
-	case HAL_PARAM_VENC_MPEG4_SHORT_HEADER:
-		break;
-	case HAL_PARAM_VENC_MPEG4_AC_PREDICTION:
-		break;
-	case HAL_CONFIG_VENC_TARGET_BITRATE:
-	{
-		struct hfi_bitrate *hfi;
-		pkt->rg_property_data[0] =
-			HFI_PROPERTY_CONFIG_VENC_TARGET_BITRATE;
-		hfi = (struct hfi_bitrate *) &pkt->rg_property_data[1];
-		hfi->bit_rate = ((struct hal_bitrate *)pdata)->bit_rate;
-		pkt->size += sizeof(u32) * 2;
-		break;
-	}
-	case HAL_PARAM_PROFILE_LEVEL_CURRENT:
-	{
-		struct hfi_profile_level *hfi;
-		struct hal_profile_level *prop =
-			(struct hal_profile_level *) pdata;
-		pkt->rg_property_data[0] =
-			HFI_PROPERTY_PARAM_PROFILE_LEVEL_CURRENT;
-		hfi = (struct hfi_profile_level *)
-			&pkt->rg_property_data[1];
-		hfi->level = (u32) prop->level;
-		hfi->profile = prop->profile;
-		if (!hfi->profile)
-			hfi->profile = HFI_H264_PROFILE_HIGH;
-		if (!hfi->level)
-			hfi->level = 1;
-		pkt->size += sizeof(u32) + sizeof(struct hfi_profile_level);
-		break;
-	}
-	case HAL_PARAM_VENC_H264_ENTROPY_CONTROL:
-	{
-		struct hfi_h264_entropy_control *hfi;
-		struct hal_h264_entropy_control *prop =
-			(struct hal_h264_entropy_control *) pdata;
-		pkt->rg_property_data[0] =
-			HFI_PROPERTY_PARAM_VENC_H264_ENTROPY_CONTROL;
-		hfi = (struct hfi_h264_entropy_control *)
-			&pkt->rg_property_data[1];
-		switch (prop->entropy_mode) {
-		case HAL_H264_ENTROPY_CAVLC:
-			hfi->cabac_model = HFI_H264_ENTROPY_CAVLC;
-			break;
-		case HAL_H264_ENTROPY_CABAC:
-			hfi->cabac_model = HFI_H264_ENTROPY_CABAC;
-			switch (prop->cabac_model) {
-			case HAL_H264_CABAC_MODEL_0:
-				hfi->cabac_model = HFI_H264_CABAC_MODEL_0;
-				break;
-			case HAL_H264_CABAC_MODEL_1:
-				hfi->cabac_model = HFI_H264_CABAC_MODEL_1;
-				break;
-			case HAL_H264_CABAC_MODEL_2:
-				hfi->cabac_model = HFI_H264_CABAC_MODEL_2;
-				break;
-			default:
-				dprintk(VIDC_ERR,
-					"Invalid cabac model 0x%x",
-					prop->entropy_mode);
-				break;
-			}
-		break;
-		default:
-			dprintk(VIDC_ERR,
-				"Invalid entropy selected: 0x%x",
-				prop->cabac_model);
-			break;
-		}
-		pkt->size += sizeof(u32) + sizeof(
-			struct hfi_h264_entropy_control);
-		break;
-	}
-	case HAL_PARAM_VENC_RATE_CONTROL:
-	{
-		u32 *rc;
-		pkt->rg_property_data[0] =
-			HFI_PROPERTY_PARAM_VENC_RATE_CONTROL;
-		rc = (u32 *)pdata;
-		switch ((enum hal_rate_control) *rc) {
-		case HAL_RATE_CONTROL_OFF:
-		pkt->rg_property_data[1] = HFI_RATE_CONTROL_OFF;
-			break;
-		case HAL_RATE_CONTROL_CBR_CFR:
-		pkt->rg_property_data[1] = HFI_RATE_CONTROL_CBR_CFR;
-			break;
-		case HAL_RATE_CONTROL_CBR_VFR:
-		pkt->rg_property_data[1] = HFI_RATE_CONTROL_CBR_VFR;
-			break;
-		case HAL_RATE_CONTROL_VBR_CFR:
-		pkt->rg_property_data[1] = HFI_RATE_CONTROL_VBR_CFR;
-			break;
-		case HAL_RATE_CONTROL_VBR_VFR:
-		pkt->rg_property_data[1] = HFI_RATE_CONTROL_VBR_VFR;
-			break;
-		default:
-			dprintk(VIDC_ERR, "Invalid Rate control setting: 0x%x",
-						  (int) pdata);
-			break;
-		}
-		pkt->size += sizeof(u32) * 2;
-		break;
-	}
-	case HAL_PARAM_VENC_MPEG4_TIME_RESOLUTION:
-	{
-		struct hfi_mpeg4_time_resolution *hfi;
-		pkt->rg_property_data[0] =
-			HFI_PROPERTY_PARAM_VENC_MPEG4_TIME_RESOLUTION;
-		hfi = (struct hfi_mpeg4_time_resolution *)
-			&pkt->rg_property_data[1];
-		hfi->time_increment_resolution =
-			((struct hal_mpeg4_time_resolution *)pdata)->
-					time_increment_resolution;
-		pkt->size += sizeof(u32) * 2;
-		break;
-	}
-	case HAL_PARAM_VENC_MPEG4_HEADER_EXTENSION:
-	{
-		struct hfi_mpeg4_header_extension *hfi;
-		pkt->rg_property_data[0] =
-			HFI_PROPERTY_PARAM_VENC_MPEG4_HEADER_EXTENSION;
-		hfi = (struct hfi_mpeg4_header_extension *)
-			&pkt->rg_property_data[1];
-		hfi->header_extension = (u32) pdata;
-		pkt->size += sizeof(u32) * 2;
-		break;
-	}
-	case HAL_PARAM_VENC_H264_DEBLOCK_CONTROL:
-	{
-		struct hfi_h264_db_control *hfi;
-		struct hal_h264_db_control *prop =
-			(struct hal_h264_db_control *) pdata;
-		pkt->rg_property_data[0] =
-			HFI_PROPERTY_PARAM_VENC_H264_DEBLOCK_CONTROL;
-		hfi = (struct hfi_h264_db_control *) &pkt->rg_property_data[1];
-		switch (prop->mode) {
-		case HAL_H264_DB_MODE_DISABLE:
-			hfi->mode = HFI_H264_DB_MODE_DISABLE;
-			break;
-		case HAL_H264_DB_MODE_SKIP_SLICE_BOUNDARY:
-			hfi->mode = HFI_H264_DB_MODE_SKIP_SLICE_BOUNDARY;
-			break;
-		case HAL_H264_DB_MODE_ALL_BOUNDARY:
-			hfi->mode = HFI_H264_DB_MODE_ALL_BOUNDARY;
-			break;
-		default:
-			dprintk(VIDC_ERR, "Invalid deblocking mode: 0x%x",
-						  prop->mode);
-			break;
-		}
-		hfi->slice_alpha_offset = prop->slice_alpha_offset;
-		hfi->slice_beta_offset = prop->slice_beta_offset;
-		pkt->size += sizeof(u32) +
-			sizeof(struct hfi_h264_db_control);
-		break;
-	}
-	case HAL_PARAM_VENC_SESSION_QP:
-	{
-		struct hfi_quantization *hfi;
-		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));
-		pkt->size += sizeof(u32) + sizeof(struct hfi_quantization);
-		break;
-	}
-	case HAL_CONFIG_VENC_INTRA_PERIOD:
-	{
-		struct hfi_intra_period *hfi;
-		pkt->rg_property_data[0] =
-			HFI_PROPERTY_CONFIG_VENC_INTRA_PERIOD;
-		hfi = (struct hfi_intra_period *) &pkt->rg_property_data[1];
-		memcpy(hfi, (struct hfi_intra_period *) pdata,
-				sizeof(struct hfi_intra_period));
-		pkt->size += sizeof(u32) + sizeof(struct hfi_intra_period);
-		break;
-	}
-	case HAL_CONFIG_VENC_IDR_PERIOD:
-	{
-		struct hfi_idr_period *hfi;
-		pkt->rg_property_data[0] = HFI_PROPERTY_CONFIG_VENC_IDR_PERIOD;
-		hfi = (struct hfi_idr_period *) &pkt->rg_property_data[1];
-		hfi->idr_period = ((struct hfi_idr_period *) pdata)->idr_period;
-		pkt->size += sizeof(u32) * 2;
-		break;
-	}
-	case HAL_CONFIG_VPE_OPERATIONS:
-		break;
-	case HAL_PARAM_VENC_INTRA_REFRESH:
-	{
-		struct hfi_intra_refresh *hfi;
-		struct hal_intra_refresh *prop =
-			(struct hal_intra_refresh *) pdata;
-		pkt->rg_property_data[0] =
-			HFI_PROPERTY_PARAM_VENC_INTRA_REFRESH;
-		hfi = (struct hfi_intra_refresh *) &pkt->rg_property_data[1];
-		switch (prop->mode) {
-		case HAL_INTRA_REFRESH_NONE:
-			hfi->mode = HFI_INTRA_REFRESH_NONE;
-			break;
-		case HAL_INTRA_REFRESH_ADAPTIVE:
-			hfi->mode = HFI_INTRA_REFRESH_ADAPTIVE;
-			break;
-		case HAL_INTRA_REFRESH_CYCLIC:
-			hfi->mode = HFI_INTRA_REFRESH_CYCLIC;
-			break;
-		case HAL_INTRA_REFRESH_CYCLIC_ADAPTIVE:
-			hfi->mode = HFI_INTRA_REFRESH_CYCLIC_ADAPTIVE;
-			break;
-		case HAL_INTRA_REFRESH_RANDOM:
-			hfi->mode = HFI_INTRA_REFRESH_RANDOM;
-			break;
-		default:
-			dprintk(VIDC_ERR, "Invalid intra refresh setting: 0x%x",
-				prop->mode);
-			break;
-		}
-		hfi->air_mbs = prop->air_mbs;
-		hfi->air_ref = prop->air_ref;
-		hfi->cir_mbs = prop->cir_mbs;
-		pkt->size += sizeof(u32) + sizeof(struct hfi_intra_refresh);
-		break;
-	}
-	case HAL_PARAM_VENC_MULTI_SLICE_CONTROL:
-	{
-		struct hfi_multi_slice_control *hfi;
-		struct hal_multi_slice_control *prop =
-			(struct hal_multi_slice_control *) pdata;
-		pkt->rg_property_data[0] =
-			HFI_PROPERTY_PARAM_VENC_MULTI_SLICE_CONTROL;
-		hfi = (struct hfi_multi_slice_control *)
-			&pkt->rg_property_data[1];
-		switch (prop->multi_slice) {
-		case HAL_MULTI_SLICE_OFF:
-			hfi->multi_slice = HFI_MULTI_SLICE_OFF;
-			break;
-		case HAL_MULTI_SLICE_GOB:
-			hfi->multi_slice = HFI_MULTI_SLICE_GOB;
-			break;
-		case HAL_MULTI_SLICE_BY_MB_COUNT:
-			hfi->multi_slice = HFI_MULTI_SLICE_BY_MB_COUNT;
-			break;
-		case HAL_MULTI_SLICE_BY_BYTE_COUNT:
-			hfi->multi_slice = HFI_MULTI_SLICE_BY_BYTE_COUNT;
-			break;
-		default:
-			dprintk(VIDC_ERR, "Invalid slice settings: 0x%x",
-				prop->multi_slice);
-			break;
-		}
-		hfi->slice_size = prop->slice_size;
-		pkt->size += sizeof(u32) + sizeof(struct
-					hfi_multi_slice_control);
-		break;
-	}
-	case HAL_PARAM_INDEX_EXTRADATA:
-	{
-		struct hfi_index_extradata_config *hfi;
-		struct hal_extradata_enable *extra = pdata;
-		int index = 0;
-		pkt->rg_property_data[0] =
-			get_hfi_extradata_index(extra->index);
-		hfi =
-			(struct hfi_index_extradata_config *)
-			&pkt->rg_property_data[1];
-		hfi->enable = extra->enable;
-		index = get_hfi_extradata_index(extra->index);
-		if (index)
-			hfi->index_extra_data_id = index;
-		else {
-			dprintk(VIDC_WARN,
-				"Failed to find extradata index: %d\n",
-				index);
-			rc = -EINVAL;
-		}
-		pkt->size += sizeof(u32) +
-			sizeof(struct hfi_index_extradata_config);
-		break;
-	}
-	case HAL_CONFIG_VPE_DEINTERLACE:
-		break;
-	/* FOLLOWING PROPERTIES ARE NOT IMPLEMENTED IN CORE YET */
-	case HAL_CONFIG_BUFFER_REQUIREMENTS:
-	case HAL_CONFIG_PRIORITY:
-	case HAL_CONFIG_BATCH_INFO:
-	case HAL_PARAM_METADATA_PASS_THROUGH:
-	case HAL_SYS_IDLE_INDICATOR:
-	case HAL_PARAM_UNCOMPRESSED_FORMAT_SUPPORTED:
-	case HAL_PARAM_INTERLACE_FORMAT_SUPPORTED:
-	case HAL_PARAM_CHROMA_SITE:
-	case HAL_PARAM_PROPERTIES_SUPPORTED:
-	case HAL_PARAM_PROFILE_LEVEL_SUPPORTED:
-	case HAL_PARAM_CAPABILITY_SUPPORTED:
-	case HAL_PARAM_NAL_STREAM_FORMAT_SUPPORTED:
-	case HAL_PARAM_MULTI_VIEW_FORMAT:
-	case HAL_PARAM_MAX_SEQUENCE_HEADER_SIZE:
-	case HAL_PARAM_CODEC_SUPPORTED:
-	case HAL_PARAM_VDEC_MULTI_VIEW_SELECT:
-	case HAL_PARAM_VDEC_MB_QUANTIZATION:
-	case HAL_PARAM_VDEC_NUM_CONCEALED_MB:
-	case HAL_PARAM_VDEC_H264_ENTROPY_SWITCHING:
-	case HAL_PARAM_VENC_SLICE_DELIVERY_MODE:
-	case HAL_PARAM_VENC_MPEG4_DATA_PARTITIONING:
-
-	case HAL_CONFIG_BUFFER_COUNT_ACTUAL:
-	case HAL_CONFIG_VDEC_MULTI_STREAM:
-	case HAL_PARAM_VENC_MULTI_SLICE_INFO:
-	case HAL_CONFIG_VENC_TIMESTAMP_SCALE:
-	case HAL_PARAM_VENC_LOW_LATENCY:
-	default:
-		dprintk(VIDC_INFO, "DEFAULT: Calling 0x%x", ptype);
-		break;
-	}
-	if (!rc)
-		rc = vidc_hal_iface_cmdq_write(session->device, pkt);
-
-	return rc;
-}
-
-int vidc_hal_session_get_property(void *sess,
-	enum hal_property ptype, void *pdata)
-{
-	struct hal_session *session;
-
-	if (!sess || !pdata) {
-		dprintk(VIDC_ERR, "Invalid Params in ");
-		return -EINVAL;
-	} else {
-		session = sess;
-	}
-	dprintk(VIDC_INFO, "IN func: , with property id: %d", ptype);
-
-	switch (ptype) {
-	case HAL_CONFIG_FRAME_RATE:
-		break;
-	case HAL_PARAM_UNCOMPRESSED_FORMAT_SELECT:
-		break;
-	case HAL_PARAM_UNCOMPRESSED_PLANE_ACTUAL_CONSTRAINTS_INFO:
-		break;
-	case HAL_PARAM_UNCOMPRESSED_PLANE_ACTUAL_INFO:
-		break;
-	case HAL_PARAM_EXTRA_DATA_HEADER_CONFIG:
-		break;
-	case HAL_PARAM_FRAME_SIZE:
-		break;
-	case HAL_CONFIG_REALTIME:
-		break;
-	case HAL_PARAM_BUFFER_COUNT_ACTUAL:
-		break;
-	case HAL_PARAM_NAL_STREAM_FORMAT_SELECT:
-		break;
-	case HAL_PARAM_VDEC_OUTPUT_ORDER:
-		break;
-	case HAL_PARAM_VDEC_PICTURE_TYPE_DECODE:
-		break;
-	case HAL_PARAM_VDEC_OUTPUT2_KEEP_ASPECT_RATIO:
-		break;
-	case HAL_CONFIG_VDEC_POST_LOOP_DEBLOCKER:
-		break;
-	case HAL_PARAM_VDEC_MULTI_STREAM:
-		break;
-	case HAL_PARAM_VDEC_DISPLAY_PICTURE_BUFFER_COUNT:
-		break;
-	case HAL_PARAM_DIVX_FORMAT:
-		break;
-	case HAL_CONFIG_VDEC_MB_ERROR_MAP_REPORTING:
-		break;
-	case HAL_PARAM_VDEC_CONTINUE_DATA_TRANSFER:
-		break;
-	case HAL_CONFIG_VDEC_MB_ERROR_MAP:
-		break;
-	case HAL_CONFIG_VENC_REQUEST_IFRAME:
-		break;
-	case HAL_PARAM_VENC_MPEG4_SHORT_HEADER:
-		break;
-	case HAL_PARAM_VENC_MPEG4_AC_PREDICTION:
-		break;
-	case HAL_CONFIG_VENC_TARGET_BITRATE:
-		break;
-	case HAL_PARAM_PROFILE_LEVEL_CURRENT:
-		break;
-	case HAL_PARAM_VENC_H264_ENTROPY_CONTROL:
-		break;
-	case HAL_PARAM_VENC_RATE_CONTROL:
-		break;
-	case HAL_PARAM_VENC_MPEG4_TIME_RESOLUTION:
-		break;
-	case HAL_PARAM_VENC_MPEG4_HEADER_EXTENSION:
-		break;
-	case HAL_PARAM_VENC_H264_DEBLOCK_CONTROL:
-		break;
-	case HAL_PARAM_VENC_SESSION_QP:
-		break;
-	case HAL_CONFIG_VENC_INTRA_PERIOD:
-		break;
-	case HAL_CONFIG_VENC_IDR_PERIOD:
-		break;
-	case HAL_CONFIG_VPE_OPERATIONS:
-		break;
-	case HAL_PARAM_VENC_INTRA_REFRESH:
-		break;
-	case HAL_PARAM_VENC_MULTI_SLICE_CONTROL:
-		break;
-	case HAL_CONFIG_VPE_DEINTERLACE:
-		break;
-	case HAL_SYS_DEBUG_CONFIG:
-		break;
-	/*FOLLOWING PROPERTIES ARE NOT IMPLEMENTED IN CORE YET*/
-	case HAL_CONFIG_BUFFER_REQUIREMENTS:
-	case HAL_CONFIG_PRIORITY:
-	case HAL_CONFIG_BATCH_INFO:
-	case HAL_PARAM_METADATA_PASS_THROUGH:
-	case HAL_SYS_IDLE_INDICATOR:
-	case HAL_PARAM_UNCOMPRESSED_FORMAT_SUPPORTED:
-	case HAL_PARAM_INTERLACE_FORMAT_SUPPORTED:
-	case HAL_PARAM_CHROMA_SITE:
-	case HAL_PARAM_PROPERTIES_SUPPORTED:
-	case HAL_PARAM_PROFILE_LEVEL_SUPPORTED:
-	case HAL_PARAM_CAPABILITY_SUPPORTED:
-	case HAL_PARAM_NAL_STREAM_FORMAT_SUPPORTED:
-	case HAL_PARAM_MULTI_VIEW_FORMAT:
-	case HAL_PARAM_MAX_SEQUENCE_HEADER_SIZE:
-	case HAL_PARAM_CODEC_SUPPORTED:
-	case HAL_PARAM_VDEC_MULTI_VIEW_SELECT:
-	case HAL_PARAM_VDEC_MB_QUANTIZATION:
-	case HAL_PARAM_VDEC_NUM_CONCEALED_MB:
-	case HAL_PARAM_VDEC_H264_ENTROPY_SWITCHING:
-	case HAL_PARAM_VENC_SLICE_DELIVERY_MODE:
-	case HAL_PARAM_VENC_MPEG4_DATA_PARTITIONING:
-
-	case HAL_CONFIG_BUFFER_COUNT_ACTUAL:
-	case HAL_CONFIG_VDEC_MULTI_STREAM:
-	case HAL_PARAM_VENC_MULTI_SLICE_INFO:
-	case HAL_CONFIG_VENC_TIMESTAMP_SCALE:
-	case HAL_PARAM_VENC_LOW_LATENCY:
-	default:
-		dprintk(VIDC_INFO, "DEFAULT: Calling 0x%x", ptype);
-		break;
-	}
-	return 0;
-}
-
-void *vidc_hal_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;
-	struct hal_device *dev;
-
-	if (device) {
-		dev = device;
-	} else {
-		dprintk(VIDC_ERR, "invalid device");
-		return NULL;
-	}
-
-	new_session = (struct hal_session *)
-		kzalloc(sizeof(struct hal_session), GFP_KERNEL);
-	new_session->session_id = (u32) session_id;
-	if (session_type == 1)
-		new_session->is_decoder = 0;
-	else if (session_type == 2)
-		new_session->is_decoder = 1;
-	new_session->device = dev;
-	list_add_tail(&new_session->list, &dev->sess_head);
-	pkt.size = sizeof(struct hfi_cmd_sys_session_init_packet);
-	pkt.packet_type = HFI_CMD_SYS_SESSION_INIT;
-	pkt.session_id = (u32) new_session;
-	pkt.session_domain = session_type;
-	pkt.session_codec = codec_type;
-	if (vidc_hal_iface_cmdq_write(dev, &pkt))
-		return NULL;
-	if (vidc_hal_sys_set_debug(dev, msm_fw_debug))
-		dprintk(VIDC_ERR, "Setting fw_debug msg ON failed");
-	return (void *) new_session;
-}
-
-static int vidc_hal_send_session_cmd(void *session_id,
-	 int pkt_type)
-{
-	struct vidc_hal_session_cmd_pkt pkt;
-	int rc = 0;
-	struct hal_session *session;
-
-	if (session_id) {
-		session = session_id;
-	} else {
-		dprintk(VIDC_ERR, "invalid session");
-		return -ENODEV;
-	}
-
-	pkt.size = sizeof(struct vidc_hal_session_cmd_pkt);
-	pkt.packet_type = pkt_type;
-	pkt.session_id = (u32) session;
-
-	if (vidc_hal_iface_cmdq_write(session->device, &pkt))
-		rc = -ENOTEMPTY;
-	return rc;
-}
-
-int vidc_hal_session_end(void *session)
-{
-	return vidc_hal_send_session_cmd(session,
-		HFI_CMD_SYS_SESSION_END);
-}
-
-int vidc_hal_session_abort(void *session)
-{
-	return vidc_hal_send_session_cmd(session,
-		HFI_CMD_SYS_SESSION_ABORT);
-}
-
-int vidc_hal_session_set_buffers(void *sess,
-	struct vidc_buffer_addr_info *buffer_info)
-{
-	u32 buffer;
-	struct hfi_cmd_session_set_buffers_packet *pkt;
-	u8 packet[VIDC_IFACEQ_VAR_LARGE_PKT_SIZE];
-	int rc = 0;
-	u16 i;
-	struct hal_session *session;
-
-	if (!sess || !buffer_info) {
-		dprintk(VIDC_ERR, "Invalid Params");
-		return -EINVAL;
-	} else {
-		session = sess;
-	}
-
-	if (buffer_info->buffer_type == HAL_BUFFER_INPUT)
-		return 0;
-
-	pkt = (struct hfi_cmd_session_set_buffers_packet *)packet;
-
-	pkt->size = sizeof(struct hfi_cmd_session_set_buffers_packet) +
-		((buffer_info->num_buffers - 1) * sizeof(u32));
-	pkt->packet_type = HFI_CMD_SESSION_SET_BUFFERS;
-	pkt->session_id = (u32) session;
-	pkt->buffer_size = buffer_info->buffer_size;
-	pkt->min_buffer_size = buffer_info->buffer_size;
-	pkt->num_buffers = buffer_info->num_buffers;
-
-	if ((buffer_info->buffer_type == HAL_BUFFER_OUTPUT) ||
-		(buffer_info->buffer_type == HAL_BUFFER_OUTPUT2)) {
-		struct hfi_buffer_info *buff;
-		pkt->extra_data_size = buffer_info->extradata_size;
-		pkt->size = sizeof(struct hfi_cmd_session_set_buffers_packet) -
-			sizeof(u32) + ((buffer_info->num_buffers) *
-			sizeof(struct hfi_buffer_info));
-		buff = (struct hfi_buffer_info *) pkt->rg_buffer_info;
-		for (i = 0; i < pkt->num_buffers; i++) {
-			buff->buffer_addr =
-				buffer_info->align_device_addr;
-			buff->extra_data_addr =
-				buffer_info->extradata_addr;
-		}
-	} else {
-		pkt->extra_data_size = 0;
-		pkt->size = sizeof(struct hfi_cmd_session_set_buffers_packet) +
-			((buffer_info->num_buffers - 1) * sizeof(u32));
-		for (i = 0; i < pkt->num_buffers; i++)
-			pkt->rg_buffer_info[i] =
-			buffer_info->align_device_addr;
-	}
-	buffer = get_hfi_buffer(buffer_info->buffer_type);
-	if (buffer)
-		pkt->buffer_type = buffer;
-	else
-		return -EINVAL;
-	dprintk(VIDC_INFO, "set buffers: 0x%x", buffer_info->buffer_type);
-	if (vidc_hal_iface_cmdq_write(session->device, pkt))
-		rc = -ENOTEMPTY;
-	return rc;
-}
-
-int vidc_hal_session_release_buffers(void *sess,
-	struct vidc_buffer_addr_info *buffer_info)
-{
-	u32 buffer;
-	struct hfi_cmd_session_release_buffer_packet *pkt;
-	u8 packet[VIDC_IFACEQ_VAR_LARGE_PKT_SIZE];
-	int rc = 0;
-	u32 i;
-	struct hal_session *session;
-
-	if (!sess || !buffer_info) {
-		dprintk(VIDC_ERR, "Invalid Params");
-		return -EINVAL;
-	} else {
-		session = sess;
-	}
-
-	if (buffer_info->buffer_type == HAL_BUFFER_INPUT)
-		return 0;
-
-	pkt = (struct hfi_cmd_session_release_buffer_packet *) packet;
-	pkt->size = sizeof(struct hfi_cmd_session_release_buffer_packet) +
-		((buffer_info->num_buffers - 1) * sizeof(u32));
-	pkt->packet_type = HFI_CMD_SESSION_RELEASE_BUFFERS;
-	pkt->session_id = (u32) session;
-	pkt->buffer_size = buffer_info->buffer_size;
-	pkt->num_buffers = buffer_info->num_buffers;
-
-	if ((buffer_info->buffer_type == HAL_BUFFER_OUTPUT) ||
-		(buffer_info->buffer_type == HAL_BUFFER_OUTPUT2)) {
-		struct hfi_buffer_info *buff;
-		buff = (struct hfi_buffer_info *) pkt->rg_buffer_info;
-		for (i = 0; i < pkt->num_buffers; i++) {
-			buff->buffer_addr =
-				buffer_info->align_device_addr;
-			buff->extra_data_addr =
-				buffer_info->extradata_addr;
-		}
-		pkt->extra_data_size = buffer_info->extradata_size;
-		pkt->size = sizeof(struct hfi_cmd_session_set_buffers_packet) -
-			sizeof(u32) + ((buffer_info->num_buffers) *
-			sizeof(struct hfi_buffer_info));
-	} else {
-		for (i = 0; i < pkt->num_buffers; i++)
-			pkt->rg_buffer_info[i] =
-			buffer_info->align_device_addr;
-		pkt->extra_data_size = 0;
-		pkt->size = sizeof(struct hfi_cmd_session_set_buffers_packet) +
-			((buffer_info->num_buffers - 1) * sizeof(u32));
-	}
-	pkt->response_req = buffer_info->response_required;
-	buffer = get_hfi_buffer(buffer_info->buffer_type);
-	if (buffer)
-		pkt->buffer_type = buffer;
-	else
-		return -EINVAL;
-	dprintk(VIDC_INFO, "Release buffers: 0x%x", buffer_info->buffer_type);
-	if (vidc_hal_iface_cmdq_write(session->device, pkt))
-		rc = -ENOTEMPTY;
-	return rc;
-}
-
-int vidc_hal_session_load_res(void *sess)
-{
-	return vidc_hal_send_session_cmd(sess,
-		HFI_CMD_SESSION_LOAD_RESOURCES);
-}
-
-int vidc_hal_session_release_res(void *sess)
-{
-	return vidc_hal_send_session_cmd(sess,
-		HFI_CMD_SESSION_RELEASE_RESOURCES);
-}
-
-int vidc_hal_session_start(void *sess)
-{
-	return vidc_hal_send_session_cmd(sess,
-		HFI_CMD_SESSION_START);
-}
-
-int vidc_hal_session_stop(void *sess)
-{
-	return vidc_hal_send_session_cmd(sess,
-		HFI_CMD_SESSION_STOP);
-}
-
-int vidc_hal_session_suspend(void *sess)
-{
-	return vidc_hal_send_session_cmd(sess,
-		HFI_CMD_SESSION_SUSPEND);
-}
-
-int vidc_hal_session_resume(void *sess)
-{
-	return vidc_hal_send_session_cmd(sess,
-		HFI_CMD_SESSION_RESUME);
-}
-
-int vidc_hal_session_etb(void *sess, struct vidc_frame_data *input_frame)
-{
-	int rc = 0;
-	struct hal_session *session;
-
-	if (!sess || !input_frame) {
-		dprintk(VIDC_ERR, "Invalid Params");
-		return -EINVAL;
-	} else {
-		session = sess;
-	}
-
-	if (session->is_decoder) {
-		struct hfi_cmd_session_empty_buffer_compressed_packet pkt;
-		pkt.size = sizeof(
-			struct hfi_cmd_session_empty_buffer_compressed_packet);
-		pkt.packet_type = HFI_CMD_SESSION_EMPTY_BUFFER;
-		pkt.session_id = (u32) session;
-		pkt.time_stamp_hi = (int) (((u64)input_frame->timestamp) >> 32);
-		pkt.time_stamp_lo = (int) input_frame->timestamp;
-		pkt.flags = input_frame->flags;
-		pkt.mark_target = input_frame->mark_target;
-		pkt.mark_data = input_frame->mark_data;
-		pkt.offset = input_frame->offset;
-		pkt.alloc_len = input_frame->alloc_len;
-		pkt.filled_len = input_frame->filled_len;
-		pkt.input_tag = input_frame->clnt_data;
-		pkt.packet_buffer = (u8 *) input_frame->device_addr;
-		dprintk(VIDC_DBG, "Q DECODER INPUT BUFFER");
-		if (vidc_hal_iface_cmdq_write(session->device, &pkt))
-			rc = -ENOTEMPTY;
-	} else {
-		struct hfi_cmd_session_empty_buffer_uncompressed_plane0_packet
-			pkt;
-		pkt.size = sizeof(struct
-		hfi_cmd_session_empty_buffer_uncompressed_plane0_packet);
-		pkt.packet_type = HFI_CMD_SESSION_EMPTY_BUFFER;
-		pkt.session_id = (u32) session;
-		pkt.view_id = 0;
-		pkt.time_stamp_hi = (u32) (((u64)input_frame->timestamp) >> 32);
-		pkt.time_stamp_lo = (u32) input_frame->timestamp;
-		pkt.flags = input_frame->flags;
-		pkt.mark_target = input_frame->mark_target;
-		pkt.mark_data = input_frame->mark_data;
-		pkt.offset = input_frame->offset;
-		pkt.alloc_len = input_frame->alloc_len;
-		pkt.filled_len = input_frame->filled_len;
-		pkt.input_tag = input_frame->clnt_data;
-		pkt.packet_buffer = (u8 *) input_frame->device_addr;
-		dprintk(VIDC_DBG, "Q ENCODER INPUT BUFFER");
-		if (vidc_hal_iface_cmdq_write(session->device, &pkt))
-			rc = -ENOTEMPTY;
-	}
-	return rc;
-}
-
-int vidc_hal_session_ftb(void *sess,
-	struct vidc_frame_data *output_frame)
-{
-	struct hfi_cmd_session_fill_buffer_packet pkt;
-	int rc = 0;
-	struct hal_session *session;
-
-	if (!sess || !output_frame) {
-		dprintk(VIDC_ERR, "Invalid Params");
-		return -EINVAL;
-	} else {
-		session = sess;
-	}
-
-	pkt.size = sizeof(struct hfi_cmd_session_fill_buffer_packet);
-	pkt.packet_type = HFI_CMD_SESSION_FILL_BUFFER;
-	pkt.session_id = (u32) session;
-	if (output_frame->buffer_type == HAL_BUFFER_OUTPUT)
-		pkt.stream_id = 0;
-	else if (output_frame->buffer_type == HAL_BUFFER_OUTPUT2)
-		pkt.stream_id = 1;
-	pkt.packet_buffer = (u8 *) output_frame->device_addr;
-	pkt.extra_data_buffer =
-		(u8 *) output_frame->extradata_addr;
-	pkt.alloc_len = output_frame->alloc_len;
-	pkt.filled_len = output_frame->filled_len;
-	pkt.offset = output_frame->offset;
-	dprintk(VIDC_DBG, "### Q OUTPUT BUFFER ###: %d, %d, %d\n",
-			pkt.alloc_len, pkt.filled_len, pkt.offset);
-	if (vidc_hal_iface_cmdq_write(session->device, &pkt))
-		rc = -ENOTEMPTY;
-	return rc;
-}
-
-int vidc_hal_session_parse_seq_hdr(void *sess,
-	struct vidc_seq_hdr *seq_hdr)
-{
-	struct hfi_cmd_session_parse_sequence_header_packet *pkt;
-	int rc = 0;
-	u8 packet[VIDC_IFACEQ_VAR_SMALL_PKT_SIZE];
-	struct hal_session *session;
-
-	if (!sess || !seq_hdr) {
-		dprintk(VIDC_ERR, "Invalid Params");
-		return -EINVAL;
-	} else {
-		session = sess;
-	}
-
-	pkt = (struct hfi_cmd_session_parse_sequence_header_packet *) packet;
-	pkt->size = sizeof(struct hfi_cmd_session_parse_sequence_header_packet);
-	pkt->packet_type = HFI_CMD_SESSION_PARSE_SEQUENCE_HEADER;
-	pkt->session_id = (u32) session;
-	pkt->header_len = seq_hdr->seq_hdr_len;
-	pkt->packet_buffer = seq_hdr->seq_hdr;
-
-	if (vidc_hal_iface_cmdq_write(session->device, pkt))
-		rc = -ENOTEMPTY;
-	return rc;
-}
-
-int vidc_hal_session_get_seq_hdr(void *sess,
-	struct vidc_seq_hdr *seq_hdr)
-{
-	struct hfi_cmd_session_get_sequence_header_packet *pkt;
-	int rc = 0;
-	u8 packet[VIDC_IFACEQ_VAR_SMALL_PKT_SIZE];
-	struct hal_session *session;
-
-	if (!sess || !seq_hdr) {
-		dprintk(VIDC_ERR, "Invalid Params");
-		return -EINVAL;
-	} else {
-		session = sess;
-	}
-
-	pkt = (struct hfi_cmd_session_get_sequence_header_packet *) packet;
-	pkt->size = sizeof(struct hfi_cmd_session_get_sequence_header_packet);
-	pkt->packet_type = HFI_CMD_SESSION_GET_SEQUENCE_HEADER;
-	pkt->session_id = (u32) session;
-	pkt->buffer_len = seq_hdr->seq_hdr_len;
-	pkt->packet_buffer = seq_hdr->seq_hdr;
-
-	if (vidc_hal_iface_cmdq_write(session->device, pkt))
-		rc = -ENOTEMPTY;
-	return rc;
-}
-
-int vidc_hal_session_get_buf_req(void *sess)
-{
-	struct hfi_cmd_session_get_property_packet pkt;
-	int rc = 0;
-	struct hal_session *session;
-
-	if (sess) {
-		session = sess;
-	} else {
-		dprintk(VIDC_ERR, "invalid session");
-		return -ENODEV;
-	}
-
-	pkt.size = sizeof(struct hfi_cmd_session_get_property_packet);
-	pkt.packet_type = HFI_CMD_SESSION_GET_PROPERTY;
-	pkt.session_id = (u32) session;
-	pkt.num_properties = 1;
-	pkt.rg_property_data[0] = HFI_PROPERTY_CONFIG_BUFFER_REQUIREMENTS;
-	if (vidc_hal_iface_cmdq_write(session->device, &pkt))
-		rc = -ENOTEMPTY;
-	return rc;
-}
-
-int vidc_hal_session_flush(void *sess, enum hal_flush flush_mode)
-{
-	struct hfi_cmd_session_flush_packet pkt;
-	int rc = 0;
-	struct hal_session *session;
-
-	if (sess) {
-		session = sess;
-	} else {
-		dprintk(VIDC_ERR, "invalid session");
-		return -ENODEV;
-	}
-
-	pkt.size = sizeof(struct hfi_cmd_session_flush_packet);
-	pkt.packet_type = HFI_CMD_SESSION_FLUSH;
-	pkt.session_id = (u32) session;
-	switch (flush_mode) {
-	case HAL_FLUSH_INPUT:
-		pkt.flush_type = HFI_FLUSH_INPUT;
-		break;
-	case HAL_FLUSH_OUTPUT:
-		pkt.flush_type = HFI_FLUSH_OUTPUT;
-		break;
-	case HAL_FLUSH_OUTPUT2:
-		pkt.flush_type = HFI_FLUSH_OUTPUT2;
-		break;
-	case HAL_FLUSH_ALL:
-		pkt.flush_type = HFI_FLUSH_ALL;
-		break;
-	default:
-		dprintk(VIDC_ERR, "Invalid flush mode: 0x%x\n", flush_mode);
-		break;
-	}
-	if (vidc_hal_iface_cmdq_write(session->device, &pkt))
-		rc = -ENOTEMPTY;
-	return rc;
-}
-
-static int vidc_hal_check_core_registered(
-	struct hal_device_data core, u32 fw_addr,
-	u32 reg_addr, u32 reg_size, u32 irq)
-{
-	struct hal_device *device;
-	struct list_head *curr, *next;
-
-	if (core.dev_count) {
-		list_for_each_safe(curr, next, &core.dev_head) {
-			device = list_entry(curr, struct hal_device, list);
-			if (device && device->hal_data->irq == irq &&
-				(CONTAINS(device->hal_data->
-						device_base_addr,
-						FIRMWARE_SIZE, fw_addr) ||
-				CONTAINS(fw_addr, FIRMWARE_SIZE,
-						device->hal_data->
-						device_base_addr) ||
-				CONTAINS((u32)device->hal_data->
-						register_base_addr,
-						reg_size, reg_addr) ||
-				CONTAINS(reg_addr, reg_size,
-						(u32)device->hal_data->
-						register_base_addr) ||
-				OVERLAPS((u32)device->hal_data->
-						register_base_addr,
-						reg_size, reg_addr, reg_size) ||
-				OVERLAPS(reg_addr, reg_size,
-						(u32)device->hal_data->
-						register_base_addr, reg_size) ||
-				OVERLAPS(device->hal_data->
-						device_base_addr,
-						FIRMWARE_SIZE, fw_addr,
-						FIRMWARE_SIZE) ||
-				OVERLAPS(fw_addr, FIRMWARE_SIZE,
-						device->hal_data->
-						device_base_addr,
-						FIRMWARE_SIZE))) {
-				return 0;
-			} else {
-				dprintk(VIDC_INFO, "Device not registered");
-				return -EINVAL;
-			}
-		}
-	} else {
-		dprintk(VIDC_INFO, "no device Registered");
-	}
-	return -EINVAL;
-}
-
-static void vidc_hal_core_work_handler(struct work_struct *work)
-{
-	struct hal_device *device = list_first_entry(
-		&hal_ctxt.dev_head, struct hal_device, list);
-
-	dprintk(VIDC_INFO, " GOT INTERRUPT () ");
-	if (!device->callback) {
-		dprintk(VIDC_ERR, "No interrupt callback function: %p\n",
-				device);
-		return;
-	}
-	vidc_hal_core_clear_interrupt(device);
-	vidc_hal_response_handler(device);
-	enable_irq(device->hal_data->irq);
-}
-static DECLARE_WORK(vidc_hal_work, vidc_hal_core_work_handler);
-
-static irqreturn_t vidc_hal_isr(int irq, void *dev)
-{
-	struct hal_device *device = dev;
-	dprintk(VIDC_INFO, "vidc_hal_isr() %d ", irq);
-	disable_irq_nosync(irq);
-	queue_work(device->vidc_workq, &vidc_hal_work);
-	dprintk(VIDC_INFO, "vidc_hal_isr() %d ", irq);
-	return IRQ_HANDLED;
-}
-
-void *vidc_hal_add_device(u32 device_id, u32 fw_base_addr, u32 reg_base,
-		u32 reg_size, u32 irq,
-		void (*callback) (enum command_response cmd, void *data))
-{
-	struct hal_device *hdevice = NULL;
-	struct hal_data *hal = NULL;
-	int rc = 0;
-
-	if (device_id || !reg_base || !reg_size ||
-			!irq || !callback) {
-		dprintk(VIDC_ERR, "Invalid Paramters");
-		return NULL;
-	} else {
-		dprintk(VIDC_INFO, "entered , device_id: %d", device_id);
-	}
-
-	if (vidc_hal_check_core_registered(hal_ctxt, fw_base_addr,
-						reg_base, reg_size, irq)) {
-		dprintk(VIDC_DBG, "HAL_DATA will be assigned now");
-		hal = (struct hal_data *)
-			kzalloc(sizeof(struct hal_data), GFP_KERNEL);
-		if (!hal) {
-			dprintk(VIDC_ERR, "Failed to alloc");
-			return NULL;
-		}
-		hal->irq = irq;
-		hal->device_base_addr = fw_base_addr;
-		hal->register_base_addr =
-			ioremap_nocache(reg_base, reg_size);
-		if (!hal->register_base_addr) {
-			dprintk(VIDC_ERR,
-				"could not map reg addr %d of size %d",
-				reg_base, reg_size);
-			goto err_map;
-		}
-		INIT_LIST_HEAD(&hal_ctxt.dev_head);
-	} else {
-		dprintk(VIDC_ERR, "Core present/Already added");
-		return NULL;
-	}
-
-	hdevice = (struct hal_device *)
-			kzalloc(sizeof(struct hal_device), GFP_KERNEL);
-	if (!hdevice) {
-		dprintk(VIDC_ERR, "failed to allocate new device");
-		goto err_map;
-	}
-
-	INIT_LIST_HEAD(&hdevice->list);
-	list_add_tail(&hdevice->list, &hal_ctxt.dev_head);
-	hal_ctxt.dev_count++;
-	hdevice->device_id = device_id;
-	hdevice->hal_data = hal;
-	hdevice->callback = callback;
-
-	hdevice->vidc_workq = create_singlethread_workqueue(
-		"msm_vidc_workerq");
-	if (!hdevice->vidc_workq) {
-		dprintk(VIDC_ERR, ": create workq failed\n");
-		goto error_createq;
-	}
-
-	rc = request_irq(irq, vidc_hal_isr, IRQF_TRIGGER_HIGH,
-			"msm_vidc", hdevice);
-	if (unlikely(rc)) {
-		dprintk(VIDC_ERR, "() :request_irq failed\n");
-		goto error_irq_fail;
-	}
-	disable_irq_nosync(irq);
-	return (void *) hdevice;
-error_irq_fail:
-	destroy_workqueue(hdevice->vidc_workq);
-error_createq:
-	hal_ctxt.dev_count--;
-	list_del(&hal_ctxt.dev_head);
-err_map:
-	kfree(hal);
-	return NULL;
-}
-
-void vidc_hal_delete_device(void *device)
-{
-	struct hal_device *close, *dev;
-
-	if (device) {
-		dev = (struct hal_device *) device;
-		list_for_each_entry(close, &hal_ctxt.dev_head, list) {
-			if (close->hal_data->irq == dev->hal_data->irq) {
-				hal_ctxt.dev_count--;
-				free_irq(dev->hal_data->irq, close);
-				list_del(&close->list);
-				destroy_workqueue(close->vidc_workq);
-				kfree(close->hal_data);
-				kfree(close);
-				break;
-			}
-		}
-
-	}
-}
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_hal.h b/drivers/media/video/msm_vidc/vidc_hfi.h
similarity index 85%
rename from drivers/media/video/msm_vidc/vidc_hal.h
rename to drivers/media/video/msm_vidc/vidc_hfi.h
index c8a7d43..6ff0921 100644
--- a/drivers/media/video/msm_vidc/vidc_hal.h
+++ b/drivers/media/video/msm_vidc/vidc_hfi.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
@@ -10,95 +10,11 @@
  * GNU General Public License for more details.
  *
  */
+#ifndef __H_VIDC_HFI_H__
+#define __H_VIDC_HFI_H__
 
-#ifndef __H_VIDC_HAL_H__
-#define __H_VIDC_HAL_H__
-
-#include <linux/spinlock.h>
-#include <linux/mutex.h>
-#include "vidc_hal_api.h"
-#include "msm_smem.h"
-#include "vidc_hal_helper.h"
-
-#define HFI_MASK_QHDR_TX_TYPE			0xFF000000
-#define HFI_MASK_QHDR_RX_TYPE			0x00FF0000
-#define HFI_MASK_QHDR_PRI_TYPE			0x0000FF00
-#define HFI_MASK_QHDR_Q_ID_TYPE			0x000000FF
-#define HFI_Q_ID_HOST_TO_CTRL_CMD_Q		0x00
-#define HFI_Q_ID_CTRL_TO_HOST_MSG_Q		0x01
-#define HFI_Q_ID_CTRL_TO_HOST_DEBUG_Q	0x02
-#define HFI_MASK_QHDR_STATUS			0x000000FF
-
-#define VIDC_MAX_UNCOMPRESSED_FMT_PLANES	3
-
-#define VIDC_IFACEQ_NUMQ					3
-#define VIDC_IFACEQ_CMDQ_IDX				0
-#define VIDC_IFACEQ_MSGQ_IDX				1
-#define VIDC_IFACEQ_DBGQ_IDX				2
-
-#define VIDC_IFACEQ_MAX_PKT_SIZE			1024
-#define VIDC_IFACEQ_MED_PKT_SIZE			768
-#define VIDC_IFACEQ_MIN_PKT_SIZE			8
-#define VIDC_IFACEQ_VAR_SMALL_PKT_SIZE		100
-#define VIDC_IFACEQ_VAR_LARGE_PKT_SIZE		512
-#define VIDC_IFACEQ_MAX_BUF_COUNT			50
-#define VIDC_IFACE_MAX_PARALLEL_CLNTS		16
-#define VIDC_IFACEQ_DFLT_QHDR				0x01010000
-
-struct hfi_queue_table_header {
-	u32 qtbl_version;
-	u32 qtbl_size;
-	u32 qtbl_qhdr0_offset;
-	u32 qtbl_qhdr_size;
-	u32 qtbl_num_q;
-	u32 qtbl_num_active_q;
-};
-
-struct hfi_queue_header {
-	u32 qhdr_status;
-	u32 qhdr_start_addr;
-	u32 qhdr_type;
-	u32 qhdr_q_size;
-	u32 qhdr_pkt_size;
-	u32 qhdr_pkt_drop_cnt;
-	u32 qhdr_rx_wm;
-	u32 qhdr_tx_wm;
-	u32 qhdr_rx_req;
-	u32 qhdr_tx_req;
-	u32 qhdr_rx_irq_status;
-	u32 qhdr_tx_irq_status;
-	u32 qhdr_read_idx;
-	u32 qhdr_write_idx;
-};
-
-#define VIDC_IFACEQ_TABLE_SIZE (sizeof(struct hfi_queue_table_header) \
-	+ sizeof(struct hfi_queue_header) * VIDC_IFACEQ_NUMQ)
-
-#define VIDC_IFACEQ_QUEUE_SIZE	(VIDC_IFACEQ_MAX_PKT_SIZE *  \
-	VIDC_IFACEQ_MAX_BUF_COUNT * VIDC_IFACE_MAX_PARALLEL_CLNTS)
-
-#define VIDC_IFACEQ_GET_QHDR_START_ADDR(ptr, i)     \
-	(void *)((((u32)ptr) + sizeof(struct hfi_queue_table_header)) + \
-		(i * sizeof(struct hfi_queue_header)))
-
-#define QDSS_SIZE 4096
-#define SFR_SIZE 4096
-
-#define UC_SIZE (VIDC_IFACEQ_TABLE_SIZE + \
-	(VIDC_IFACEQ_QUEUE_SIZE * VIDC_IFACEQ_NUMQ) + QDSS_SIZE + SFR_SIZE)
-
-enum vidc_hw_reg {
-	VIDC_HWREG_CTRL_STATUS =  0x1,
-	VIDC_HWREG_QTBL_INFO =  0x2,
-	VIDC_HWREG_QTBL_ADDR =  0x3,
-	VIDC_HWREG_CTRLR_RESET =  0x4,
-	VIDC_HWREG_IFACEQ_FWRXREQ =  0x5,
-	VIDC_HWREG_IFACEQ_FWTXREQ =  0x6,
-	VIDC_HWREG_VHI_SOFTINTEN =  0x7,
-	VIDC_HWREG_VHI_SOFTINTSTATUS =  0x8,
-	VIDC_HWREG_VHI_SOFTINTCLR =  0x9,
-	VIDC_HWREG_HVI_SOFTINTEN =  0xA,
-};
+#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)
@@ -140,11 +56,6 @@
 #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)
@@ -171,6 +82,12 @@
 #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;
@@ -436,6 +353,8 @@
 #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;
@@ -887,51 +806,11 @@
 	u32 flag;
 };
 
-struct vidc_mem_addr {
-	u8 *align_device_addr;
-	u8 *align_virtual_addr;
-	u32 mem_size;
-	struct msm_smem *mem_data;
-};
-
-struct vidc_iface_q_info {
-	void *q_hdr;
-	struct vidc_mem_addr q_array;
-};
-
-/* Internal data used in vidc_hal not exposed to msm_vidc*/
-
-struct hal_data {
-	u32 irq;
-	u32 device_base_addr;
-	u8 *register_base_addr;
-};
-
-struct hal_device {
-	struct list_head list;
-	struct list_head sess_head;
-	u32 intr_status;
-	u32 device_id;
-	spinlock_t read_lock;
-	spinlock_t write_lock;
-	void (*callback) (u32 response, void *callback);
-	struct vidc_mem_addr iface_q_table;
-	struct vidc_mem_addr qdss;
-	struct vidc_mem_addr sfr;
-	struct vidc_mem_addr mem_addr;
-	struct vidc_iface_q_info iface_queues[VIDC_IFACEQ_NUMQ];
-	struct smem_client *hal_client;
-	struct hal_data *hal_data;
-	struct workqueue_struct *vidc_workq;
-	int spur_count;
-	int reg_count;
-};
-
 struct hal_session {
 	struct list_head list;
 	u32 session_id;
 	u32 is_decoder;
-	struct hal_device *device;
+	void *device;
 };
 
 struct hal_device_data {
@@ -941,10 +820,7 @@
 
 extern struct hal_device_data hal_ctxt;
 
-int vidc_hal_iface_msgq_read(struct hal_device *device, void *pkt);
-int vidc_hal_iface_dbgq_read(struct hal_device *device, void *pkt);
-
-/* Interrupt Processing:*/
-void vidc_hal_response_handler(struct hal_device *device);
-
+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_hal_api.h b/drivers/media/video/msm_vidc/vidc_hfi_api.h
similarity index 89%
rename from drivers/media/video/msm_vidc/vidc_hal_api.h
rename to drivers/media/video/msm_vidc/vidc_hfi_api.h
index 3e70342..9366e0a 100644
--- a/drivers/media/video/msm_vidc/vidc_hal_api.h
+++ b/drivers/media/video/msm_vidc/vidc_hfi_api.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
@@ -11,10 +11,12 @@
  *
  */
 
-#ifndef __VIDC_HAL_API_H__
-#define __VIDC_HAL_API_H__
+#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 && \
@@ -979,48 +981,84 @@
 	struct hal_buffer_requirements buffer[HAL_BUFFER_MAX];
 };
 
-/* VIDC_HAL CORE API's */
-int vidc_hal_core_init(void *device, int domain);
-int vidc_hal_core_release(void *device);
-int vidc_hal_core_pc_prep(void *device);
-int vidc_hal_core_set_resource(void *device,
-	struct vidc_resource_hdr *resource_hdr, void *resource_value);
-int vidc_hal_core_release_resource(void *device,
-	struct vidc_resource_hdr *resource_hdr);
-int vidc_hal_core_ping(void *device);
+enum msm_vidc_hfi_type {
+	VIDC_HFI_VENUS,
+	VIDC_HFI_Q6,
+};
 
-/* VIDC_HAL SESSION API's */
-void *vidc_hal_session_init(void *device, u32 session_id,
-	enum hal_domain session_type, enum hal_video_codec codec_type);
-int vidc_hal_session_end(void *session);
-int vidc_hal_session_abort(void *session);
-int vidc_hal_session_set_buffers(void *sess,
-	struct vidc_buffer_addr_info *buffer_info);
-int vidc_hal_session_release_buffers(void *sess,
-	struct vidc_buffer_addr_info *buffer_info);
-int vidc_hal_session_load_res(void *sess);
-int vidc_hal_session_release_res(void *sess);
-int vidc_hal_session_start(void *sess);
-int vidc_hal_session_stop(void *sess);
-int vidc_hal_session_suspend(void *sess);
-int vidc_hal_session_resume(void *sess);
-int vidc_hal_session_etb(void *sess,
-	struct vidc_frame_data *input_frame);
-int vidc_hal_session_ftb(void *sess,
-	struct vidc_frame_data *output_frame);
-int vidc_hal_session_parse_seq_hdr(void *sess,
-	struct vidc_seq_hdr *seq_hdr);
-int vidc_hal_session_get_seq_hdr(void *sess,
-	struct vidc_seq_hdr *seq_hdr);
-int vidc_hal_session_get_buf_req(void *sess);
-int vidc_hal_session_flush(void *sess, enum hal_flush flush_mode);
-int vidc_hal_session_set_property(void *sess, enum hal_property ptype,
-								  void *pdata);
-int vidc_hal_session_get_property(void *sess, enum hal_property ptype,
-								  void *pdata);
-void *vidc_hal_add_device(u32 device_id, u32 base_addr,
-	u32 reg_base, u32 reg_size, u32 irq,
-	void (*callback) (enum command_response cmd, void *data));
-void vidc_hal_delete_device(void *device);
+enum mem_type {
+	DDR_MEM = 0x1,
+	OCMEM_MEM = 0x2,
+};
 
-#endif /*__VIDC_HAL_API_H__ */
+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_vidc/vidc_hal_helper.h b/drivers/media/video/msm_vidc/vidc_hfi_helper.h
similarity index 99%
rename from drivers/media/video/msm_vidc/vidc_hal_helper.h
rename to drivers/media/video/msm_vidc/vidc_hfi_helper.h
index 9f805d7..7531811 100644
--- a/drivers/media/video/msm_vidc/vidc_hal_helper.h
+++ b/drivers/media/video/msm_vidc/vidc_hfi_helper.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+/* 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
@@ -11,8 +11,8 @@
  *
  */
 
-#ifndef __H_VIDC_HAL_HELPER_H__
-#define __H_VIDC_HAL_HELPER_H__
+#ifndef __H_VIDC_HFI_HELPER_H__
+#define __H_VIDC_HFI_HELPER_H__
 
 #define HFI_COMMON_BASE				(0)
 #define HFI_OX_BASE					(0x01000000)
diff --git a/drivers/media/video/msm_vidc/vidc_hal_io.h b/drivers/media/video/msm_vidc/vidc_hfi_io.h
similarity index 98%
rename from drivers/media/video/msm_vidc/vidc_hal_io.h
rename to drivers/media/video/msm_vidc/vidc_hfi_io.h
index 9888adb..2bc8e6a 100644
--- a/drivers/media/video/msm_vidc/vidc_hal_io.h
+++ b/drivers/media/video/msm_vidc/vidc_hfi_io.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+/* 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
@@ -11,8 +11,8 @@
  *
  */
 
-#ifndef __VIDCHALIO_H__
-#define __VIDCHALIO_H__
+#ifndef __VIDC_HFI_IO_H__
+#define __VIDC_HFI_IO_H__
 
 #include <linux/io.h>
 
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/mfd/Kconfig b/drivers/mfd/Kconfig
index 464f19f..ff0fc74 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -1054,6 +1054,16 @@
 	  The WCD9320 codec support either I2C/I2S or Slimbus for
 	  control and data exchnage with master processor.
 
+config WCD9306_CODEC
+	tristate "WCD9306 Codec"
+	select SLIMBUS
+	select MFD_CORE
+	help
+	  Enables the WCD9xxx codec core driver. The core driver provides
+	  read/write capability to registers which are part of the
+	  WCD9306 core and gives the ability to use the WCD9306 codec.
+	  The WCD9306 codec supports either I2C/I2S or Slimbus for
+	  control and data exchnage with master processor.
 
 config MFD_RC5T583
 	bool "Ricoh RC5T583 Power Management system device"
diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
index 07552c8..ce65e3f 100644
--- a/drivers/mfd/Makefile
+++ b/drivers/mfd/Makefile
@@ -81,6 +81,7 @@
 obj-$(CONFIG_WCD9310_CODEC)       += wcd9xxx-core.o wcd9xxx-irq.o wcd9xxx-slimslave.o
 obj-$(CONFIG_WCD9304_CODEC)       += wcd9xxx-core.o wcd9xxx-irq.o wcd9xxx-slimslave.o
 obj-$(CONFIG_WCD9320_CODEC)       += wcd9xxx-core.o wcd9xxx-irq.o wcd9xxx-slimslave.o
+obj-$(CONFIG_WCD9306_CODEC)       += wcd9xxx-core.o wcd9xxx-irq.o wcd9xxx-slimslave.o
 
 
 ifeq ($(CONFIG_SA1100_ASSABET),y)
diff --git a/drivers/mfd/pm8038-core.c b/drivers/mfd/pm8038-core.c
index 4996279..479fc02c 100644
--- a/drivers/mfd/pm8038-core.c
+++ b/drivers/mfd/pm8038-core.c
@@ -711,6 +711,8 @@
 	}
 
 	if (pdata->ccadc_pdata) {
+		pdata->ccadc_pdata->ccadc_cdata.batt_temp_channel
+						= CHANNEL_BATT_THERM;
 		ccadc_cell.platform_data = pdata->ccadc_pdata;
 		ccadc_cell.pdata_size =
 				sizeof(struct pm8xxx_ccadc_platform_data);
diff --git a/drivers/mfd/pm8921-core.c b/drivers/mfd/pm8921-core.c
index 7d63129..685bb32 100644
--- a/drivers/mfd/pm8921-core.c
+++ b/drivers/mfd/pm8921-core.c
@@ -804,6 +804,8 @@
 	}
 
 	if (pdata->ccadc_pdata) {
+		pdata->ccadc_pdata->ccadc_cdata.batt_temp_channel
+						= CHANNEL_BATT_THERM;
 		ccadc_cell.platform_data = pdata->ccadc_pdata;
 		ccadc_cell.pdata_size =
 				sizeof(struct pm8xxx_ccadc_platform_data);
diff --git a/drivers/mfd/wcd9xxx-core.c b/drivers/mfd/wcd9xxx-core.c
index d43b399..bc129da 100644
--- a/drivers/mfd/wcd9xxx-core.c
+++ b/drivers/mfd/wcd9xxx-core.c
@@ -46,6 +46,11 @@
 #define WCD9XXX_I2C_DIGITAL_1	2
 #define WCD9XXX_I2C_DIGITAL_2	3
 
+/* Number of return values needs to be checked for each
+ * registration of Slimbus of I2C bus for each codec
+ */
+#define NUM_WCD9XXX_REG_RET	8
+
 struct wcd9xxx_i2c {
 	struct i2c_client *client;
 	struct i2c_msg xfer_msg[2];
@@ -58,6 +63,11 @@
 	"cdc-vdd-a-1p2v", "cdc-vddcx-1", "cdc-vddcx-2",
 };
 
+static char *tapan_supplies[] = {
+	"cdc-vdd-buck", "cdc-vdd-h", "cdc-vdd-px",
+	"cdc-vdd-a-1p2v", "cdc-vdd-cx"
+};
+
 static int wcd9xxx_dt_parse_vreg_info(struct device *dev,
 	struct wcd9xxx_regulator *vreg, const char *vreg_name);
 static int wcd9xxx_dt_parse_micbias_info(struct device *dev,
@@ -275,6 +285,12 @@
 	},
 };
 
+static struct mfd_cell tapan_devs[] = {
+	{
+		.name = "tapan_codec",
+	},
+};
+
 static struct wcd9xx_codec_type {
 	u8 byte[4];
 	struct mfd_cell *dev;
@@ -287,6 +303,8 @@
 	 TABLA_NUM_IRQS},
 	{{0x0, 0x0, 0x2, 0x1}, taiko_devs, ARRAY_SIZE(taiko_devs),
 	 TAIKO_NUM_IRQS},
+	{{0x0, 0x0, 0x3, 0x1}, tapan_devs, ARRAY_SIZE(tapan_devs),
+	 TAPAN_NUM_IRQS},
 	{{0x0, 0x0, 0x0, 0x1}, sitar_devs, ARRAY_SIZE(sitar_devs),
 	 SITAR_NUM_IRQS},
 	{{0x1, 0x0, 0x1, 0x1}, sitar_devs, ARRAY_SIZE(sitar_devs),
@@ -987,92 +1005,54 @@
 	return 0;
 }
 
+static int wcd9xxx_read_of_property_u32(struct device *dev,
+	const char *name, u32 *val)
+{
+	int ret = 0;
+	ret = of_property_read_u32(dev->of_node, name, val);
+	if (ret)
+		dev_err(dev, "Looking up %s property in node %s failed",
+				name, dev->of_node->full_name);
+	return ret;
+}
+
 static int wcd9xxx_dt_parse_micbias_info(struct device *dev,
 	struct wcd9xxx_micbias_setting *micbias)
 {
-	int ret = 0;
-	char prop_name[CODEC_DT_MAX_PROP_SIZE];
 	u32 prop_val;
 
-	snprintf(prop_name, CODEC_DT_MAX_PROP_SIZE,
-			"qcom,cdc-micbias-ldoh-v");
-	ret = of_property_read_u32(dev->of_node, prop_name, &prop_val);
-	if (ret) {
-		dev_err(dev, "Looking up %s property in node %s failed",
-			prop_name, dev->of_node->full_name);
-		return -ENODEV;
-	}
-	micbias->ldoh_v  =  (u8)prop_val;
+	if (!(wcd9xxx_read_of_property_u32(dev, "qcom,cdc-micbias-ldoh-v",
+				&prop_val)))
+		micbias->ldoh_v  =  (u8)prop_val;
 
-	snprintf(prop_name, CODEC_DT_MAX_PROP_SIZE,
-			"qcom,cdc-micbias-cfilt1-mv");
-	ret = of_property_read_u32(dev->of_node, prop_name,
-				   &micbias->cfilt1_mv);
-	if (ret) {
-		dev_err(dev, "Looking up %s property in node %s failed",
-			prop_name, dev->of_node->full_name);
-		return -ENODEV;
-	}
+	wcd9xxx_read_of_property_u32(dev, "qcom,cdc-micbias-cfilt1-mv",
+				&micbias->cfilt1_mv);
 
-	snprintf(prop_name, CODEC_DT_MAX_PROP_SIZE,
-			"qcom,cdc-micbias-cfilt2-mv");
-	ret = of_property_read_u32(dev->of_node, prop_name,
-				   &micbias->cfilt2_mv);
-	if (ret) {
-		dev_err(dev, "Looking up %s property in node %s failed",
-			prop_name, dev->of_node->full_name);
-		return -ENODEV;
-	}
+	wcd9xxx_read_of_property_u32(dev, "qcom,cdc-micbias-cfilt2-mv",
+				&micbias->cfilt2_mv);
 
-	snprintf(prop_name, CODEC_DT_MAX_PROP_SIZE,
-			"qcom,cdc-micbias-cfilt3-mv");
-	ret = of_property_read_u32(dev->of_node, prop_name,
-				   &micbias->cfilt3_mv);
-	if (ret) {
-		dev_err(dev, "Looking up %s property in node %s failed",
-			prop_name, dev->of_node->full_name);
-		return -ENODEV;
-	}
+	wcd9xxx_read_of_property_u32(dev, "qcom,cdc-micbias-cfilt3-mv",
+				&micbias->cfilt3_mv);
 
-	snprintf(prop_name, CODEC_DT_MAX_PROP_SIZE,
-			"qcom,cdc-micbias1-cfilt-sel");
-	ret = of_property_read_u32(dev->of_node, prop_name, &prop_val);
-	if (ret) {
-		dev_err(dev, "Looking up %s property in node %s failed",
-			prop_name, dev->of_node->full_name);
-		return -ENODEV;
-	}
-	micbias->bias1_cfilt_sel = (u8)prop_val;
+	/* Read micbias values for codec. Does not matter even if a few
+	 * micbias values are not defined in the Device Tree. Codec will
+	 * anyway not use those values
+	 */
+	if (!(wcd9xxx_read_of_property_u32(dev, "qcom,cdc-micbias1-cfilt-sel",
+				&prop_val)))
+		micbias->bias1_cfilt_sel = (u8)prop_val;
 
-	snprintf(prop_name, CODEC_DT_MAX_PROP_SIZE,
-			"qcom,cdc-micbias2-cfilt-sel");
-	ret = of_property_read_u32(dev->of_node, prop_name, &prop_val);
-	if (ret) {
-		dev_err(dev, "Looking up %s property in node %s failed",
-			prop_name, dev->of_node->full_name);
-		return -ENODEV;
-	}
-	micbias->bias2_cfilt_sel = (u8)prop_val;
+	if (!(wcd9xxx_read_of_property_u32(dev, "qcom,cdc-micbias2-cfilt-sel",
+				&prop_val)))
+		micbias->bias2_cfilt_sel = (u8)prop_val;
 
-	snprintf(prop_name, CODEC_DT_MAX_PROP_SIZE,
-			"qcom,cdc-micbias3-cfilt-sel");
-	ret = of_property_read_u32(dev->of_node, prop_name, &prop_val);
-	if (ret) {
-		dev_err(dev, "Looking up %s property in node %s failed",
-			prop_name, dev->of_node->full_name);
-		return -ENODEV;
-	}
-	micbias->bias3_cfilt_sel = (u8)prop_val;
+	if (!(wcd9xxx_read_of_property_u32(dev, "qcom,cdc-micbias3-cfilt-sel",
+				&prop_val)))
+		micbias->bias3_cfilt_sel = (u8)prop_val;
 
-	snprintf(prop_name, CODEC_DT_MAX_PROP_SIZE,
-			"qcom,cdc-micbias4-cfilt-sel");
-	ret = of_property_read_u32(dev->of_node, prop_name, &prop_val);
-	if (ret) {
-		dev_err(dev, "Looking up %s property in node %s failed",
-			prop_name, dev->of_node->full_name);
-		return -ENODEV;
-	}
-	micbias->bias4_cfilt_sel = (u8)prop_val;
+	if (!(wcd9xxx_read_of_property_u32(dev, "qcom,cdc-micbias4-cfilt-sel",
+				&prop_val)))
+		micbias->bias4_cfilt_sel = (u8)prop_val;
 
 	/* micbias external cap */
 	micbias->bias1_cap_mode =
@@ -1153,6 +1133,9 @@
 		(!strcmp(dev_name(dev), WCD9XXX_I2C_GSBI_SLAVE_ID))) {
 		codec_supplies = taiko_supplies;
 		num_of_supplies = ARRAY_SIZE(taiko_supplies);
+	} else if (!strcmp(dev_name(dev), "tapan-slim-pgd")) {
+		codec_supplies = tapan_supplies;
+		num_of_supplies = ARRAY_SIZE(tapan_supplies);
 	} else {
 		dev_err(dev, "%s unsupported device %s\n",
 				__func__, dev_name(dev));
@@ -1552,6 +1535,23 @@
 	.suspend = wcd9xxx_slim_suspend,
 };
 
+static const struct slim_device_id tapan_slimtest_id[] = {
+	{"tapan-slim-pgd", 0},
+	{}
+};
+
+static struct slim_driver tapan_slim_driver = {
+	.driver = {
+		.name = "tapan-slim",
+		.owner = THIS_MODULE,
+	},
+	.probe = wcd9xxx_slim_probe,
+	.remove = wcd9xxx_slim_remove,
+	.id_table = tapan_slimtest_id,
+	.resume = wcd9xxx_slim_resume,
+	.suspend = wcd9xxx_slim_suspend,
+};
+
 static struct i2c_device_id wcd9xxx_id_table[] = {
 	{"wcd9xxx-i2c", WCD9XXX_I2C_TOP_LEVEL},
 	{"wcd9xxx-i2c", WCD9XXX_I2C_ANALOG},
@@ -1596,39 +1596,48 @@
 
 static int __init wcd9xxx_init(void)
 {
-	int ret1, ret2, ret3, ret4, ret5, ret6, ret7;
+	int ret[NUM_WCD9XXX_REG_RET];
+	int i = 0;
 
 	wcd9xxx_intf = WCD9XXX_INTERFACE_TYPE_PROBING;
 
-	ret1 = slim_driver_register(&tabla_slim_driver);
-	if (ret1 != 0)
-		pr_err("Failed to register tabla SB driver: %d\n", ret1);
+	ret[0] = slim_driver_register(&tabla_slim_driver);
+	if (ret[0])
+		pr_err("Failed to register tabla SB driver: %d\n", ret[0]);
 
-	ret2 = slim_driver_register(&tabla2x_slim_driver);
-	if (ret2 != 0)
-		pr_err("Failed to register tabla2x SB driver: %d\n", ret2);
+	ret[1] = slim_driver_register(&tabla2x_slim_driver);
+	if (ret[1])
+		pr_err("Failed to register tabla2x SB driver: %d\n", ret[1]);
 
-	ret3 = i2c_add_driver(&tabla_i2c_driver);
-	if (ret3 != 0)
-		pr_err("failed to add the tabla2x I2C driver\n");
+	ret[2] = i2c_add_driver(&tabla_i2c_driver);
+	if (ret[2])
+		pr_err("failed to add the tabla2x I2C driver: %d\n", ret[2]);
 
-	ret4 = slim_driver_register(&sitar_slim_driver);
-	if (ret4 != 0)
-		pr_err("Failed to register sitar SB driver: %d\n", ret4);
+	ret[3] = slim_driver_register(&sitar_slim_driver);
+	if (ret[3])
+		pr_err("Failed to register sitar SB driver: %d\n", ret[3]);
 
-	ret5 = slim_driver_register(&sitar1p1_slim_driver);
-	if (ret5 != 0)
-		pr_err("Failed to register sitar SB driver: %d\n", ret5);
+	ret[4] = slim_driver_register(&sitar1p1_slim_driver);
+	if (ret[4])
+		pr_err("Failed to register sitar SB driver: %d\n", ret[4]);
 
-	ret6 = slim_driver_register(&taiko_slim_driver);
-	if (ret6 != 0)
-		pr_err("Failed to register taiko SB driver: %d\n", ret6);
+	ret[5] = slim_driver_register(&taiko_slim_driver);
+	if (ret[5])
+		pr_err("Failed to register taiko SB driver: %d\n", ret[5]);
 
-	ret7 = i2c_add_driver(&wcd9xxx_i2c_driver);
-	if (ret7 != 0)
-		pr_err("failed to add the wcd9xxx I2C driver\n");
+	ret[6] = i2c_add_driver(&wcd9xxx_i2c_driver);
+	if (ret[6])
+		pr_err("failed to add the wcd9xxx I2C driver: %d\n", ret[6]);
 
-	return (ret1 && ret2 && ret3 && ret4 && ret5 && ret6 && ret7) ? -1 : 0;
+	ret[7] = slim_driver_register(&tapan_slim_driver);
+	if (ret[7])
+		pr_err("Failed to register tapan SB driver: %d\n", ret[7]);
+
+	for (i = 0; i < NUM_WCD9XXX_REG_RET; i++) {
+		if (ret[i])
+			return ret[i];
+	}
+	return 0;
 }
 module_init(wcd9xxx_init);
 
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 eebaab9..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;
 		}
 	}
@@ -1005,7 +1020,7 @@
 			TSPP_CONFIG_PS_CONT_ERR_MASK);
 	TSPP_CONFIG_SET_PACKET_LENGTH(val, TSPP_PACKET_LENGTH);
 	writel_relaxed(val, pdev->base + TSPP_CONFIG);
-	writel_relaxed(0x000fffff, pdev->base + TSPP_IRQ_MASK);
+	writel_relaxed(0x0007ffff, pdev->base + TSPP_IRQ_MASK);
 	writel_relaxed(0x000fffff, pdev->base + TSPP_IRQ_CLEAR);
 	writel_relaxed(0, pdev->base + TSPP_RST);
 	wmb();
@@ -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 b748228..0f9ee46d 100644
--- a/drivers/mmc/card/block.c
+++ b/drivers/mmc/card/block.c
@@ -121,7 +121,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;
 };
 
@@ -332,47 +333,113 @@
 }
 
 static ssize_t
-min_sectors_to_check_bkops_status_show(struct device *dev,
+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));
-	unsigned int min_sectors_to_check_bkops_status;
 	struct mmc_card *card = md->queue.card;
 	int ret;
 
 	if (!card)
 		ret = -EINVAL;
-	else {
-	    min_sectors_to_check_bkops_status =
-		    card->bkops_info.min_sectors_to_queue_delayed_work;
+	else
 	    ret = snprintf(buf, PAGE_SIZE, "%d\n",
-			   min_sectors_to_check_bkops_status);
-	}
+		card->bkops_info.size_percentage_to_queue_delayed_work);
 
 	mmc_blk_put(md);
 	return ret;
 }
 
 static ssize_t
-min_sectors_to_check_bkops_status_store(struct device *dev,
+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)
-		return -EINVAL;
+	if (!card) {
+		ret = -EINVAL;
+		goto exit;
+	}
 
 	sscanf(buf, "%d", &value);
-	if (value >= 0)
-		card->bkops_info.min_sectors_to_queue_delayed_work = 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);
@@ -1702,6 +1769,15 @@
 			break;
 		}
 
+		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)
@@ -1973,8 +2049,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:
 			/*
@@ -2047,6 +2121,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) {
@@ -2102,6 +2181,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)) {
@@ -2110,9 +2191,12 @@
 	}
 #endif
 
-	if (req && !mq->mqrq_prev->req)
+	if (req && !mq->mqrq_prev->req) {
 		/* claim host only for the first request */
 		mmc_claim_host(card->host);
+		if (card->ext_csd.bkops_en)
+			mmc_stop_bkops(card);
+	}
 
 	ret = mmc_blk_part_switch(card, md);
 	if (ret) {
@@ -2146,13 +2230,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;
 }
 
@@ -2171,6 +2263,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)
@@ -2250,6 +2344,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) &&
@@ -2442,22 +2540,32 @@
 	if (ret)
 		goto num_wr_reqs_to_start_packing_fail;
 
-	md->min_sectors_to_check_bkops_status.show =
-		min_sectors_to_check_bkops_status_show;
-	md->min_sectors_to_check_bkops_status.store =
-		min_sectors_to_check_bkops_status_store;
-	sysfs_attr_init(&md->min_sectors_to_check_bkops_status.attr);
-	md->min_sectors_to_check_bkops_status.attr.name =
-		"min_sectors_to_check_bkops_status";
-	md->min_sectors_to_check_bkops_status.attr.mode = S_IRUGO | S_IWUSR;
+	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->min_sectors_to_check_bkops_status);
+				 &md->bkops_check_threshold);
 	if (ret)
-		goto min_sectors_to_check_bkops_status_fails;
+		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;
 
-min_sectors_to_check_bkops_status_fails:
+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:
diff --git a/drivers/mmc/card/mmc_block_test.c b/drivers/mmc/card/mmc_block_test.c
index 08c75a0..4a21fd4 100644
--- a/drivers/mmc/card/mmc_block_test.c
+++ b/drivers/mmc/card/mmc_block_test.c
@@ -1244,9 +1244,9 @@
 		break;
 	case TEST_PACKING_NOT_EXP_LESS_THAN_TRIGGER_REQUESTS:
 	case TEST_PACKING_NOT_EXP_TRIGGER_REQUESTS:
-		mbtd->exp_packed_stats.packing_events[num_packed_reqs] = 1;
 		break;
 	default:
+		BUG_ON(num_packed_reqs < 0);
 		mbtd->exp_packed_stats.pack_stop_reason[EMPTY_QUEUE] = 1;
 		mbtd->exp_packed_stats.packing_events[num_packed_reqs] = 1;
 	}
diff --git a/drivers/mmc/card/queue.c b/drivers/mmc/card/queue.c
index 7b80dfb..9babeab 100644
--- a/drivers/mmc/card/queue.c
+++ b/drivers/mmc/card/queue.c
@@ -78,28 +78,9 @@
 		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) {
-			/*
-			 * If this is the first request, BKOPs might be in
-			 * progress and needs to be stopped before issuing the
-			 * request
-			 */
-			if (card->ext_csd.bkops_en &&
-			    card->bkops_info.started_delayed_bkops) {
-				card->bkops_info.started_delayed_bkops = false;
-				mmc_stop_bkops(card);
-			}
-
 			set_current_state(TASK_RUNNING);
 			mq->issue_fn(mq, req);
 			if (mq->flags & MMC_QUEUE_NEW_REQUEST) {
@@ -108,6 +89,16 @@
 					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);
@@ -118,13 +109,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);
 
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 1ea580e..47a21cd 100644
--- a/drivers/mmc/core/core.c
+++ b/drivers/mmc/core/core.c
@@ -51,7 +51,7 @@
  * Background operations can take a long time, depending on the housekeeping
  * operations the card has to perform.
  */
-#define MMC_BKOPS_MAX_TIMEOUT	(4 * 60 * 1000) /* max time to wait in ms */
+#define MMC_BKOPS_MAX_TIMEOUT	(30 * 1000) /* max time to wait in ms */
 
 static struct workqueue_struct *workqueue;
 
@@ -364,15 +364,12 @@
 	pr_debug("%s: %s: queueing delayed_bkops_work\n",
 		 mmc_hostname(card->host), __func__);
 
-	card->bkops_info.sectors_changed = 0;
-
 	/*
 	 * cancel_delayed_bkops_work will prevent a race condition between
 	 * fetching a request by the mmcqd and the delayed work, in case
 	 * 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));
@@ -392,8 +389,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)
@@ -414,42 +409,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);
+			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);
@@ -457,19 +455,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);
@@ -523,7 +515,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;
 		}
 
@@ -536,8 +528,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:
@@ -564,6 +560,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
@@ -627,7 +624,8 @@
  * 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;
@@ -669,8 +667,10 @@
 			context_info->is_new_req = false;
 			if (stats->enabled)
 				stats->new_request_flag++;
-			err = MMC_BLK_NEW_REQUEST;
-			break; /* return err */
+			if (!next_req) {
+				err = MMC_BLK_NEW_REQUEST;
+				break; /* return err */
+			}
 		}
 	} /* while */
 	return err;
@@ -685,6 +685,24 @@
 		wait_for_completion_io(&mrq->completion);
 
 		cmd = mrq->cmd;
+
+		/*
+		 * If host has timed out waiting for the blocking BKOPs
+		 * to complete, card might be still in programming state
+		 * so let's try to bring the card out of programming state.
+		 */
+		if (cmd->bkops_busy && cmd->error == -ETIMEDOUT) {
+			if (!mmc_interrupt_hpi(host->card)) {
+				pr_warning("%s: %s: Interrupted blocking bkops\n",
+					   mmc_hostname(host), __func__);
+				cmd->error = 0;
+				break;
+			} else {
+				pr_err("%s: %s: Failed to interrupt blocking bkops\n",
+				       mmc_hostname(host), __func__);
+			}
+		}
+
 		if (!cmd->error || !cmd->retries ||
 		    mmc_card_removed(host->card))
 			break;
@@ -765,13 +783,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;
 			/*
@@ -923,7 +937,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)
 {
@@ -931,8 +947,6 @@
 
 	BUG_ON(!card);
 
-	mmc_claim_host(card->host);
-
 	/*
 	 * Notify the delayed work to be cancelled, in case it was already
 	 * removed from the queue, but was not started yet
@@ -957,7 +971,6 @@
 	MMC_UPDATE_BKOPS_STATS_HPI(card->bkops_info.bkops_stats);
 
 out:
-	mmc_release_host(card->host);
 	return err;
 }
 EXPORT_SYMBOL(mmc_stop_bkops);
@@ -3051,6 +3064,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)
 {
@@ -3062,9 +3076,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;
@@ -3082,7 +3093,6 @@
 				card->ext_csd.cache_ctrl = enable;
 		}
 	}
-	mmc_release_host(host);
 
 	return err;
 }
@@ -3104,9 +3114,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) {
@@ -3164,7 +3171,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)))
@@ -3238,7 +3244,9 @@
 	case PM_HIBERNATION_PREPARE:
 	case PM_SUSPEND_PREPARE:
 		if (host->card && mmc_card_mmc(host->card)) {
+			mmc_claim_host(host);
 			err = mmc_stop_bkops(host->card);
+			mmc_release_host(host);
 			if (err) {
 				pr_err("%s: didn't stop bkops\n",
 					mmc_hostname(host));
@@ -3305,6 +3313,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 9642a06..d91bc31 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);
 
@@ -812,7 +819,7 @@
 				&mmc_dbg_new_req_stats_fops))
 		goto err;
 
-	if (mmc_card_mmc(card) && (card->ext_csd.rev >= 6) &&
+	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,
 					 &mmc_dbg_bkops_stats_fops))
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 c1a6b28..ec30cad 100644
--- a/drivers/mmc/core/mmc.c
+++ b/drivers/mmc/core/mmc.c
@@ -1402,20 +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);
-
-			card->bkops_info.min_sectors_to_queue_delayed_work =
-				BKOPS_MIN_SECTORS_TO_QUEUE_DELAYED_WORK;
+			if (card->bkops_info.host_delay_ms)
+				card->bkops_info.delay_ms =
+					card->bkops_info.host_delay_ms;
 		}
 	}
 
@@ -1533,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))
@@ -1540,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 4f46ed1..f8c9720 100644
--- a/drivers/mmc/core/mmc_ops.c
+++ b/drivers/mmc/core/mmc_ops.c
@@ -376,11 +376,13 @@
  *	@timeout_ms: timeout (ms) for operation performed by register write,
  *                   timeout of zero implies maximum possible timeout
  *	@use_busy_signal: use the busy signal as response type
+ *	@bkops_busy: set this to indicate that we are starting blocking bkops
  *
  *	Modifies the EXT_CSD register for selected card.
  */
 int __mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value,
-	       unsigned int timeout_ms, bool use_busy_signal)
+		 unsigned int timeout_ms, bool use_busy_signal,
+		 bool bkops_busy)
 {
 	int err;
 	struct mmc_command cmd = {0};
@@ -402,6 +404,7 @@
 
 
 	cmd.cmd_timeout_ms = timeout_ms;
+	cmd.bkops_busy = bkops_busy;
 
 	err = mmc_wait_for_cmd(card->host, &cmd, MMC_CMD_RETRIES);
 	if (err)
@@ -440,7 +443,7 @@
 int mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value,
 		unsigned int timeout_ms)
 {
-	return __mmc_switch(card, set, index, value, timeout_ms, true);
+	return __mmc_switch(card, set, index, value, timeout_ms, true, false);
 }
 EXPORT_SYMBOL_GPL(mmc_switch);
 
diff --git a/drivers/mmc/host/msm_sdcc.c b/drivers/mmc/host/msm_sdcc.c
index e8f3d38..91720ee 100644
--- a/drivers/mmc/host/msm_sdcc.c
+++ b/drivers/mmc/host/msm_sdcc.c
@@ -163,6 +163,10 @@
 static int msmsdcc_dt_get_array(struct device *dev, const char *prop_name,
 		u32 **out_array, int *len, int size);
 static int msmsdcc_execute_tuning(struct mmc_host *mmc, u32 opcode);
+static bool msmsdcc_is_wait_for_auto_prog_done(struct msmsdcc_host *host,
+					       struct mmc_request *mrq);
+static bool msmsdcc_is_wait_for_prog_done(struct msmsdcc_host *host,
+					  struct mmc_request *mrq);
 
 static inline unsigned short msmsdcc_get_nr_sg(struct msmsdcc_host *host)
 {
@@ -232,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) {
@@ -272,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;
 }
 
@@ -440,18 +444,23 @@
 {
 	struct mmc_request *mrq = host->curr.mrq;
 
-	if (!mrq || !mrq->cmd || (!mrq->data && !host->pending_dpsm_reset))
-			goto out;
+	if (!mrq || !mrq->cmd || !mrq->data)
+		goto out;
 
 	/*
-	 * For CMD24, if auto prog done is not supported defer
-	 * dpsm reset until prog done is received. Otherwise,
-	 * we poll here unnecessarily as TXACTIVE will not be
-	 * deasserted until DAT0 goes high.
+	 * If we have not waited for the prog done for write transfer then
+	 * perform the DPSM reset without polling for TXACTIVE.
+	 * Otherwise, we poll here unnecessarily as TXACTIVE will not be
+	 * deasserted until DAT0 (Busy line) goes high.
 	 */
-	if ((mrq->cmd->opcode == MMC_WRITE_BLOCK) && !is_auto_prog_done(host)) {
-		host->pending_dpsm_reset = true;
-		goto out;
+	if (mrq->data->flags & MMC_DATA_WRITE) {
+		if (!msmsdcc_is_wait_for_prog_done(host, mrq)) {
+			if (is_wait_for_tx_rx_active(host) &&
+			    !is_auto_prog_done(host))
+				pr_warning("%s: %s: AUTO_PROG_DONE capability is must\n",
+					   mmc_hostname(host->mmc), __func__);
+			goto no_polling;
+		}
 	}
 
 	/* Make sure h/w (TX/RX) is inactive before resetting DPSM */
@@ -473,15 +482,14 @@
 					& MCI_TXACTIVE ? "TX" : "RX");
 				msmsdcc_dump_sdcc_state(host);
 				msmsdcc_reset_and_restore(host);
-				host->pending_dpsm_reset = false;
 				goto out;
 			}
 		}
 	}
 
+no_polling:
 	writel_relaxed(0, host->base + MMCIDATACTRL);
 	msmsdcc_sync_reg_wr(host); /* Allow the DPSM to be reset */
-	host->pending_dpsm_reset = false;
 out:
 	return;
 }
@@ -1240,13 +1248,10 @@
 				MCI_DLL_CONFIG) & ~MCI_CDR_EN),
 				host->base + MCI_DLL_CONFIG);
 
-	if (((cmd->flags & MMC_RSP_R1B) == MMC_RSP_R1B) ||
-			(cmd->opcode == MMC_SEND_STATUS &&
-			 !(cmd->flags & MMC_CMD_ADTC))) {
+	if ((cmd->flags & MMC_RSP_R1B) == MMC_RSP_R1B) {
 		*c |= MCI_CPSM_PROGENA;
 		host->prog_enable = 1;
 	}
-
 	if (cmd == cmd->mrq->stop)
 		*c |= MCI_CSPM_MCIABORT;
 
@@ -2139,6 +2144,43 @@
 	}
 }
 
+/*
+ * This function returns true if AUTO_PROG_DONE feature of host is
+ * applicable for current request, returns "false" otherwise.
+ *
+ * NOTE: Caller should call this function only for data write operations.
+ */
+static bool msmsdcc_is_wait_for_auto_prog_done(struct msmsdcc_host *host,
+					       struct mmc_request *mrq)
+{
+	/*
+	 * Auto-prog done will be enabled for following cases:
+	 * mrq->sbc	|	mrq->stop
+	 * _____________|________________
+	 *	True	|	Don't care
+	 *	False	|	False (CMD24, ACMD25 use case)
+	 */
+	if (is_auto_prog_done(host) && (mrq->sbc || !mrq->stop))
+		return true;
+
+	return false;
+}
+
+/*
+ * This function returns true if controller can wait for prog done
+ * for current request, returns "false" otherwise.
+ *
+ * NOTE: Caller should call this function only for data write operations.
+ */
+static bool msmsdcc_is_wait_for_prog_done(struct msmsdcc_host *host,
+					  struct mmc_request *mrq)
+{
+	if (msmsdcc_is_wait_for_auto_prog_done(host, mrq) || mrq->stop)
+		return true;
+
+	return false;
+}
+
 static void
 msmsdcc_request(struct mmc_host *mmc, struct mmc_request *mrq)
 {
@@ -2235,16 +2277,8 @@
 	}
 
 	if (mrq->data && (mrq->data->flags & MMC_DATA_WRITE)) {
-		if (is_auto_prog_done(host)) {
-			/*
-			 * Auto-prog done will be enabled for following cases:
-			 * mrq->sbc	|	mrq->stop
-			 * _____________|________________
-			 *	True	|	Don't care
-			 *	False	|	False (CMD24, ACMD25 use case)
-			 */
-			if (mrq->sbc || !mrq->stop)
-				host->curr.wait_for_auto_prog_done = true;
+		if (msmsdcc_is_wait_for_auto_prog_done(host, mrq)) {
+			host->curr.wait_for_auto_prog_done = true;
 		} else {
 			if ((mrq->cmd->opcode == SD_IO_RW_EXTENDED) ||
 			    (mrq->cmd->opcode == 54))
@@ -5200,9 +5234,11 @@
 	mrq = host->curr.mrq;
 
 	if (mrq && mrq->cmd) {
-		pr_info("%s: CMD%d: Request timeout\n", mmc_hostname(host->mmc),
-				mrq->cmd->opcode);
-		msmsdcc_dump_sdcc_state(host);
+		if (!mrq->cmd->bkops_busy) {
+			pr_info("%s: CMD%d: Request timeout\n",
+				mmc_hostname(host->mmc), mrq->cmd->opcode);
+			msmsdcc_dump_sdcc_state(host);
+		}
 
 		if (!mrq->cmd->error)
 			mrq->cmd->error = -ETIMEDOUT;
@@ -6170,6 +6206,11 @@
 
 	mmc_add_host(mmc);
 
+	mmc->clk_scaling.up_threshold = 35;
+	mmc->clk_scaling.down_threshold = 5;
+	mmc->clk_scaling.polling_delay_ms = 100;
+	mmc->caps2 |= MMC_CAP2_CLK_SCALE;
+
 #ifdef CONFIG_HAS_EARLYSUSPEND
 	host->early_suspend.suspend = msmsdcc_early_suspend;
 	host->early_suspend.resume  = msmsdcc_late_resume;
diff --git a/drivers/mmc/host/msm_sdcc.h b/drivers/mmc/host/msm_sdcc.h
index 7469c8e..8ae5b86 100644
--- a/drivers/mmc/host/msm_sdcc.h
+++ b/drivers/mmc/host/msm_sdcc.h
@@ -422,7 +422,6 @@
 	struct mutex clk_mutex;
 	bool pending_resume;
 	unsigned int idle_tout;			/* Timeout in msecs */
-	bool pending_dpsm_reset;
 	bool enforce_pio_mode;
 	bool print_pm_stats;
 	struct msmsdcc_msm_bus_vote msm_bus_vote;
diff --git a/drivers/platform/msm/ipa/ipa.c b/drivers/platform/msm/ipa/ipa.c
index 7973cfe..d673e5a 100644
--- a/drivers/platform/msm/ipa/ipa.c
+++ b/drivers/platform/msm/ipa/ipa.c
@@ -73,6 +73,7 @@
 static struct clk *ipa_clk;
 static struct clk *sys_noc_ipa_axi_clk;
 static struct clk *ipa_cnoc_clk;
+static struct clk *ipa_inactivity_clk;
 static struct device *ipa_dev;
 
 struct ipa_context *ipa_ctx;
@@ -928,23 +929,30 @@
 static void ipa_set_aggregation_params(void)
 {
 	struct ipa_ep_cfg_aggr agg_params;
+	struct ipa_ep_cfg_hdr hdr_params;
 	u32 producer_hdl = 0;
 	u32 consumer_hdl = 0;
 
 	rmnet_bridge_get_client_handles(&producer_hdl, &consumer_hdl);
 
+	/* configure aggregation on producer */
+	memset(&agg_params, 0, sizeof(struct ipa_ep_cfg_aggr));
+	agg_params.aggr_en = IPA_ENABLE_AGGR;
 	agg_params.aggr = ipa_ctx->aggregation_type;
 	agg_params.aggr_byte_limit = ipa_ctx->aggregation_byte_limit;
 	agg_params.aggr_time_limit = ipa_ctx->aggregation_time_limit;
-
-	/* configure aggregation on producer */
-	agg_params.aggr_en = IPA_ENABLE_AGGR;
 	ipa_cfg_ep_aggr(producer_hdl, &agg_params);
 
-	/* configure deaggregation on consumer */
-	agg_params.aggr_en = IPA_ENABLE_DEAGGR;
-	ipa_cfg_ep_aggr(consumer_hdl, &agg_params);
+	/* configure header on producer */
+	memset(&hdr_params, 0, sizeof(struct ipa_ep_cfg_hdr));
+	hdr_params.hdr_len = 1;
+	ipa_cfg_ep_hdr(producer_hdl, &hdr_params);
 
+	/* configure deaggregation on consumer */
+	memset(&agg_params, 0, sizeof(struct ipa_ep_cfg_aggr));
+	agg_params.aggr_en = IPA_ENABLE_DEAGGR;
+	agg_params.aggr = ipa_ctx->aggregation_type;
+	ipa_cfg_ep_aggr(consumer_hdl, &agg_params);
 }
 
 /*
@@ -1158,6 +1166,13 @@
 		return -ENODEV;
 	}
 
+	ipa_inactivity_clk = clk_get(dev, "inactivity_clk");
+	if (IS_ERR(ipa_inactivity_clk)) {
+		ipa_inactivity_clk = NULL;
+		IPAERR("fail to get inactivity clk\n");
+		return -ENODEV;
+	}
+
 	return 0;
 }
 
@@ -1192,6 +1207,11 @@
 	else
 		WARN_ON(1);
 
+	if (ipa_inactivity_clk)
+		clk_prepare(ipa_inactivity_clk);
+	else
+		WARN_ON(1);
+
 	if (ipa_clk)
 		clk_enable(ipa_clk);
 	else
@@ -1201,6 +1221,11 @@
 		clk_enable(sys_noc_ipa_axi_clk);
 	else
 		WARN_ON(1);
+
+	if (ipa_inactivity_clk)
+		clk_enable(ipa_inactivity_clk);
+	else
+		WARN_ON(1);
 }
 
 /**
@@ -1211,6 +1236,11 @@
 */
 void ipa_disable_clks(void)
 {
+	if (ipa_inactivity_clk)
+		clk_disable_unprepare(ipa_inactivity_clk);
+	else
+		WARN_ON(1);
+
 	if (sys_noc_ipa_axi_clk)
 		clk_disable_unprepare(sys_noc_ipa_axi_clk);
 	else
@@ -1317,6 +1347,22 @@
 		result = -ENODEV;
 		goto fail_init_hw;
 	}
+
+	/* setup chicken bits */
+	result = ipa_set_single_ndp_per_mbim(true);
+	if (result) {
+		IPAERR(":failed to set single ndp per mbim.\n");
+		result = -EFAULT;
+		goto fail_init_hw;
+	}
+
+	result = ipa_set_hw_timer_fix_for_mbim_aggr(true);
+	if (result) {
+		IPAERR(":failed to set HW timer fix for MBIM aggregation.\n");
+		result = -EFAULT;
+		goto fail_init_hw;
+	}
+
 	/* read how much SRAM is available for SW use */
 	ipa_ctx->smem_sz = ipa_read_reg(ipa_ctx->mmio,
 			IPA_SHARED_MEM_SIZE_OFST);
@@ -1511,10 +1557,6 @@
 
 	ipa_replenish_rx_cache();
 
-	/* init the filtering block */
-	ipa_commit_flt(IPA_IP_v4);
-	ipa_commit_flt(IPA_IP_v6);
-
 	/*
 	 * setup an empty routing table in system memory, this will be used
 	 * to delete a routing table cleanly and safely
diff --git a/drivers/platform/msm/ipa/ipa_i.h b/drivers/platform/msm/ipa/ipa_i.h
index 3be2369..4172371 100644
--- a/drivers/platform/msm/ipa/ipa_i.h
+++ b/drivers/platform/msm/ipa/ipa_i.h
@@ -654,6 +654,8 @@
 int ipa_generate_hdr_hw_tbl(struct ipa_mem_buffer *mem);
 int ipa_generate_rt_hw_tbl(enum ipa_ip_type ip, struct ipa_mem_buffer *mem);
 int ipa_generate_flt_hw_tbl(enum ipa_ip_type ip, struct ipa_mem_buffer *mem);
+int ipa_set_single_ndp_per_mbim(bool);
+int ipa_set_hw_timer_fix_for_mbim_aggr(bool);
 void ipa_debugfs_init(void);
 void ipa_debugfs_remove(void);
 
diff --git a/drivers/platform/msm/ipa/ipa_reg.h b/drivers/platform/msm/ipa/ipa_reg.h
index 61913b6..ca67e35 100644
--- a/drivers/platform/msm/ipa/ipa_reg.h
+++ b/drivers/platform/msm/ipa/ipa_reg.h
@@ -213,6 +213,8 @@
 #define IPA_AGGREGATION_QCNCM_SIG_BMSK 0xff000000
 #define IPA_AGGREGATION_SINGLE_NDP_MSK 0x1
 #define IPA_AGGREGATION_SINGLE_NDP_BMSK 0xfffffffe
+#define IPA_AGGREGATION_HW_TIMER_FIX_MBIM_AGGR_SHFT 2
+#define IPA_AGGREGATION_HW_TIMER_FIX_MBIM_AGGR_BMSK 0x4
 
 #define IPA_SRAM_DIRECT_ACCESS_n_OFST(n) (0x00004000 + 0x4 * (n))
 #define IPA_SRAM_DIRECT_ACCESS_n_RMSK 0xffffffff
diff --git a/drivers/platform/msm/ipa/ipa_utils.c b/drivers/platform/msm/ipa/ipa_utils.c
index d5d5566..7cdde4a 100644
--- a/drivers/platform/msm/ipa/ipa_utils.c
+++ b/drivers/platform/msm/ipa/ipa_utils.c
@@ -1323,6 +1323,24 @@
 EXPORT_SYMBOL(ipa_set_single_ndp_per_mbim);
 
 /**
+ * ipa_set_hw_timer_fix_for_mbim_aggr() - Enable/disable HW timer fix
+ * for MBIM aggregation.
+ * @enable:	[in] true for enable HW fix; false otherwise
+ *
+ * Returns:	0 on success
+ */
+int ipa_set_hw_timer_fix_for_mbim_aggr(bool enable)
+{
+	u32 reg_val;
+	reg_val = ipa_read_reg(ipa_ctx->mmio, IPA_AGGREGATION_SPARE_REG_1_OFST);
+	ipa_write_reg(ipa_ctx->mmio, IPA_AGGREGATION_SPARE_REG_1_OFST,
+		(enable << IPA_AGGREGATION_HW_TIMER_FIX_MBIM_AGGR_SHFT) |
+		(reg_val & ~IPA_AGGREGATION_HW_TIMER_FIX_MBIM_AGGR_BMSK));
+	return 0;
+}
+EXPORT_SYMBOL(ipa_set_hw_timer_fix_for_mbim_aggr);
+
+/**
  * ipa_straddle_boundary() - Checks whether a memory buffer straddles a boundary
  * @start: start address of the memory buffer
  * @end: end address of the memory buffer
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 6b067e7..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
@@ -26,6 +26,7 @@
 #include <mach/ipa.h>
 #include <linux/workqueue.h>
 #include <linux/dma-mapping.h>
+#include <mach/msm_smsm.h>
 
 #define USB_SUMMING_THRESHOLD 512
 #define CONNECTIONS_NUM	8
@@ -37,29 +38,47 @@
 static struct sps_mem_buffer desc_mem_buf[CONNECTIONS_NUM][2];
 static struct platform_device *usb_bam_pdev;
 static struct workqueue_struct *usb_bam_wq;
+static u32 h_bam;
+static spinlock_t usb_bam_lock;
 
-struct usb_bam_wake_event_info {
+struct usb_bam_event_info {
 	struct sps_register_event event;
 	int (*callback)(void *);
 	void *param;
-	struct work_struct wake_w;
+	struct work_struct event_w;
 };
 
 struct usb_bam_connect_info {
 	u8 idx;
 	u32 *src_pipe;
 	u32 *dst_pipe;
-	struct usb_bam_wake_event_info peer_event;
+	struct usb_bam_event_info wake_event;
 	bool src_enabled;
 	bool dst_enabled;
 };
 
+enum usb_bam_sm {
+	USB_BAM_SM_INIT = 0,
+	USB_BAM_SM_PLUG_NOTIFIED,
+	USB_BAM_SM_PLUG_ACKED,
+	USB_BAM_SM_UNPLUG_NOTIFIED,
+};
+
+struct usb_bam_peer_handhskae_info {
+	enum usb_bam_sm state;
+	bool client_ready;
+	bool ack_received;
+	int pending_work;
+	struct usb_bam_event_info reset_event;
+};
+
 static struct usb_bam_connect_info usb_bam_connections[CONNECTIONS_NUM];
 static struct usb_bam_pipe_connect ***msm_usb_bam_connections_info;
 static struct usb_bam_pipe_connect *bam_connection_arr;
 void __iomem *qscratch_ram1_reg;
 struct clk *mem_clk;
 struct clk *mem_iface_clk;
+struct usb_bam_peer_handhskae_info peer_handhskae_info;
 
 static int connect_pipe(u8 conn_idx, enum usb_bam_pipe_dir pipe_dir,
 						u32 *usb_pipe_idx)
@@ -368,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) {
@@ -390,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,
@@ -457,20 +483,122 @@
 	return 0;
 }
 
-static void usb_bam_wake_work(struct work_struct *w)
+int usb_bam_client_ready(bool ready)
 {
-	struct usb_bam_wake_event_info *wake_event_info =
-		container_of(w, struct usb_bam_wake_event_info, wake_w);
+	spin_lock(&usb_bam_lock);
+	if (peer_handhskae_info.client_ready == ready) {
+		pr_debug("%s: client state is already %d\n",
+			__func__, ready);
+		spin_unlock(&usb_bam_lock);
+		return 0;
+	}
 
-	wake_event_info->callback(wake_event_info->param);
+	peer_handhskae_info.client_ready = ready;
+
+	spin_unlock(&usb_bam_lock);
+	if (!queue_work(usb_bam_wq, &peer_handhskae_info.reset_event.event_w)) {
+		spin_lock(&usb_bam_lock);
+		peer_handhskae_info.pending_work++;
+		spin_unlock(&usb_bam_lock);
+	}
+
+	return 0;
+}
+
+static void usb_bam_work(struct work_struct *w)
+{
+	struct usb_bam_event_info *event_info =
+		container_of(w, struct usb_bam_event_info, event_w);
+
+	event_info->callback(event_info->param);
 }
 
 static void usb_bam_wake_cb(struct sps_event_notify *notify)
 {
-	struct usb_bam_wake_event_info *wake_event_info =
-		(struct usb_bam_wake_event_info *)notify->user;
+	struct usb_bam_event_info *wake_event_info =
+		(struct usb_bam_event_info *)notify->user;
 
-	queue_work(usb_bam_wq, &wake_event_info->wake_w);
+	queue_work(usb_bam_wq, &wake_event_info->event_w);
+}
+
+static void usb_bam_sm_work(struct work_struct *w)
+{
+	pr_debug("%s: current state: %d\n", __func__,
+		peer_handhskae_info.state);
+
+	spin_lock(&usb_bam_lock);
+
+	switch (peer_handhskae_info.state) {
+	case USB_BAM_SM_INIT:
+		if (peer_handhskae_info.client_ready) {
+			spin_unlock(&usb_bam_lock);
+			smsm_change_state(SMSM_APPS_STATE, 0,
+				SMSM_USB_PLUG_UNPLUG);
+			spin_lock(&usb_bam_lock);
+			peer_handhskae_info.state = USB_BAM_SM_PLUG_NOTIFIED;
+		}
+		break;
+	case USB_BAM_SM_PLUG_NOTIFIED:
+		if (peer_handhskae_info.ack_received) {
+			peer_handhskae_info.state = USB_BAM_SM_PLUG_ACKED;
+			peer_handhskae_info.ack_received = 0;
+		}
+		break;
+	case USB_BAM_SM_PLUG_ACKED:
+		if (!peer_handhskae_info.client_ready) {
+			spin_unlock(&usb_bam_lock);
+			smsm_change_state(SMSM_APPS_STATE,
+				SMSM_USB_PLUG_UNPLUG, 0);
+			spin_lock(&usb_bam_lock);
+			peer_handhskae_info.state = USB_BAM_SM_UNPLUG_NOTIFIED;
+		}
+		break;
+	case USB_BAM_SM_UNPLUG_NOTIFIED:
+		if (peer_handhskae_info.ack_received) {
+			spin_unlock(&usb_bam_lock);
+			peer_handhskae_info.reset_event.
+				callback(peer_handhskae_info.reset_event.param);
+			spin_lock(&usb_bam_lock);
+			peer_handhskae_info.state = USB_BAM_SM_INIT;
+			peer_handhskae_info.ack_received = 0;
+		}
+		break;
+	}
+
+	if (peer_handhskae_info.pending_work) {
+		peer_handhskae_info.pending_work--;
+		spin_unlock(&usb_bam_lock);
+		queue_work(usb_bam_wq,
+			&peer_handhskae_info.reset_event.event_w);
+		spin_lock(&usb_bam_lock);
+	}
+	spin_unlock(&usb_bam_lock);
+}
+
+static void usb_bam_ack_toggle_cb(void *priv, uint32_t old_state,
+	uint32_t new_state)
+{
+	static int last_processed_state;
+	int current_state;
+
+	spin_lock(&usb_bam_lock);
+
+	current_state = new_state & SMSM_USB_PLUG_UNPLUG;
+
+	if (current_state == last_processed_state) {
+		spin_unlock(&usb_bam_lock);
+		return;
+	}
+
+	last_processed_state = current_state;
+	peer_handhskae_info.ack_received = true;
+
+	spin_unlock(&usb_bam_lock);
+	if (!queue_work(usb_bam_wq, &peer_handhskae_info.reset_event.event_w)) {
+		spin_lock(&usb_bam_lock);
+		peer_handhskae_info.pending_work++;
+		spin_unlock(&usb_bam_lock);
+	}
 }
 
 int usb_bam_register_wake_cb(u8 idx,
@@ -480,8 +608,8 @@
 	struct sps_connect *sps_connection =
 		&sps_connections[idx][PEER_PERIPHERAL_TO_USB];
 	struct usb_bam_connect_info *connection = &usb_bam_connections[idx];
-	struct usb_bam_wake_event_info *wake_event_info =
-		&connection->peer_event;
+	struct usb_bam_event_info *wake_event_info =
+		&connection->wake_event;
 	int ret;
 
 	wake_event_info->param = param;
@@ -509,6 +637,36 @@
 	return 0;
 }
 
+int usb_bam_register_peer_reset_cb(u8 idx,
+	 int (*callback)(void *), void *param)
+{
+	u32 ret = 0;
+
+	if (callback) {
+		peer_handhskae_info.reset_event.param = param;
+		peer_handhskae_info.reset_event.callback = callback;
+
+		ret = smsm_state_cb_register(SMSM_MODEM_STATE,
+			SMSM_USB_PLUG_UNPLUG, usb_bam_ack_toggle_cb, NULL);
+		if (ret) {
+			pr_err("%s: failed to register SMSM callback\n",
+				__func__);
+		} else {
+			if (smsm_get_state(SMSM_MODEM_STATE) &
+				SMSM_USB_PLUG_UNPLUG)
+				usb_bam_ack_toggle_cb(NULL, 0,
+					SMSM_USB_PLUG_UNPLUG);
+		}
+	} else {
+		peer_handhskae_info.reset_event.param = NULL;
+		peer_handhskae_info.reset_event.callback = NULL;
+		smsm_state_cb_deregister(SMSM_MODEM_STATE,
+			SMSM_USB_PLUG_UNPLUG, usb_bam_ack_toggle_cb, NULL);
+	}
+
+	return ret;
+}
+
 int usb_bam_disconnect_pipe(u8 idx)
 {
 	struct usb_bam_connect_info *connection = &usb_bam_connections[idx];
@@ -550,6 +708,7 @@
 
 	return 0;
 }
+
 int usb_bam_disconnect_ipa(u8 idx,
 		struct usb_bam_connect_ipa_params *ipa_params)
 {
@@ -592,6 +751,55 @@
 	return 0;
 
 }
+
+int usb_bam_reset(void)
+{
+	struct usb_bam_connect_info *connection;
+	int i;
+	int ret = 0, ret_int;
+	bool reconnect[CONNECTIONS_NUM];
+	u32 *reconnect_src_pipe[CONNECTIONS_NUM];
+	u32 *reconnect_dst_pipe[CONNECTIONS_NUM];
+
+	/* Disconnect all pipes */
+	for (i = 0; i < CONNECTIONS_NUM; i++) {
+		connection = &usb_bam_connections[i];
+		reconnect[i] = connection->src_enabled ||
+			connection->dst_enabled;
+		reconnect_src_pipe[i] = connection->src_pipe;
+		reconnect_dst_pipe[i] = connection->dst_pipe;
+
+		ret_int = usb_bam_disconnect_pipe(i);
+		if (ret_int) {
+			pr_err("%s: failure to connect pipe %d\n",
+				__func__, i);
+			ret = ret_int;
+			continue;
+		}
+	}
+
+	/* Reset USB/HSIC BAM */
+	if (sps_device_reset(h_bam))
+		pr_err("%s: BAM reset failed\n", __func__);
+
+	/* Reconnect all pipes */
+	for (i = 0; i < CONNECTIONS_NUM; i++) {
+		connection = &usb_bam_connections[i];
+		if (reconnect[i]) {
+			ret_int = usb_bam_connect(i, reconnect_src_pipe[i],
+				reconnect_dst_pipe[i]);
+			if (ret_int) {
+				pr_err("%s: failure to reconnect pipe %d\n",
+					__func__, i);
+				ret = ret_int;
+				continue;
+			}
+		}
+	}
+
+	return ret;
+}
+
 static int update_connections_info(struct device_node *node, int bam,
 	int conn_num, int dir, enum usb_pipe_mem_type mem_type)
 {
@@ -698,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) {
@@ -784,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;
@@ -825,7 +1038,6 @@
 
 static int usb_bam_init(void)
 {
-	u32 h_usb;
 	int ret;
 	void *usb_virt_addr;
 	struct msm_usb_bam_platform_data *pdata =
@@ -892,7 +1104,7 @@
 	if (pdata->ignore_core_reset_ack && pdata->usb_active_bam != SSUSB_BAM)
 		usb_props.options = SPS_BAM_NO_EXT_P_RST;
 
-	ret = sps_register_bam_device(&usb_props, &h_usb);
+	ret = sps_register_bam_device(&usb_props, &h_bam);
 	if (ret < 0) {
 		pr_err("%s: register bam error %d\n", __func__, ret);
 		ret = -EFAULT;
@@ -967,10 +1179,13 @@
 	for (i = 0; i < CONNECTIONS_NUM; i++) {
 		usb_bam_connections[i].src_enabled = 0;
 		usb_bam_connections[i].dst_enabled = 0;
-		INIT_WORK(&usb_bam_connections[i].peer_event.wake_w,
-			usb_bam_wake_work);
+		INIT_WORK(&usb_bam_connections[i].wake_event.event_w,
+			usb_bam_work);
 	}
 
+	spin_lock_init(&usb_bam_lock);
+	INIT_WORK(&peer_handhskae_info.reset_event.event_w, usb_bam_sm_work);
+
 	mem_clk = devm_clk_get(&pdev->dev, "mem_clk");
 	if (IS_ERR(mem_clk))
 		dev_dbg(&pdev->dev, "failed to get mem_clock\n");
diff --git a/drivers/power/pm8921-bms.c b/drivers/power/pm8921-bms.c
index 12bdf30..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
@@ -100,7 +100,8 @@
 	struct sf_lut		*rbatt_sf_lut;
 	int			delta_rbatt_mohm;
 	struct work_struct	calib_hkadc_work;
-	struct delayed_work	calib_hkadc_delayed_work;
+	unsigned long		last_calib_time;
+	int			last_calib_temp;
 	struct mutex		calib_mutex;
 	unsigned int		revision;
 	unsigned int		xoadc_v0625_usb_present;
@@ -133,6 +134,7 @@
 	int			rconn_mohm;
 	struct mutex		last_ocv_uv_mutex;
 	int			last_ocv_uv;
+	int			last_ocv_temp_decidegc;
 	int			pon_ocv_uv;
 	int			last_cc_uah;
 	unsigned long		tm_sec;
@@ -141,6 +143,7 @@
 	int			shutdown_iavg_ua;
 	struct delayed_work	calculate_soc_delayed_work;
 	struct timespec		t_soc_queried;
+	unsigned long		last_recalc_time;
 	int			shutdown_soc_valid_limit;
 	int			ignore_shutdown_soc;
 	int			prev_iavg_ua;
@@ -157,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;
 };
 
 /*
@@ -725,10 +730,12 @@
  * 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)
+				struct pm8921_soc_params *raw,
+				int batt_temp_decidegc)
 {
 	int usb_chg;
 	int est_ocv_uv;
@@ -745,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,
@@ -781,12 +788,14 @@
 				raw->cc = 0;
 			}
 		}
+		chip->last_ocv_temp_decidegc = batt_temp_decidegc;
 		pr_debug("PON_OCV_UV = %d\n", chip->last_ocv_uv);
 	} else if (chip->prev_last_good_ocv_raw != raw->last_good_ocv_raw) {
 		chip->prev_last_good_ocv_raw = raw->last_good_ocv_raw;
 		convert_vbatt_raw_to_uv(chip, usb_chg,
 			raw->last_good_ocv_raw, &raw->last_good_ocv_uv);
 		chip->last_ocv_uv = raw->last_good_ocv_uv;
+		chip->last_ocv_temp_decidegc = batt_temp_decidegc;
 		/* forget the old cc value upon ocv */
 		chip->last_cc_uah = 0;
 	} else {
@@ -795,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 {
 		/*
@@ -804,6 +813,7 @@
 		 */
 		raw->last_good_ocv_uv = chip->max_voltage_uv;
 		chip->last_ocv_uv = chip->max_voltage_uv;
+		chip->last_ocv_temp_decidegc = batt_temp_decidegc;
 	}
 	pr_debug("0p625 = %duV\n", chip->xoadc_v0625);
 	pr_debug("1p25 = %duV\n", chip->xoadc_v125);
@@ -906,18 +916,19 @@
 }
 
 static int calculate_pc(struct pm8921_bms_chip *chip, int ocv_uv,
-					int batt_temp, int chargecycles)
+				int batt_temp_decidegc, int chargecycles)
 {
 	int pc, scalefactor;
 
 	pc = interpolate_pc(chip->pc_temp_ocv_lut,
-			batt_temp / 10, ocv_uv / 1000);
+			batt_temp_decidegc / 10, ocv_uv / 1000);
 	pr_debug("pc = %u for ocv = %dmicroVolts batt_temp = %d\n",
-					pc, ocv_uv, batt_temp);
+					pc, ocv_uv, batt_temp_decidegc);
 
 	scalefactor = interpolate_scalingfactor(chip->pc_sf_lut,
 			chargecycles, pc);
-	pr_debug("scalefactor = %u batt_temp = %d\n", scalefactor, batt_temp);
+	pr_debug("scalefactor = %u batt_temp = %d\n",
+					scalefactor, batt_temp_decidegc);
 
 	/* Multiply the initial FCC value by the scale factor. */
 	pc = (pc * scalefactor) / 100;
@@ -1017,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 */
@@ -1057,75 +1074,89 @@
 	return new_uuc;
 }
 
-static void calculate_iavg_ua(struct pm8921_bms_chip *chip, int cc_uah,
-				int *iavg_ua, int *delta_time_s)
+static int get_current_time(unsigned long *now_tm_sec)
 {
-	int delta_cc_uah;
 	struct rtc_time tm;
 	struct rtc_device *rtc;
-	unsigned long now_tm_sec = 0;
-	int rc = 0;
-
-	/* if anything fails report the previous iavg_ua */
-	*iavg_ua = chip->prev_iavg_ua;
+	int rc;
 
 	rtc = rtc_class_open(CONFIG_RTC_HCTOSYS_DEVICE);
 	if (rtc == NULL) {
 		pr_err("%s: unable to open rtc device (%s)\n",
 			__FILE__, CONFIG_RTC_HCTOSYS_DEVICE);
-		goto out;
+		return -EINVAL;
 	}
 
 	rc = rtc_read_time(rtc, &tm);
 	if (rc) {
 		pr_err("Error reading rtc device (%s) : %d\n",
 			CONFIG_RTC_HCTOSYS_DEVICE, rc);
-		goto out;
+		return rc;
 	}
 
 	rc = rtc_valid_tm(&tm);
 	if (rc) {
 		pr_err("Invalid RTC time (%s): %d\n",
 			CONFIG_RTC_HCTOSYS_DEVICE, rc);
-		goto out;
+		return rc;
 	}
-	rtc_tm_to_time(&tm, &now_tm_sec);
+	rtc_tm_to_time(&tm, now_tm_sec);
 
-	if (chip->tm_sec == 0) {
-		*delta_time_s = 0;
+	return 0;
+}
+
+static int calculate_delta_time(struct pm8921_bms_chip *chip, int *delta_time_s)
+{
+	unsigned long now_tm_sec = 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;
+
+	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,
@@ -1159,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++;
@@ -1184,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;
@@ -1201,10 +1232,11 @@
 						int fcc_uah, int batt_temp,
 						int chargecycles)
 {
-	int  ocv, pc;
+	int  ocv, pc, batt_temp_decidegc;
 
 	ocv = raw->last_good_ocv_uv;
-	pc = calculate_pc(chip, ocv, batt_temp, chargecycles);
+	batt_temp_decidegc = chip->last_ocv_temp_decidegc;
+	pc = calculate_pc(chip, ocv, batt_temp_decidegc, chargecycles);
 	pr_debug("ocv = %d pc = %d\n", ocv, pc);
 	return (fcc_uah * pc) / 100;
 }
@@ -1217,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);
@@ -1249,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);
 }
 
@@ -1264,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,
@@ -1272,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;
@@ -1384,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);
@@ -1511,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);
@@ -1547,16 +1591,18 @@
 	last_soc_est = soc_est;
 
 	pc = calculate_pc(chip, chip->last_ocv_uv,
-				batt_temp, last_chargecycles);
+			chip->last_ocv_temp_decidegc, last_chargecycles);
 	if (pc > 0) {
 		pc_new = calculate_pc(chip, chip->last_ocv_uv - (++m * 1000),
-						batt_temp, last_chargecycles);
+					chip->last_ocv_temp_decidegc,
+					last_chargecycles);
 		while (pc_new == pc) {
 			/* start taking 10mV steps */
 			m = m + 10;
 			pc_new = calculate_pc(chip,
 						chip->last_ocv_uv - (m * 1000),
-						batt_temp, last_chargecycles);
+						chip->last_ocv_temp_decidegc,
+						last_chargecycles);
 		}
 	} else {
 		/*
@@ -1589,7 +1635,7 @@
 
 	/* calculate the soc based on this new ocv */
 	pc_new = calculate_pc(chip, chip->last_ocv_uv,
-						batt_temp, last_chargecycles);
+			chip->last_ocv_temp_decidegc, last_chargecycles);
 	rc_new_uah = (fcc_uah * pc_new) / 100;
 	soc_new = (rc_new_uah - cc_uah - uuc_uah)*100 / (fcc_uah - uuc_uah);
 	soc_new = bound_soc(soc_new);
@@ -1716,6 +1762,8 @@
 
 	chg_time_sec = DIV_ROUND_UP(the_chip->charge_time_us, USEC_PER_SEC);
 	catch_up_sec = DIV_ROUND_UP(the_chip->catch_up_time_us, USEC_PER_SEC);
+	if (catch_up_sec == 0)
+		return new_soc;
 	pr_debug("cts= %d catch_up_sec = %d\n", chg_time_sec, catch_up_sec);
 
 	/*
@@ -1762,6 +1810,106 @@
 		power_supply_changed(chip->batt_psy);
 }
 
+static int get_batt_temp(struct pm8921_bms_chip *chip, int *batt_temp)
+{
+	int rc;
+	struct pm8xxx_adc_chan_result result;
+
+	rc = pm8xxx_adc_read(chip->batt_temp_channel, &result);
+	if (rc) {
+		pr_err("error reading batt_temp_channel = %d, rc = %d\n",
+					chip->batt_temp_channel, rc);
+		return rc;
+	}
+	*batt_temp = result.physical;
+	pr_debug("batt_temp phy = %lld meas = 0x%llx\n", result.physical,
+						result.measurement);
+	return 0;
+}
+
+#define MIN_DELTA_625_UV	1000
+static void calib_hkadc(struct pm8921_bms_chip *chip)
+{
+	int voltage, rc;
+	struct pm8xxx_adc_chan_result result;
+	int usb_chg;
+	int this_delta;
+
+	mutex_lock(&chip->calib_mutex);
+	rc = pm8xxx_adc_read(the_chip->ref1p25v_channel, &result);
+	if (rc) {
+		pr_err("ADC failed for 1.25volts rc = %d\n", rc);
+		goto out;
+	}
+	voltage = xoadc_reading_to_microvolt(result.adc_code);
+
+	pr_debug("result 1.25v = 0x%x, voltage = %duV adc_meas = %lld\n",
+				result.adc_code, voltage, result.measurement);
+
+	chip->xoadc_v125 = voltage;
+
+	rc = pm8xxx_adc_read(the_chip->ref625mv_channel, &result);
+	if (rc) {
+		pr_err("ADC failed for 1.25volts rc = %d\n", rc);
+		goto out;
+	}
+	voltage = xoadc_reading_to_microvolt(result.adc_code);
+
+	usb_chg = usb_chg_plugged_in(chip);
+	pr_debug("result 0.625V = 0x%x, voltage = %duV adc_meas = %lld usb_chg = %d\n",
+				result.adc_code, voltage, result.measurement,
+				usb_chg);
+
+	if (usb_chg)
+		chip->xoadc_v0625_usb_present = voltage;
+	else
+		chip->xoadc_v0625_usb_absent = voltage;
+
+	chip->xoadc_v0625 = voltage;
+	if (chip->xoadc_v0625_usb_present && chip->xoadc_v0625_usb_absent) {
+		this_delta = chip->xoadc_v0625_usb_present
+						- chip->xoadc_v0625_usb_absent;
+		pr_debug("this_delta= %duV\n", this_delta);
+		if (this_delta > MIN_DELTA_625_UV)
+			last_usb_cal_delta_uv = this_delta;
+		pr_debug("625V_present= %d, 625V_absent= %d, delta = %duV\n",
+			chip->xoadc_v0625_usb_present,
+			chip->xoadc_v0625_usb_absent,
+			last_usb_cal_delta_uv);
+	}
+	pr_debug("calibration batt_temp = %d\n", chip->last_calib_temp);
+out:
+	mutex_unlock(&chip->calib_mutex);
+}
+
+#define HKADC_CALIB_DELAY_S	600
+#define HKADC_CALIB_DELTA_TEMP	20
+static void calib_hkadc_check(struct pm8921_bms_chip *chip, int batt_temp)
+{
+	unsigned long time_since_last_calib;
+	unsigned long tm_now_sec;
+	int delta_temp;
+	int rc;
+
+	rc = get_current_time(&tm_now_sec);
+	if (rc) {
+		pr_err("Could not read current time: %d\n", rc);
+		return;
+	}
+	if (tm_now_sec > chip->last_calib_time) {
+		time_since_last_calib = tm_now_sec - chip->last_calib_time;
+		delta_temp = abs(chip->last_calib_temp - batt_temp);
+		pr_debug("time since last calib: %lu, temp diff = %d\n",
+				time_since_last_calib, delta_temp);
+		if (time_since_last_calib >= HKADC_CALIB_DELAY_S
+			|| delta_temp > HKADC_CALIB_DELTA_TEMP) {
+			chip->last_calib_temp = batt_temp;
+			chip->last_calib_time = tm_now_sec;
+			calib_hkadc(chip);
+		}
+	}
+}
+
 /*
  * Remaining Usable Charge = remaining_charge (charge at ocv instance)
  *				- coloumb counter charge
@@ -1777,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;
@@ -1786,14 +1933,14 @@
 	int new_calculated_soc;
 	static int firsttime = 1;
 
+	calib_hkadc_check(chip, batt_temp);
 	calculate_soc_params(chip, raw, batt_temp, chargecycles,
 						&fcc_uah,
 						&unusable_charge_uah,
 						&remaining_charge_uah,
 						&cc_uah,
 						&rbatt,
-						&iavg_ua,
-						&delta_time_s);
+						&iavg_ua);
 
 	/* calculate remaining usable charge */
 	remaining_usable_charge_uah = remaining_charge_uah
@@ -1910,36 +2057,36 @@
 
 	calculated_soc = new_calculated_soc;
 	firsttime = 0;
+	get_current_time(&chip->last_recalc_time);
 	return calculated_soc;
 }
 
+static int recalculate_soc(struct pm8921_bms_chip *chip)
+{
+	int batt_temp;
+	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);
+	read_soc_params_raw(chip, &raw, batt_temp);
+
+	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;
+}
+
 static void calculate_soc_work(struct work_struct *work)
 {
 	struct pm8921_bms_chip *chip = container_of(work,
 				struct pm8921_bms_chip,
 				calculate_soc_delayed_work.work);
-	int batt_temp, rc;
-	struct pm8xxx_adc_chan_result result;
-	struct pm8921_soc_params raw;
-	int soc;
 
-	rc = pm8xxx_adc_read(chip->batt_temp_channel, &result);
-	if (rc) {
-		pr_err("error reading adc channel = %d, rc = %d\n",
-					chip->batt_temp_channel, rc);
-		return;
-	}
-	pr_debug("batt_temp phy = %lld meas = 0x%llx\n", result.physical,
-						result.measurement);
-	batt_temp = (int)result.physical;
-
-	mutex_lock(&chip->last_ocv_uv_mutex);
-	read_soc_params_raw(chip, &raw);
-
-	soc = calculate_state_of_charge(chip, &raw,
-					batt_temp, last_chargecycles);
-	mutex_unlock(&chip->last_ocv_uv_mutex);
-
+	recalculate_soc(chip);
 	schedule_delayed_work(&chip->calculate_soc_delayed_work,
 			round_jiffies_relative(msecs_to_jiffies
 			(chip->soc_calc_period)));
@@ -1950,24 +2097,14 @@
 	int soc = calculated_soc;
 	int delta_time_us;
 	struct timespec now;
-	struct pm8xxx_adc_chan_result result;
 	int batt_temp;
-	int rc;
 
 	if (bms_fake_battery != -EINVAL) {
 		pr_debug("Returning Fake SOC = %d%%\n", bms_fake_battery);
 		return bms_fake_battery;
 	}
 
-	rc = pm8xxx_adc_read(the_chip->batt_temp_channel, &result);
-	if (rc) {
-		pr_err("error reading adc channel = %d, rc = %d\n",
-					the_chip->batt_temp_channel, rc);
-		return rc;
-	}
-	pr_debug("batt_temp phy = %lld meas = 0x%llx\n", result.physical,
-						result.measurement);
-	batt_temp = (int)result.physical;
+	get_batt_temp(chip, &batt_temp);
 
 	do_posix_clock_monotonic_gettime(&now);
 	if (chip->t_soc_queried.tv_sec != 0) {
@@ -2012,8 +2149,7 @@
 	}
 
 	/* last_soc < soc  ... scale and catch up */
-	if (last_soc != -EINVAL && last_soc < soc && soc != 100
-				&& chip->catch_up_time_us != 0)
+	if (last_soc != -EINVAL && last_soc < soc && soc != 100)
 		soc = scale_soc_while_chg(chip, delta_time_us, soc, last_soc);
 
 	last_soc = soc;
@@ -2028,10 +2164,6 @@
 {
 	int calculate_soc = 0;
 	struct pm8921_bms_chip *chip = the_chip;
-	int batt_temp, rc;
-	struct pm8xxx_adc_chan_result result;
-	struct pm8921_soc_params raw;
-	int soc;
 
 	pr_debug("Invalidating shutdown soc - the battery was removed\n");
 	if (shutdown_soc_invalid)
@@ -2052,81 +2184,10 @@
 	mutex_unlock(&soc_invalidation_mutex);
 	if (!calculate_soc)
 		return;
-
-	rc = pm8xxx_adc_read(chip->batt_temp_channel, &result);
-	if (rc) {
-		pr_err("error reading adc channel = %d, rc = %d\n",
-					chip->batt_temp_channel, rc);
-		return;
-	}
-	pr_debug("batt_temp phy = %lld meas = 0x%llx\n", result.physical,
-						result.measurement);
-	batt_temp = (int)result.physical;
-
-	mutex_lock(&chip->last_ocv_uv_mutex);
-	read_soc_params_raw(chip, &raw);
-
-	soc = calculate_state_of_charge(chip, &raw,
-					batt_temp, last_chargecycles);
-	mutex_unlock(&chip->last_ocv_uv_mutex);
+	recalculate_soc(chip);
 }
 EXPORT_SYMBOL(pm8921_bms_invalidate_shutdown_soc);
 
-#define MIN_DELTA_625_UV	1000
-static void calib_hkadc(struct pm8921_bms_chip *chip)
-{
-	int voltage, rc;
-	struct pm8xxx_adc_chan_result result;
-	int usb_chg;
-	int this_delta;
-
-	mutex_lock(&chip->calib_mutex);
-	rc = pm8xxx_adc_read(the_chip->ref1p25v_channel, &result);
-	if (rc) {
-		pr_err("ADC failed for 1.25volts rc = %d\n", rc);
-		goto out;
-	}
-	voltage = xoadc_reading_to_microvolt(result.adc_code);
-
-	pr_debug("result 1.25v = 0x%x, voltage = %duV adc_meas = %lld\n",
-				result.adc_code, voltage, result.measurement);
-
-	chip->xoadc_v125 = voltage;
-
-	rc = pm8xxx_adc_read(the_chip->ref625mv_channel, &result);
-	if (rc) {
-		pr_err("ADC failed for 1.25volts rc = %d\n", rc);
-		goto out;
-	}
-	voltage = xoadc_reading_to_microvolt(result.adc_code);
-
-	usb_chg = usb_chg_plugged_in(chip);
-	pr_debug("result 0.625V = 0x%x, voltage = %duV adc_meas = %lld "
-				"usb_chg = %d\n",
-				result.adc_code, voltage, result.measurement,
-				usb_chg);
-
-	if (usb_chg)
-		chip->xoadc_v0625_usb_present = voltage;
-	else
-		chip->xoadc_v0625_usb_absent = voltage;
-
-	chip->xoadc_v0625 = voltage;
-	if (chip->xoadc_v0625_usb_present && chip->xoadc_v0625_usb_absent) {
-		this_delta = chip->xoadc_v0625_usb_present
-						- chip->xoadc_v0625_usb_absent;
-		pr_debug("this_delta= %duV\n", this_delta);
-		if (this_delta > MIN_DELTA_625_UV)
-			last_usb_cal_delta_uv = this_delta;
-		pr_debug("625V_present= %d, 625V_absent= %d, delta = %duV\n",
-			chip->xoadc_v0625_usb_present,
-			chip->xoadc_v0625_usb_absent,
-			last_usb_cal_delta_uv);
-	}
-out:
-	mutex_unlock(&chip->calib_mutex);
-}
-
 static void calibrate_hkadc_work(struct work_struct *work)
 {
 	struct pm8921_bms_chip *chip = container_of(work,
@@ -2140,19 +2201,6 @@
 	schedule_work(&the_chip->calib_hkadc_work);
 }
 
-#define HKADC_CALIB_DELAY_MS	600000
-static void calibrate_hkadc_delayed_work(struct work_struct *work)
-{
-	struct pm8921_bms_chip *chip = container_of(work,
-				struct pm8921_bms_chip,
-				calib_hkadc_delayed_work.work);
-
-	calib_hkadc(chip);
-	schedule_delayed_work(&chip->calib_hkadc_delayed_work,
-			round_jiffies_relative(msecs_to_jiffies
-			(HKADC_CALIB_DELAY_MS)));
-}
-
 int pm8921_bms_get_vsense_avg(int *result)
 {
 	int rc = -EINVAL;
@@ -2215,71 +2263,26 @@
 }
 EXPORT_SYMBOL_GPL(pm8921_bms_get_percent_charge);
 
-int pm8921_bms_get_rbatt(void)
+int pm8921_bms_get_current_max(void)
 {
-	int batt_temp, rc;
-	struct pm8xxx_adc_chan_result result;
-	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;
 	}
-
-	rc = pm8xxx_adc_read(the_chip->batt_temp_channel, &result);
-	if (rc) {
-		pr_err("error reading adc channel = %d, rc = %d\n",
-					the_chip->batt_temp_channel, rc);
-		return rc;
-	}
-	pr_debug("batt_temp phy = %lld meas = 0x%llx\n", result.physical,
-						result.measurement);
-	batt_temp = (int)result.physical;
-
-	mutex_lock(&the_chip->last_ocv_uv_mutex);
-
-	read_soc_params_raw(the_chip, &raw);
-
-	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)
 {
-	int batt_temp, rc;
-	struct pm8xxx_adc_chan_result result;
+	int batt_temp;
 
 	if (!the_chip) {
 		pr_err("called before initialization\n");
 		return -EINVAL;
 	}
 
-	rc = pm8xxx_adc_read(the_chip->batt_temp_channel, &result);
-	if (rc) {
-		pr_err("error reading adc channel = %d, rc = %d\n",
-					the_chip->batt_temp_channel, rc);
-		return rc;
-	}
-	pr_debug("batt_temp phy = %lld meas = 0x%llx", result.physical,
-						result.measurement);
-	batt_temp = (int)result.physical;
+	get_batt_temp(the_chip, &batt_temp);
 	return calculate_fcc_uah(the_chip, batt_temp, last_chargecycles);
 }
 EXPORT_SYMBOL_GPL(pm8921_bms_get_fcc);
@@ -2293,9 +2296,12 @@
 void pm8921_bms_charging_began(void)
 {
 	struct pm8921_soc_params raw;
+	int batt_temp;
+
+	get_batt_temp(the_chip, &batt_temp);
 
 	mutex_lock(&the_chip->last_ocv_uv_mutex);
-	read_soc_params_raw(the_chip, &raw);
+	read_soc_params_raw(the_chip, &raw, batt_temp);
 	mutex_unlock(&the_chip->last_ocv_uv_mutex);
 
 	the_chip->start_percent = report_state_of_charge(the_chip);
@@ -2318,26 +2324,17 @@
 #define MIN_START_PERCENT_FOR_LEARNING	30
 void pm8921_bms_charging_end(int is_battery_full)
 {
-	int batt_temp, rc;
-	struct pm8xxx_adc_chan_result result;
+	int batt_temp;
 	struct pm8921_soc_params raw;
 
 	if (the_chip == NULL)
 		return;
 
-	rc = pm8xxx_adc_read(the_chip->batt_temp_channel, &result);
-	if (rc) {
-		pr_err("error reading adc channel = %d, rc = %d\n",
-				the_chip->batt_temp_channel, rc);
-		return;
-	}
-	pr_debug("batt_temp phy = %lld meas = 0x%llx\n", result.physical,
-						result.measurement);
-	batt_temp = (int)result.physical;
+	get_batt_temp(the_chip, &batt_temp);
 
 	mutex_lock(&the_chip->last_ocv_uv_mutex);
 
-	read_soc_params_raw(the_chip, &raw);
+	read_soc_params_raw(the_chip, &raw, batt_temp);
 
 	calculate_cc_uah(the_chip, raw.cc, &bms_end_cc_uah);
 
@@ -2730,7 +2727,7 @@
 	int ibat_ua, vbat_uv;
 	struct pm8921_soc_params raw;
 
-	read_soc_params_raw(the_chip, &raw);
+	read_soc_params_raw(the_chip, &raw, 300);
 
 	*val = 0;
 
@@ -2796,7 +2793,7 @@
 	struct pm8921_soc_params raw;
 
 	mutex_lock(&the_chip->bms_output_lock);
-	read_soc_params_raw(the_chip, &raw);
+	read_soc_params_raw(the_chip, &raw, 300);
 	mutex_unlock(&the_chip->bms_output_lock);
 
 	*val = 0;
@@ -3016,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;
 
@@ -3029,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);
@@ -3057,16 +3058,16 @@
 
 	mutex_init(&chip->calib_mutex);
 	INIT_WORK(&chip->calib_hkadc_work, calibrate_hkadc_work);
-	INIT_DELAYED_WORK(&chip->calib_hkadc_delayed_work,
-				calibrate_hkadc_delayed_work);
 
 	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,
@@ -3091,12 +3092,6 @@
 	}
 	check_initial_ocv(chip);
 
-	/* start periodic hkadc calibration */
-	calib_hkadc(chip);
-	schedule_delayed_work(&chip->calib_hkadc_delayed_work,
-			round_jiffies_relative(msecs_to_jiffies
-			(HKADC_CALIB_DELAY_MS)));
-
 	/* enable the vbatt reading interrupts for scheduling hkadc calib */
 	pm8921_bms_enable_irq(chip, PM8921_BMS_GOOD_OCV);
 	pm8921_bms_enable_irq(chip, PM8921_BMS_OCV_FOR_R);
@@ -3114,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;
@@ -3134,17 +3132,26 @@
 
 static int pm8921_bms_resume(struct device *dev)
 {
-	int rc, ibat_ua, vbat_uv;
+	int rc;
+	unsigned long time_since_last_recalc;
+	unsigned long tm_now_sec;
 
-	rc = pm8921_bms_get_simultaneous_battery_voltage_and_current(
-							&ibat_ua,
-							&vbat_uv);
-	if (rc < 0) {
-		pr_err("simultaneous vbat ibat failed err = %d\n", rc);
+	rc = get_current_time(&tm_now_sec);
+	if (rc) {
+		pr_err("Could not read current time: %d\n", rc);
 		return 0;
 	}
+	if (tm_now_sec > the_chip->last_recalc_time) {
+		time_since_last_recalc = tm_now_sec -
+				the_chip->last_recalc_time;
+		pr_debug("Time since last recalc: %lu\n",
+				time_since_last_recalc);
+		if (time_since_last_recalc >= the_chip->soc_calc_period) {
+			the_chip->last_recalc_time = tm_now_sec;
+			recalculate_soc(the_chip);
+		}
+	}
 
-	very_low_voltage_check(the_chip, ibat_ua, vbat_uv);
 	return 0;
 }
 
diff --git a/drivers/power/pm8921-charger.c b/drivers/power/pm8921-charger.c
index bd62cf1..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
@@ -293,6 +293,7 @@
 	int				btc_override_hot_decidegc;
 	int				btc_delay_ms;
 	bool				btc_panic_if_cant_stop_chg;
+	int				stop_chg_upon_expiry;
 };
 
 /* user space parameter to limit usb current */
@@ -1662,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)
@@ -2538,7 +2514,11 @@
 			break;
 		}
 	}
-	pm_chg_masked_write(chip, ovpreg, OVP_DEBOUNCE_TIME, 0x2);
+	if (pm8xxx_get_version(chip->dev->parent) == PM8XXX_VERSION_8917)
+		pm_chg_masked_write(chip, ovpreg, OVP_DEBOUNCE_TIME, 0x6);
+	else
+		pm_chg_masked_write(chip, ovpreg, OVP_DEBOUNCE_TIME, 0x2);
+
 	pr_debug("Exit count=%d chg_gone=%d, active_valid=%d\n",
 		count, chg_gone, active_chg_plugged_in);
 	return;
@@ -2729,9 +2709,11 @@
 	struct pm8921_chg_chip *chip = data;
 	int ret;
 
-	ret = pm_chg_failed_clear(chip, 1);
-	if (ret)
-		pr_err("Failed to write CHG_FAILED_CLEAR bit\n");
+	if (!chip->stop_chg_upon_expiry) {
+		ret = pm_chg_failed_clear(chip, 1);
+		if (ret)
+			pr_err("Failed to write CHG_FAILED_CLEAR bit\n");
+	}
 
 	pr_err("batt_present = %d, batt_temp_ok = %d, state_changed_to=%d\n",
 			get_prop_batt_present(chip),
@@ -3233,7 +3215,6 @@
 	struct pm8921_chg_chip *chip = container_of(dwork,
 				struct pm8921_chg_chip, update_heartbeat_work);
 
-	pm_chg_failed_clear(chip, 1);
 	power_supply_changed(&chip->batt_psy);
 	if (chip->recent_reported_soc <= 20)
 		schedule_delayed_work(&chip->update_heartbeat_work,
@@ -3666,8 +3647,6 @@
 	int ichg_meas_ua, ichg_meas_ma;
 	int vbat_batt_terminal_uv;
 
-	pm_chg_failed_clear(chip, 1);
-
 	pm8921_bms_get_simultaneous_battery_voltage_and_current(
 					&ichg_meas_ua,	&vbat_meas_uv);
 	vbat_meas_mv = vbat_meas_uv / 1000;
@@ -4237,8 +4216,16 @@
 			pm_chg_write(chip, CHG_BUCK_CTRL_TEST3, 0xAC);
 	}
 
-	/* Enable isub_fine resolution AICL for PM8917 */
 	if (pm8xxx_get_version(chip->dev->parent) == PM8XXX_VERSION_8917) {
+		/* Set PM8917 USB_OVP debounce time to 15 ms */
+		rc = pm_chg_masked_write(chip, USB_OVP_CONTROL,
+			OVP_DEBOUNCE_TIME, 0x6);
+		if (rc) {
+			pr_err("Failed to set USB OVP db rc=%d\n", rc);
+			return rc;
+		}
+
+		/* Enable isub_fine resolution AICL for PM8917 */
 		chip->iusb_fine_res = true;
 		if (chip->uvd_voltage_mv) {
 			rc = pm_chg_uvd_threshold_set(chip,
@@ -4608,6 +4595,11 @@
 		disable_irq_wake(chip->pmic_chg_irq[LOOP_CHANGE_IRQ]);
 		pm8921_chg_disable_irq(chip, LOOP_CHANGE_IRQ);
 	}
+
+	if (chip->btc_override && (is_dc_chg_plugged_in(the_chip) ||
+					is_usb_chg_plugged_in(the_chip)))
+		schedule_delayed_work(&chip->btc_override_work, 0);
+
 	return 0;
 }
 
@@ -4615,6 +4607,9 @@
 {
 	struct pm8921_chg_chip *chip = dev_get_drvdata(dev);
 
+	if (chip->btc_override)
+		cancel_delayed_work_sync(&chip->btc_override_work);
+
 	if (is_usb_chg_plugged_in(chip)) {
 		pm8921_chg_enable_irq(chip, LOOP_CHANGE_IRQ);
 		enable_irq_wake(chip->pmic_chg_irq[LOOP_CHANGE_IRQ]);
@@ -4716,6 +4711,8 @@
 	if (chip->btc_override)
 		pm8921_chg_btc_override_init(chip);
 
+	chip->stop_chg_upon_expiry = pdata->stop_chg_upon_expiry;
+
 	chip->usb_psy.name = "usb",
 	chip->usb_psy.type = POWER_SUPPLY_TYPE_USB,
 	chip->usb_psy.supplied_to = pm_power_supplied_to,
diff --git a/drivers/power/pm8xxx-ccadc.c b/drivers/power/pm8xxx-ccadc.c
index 6aeced0..bfc5eea 100644
--- a/drivers/power/pm8xxx-ccadc.c
+++ b/drivers/power/pm8xxx-ccadc.c
@@ -17,6 +17,7 @@
 #include <linux/platform_device.h>
 #include <linux/errno.h>
 #include <linux/mfd/pm8xxx/core.h>
+#include <linux/mfd/pm8xxx/pm8xxx-adc.h>
 #include <linux/mfd/pm8xxx/ccadc.h>
 #include <linux/interrupt.h>
 #include <linux/irq.h>
@@ -24,6 +25,7 @@
 #include <linux/debugfs.h>
 #include <linux/slab.h>
 #include <linux/delay.h>
+#include <linux/rtc.h>
 
 #define CCADC_ANA_PARAM		0x240
 #define CCADC_DIG_PARAM		0x241
@@ -68,10 +70,13 @@
 struct pm8xxx_ccadc_chip {
 	struct device		*dev;
 	struct dentry		*dent;
+	unsigned int		batt_temp_channel;
 	u16			ccadc_offset;
 	int			ccadc_gain_uv;
 	unsigned int		revision;
 	unsigned int		calib_delay_ms;
+	unsigned long		last_calib_time;
+	int			last_calib_temp;
 	int			eoc_irq;
 	int			r_sense_uohm;
 	struct delayed_work	calib_ccadc_work;
@@ -313,6 +318,54 @@
 	return 0;
 }
 
+static int get_batt_temp(struct pm8xxx_ccadc_chip *chip, int *batt_temp)
+{
+	int rc;
+	struct pm8xxx_adc_chan_result result;
+
+	rc = pm8xxx_adc_read(chip->batt_temp_channel, &result);
+	if (rc) {
+		pr_err("error reading batt_temp_channel = %d, rc = %d\n",
+					chip->batt_temp_channel, rc);
+		return rc;
+	}
+	*batt_temp = result.physical;
+	pr_debug("batt_temp phy = %lld meas = 0x%llx\n", result.physical,
+						result.measurement);
+	return 0;
+}
+
+static int get_current_time(unsigned long *now_tm_sec)
+{
+	struct rtc_time tm;
+	struct rtc_device *rtc;
+	int rc;
+
+	rtc = rtc_class_open(CONFIG_RTC_HCTOSYS_DEVICE);
+	if (rtc == NULL) {
+		pr_err("%s: unable to open rtc device (%s)\n",
+			__FILE__, CONFIG_RTC_HCTOSYS_DEVICE);
+		return -EINVAL;
+	}
+
+	rc = rtc_read_time(rtc, &tm);
+	if (rc) {
+		pr_err("Error reading rtc device (%s) : %d\n",
+			CONFIG_RTC_HCTOSYS_DEVICE, rc);
+		return rc;
+	}
+
+	rc = rtc_valid_tm(&tm);
+	if (rc) {
+		pr_err("Invalid RTC time (%s): %d\n",
+			CONFIG_RTC_HCTOSYS_DEVICE, rc);
+		return rc;
+	}
+	rtc_tm_to_time(&tm, now_tm_sec);
+
+	return 0;
+}
+
 void pm8xxx_calib_ccadc(void)
 {
 	u8 data_msb, data_lsb, sec_cntrl;
@@ -679,6 +732,7 @@
 	chip->eoc_irq = res->start;
 	chip->r_sense_uohm = pdata->r_sense_uohm;
 	chip->calib_delay_ms = pdata->calib_delay_ms;
+	chip->batt_temp_channel = pdata->ccadc_cdata.batt_temp_channel;
 
 	calib_ccadc_read_offset_and_gain(chip,
 					&chip->ccadc_gain_uv,
@@ -716,12 +770,50 @@
 	return 0;
 }
 
+#define CCADC_CALIB_TEMP_THRESH 20
+static int pm8xxx_ccadc_resume(struct device *dev)
+{
+	int rc, batt_temp, delta_temp;
+	unsigned long current_time_sec;
+	unsigned long time_since_last_calib;
+
+	rc = get_batt_temp(the_chip, &batt_temp);
+	if (rc) {
+		pr_err("unable to get batt_temp: %d\n", rc);
+		return 0;
+	}
+	rc = get_current_time(&current_time_sec);
+	if (rc) {
+		pr_err("unable to get current time: %d\n", rc);
+		return 0;
+	}
+	if (current_time_sec > the_chip->last_calib_time) {
+		time_since_last_calib = current_time_sec -
+					the_chip->last_calib_time;
+		delta_temp = abs(batt_temp - the_chip->last_calib_temp);
+		pr_debug("time since last calib: %lu, delta_temp = %d\n",
+					time_since_last_calib, delta_temp);
+		if (time_since_last_calib >= the_chip->calib_delay_ms/1000
+				|| delta_temp > CCADC_CALIB_TEMP_THRESH) {
+			the_chip->last_calib_time = current_time_sec;
+			the_chip->last_calib_temp = batt_temp;
+			pm8xxx_calib_ccadc();
+		}
+	}
+	return 0;
+}
+
+static const struct dev_pm_ops pm8xxx_ccadc_pm_ops = {
+	.resume		= pm8xxx_ccadc_resume,
+};
+
 static struct platform_driver pm8xxx_ccadc_driver = {
 	.probe	= pm8xxx_ccadc_probe,
 	.remove	= __devexit_p(pm8xxx_ccadc_remove),
 	.driver	= {
 		.name	= PM8XXX_CCADC_DEV_NAME,
 		.owner	= THIS_MODULE,
+		.pm	= &pm8xxx_ccadc_pm_ops,
 	},
 };
 
diff --git a/drivers/power/qpnp-bms.c b/drivers/power/qpnp-bms.c
index 5dbf3c2..1bc027c 100644
--- a/drivers/power/qpnp-bms.c
+++ b/drivers/power/qpnp-bms.c
@@ -89,7 +89,7 @@
 struct soc_params {
 	int		fcc_uah;
 	int		cc_uah;
-	int		rbatt;
+	int		rbatt_mohm;
 	int		iavg_ua;
 	int		uuc_uah;
 	int		ocv_charge_uah;
@@ -174,6 +174,7 @@
 	unsigned int			vadc_v0625;
 	unsigned int			vadc_v1250;
 
+	int				ibat_max_ua;
 	int				prev_iavg_ua;
 	int				prev_uuc_iavg_ma;
 	int				prev_pc_unusable;
@@ -199,6 +200,7 @@
 	POWER_SUPPLY_PROP_ONLINE,
 	POWER_SUPPLY_PROP_CAPACITY,
 	POWER_SUPPLY_PROP_CURRENT_NOW,
+	POWER_SUPPLY_PROP_CURRENT_MAX,
 	POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN,
 };
 
@@ -855,7 +857,7 @@
 		new_unusable_mv = chip->v_cutoff_uv/1000;
 
 	new_iavg_ma = (new_unusable_mv * 1000 - chip->v_cutoff_uv)
-						/ params->rbatt;
+						/ params->rbatt_mohm;
 	if (new_iavg_ma == 0)
 		new_iavg_ma = 1;
 	chip->prev_uuc_iavg_ma = new_iavg_ma;
@@ -1002,7 +1004,7 @@
 							/ params->fcc_uah;
 	if (soc_rbatt < 0)
 		soc_rbatt = 0;
-	params->rbatt = get_rbatt(chip, soc_rbatt, batt_temp);
+	params->rbatt_mohm = get_rbatt(chip, soc_rbatt, batt_temp);
 
 	calculate_iavg(chip, params->cc_uah, &params->iavg_ua);
 
@@ -1213,7 +1215,11 @@
 
 	delta_ocv_uv_limit = DIV_ROUND_CLOSEST(ibat_ua, 1000);
 
-	ocv_est_uv = vbat_uv + (ibat_ua * params->rbatt)/1000;
+	ocv_est_uv = vbat_uv + (ibat_ua * params->rbatt_mohm)/1000;
+
+	chip->ibat_max_ua = (ocv_est_uv - chip->v_cutoff_uv) * 1000
+					/ (params->rbatt_mohm);
+
 	pc_est = calculate_pc(chip, ocv_est_uv, batt_temp);
 	soc_est = div_s64((s64)params->fcc_uah * pc_est - params->uuc_uah*100,
 				(s64)params->fcc_uah - params->uuc_uah);
@@ -1308,7 +1314,7 @@
 	pr_debug("ibat_ua = %d, vbat_uv = %d, ocv_est_uv = %d, pc_est = %d, soc_est = %d, n = %d, delta_ocv_uv = %d, last_ocv_uv = %d, pc_new = %d, soc_new = %d, rbatt = %d, slope = %d\n",
 		ibat_ua, vbat_uv, ocv_est_uv, pc_est,
 		soc_est, n, delta_ocv_uv, chip->last_ocv_uv,
-		pc_new, soc_new, params->rbatt, slope);
+		pc_new, soc_new, params->rbatt_mohm, slope);
 
 	return soc;
 }
@@ -1713,10 +1719,15 @@
 	return report_state_of_charge(chip);
 }
 
+/* Returns estimated max current that the battery can supply in uA */
+static int get_prop_bms_current_max(struct qpnp_bms_chip *chip)
+{
+	return chip->ibat_max_ua;
+}
+
 /* Returns instantaneous current in uA */
 static int get_prop_bms_current_now(struct qpnp_bms_chip *chip)
 {
-	/* temporarily return 0 until a real algorithm is put in */
 	int rc, result_ua;
 
 	rc = get_battery_current(chip, &result_ua);
@@ -1771,6 +1782,9 @@
 	case POWER_SUPPLY_PROP_CURRENT_NOW:
 		val->intval = get_prop_bms_current_now(chip);
 		break;
+	case POWER_SUPPLY_PROP_CURRENT_MAX:
+		val->intval = get_prop_bms_current_max(chip);
+		break;
 	case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN:
 		val->intval = get_prop_bms_charge_full_design(chip);
 		break;
diff --git a/drivers/power/qpnp-charger.c b/drivers/power/qpnp-charger.c
index 005f789..ee0ff3a 100644
--- a/drivers/power/qpnp-charger.c
+++ b/drivers/power/qpnp-charger.c
@@ -481,6 +481,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,
@@ -1157,14 +1161,6 @@
 	case SMBB_BUCK_SUBTYPE:
 		break;
 	case SMBB_BAT_IF_SUBTYPE:
-		/* HACK: Unlock secure access to override temp comparator */
-		rc = qpnp_chg_masked_write(chip,
-				chip->bat_if_base + SEC_ACCESS,
-				0xA5, 0xA5, 1);
-		pr_debug("override hot cold\n");
-		rc = qpnp_chg_masked_write(chip,
-				chip->bat_if_base + 0xE5,
-				0xFF, 0x28, 1);
 		break;
 	case SMBB_USB_CHGPTH_SUBTYPE:
 		chip->usbin_valid_irq = spmi_get_irq_byname(chip->spmi,
diff --git a/drivers/thermal/qpnp-adc-tm.c b/drivers/thermal/qpnp-adc-tm.c
index bcc85f3..4818941 100644
--- a/drivers/thermal/qpnp-adc-tm.c
+++ b/drivers/thermal/qpnp-adc-tm.c
@@ -944,6 +944,9 @@
 	u8 thr_int_disable = 0;
 	int rc = 0, sensor_notify_num = 0;
 
+	if (!adc_tm || !adc_tm->adc_tm_initialized)
+		return -ENODEV;
+
 	rc = qpnp_adc_tm_read_reg(QPNP_ADC_TM_STATUS_LOW, &status_low);
 	if (rc) {
 		pr_err("adc-tm-tm read status low failed with %d\n", rc);
@@ -1364,7 +1367,8 @@
 			GFP_KERNEL);
 	if (!adc_qpnp) {
 		dev_err(&spmi->dev, "Unable to allocate memory\n");
-		return -ENOMEM;
+		rc = -ENOMEM;
+		goto fail;
 	}
 
 	adc_tm->adc = adc_qpnp;
@@ -1372,7 +1376,7 @@
 	rc = qpnp_adc_get_devicetree_data(spmi, adc_tm->adc);
 	if (rc) {
 		dev_err(&spmi->dev, "failed to read device tree\n");
-		return rc;
+		goto fail;
 	}
 
 	/* Register the ADC peripheral interrupt */
@@ -1380,14 +1384,16 @@
 						NULL, "high-thr-en-set");
 	if (adc_tm->adc->adc_high_thr_irq < 0) {
 		pr_err("Invalid irq\n");
-		return -ENXIO;
+		rc = -ENXIO;
+		goto fail;
 	}
 
 	adc_tm->adc->adc_low_thr_irq = spmi_get_irq_byname(spmi,
 						NULL, "low-thr-en-set");
 	if (adc_tm->adc->adc_low_thr_irq < 0) {
 		pr_err("Invalid irq\n");
-		return -ENXIO;
+		rc = -ENXIO;
+		goto fail;
 	}
 
 	rc = devm_request_irq(&spmi->dev, adc_tm->adc->adc_irq_eoc,
@@ -1396,7 +1402,7 @@
 	if (rc) {
 		dev_err(&spmi->dev,
 			"failed to request adc irq with error %d\n", rc);
-		return rc;
+		goto fail;
 	} else {
 		enable_irq_wake(adc_tm->adc->adc_irq_eoc);
 	}
@@ -1406,7 +1412,7 @@
 		IRQF_TRIGGER_RISING, "qpnp_adc_tm_high_interrupt", adc_tm);
 	if (rc) {
 		dev_err(&spmi->dev, "failed to request adc irq\n");
-		return rc;
+		goto fail;
 	} else {
 		enable_irq_wake(adc_tm->adc->adc_high_thr_irq);
 	}
@@ -1416,7 +1422,7 @@
 		IRQF_TRIGGER_RISING, "qpnp_adc_tm_low_interrupt", adc_tm);
 	if (rc) {
 		dev_err(&spmi->dev, "failed to request adc irq\n");
-		return rc;
+		goto fail;
 	} else {
 		enable_irq_wake(adc_tm->adc->adc_low_thr_irq);
 	}
@@ -1428,7 +1434,7 @@
 				"qcom,btm-channel-number", &btm_channel_num);
 		if (rc) {
 			pr_err("Invalid btm channel number\n");
-			return -EINVAL;
+			goto fail;
 		}
 
 		if ((btm_channel_num != QPNP_ADC_TM_M0_ADC_CH_SEL_CTL) &&
@@ -1463,24 +1469,27 @@
 	rc = qpnp_adc_tm_write_reg(QPNP_ADC_TM_HIGH_THR_INT_EN, thr_init);
 	if (rc < 0) {
 		pr_err("high thr init failed\n");
-		return rc;
+		goto fail;
 	}
 
 	rc = qpnp_adc_tm_write_reg(QPNP_ADC_TM_LOW_THR_INT_EN, thr_init);
 	if (rc < 0) {
 		pr_err("low thr init failed\n");
-		return rc;
+		goto fail;
 	}
 
 	rc = qpnp_adc_tm_write_reg(QPNP_ADC_TM_MULTI_MEAS_EN, thr_init);
 	if (rc < 0) {
 		pr_err("multi meas en failed\n");
-		return rc;
+		goto fail;
 	}
 
 	adc_tm->adc_tm_initialized = true;
 
 	return 0;
+fail:
+	qpnp_adc_tm = NULL;
+	return rc;
 }
 
 static int __devexit qpnp_adc_tm_remove(struct spmi_device *spmi)
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 f577fdb..1ee0828 100644
--- a/drivers/usb/dwc3/dwc3-msm.c
+++ b/drivers/usb/dwc3/dwc3-msm.c
@@ -59,6 +59,10 @@
 module_param(adc_meas_interval, int, S_IRUGO | S_IWUSR);
 MODULE_PARM_DESC(adc_meas_interval, "ADC ID polling period");
 
+static int override_phy_init;
+module_param(override_phy_init, int, S_IRUGO|S_IWUSR);
+MODULE_PARM_DESC(override_phy_init, "Override HSPHY Init Seq");
+
 /**
  *  USB DBM Hardware registers.
  *
@@ -124,6 +128,7 @@
 #define QSCRATCH_REG_OFFSET	(0x000F8800)
 #define QSCRATCH_GENERAL_CFG	(QSCRATCH_REG_OFFSET + 0x08)
 #define HS_PHY_CTRL_REG		(QSCRATCH_REG_OFFSET + 0x10)
+#define PARAMETER_OVERRIDE_X_REG (QSCRATCH_REG_OFFSET + 0x14)
 #define CHARGING_DET_CTRL_REG	(QSCRATCH_REG_OFFSET + 0x18)
 #define CHARGING_DET_OUTPUT_REG	(QSCRATCH_REG_OFFSET + 0x1C)
 #define ALT_INTERRUPT_EN_REG	(QSCRATCH_REG_OFFSET + 0x20)
@@ -169,6 +174,7 @@
 	atomic_t                pm_suspended;
 	atomic_t		in_lpm;
 	int			hs_phy_irq;
+	int			hsphy_init_seq;
 	bool			lpm_irq_seen;
 	struct delayed_work	resume_work;
 	struct wake_lock	wlock;
@@ -183,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;
@@ -191,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 */
@@ -584,7 +592,6 @@
 static void dwc3_msm_req_complete_func(struct usb_ep *ep,
 				       struct usb_request *request)
 {
-	struct dwc3_request *req = to_dwc3_request(request);
 	struct dwc3_ep *dep = to_dwc3_ep(ep);
 	struct dwc3_msm_req_complete *req_complete = NULL;
 
@@ -607,8 +614,7 @@
 	 * (normal and link), and the dwc3/gadget.c :: dwc3_gadget_giveback
 	 * released only one.
 	 */
-	if (req->queued)
-		dep->busy_slot++;
+	dep->busy_slot++;
 
 	/* Unconfigure dbm ep */
 	dwc3_msm_dbm_ep_unconfig(dep->number);
@@ -854,6 +860,10 @@
 	struct dwc3_ep *dep = to_dwc3_ep(ep);
 	struct usb_ep_ops *new_ep_ops;
 
+	dwc3_msm_event_buffer_config(dwc3_msm_read_reg(context->base,
+			DWC3_GEVNTADRLO(0)),
+			dwc3_msm_read_reg(context->base, DWC3_GEVNTSIZ(0)));
+
 	/* Save original ep ops for future restore*/
 	if (context->original_ep_ops[dep->number]) {
 		dev_err(context->dev,
@@ -1204,6 +1214,17 @@
 	usleep_range(2000, 2200);
 	/* Disable (bypass) VBUS and ID filters */
 	dwc3_msm_write_reg(msm->base, QSCRATCH_GENERAL_CFG, 0x78);
+	/*
+	 * write HSPHY init value to QSCRATCH reg to set HSPHY parameters like
+	 * VBUS valid threshold, disconnect valid threshold, DC voltage level,
+	 * preempasis and rise/fall time.
+	 */
+	if (override_phy_init)
+		msm->hsphy_init_seq = override_phy_init;
+	if (msm->hsphy_init_seq)
+		dwc3_msm_write_readback(msm->base,
+					PARAMETER_OVERRIDE_X_REG, 0x03FFFFFF,
+					msm->hsphy_init_seq & 0x03FFFFFF);
 
 	/* Enable master clock for RAMs to allow BAM to access RAMs when
 	 * RAM clock gating is enabled via DWC3's GCTL. Otherwise, issues
@@ -1245,6 +1266,11 @@
 
 	/* Reinitialize QSCRATCH registers after block reset */
 	dwc3_msm_qscratch_reg_init(mdwc);
+
+	/* Reset the DBM */
+	dwc3_msm_dbm_soft_reset(1);
+	usleep_range(1000, 1200);
+	dwc3_msm_dbm_soft_reset(0);
 }
 
 static void dwc3_chg_enable_secondary_det(struct dwc3_msm *mdwc)
@@ -1417,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;
@@ -1773,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,
@@ -1786,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:
@@ -1805,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",
 };
@@ -1821,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__);
@@ -1829,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,
@@ -1863,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)
@@ -2174,6 +2255,12 @@
 	msm->resource_size = resource_size(res);
 	msm->dwc3 = dwc3;
 
+	if (of_property_read_u32(node, "qcom,dwc-hsphy-init",
+						&msm->hsphy_init_seq))
+		dev_dbg(&pdev->dev, "unable to read hsphy init seq\n");
+	else if (!msm->hsphy_init_seq)
+		dev_warn(&pdev->dev, "incorrect hsphyinitseq.Using PORvalue\n");
+
 	dwc3_msm_qscratch_reg_init(msm);
 
 	pm_runtime_set_active(msm->dev);
@@ -2204,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) {
@@ -2238,15 +2327,6 @@
 			dev_err(&pdev->dev, "Failed to vote for bus scaling\n");
 	}
 
-	/* Reset the DBM */
-	dwc3_msm_dbm_soft_reset(1);
-	usleep_range(1000, 1200);
-	dwc3_msm_dbm_soft_reset(0);
-
-	dwc3_msm_event_buffer_config(dwc3_msm_read_reg(msm->base,
-							DWC3_GEVNTADRLO(0)),
-				dwc3_msm_read_reg(msm->base, DWC3_GEVNTSIZ(0)));
-
 	msm->otg_xceiv = usb_get_transceiver();
 	if (msm->otg_xceiv) {
 		msm->charger.start_detection = dwc3_start_chg_det;
diff --git a/drivers/usb/dwc3/dwc3_otg.c b/drivers/usb/dwc3/dwc3_otg.c
index 361aa32..eb879e3 100644
--- a/drivers/usb/dwc3/dwc3_otg.c
+++ b/drivers/usb/dwc3/dwc3_otg.c
@@ -179,16 +179,6 @@
 			return ret;
 		}
 		dwc3_otg_notify_host_mode(otg, on);
-
-		/* Do block reset for Host <-> peripheral switching to work */
-		if (ext_xceiv && ext_xceiv->otg_capability &&
-						ext_xceiv->ext_block_reset)
-			ext_xceiv->ext_block_reset();
-
-		/* re-init core and OTG register as XHCI reset clears it */
-		dwc3_post_host_reset_core_init(dwc);
-		if (ext_xceiv && !ext_xceiv->otg_capability)
-			dwc3_otg_reset(dotg);
 	}
 
 	return 0;
@@ -235,6 +225,8 @@
 static int dwc3_otg_start_peripheral(struct usb_otg *otg, int on)
 {
 	struct dwc3_otg *dotg = container_of(otg, struct dwc3_otg, otg);
+	struct dwc3_ext_xceiv *ext_xceiv = dotg->ext_xceiv;
+	struct dwc3 *dwc = dotg->dwc;
 
 	if (!otg->gadget)
 		return -EINVAL;
@@ -242,6 +234,22 @@
 	if (on) {
 		dev_dbg(otg->phy->dev, "%s: turn on gadget %s\n",
 					__func__, otg->gadget->name);
+
+		/*
+		 * Hardware reset is required to support below scenarios:
+		 * 1. Host <-> peripheral switching
+		 * 2. Once an endpoint is configured in DBM (BAM) mode, it
+		 * can be unconfigured only after RESET
+		 */
+		if (ext_xceiv && ext_xceiv->otg_capability &&
+						ext_xceiv->ext_block_reset)
+			ext_xceiv->ext_block_reset();
+
+		/* re-init core and OTG registers as block reset clears these */
+		dwc3_post_host_reset_core_init(dwc);
+		if (ext_xceiv && !ext_xceiv->otg_capability)
+			dwc3_otg_reset(dotg);
+
 		dwc3_otg_set_peripheral_regs(dotg);
 		usb_gadget_vbus_connect(otg->gadget);
 	} else {
diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
index c2bc3f3..0cce630 100644
--- a/drivers/usb/dwc3/gadget.c
+++ b/drivers/usb/dwc3/gadget.c
@@ -244,6 +244,8 @@
 	struct dwc3			*dwc = dep->dwc;
 
 	if (req->queued) {
+		req->queued = false;
+
 		if (req->request.num_mapped_sgs)
 			dep->busy_slot += req->request.num_mapped_sgs;
 		else
diff --git a/drivers/usb/gadget/android.c b/drivers/usb/gadget/android.c
index fe59036..6df0c96 100644
--- a/drivers/usb/gadget/android.c
+++ b/drivers/usb/gadget/android.c
@@ -141,6 +141,46 @@
 	struct list_head enabled_list;
 };
 
+/**
+* struct android_dev - represents android USB gadget device
+* @name: device name.
+* @functions: an array of all the supported USB function
+*    drivers that this gadget support but not necessarily
+*    added to one of the gadget configurations.
+* @cdev: The internal composite device. Android gadget device
+*    is a composite device, such that it can support configurations
+*    with more than one function driver.
+* @dev: The kernel device that represents this android device.
+* @enabled: True if the android gadget is enabled, means all
+*    the configurations were set and all function drivers were
+*    bind and ready for USB enumeration.
+* @disable_depth: Number of times the device was disabled, after
+*    symmetrical number of enables the device willl be enabled.
+*    Used for controlling ADB userspace disable/enable requests.
+* @mutex: Internal mutex for protecting device member fields.
+* @pdata: Platform data fetched from the kernel device platfrom data.
+* @connected: True if got connect notification from the gadget UDC.
+*    False if got disconnect notification from the gadget UDC.
+* @sw_connected: Equal to 'connected' only after the connect
+*    notification was handled by the android gadget work function.
+* @suspended: True if got suspend notification from the gadget UDC.
+*    False if got resume notification from the gadget UDC.
+* @sw_suspended: Equal to 'suspended' only after the susped
+*    notification was handled by the android gadget work function.
+* @pm_qos: An attribute string that can be set by user space in order to
+*    determine pm_qos policy. Set to 'high' for always demand pm_qos
+*    when USB bus is connected and resumed. Set to 'low' for disable
+*    any setting of pm_qos by this driver. Default = 'high'.
+* @work: workqueue used for handling notifications from the gadget UDC.
+* @configs: List of configurations currently configured into the device.
+*    The android gadget supports more than one configuration. The host
+*    may choose one configuration from the suggested.
+* @configs_num: Number of configurations currently configured and existing
+*    in the configs list.
+* @list_item: This driver supports more than one android gadget device (for
+*    example in order to support multiple USB cores), therefore this is
+*    a item in a linked list of android devices.
+*/
 struct android_dev {
 	const char *name;
 	struct android_usb_function **functions;
@@ -154,6 +194,8 @@
 
 	bool connected;
 	bool sw_connected;
+	bool suspended;
+	bool sw_suspended;
 	char pm_qos[5];
 	struct pm_qos_request pm_qos_req_dma;
 	struct work_struct work;
@@ -164,7 +206,6 @@
 
 	/* A list node inside the android_dev_list */
 	struct list_head list_item;
-
 };
 
 struct android_configuration {
@@ -244,6 +285,8 @@
 	USB_DISCONNECTED,
 	USB_CONNECTED,
 	USB_CONFIGURED,
+	USB_SUSPENDED,
+	USB_RESUMED
 };
 
 static void android_pm_qos_update_latency(struct android_dev *dev, int vote)
@@ -273,13 +316,20 @@
 	char *disconnected[2] = { "USB_STATE=DISCONNECTED", NULL };
 	char *connected[2]    = { "USB_STATE=CONNECTED", NULL };
 	char *configured[2]   = { "USB_STATE=CONFIGURED", NULL };
+	char *suspended[2]   = { "USB_STATE=SUSPENDED", NULL };
+	char *resumed[2]   = { "USB_STATE=RESUMED", NULL };
 	char **uevent_envp = NULL;
 	static enum android_device_state last_uevent, next_state;
 	unsigned long flags;
 	int pm_qos_vote = -1;
 
 	spin_lock_irqsave(&cdev->lock, flags);
-	if (cdev->config) {
+	if (dev->suspended != dev->sw_suspended && cdev->config) {
+		if (strncmp(dev->pm_qos, "low", 3))
+			pm_qos_vote = dev->suspended ? 0 : 1;
+		next_state = dev->suspended ? USB_SUSPENDED : USB_RESUMED;
+		uevent_envp = dev->suspended ? suspended : resumed;
+	} else if (cdev->config) {
 		uevent_envp = configured;
 		next_state = USB_CONFIGURED;
 	} else if (dev->connected != dev->sw_connected) {
@@ -291,6 +341,7 @@
 			pm_qos_vote = 0;
 	}
 	dev->sw_connected = dev->connected;
+	dev->sw_suspended = dev->suspended;
 	spin_unlock_irqrestore(&cdev->lock, flags);
 
 	if (pm_qos_vote != -1)
@@ -319,8 +370,12 @@
 		if (uevent_envp == configured)
 			msleep(50);
 
-		kobject_uevent_env(&dev->dev->kobj, KOBJ_CHANGE, uevent_envp);
-		last_uevent = next_state;
+		/* Do not notify on suspend / resume */
+		if (next_state != USB_SUSPENDED && next_state != USB_RESUMED) {
+			kobject_uevent_env(&dev->dev->kobj, KOBJ_CHANGE,
+					   uevent_envp);
+			last_uevent = next_state;
+		}
 		pr_info("%s: sent uevent %s\n", __func__, uevent_envp[0]);
 	} else {
 		pr_info("%s: did not send uevent (%d %d %p)\n", __func__,
@@ -1988,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;
@@ -2006,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) {
@@ -2331,6 +2397,35 @@
 	spin_unlock_irqrestore(&cdev->lock, flags);
 }
 
+static void android_suspend(struct usb_gadget *gadget)
+{
+	struct usb_composite_dev *cdev = get_gadget_data(gadget);
+	struct android_dev *dev = cdev_to_android_dev(cdev);
+	unsigned long flags;
+
+	spin_lock_irqsave(&cdev->lock, flags);
+	dev->suspended = 1;
+	schedule_work(&dev->work);
+	spin_unlock_irqrestore(&cdev->lock, flags);
+
+	composite_suspend(gadget);
+}
+
+static void android_resume(struct usb_gadget *gadget)
+{
+	struct usb_composite_dev *cdev = get_gadget_data(gadget);
+	struct android_dev *dev = cdev_to_android_dev(cdev);
+	unsigned long flags;
+
+	spin_lock_irqsave(&cdev->lock, flags);
+	dev->suspended = 0;
+	schedule_work(&dev->work);
+	spin_unlock_irqrestore(&cdev->lock, flags);
+
+	composite_resume(gadget);
+}
+
+
 static int android_create_device(struct android_dev *dev, u8 usb_core_id)
 {
 	struct device_attribute **attrs = android_usb_attributes;
@@ -2622,6 +2717,8 @@
 	/* Override composite driver functions */
 	composite_driver.setup = android_setup;
 	composite_driver.disconnect = android_disconnect;
+	composite_driver.suspend = android_suspend;
+	composite_driver.resume = android_resume;
 
 	INIT_LIST_HEAD(&android_dev_list);
 	android_dev_count = 0;
diff --git a/drivers/usb/gadget/ci13xxx_msm.c b/drivers/usb/gadget/ci13xxx_msm.c
index e3c1216..9ecfaaf 100644
--- a/drivers/usb/gadget/ci13xxx_msm.c
+++ b/drivers/usb/gadget/ci13xxx_msm.c
@@ -233,6 +233,19 @@
 	return 0;
 }
 
+void msm_hw_bam_disable(bool bam_disable)
+{
+	u32 val;
+	struct ci13xxx *udc = _udc;
+
+	if (bam_disable)
+		val = readl_relaxed(USB_GENCONFIG) | GENCONFIG_BAM_DISABLE;
+	else
+		val = readl_relaxed(USB_GENCONFIG) & ~GENCONFIG_BAM_DISABLE;
+
+	writel_relaxed(val, USB_GENCONFIG);
+}
+
 static struct platform_driver ci13xxx_msm_driver = {
 	.probe = ci13xxx_msm_probe,
 	.driver = { .name = "msm_hsusb", },
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/f_mbim.c b/drivers/usb/gadget/f_mbim.c
index 98c6dbc..2ff9426 100644
--- a/drivers/usb/gadget/f_mbim.c
+++ b/drivers/usb/gadget/f_mbim.c
@@ -91,6 +91,7 @@
 	struct mbim_ep_descs		hs;
 
 	u8				ctrl_id, data_id;
+	u8				data_alt_int;
 
 	struct ndp_parser_opts		*parser_opts;
 
@@ -659,7 +660,7 @@
 	pr_info("dev:%p port:%d. Do nothing.\n",
 			dev, dev->port_num);
 
-	/* bam_data_disconnect(&dev->bam_port, dev->port_num); */
+	bam_data_disconnect(&dev->bam_port, dev->port_num);
 
 	return 0;
 }
@@ -1273,7 +1274,6 @@
 		if (mbim->bam_port.in->driver_data) {
 			pr_info("reset mbim\n");
 			mbim_reset_values(mbim);
-			mbim_bam_disconnect(mbim);
 		}
 
 		/*
@@ -1319,6 +1319,7 @@
 			}
 		}
 
+		mbim->data_alt_int = alt;
 		spin_lock(&mbim->lock);
 		mbim_notify(mbim);
 		spin_unlock(&mbim->lock);
@@ -1351,7 +1352,10 @@
 
 	if (intf == mbim->ctrl_id)
 		return 0;
-	return mbim->bam_port.in->driver_data ? 1 : 0;
+	else if (intf == mbim->data_id)
+		return mbim->data_alt_int;
+
+	return -EINVAL;
 }
 
 static void mbim_disable(struct usb_function *f)
@@ -1418,6 +1422,7 @@
 	if (status < 0)
 		goto fail;
 	mbim->data_id = status;
+	mbim->data_alt_int = 0;
 
 	mbim_data_nop_intf.bInterfaceNumber = status;
 	mbim_data_intf.bInterfaceNumber = status;
diff --git a/drivers/usb/gadget/f_qc_ecm.c b/drivers/usb/gadget/f_qc_ecm.c
index 0b41197..b1c5985 100644
--- a/drivers/usb/gadget/f_qc_ecm.c
+++ b/drivers/usb/gadget/f_qc_ecm.c
@@ -324,8 +324,9 @@
 
 static int ecm_qc_bam_disconnect(struct f_ecm_qc *dev)
 {
-	pr_debug("dev:%p. %s Do nothing.\n",
-			 dev, __func__);
+	pr_debug("dev:%p. %s Disconnect BAM.\n", dev, __func__);
+
+	bam_data_disconnect(&ecm_qc_bam_port, 0);
 
 	return 0;
 }
@@ -518,8 +519,12 @@
 
 		if (ecm->port.in_ep->driver_data) {
 			DBG(cdev, "reset ecm\n");
-			gether_qc_disconnect_name(&ecm->port, "ecm0");
+			/* ecm->port is needed for disconnecting the BAM data
+			 * path. Only after the BAM data path is disconnected,
+			 * we can disconnect the port from the network layer.
+			 */
 			ecm_qc_bam_disconnect(ecm);
+			gether_qc_disconnect_name(&ecm->port, "ecm0");
 		}
 
 		if (!ecm->port.in_ep->desc ||
@@ -591,8 +596,8 @@
 	DBG(cdev, "ecm deactivated\n");
 
 	if (ecm->port.in_ep->driver_data) {
-		gether_qc_disconnect_name(&ecm->port, "ecm0");
 		ecm_qc_bam_disconnect(ecm);
+		gether_qc_disconnect_name(&ecm->port, "ecm0");
 	}
 
 	if (ecm->notify->driver_data) {
diff --git a/drivers/usb/gadget/f_qc_rndis.c b/drivers/usb/gadget/f_qc_rndis.c
index b632b54..0d229dc 100644
--- a/drivers/usb/gadget/f_qc_rndis.c
+++ b/drivers/usb/gadget/f_qc_rndis.c
@@ -441,8 +441,9 @@
 
 static int rndis_qc_bam_disconnect(struct f_rndis_qc *dev)
 {
-	pr_info("dev:%p. %s Do nothing.\n",
-			dev, __func__);
+	pr_debug("dev:%p. %s Disconnect BAM.\n", dev, __func__);
+
+	bam_data_disconnect(&dev->bam_port, 0);
 
 	return 0;
 }
@@ -674,8 +675,12 @@
 
 		if (rndis->port.in_ep->driver_data) {
 			DBG(cdev, "reset rndis\n");
-			gether_qc_disconnect_name(&rndis->port, "rndis0");
+			/* rndis->port is needed for disconnecting the BAM data
+			 * path. Only after the BAM data path is disconnected,
+			 * we can disconnect the port from the network layer.
+			 */
 			rndis_qc_bam_disconnect(rndis);
+			gether_qc_disconnect_name(&rndis->port, "rndis0");
 		}
 
 		if (!rndis->port.in_ep->desc || !rndis->port.out_ep->desc) {
@@ -735,8 +740,8 @@
 	pr_info("rndis deactivated\n");
 
 	rndis_uninit(rndis->config);
-	gether_qc_disconnect_name(&rndis->port, "rndis0");
 	rndis_qc_bam_disconnect(rndis);
+	gether_qc_disconnect_name(&rndis->port, "rndis0");
 
 	usb_ep_disable(rndis->notify);
 	rndis->notify->driver_data = NULL;
diff --git a/drivers/usb/gadget/f_qdss.c b/drivers/usb/gadget/f_qdss.c
index c3eddcc..085d0bd 100644
--- a/drivers/usb/gadget/f_qdss.c
+++ b/drivers/usb/gadget/f_qdss.c
@@ -420,19 +420,16 @@
 	if (qdss->ctrl_in_enabled) {
 		usb_ep_disable(qdss->ctrl_in);
 		qdss->ctrl_in_enabled = 0;
-		qdss->ctrl_in->driver_data = NULL;
 	}
 
 	if (qdss->ctrl_out_enabled) {
 		usb_ep_disable(qdss->ctrl_out);
 		qdss->ctrl_out_enabled = 0;
-		qdss->ctrl_out->driver_data = NULL;
 	}
 
 	if (qdss->data_enabled) {
 		usb_ep_disable(qdss->data);
 		qdss->data_enabled = 0;
-		qdss->data->driver_data = NULL;
 	}
 }
 
diff --git a/drivers/usb/gadget/u_bam.c b/drivers/usb/gadget/u_bam.c
index aa93a7d..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
@@ -137,6 +137,7 @@
 static void gbam_start_rx(struct gbam_port *port);
 static void gbam_start_endless_rx(struct gbam_port *port);
 static void gbam_start_endless_tx(struct gbam_port *port);
+static int gbam_peer_reset_cb(void *param);
 
 /*---------------misc functions---------------- */
 static void gbam_free_requests(struct usb_ep *ep, struct list_head *head)
@@ -219,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;
@@ -516,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);
@@ -533,6 +535,9 @@
 	struct bam_ch_info *d = &port->data_ch;
 	int status;
 
+	if (!port->port_usb)
+		return;
+
 	status = usb_ep_queue(port->port_usb->out, d->rx_req, GFP_ATOMIC);
 	if (status)
 		pr_err("%s: error enqueuing transfer, %d\n", __func__, status);
@@ -543,6 +548,9 @@
 	struct bam_ch_info *d = &port->data_ch;
 	int status;
 
+	if (!port->port_usb)
+		return;
+
 	status = usb_ep_queue(port->port_usb->in, d->tx_req, GFP_ATOMIC);
 	if (status)
 		pr_err("%s: error enqueuing transfer, %d\n", __func__, status);
@@ -756,9 +764,93 @@
 	gbam_start_endless_rx(port);
 	gbam_start_endless_tx(port);
 
+	if (d->trans == USB_GADGET_XPORT_BAM2BAM && port->port_num == 0) {
+		/* Register for peer reset callback */
+		usb_bam_register_peer_reset_cb(d->connection_idx,
+			gbam_peer_reset_cb, port);
+
+		ret = usb_bam_client_ready(true);
+		if (ret) {
+			pr_err("%s: usb_bam_client_ready failed: err:%d\n",
+				__func__, ret);
+			return;
+		}
+	}
+
 	pr_debug("%s: done\n", __func__);
 }
 
+static int gbam_peer_reset_cb(void *param)
+{
+	struct gbam_port	*port = (struct gbam_port *)param;
+	struct bam_ch_info *d;
+	struct f_rmnet		*dev;
+	struct usb_gadget *gadget;
+	int ret;
+	bool reenable_eps = false;
+
+	dev = port_to_rmnet(port->gr);
+	d = &port->data_ch;
+
+	gadget = dev->cdev->gadget;
+
+	pr_debug("%s: reset by peer\n", __func__);
+
+	/* Disable the relevant EPs if currently EPs are enabled */
+	if (port->port_usb && port->port_usb->in &&
+	  port->port_usb->in->driver_data) {
+		usb_ep_disable(port->port_usb->out);
+		usb_ep_disable(port->port_usb->in);
+
+		port->port_usb->in->driver_data = NULL;
+		port->port_usb->out->driver_data = NULL;
+		reenable_eps = true;
+	}
+
+	/* Disable BAM */
+	msm_hw_bam_disable(1);
+
+	/* Reset BAM */
+	ret = usb_bam_reset();
+	if (ret) {
+		pr_err("%s: BAM reset failed %d\n", __func__, ret);
+		goto reenable_eps;
+	}
+
+	/* Enable BAM */
+	msm_hw_bam_disable(0);
+
+reenable_eps:
+	/* Re-Enable the relevant EPs, if EPs were originally enabled */
+	if (reenable_eps) {
+		ret = usb_ep_enable(port->port_usb->in);
+		if (ret) {
+			pr_err("%s: usb_ep_enable failed eptype:IN ep:%p",
+				__func__, port->port_usb->in);
+			return ret;
+		}
+		port->port_usb->in->driver_data = port;
+
+		ret = usb_ep_enable(port->port_usb->out);
+		if (ret) {
+			pr_err("%s: usb_ep_enable failed eptype:OUT ep:%p",
+				__func__, port->port_usb->out);
+			port->port_usb->in->driver_data = 0;
+			return ret;
+		}
+		port->port_usb->out->driver_data = port;
+
+		gbam_start_endless_rx(port);
+		gbam_start_endless_tx(port);
+	}
+
+	/* Unregister the peer reset callback */
+	if (d->trans == USB_GADGET_XPORT_BAM2BAM && port->port_num == 0)
+		usb_bam_register_peer_reset_cb(d->connection_idx, NULL, NULL);
+
+	return 0;
+}
+
 /* BAM data channel ready, allow attempt to open */
 static int gbam_data_ch_probe(struct platform_device *pdev)
 {
@@ -1092,6 +1184,14 @@
 	if (trans == USB_GADGET_XPORT_BAM ||
 		trans == USB_GADGET_XPORT_BAM2BAM_IPA)
 		queue_work(gbam_wq, &port->disconnect_w);
+	else if (trans == USB_GADGET_XPORT_BAM2BAM) {
+		if (port_num == 0) {
+			if (usb_bam_client_ready(false)) {
+				pr_err("%s: usb_bam_client_ready failed\n",
+					__func__);
+			}
+		}
+	}
 }
 
 int gbam_connect(struct grmnet *gr, u8 port_num,
diff --git a/drivers/usb/gadget/u_bam_data.c b/drivers/usb/gadget/u_bam_data.c
index 32f683e..3cc0419 100644
--- a/drivers/usb/gadget/u_bam_data.c
+++ b/drivers/usb/gadget/u_bam_data.c
@@ -73,7 +73,7 @@
 {
 	int status = req->status;
 
-	pr_info("status: %d\n", status);
+	pr_debug("%s: status: %d\n", __func__, status);
 }
 
 static void bam_data_endless_tx_complete(struct usb_ep *ep,
@@ -81,7 +81,7 @@
 {
 	int status = req->status;
 
-	pr_info("status: %d\n", status);
+	pr_debug("%s: status: %d\n", __func__, status);
 }
 
 static void bam_data_start_endless_rx(struct bam_data_port *port)
@@ -89,6 +89,9 @@
 	struct bam_data_ch_info *d = &port->data_ch;
 	int status;
 
+	if (!port->port_usb)
+		return;
+
 	status = usb_ep_queue(port->port_usb->out, d->rx_req, GFP_ATOMIC);
 	if (status)
 		pr_err("error enqueuing transfer, %d\n", status);
@@ -99,32 +102,77 @@
 	struct bam_data_ch_info *d = &port->data_ch;
 	int status;
 
+	if (!port->port_usb)
+		return;
+
 	status = usb_ep_queue(port->port_usb->in, d->tx_req, GFP_ATOMIC);
 	if (status)
 		pr_err("error enqueuing transfer, %d\n", status);
 }
 
-static void bam2bam_data_disconnect_work(struct work_struct *w)
+static int bam_data_peer_reset_cb(void *param)
 {
-	struct bam_data_port *port =
-			container_of(w, struct bam_data_port, disconnect_w);
+	struct bam_data_port	*port = (struct bam_data_port *)param;
+	struct bam_data_ch_info *d;
+	int ret;
+	bool reenable_eps = false;
 
-	pr_info("Enter");
+	d = &port->data_ch;
 
-	/* disable endpoints */
-	if (!port->port_usb || !port->port_usb->out || !port->port_usb->in) {
-		pr_err("port_usb->out/in == NULL. Exit");
-		return;
+	pr_debug("%s: reset by peer\n", __func__);
+
+	/* Disable the relevant EPs if currently EPs are enabled */
+	if (port->port_usb && port->port_usb->in &&
+	  port->port_usb->in->driver_data) {
+		usb_ep_disable(port->port_usb->out);
+		usb_ep_disable(port->port_usb->in);
+
+		port->port_usb->in->driver_data = NULL;
+		port->port_usb->out->driver_data = NULL;
+		reenable_eps = true;
 	}
-	usb_ep_disable(port->port_usb->out);
-	usb_ep_disable(port->port_usb->in);
 
-	port->port_usb->in->driver_data = NULL;
-	port->port_usb->out->driver_data = NULL;
+	/* Disable BAM */
+	msm_hw_bam_disable(1);
 
-	port->port_usb = 0;
+	/* Reset BAM */
+	ret = usb_bam_reset();
+	if (ret) {
+		pr_err("%s: BAM reset failed %d\n", __func__, ret);
+		goto reenable_eps;
+	}
 
-	pr_info("Exit");
+	/* Enable BAM */
+	msm_hw_bam_disable(0);
+
+reenable_eps:
+	/* Re-Enable the relevant EPs, if EPs were originally enabled */
+	if (reenable_eps) {
+		ret = usb_ep_enable(port->port_usb->in);
+		if (ret) {
+			pr_err("%s: usb_ep_enable failed eptype:IN ep:%p",
+				__func__, port->port_usb->in);
+			return ret;
+		}
+		port->port_usb->in->driver_data = port;
+
+		ret = usb_ep_enable(port->port_usb->out);
+		if (ret) {
+			pr_err("%s: usb_ep_enable failed eptype:OUT ep:%p",
+				__func__, port->port_usb->out);
+			port->port_usb->in->driver_data = 0;
+			return ret;
+		}
+		port->port_usb->out->driver_data = port;
+
+		bam_data_start_endless_rx(port);
+		bam_data_start_endless_tx(port);
+	}
+
+	/* Unregister the peer reset callback */
+	usb_bam_register_peer_reset_cb(d->connection_idx, NULL, NULL);
+
+	return 0;
 }
 
 static void bam2bam_data_connect_work(struct work_struct *w)
@@ -135,7 +183,7 @@
 	u32 sps_params;
 	int ret;
 
-	pr_info("Enter");
+	pr_debug("%s: Connect workqueue started", __func__);
 
 	ret = usb_bam_connect(d->connection_idx, &d->src_pipe_idx,
 						  &d->dst_pipe_idx);
@@ -182,7 +230,18 @@
 	bam_data_start_endless_rx(port);
 	bam_data_start_endless_tx(port);
 
-	pr_info("Done\n");
+	/* Register for peer reset callback */
+	usb_bam_register_peer_reset_cb(d->connection_idx,
+			bam_data_peer_reset_cb, port);
+
+	ret = usb_bam_client_ready(true);
+	if (ret) {
+		pr_err("%s: usb_bam_client_ready failed: err:%d\n",
+			__func__, ret);
+		return;
+	}
+
+	pr_debug("%s: Connect workqueue done", __func__);
 }
 
 static void bam2bam_data_port_free(int portno)
@@ -203,14 +262,13 @@
 	port->port_num = portno;
 
 	INIT_WORK(&port->connect_w, bam2bam_data_connect_work);
-	INIT_WORK(&port->disconnect_w, bam2bam_data_disconnect_work);
 
 	/* data ch */
 	d = &port->data_ch;
 	d->port = port;
 	bam2bam_data_ports[portno] = port;
 
-	pr_info("port:%p portno:%d\n", port, portno);
+	pr_debug("port:%p portno:%d\n", port, portno);
 
 	return 0;
 }
@@ -218,9 +276,8 @@
 void bam_data_disconnect(struct data_port *gr, u8 port_num)
 {
 	struct bam_data_port	*port;
-	struct bam_data_ch_info	*d;
 
-	pr_info("dev:%p port#%d\n", gr, port_num);
+	pr_debug("dev:%p port#%d\n", gr, port_num);
 
 	if (port_num >= n_bam2bam_data_ports) {
 		pr_err("invalid bam2bam portno#%d\n", port_num);
@@ -234,10 +291,20 @@
 
 	port = bam2bam_data_ports[port_num];
 
-	d = &port->data_ch;
-	port->port_usb = gr;
+	if (port->port_usb && port->port_usb->in &&
+	  port->port_usb->in->driver_data) {
+		/* disable endpoints */
+		usb_ep_disable(port->port_usb->out);
+		usb_ep_disable(port->port_usb->in);
 
-	queue_work(bam_data_wq, &port->disconnect_w);
+		port->port_usb->in->driver_data = NULL;
+		port->port_usb->out->driver_data = NULL;
+
+		port->port_usb = 0;
+	}
+
+	if (usb_bam_client_ready(false))
+		pr_err("%s: usb_bam_client_ready failed\n", __func__);
 }
 
 int bam_data_connect(struct data_port *gr, u8 port_num,
@@ -247,7 +314,7 @@
 	struct bam_data_ch_info	*d;
 	int			ret;
 
-	pr_info("dev:%p port#%d\n", gr, port_num);
+	pr_debug("dev:%p port#%d\n", gr, port_num);
 
 	if (port_num >= n_bam2bam_data_ports) {
 		pr_err("invalid portno#%d\n", port_num);
@@ -292,7 +359,7 @@
 	int	i;
 	int	ret;
 
-	pr_info("requested %d BAM2BAM ports", no_bam2bam_port);
+	pr_debug("requested %d BAM2BAM ports", no_bam2bam_port);
 
 	if (!no_bam2bam_port || no_bam2bam_port > BAM2BAM_DATA_N_PORTS) {
 		pr_err("Invalid num of ports count:%d\n", no_bam2bam_port);
@@ -331,7 +398,7 @@
 	struct bam_data_port *port = (struct bam_data_port *)param;
 	struct data_port *d_port = port->port_usb;
 
-	pr_info("%s: woken up by peer\n", __func__);
+	pr_debug("%s: woken up by peer\n", __func__);
 
 	if (!d_port) {
 		pr_err("FAILED: d_port == NULL");
@@ -360,7 +427,7 @@
 	port = bam2bam_data_ports[port_num];
 	d = &port->data_ch;
 
-	pr_info("%s: suspended port %d\n", __func__, port_num);
+	pr_debug("%s: suspended port %d\n", __func__, port_num);
 	usb_bam_register_wake_cb(d->connection_idx, bam_data_wake_cb, port);
 }
 
@@ -373,7 +440,7 @@
 	port = bam2bam_data_ports[port_num];
 	d = &port->data_ch;
 
-	pr_info("%s: resumed port %d\n", __func__, port_num);
+	pr_debug("%s: resumed port %d\n", __func__, port_num);
 	usb_bam_register_wake_cb(d->connection_idx, NULL, NULL);
 }
 
diff --git a/drivers/usb/host/ehci-msm-hsic.c b/drivers/usb/host/ehci-msm-hsic.c
index 57598c8..1141a24 100644
--- a/drivers/usb/host/ehci-msm-hsic.c
+++ b/drivers/usb/host/ehci-msm-hsic.c
@@ -575,20 +575,53 @@
 {
 	int ret;
 
-	ret = clk_reset(mehci->core_clk, CLK_RESET_ASSERT);
-	if (ret) {
-		dev_err(mehci->dev, "hsic clk assert failed:%d\n", ret);
-		return;
+	/* alt_core_clk exists in targets that do not use asynchronous reset */
+	if (!IS_ERR(mehci->alt_core_clk)) {
+		ret = clk_reset(mehci->core_clk, CLK_RESET_ASSERT);
+		if (ret) {
+			dev_err(mehci->dev, "hsic clk assert failed:%d\n", ret);
+			return;
+		}
+
+		/* Since a hw bug, turn off the clock before complete reset */
+		clk_disable(mehci->core_clk);
+
+		ret = clk_reset(mehci->core_clk, CLK_RESET_DEASSERT);
+		if (ret)
+			dev_err(mehci->dev, "hsic clk deassert failed:%d\n",
+					ret);
+
+		usleep_range(10000, 12000);
+
+		clk_enable(mehci->core_clk);
+	} else {
+		/* Using asynchronous block reset to the hardware */
+		clk_disable_unprepare(mehci->core_clk);
+		clk_disable_unprepare(mehci->phy_clk);
+		clk_disable_unprepare(mehci->cal_clk);
+		clk_disable_unprepare(mehci->ahb_clk);
+
+		ret = clk_reset(mehci->core_clk, CLK_RESET_ASSERT);
+		if (ret) {
+			dev_err(mehci->dev, "hsic clk assert failed:%d\n", ret);
+			return;
+		}
+		usleep_range(10000, 12000);
+
+		ret = clk_reset(mehci->core_clk, CLK_RESET_DEASSERT);
+		if (ret)
+			dev_err(mehci->dev, "hsic clk deassert failed:%d\n",
+					ret);
+		/*
+		 * Required delay between the deassertion and
+		 *  clock enablement.
+		*/
+		ndelay(200);
+		clk_prepare_enable(mehci->core_clk);
+		clk_prepare_enable(mehci->phy_clk);
+		clk_prepare_enable(mehci->cal_clk);
+		clk_prepare_enable(mehci->ahb_clk);
 	}
-	clk_disable(mehci->core_clk);
-
-	ret = clk_reset(mehci->core_clk, CLK_RESET_DEASSERT);
-	if (ret)
-		dev_err(mehci->dev, "hsic clk deassert failed:%d\n", ret);
-
-	usleep_range(10000, 12000);
-
-	clk_enable(mehci->core_clk);
 }
 
 #define HSIC_STROBE_GPIO_PAD_CTL	(MSM_TLMM_BASE+0x20C0)
@@ -1286,7 +1319,8 @@
 		return ret;
 	}
 
-	/* alt_core_clk is for LINK to be used during PHY RESET
+	/* alt_core_clk is for LINK to be used during PHY RESET in
+	 * targets on which link does NOT use asynchronous reset methodology.
 	 * clock rate appropriately set by target specific clock driver */
 	mehci->alt_core_clk = clk_get(mehci->dev, "alt_core_clk");
 	if (IS_ERR(mehci->alt_core_clk))
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.c b/drivers/video/msm/mdp.c
index b00c7b5..31869f1 100644
--- a/drivers/video/msm/mdp.c
+++ b/drivers/video/msm/mdp.c
@@ -2308,6 +2308,10 @@
 	mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
 
 	mdp_histogram_ctrl_all(TRUE);
+
+	if (ret == 0)
+		ret = panel_next_late_init(pdev);
+
 	pr_debug("%s:-\n", __func__);
 
 	return ret;
@@ -2744,6 +2748,7 @@
 	pdata = msm_fb_dev->dev.platform_data;
 	pdata->on = mdp_on;
 	pdata->off = mdp_off;
+	pdata->late_init = NULL;
 	pdata->next = pdev;
 
 	mdp_clk_ctrl(1);
diff --git a/drivers/video/msm/mdp.h b/drivers/video/msm/mdp.h
index eab4dbe..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 {
@@ -927,7 +928,7 @@
 
 int mdp_ppp_v4l2_overlay_set(struct fb_info *info, struct mdp_overlay *req);
 int mdp_ppp_v4l2_overlay_clear(void);
-int mdp_ppp_v4l2_overlay_play(struct fb_info *info,
+int mdp_ppp_v4l2_overlay_play(struct fb_info *info, bool bUserPtr,
 	unsigned long srcp0_addr, unsigned long srcp0_size,
 	unsigned long srcp1_addr, unsigned long srcp1_size);
 void mdp_update_pm(struct msm_fb_data_type *mfd, ktime_t pre_vsync);
diff --git a/drivers/video/msm/mdp4_overlay_dsi_cmd.c b/drivers/video/msm/mdp4_overlay_dsi_cmd.c
index 9cb2b34..1d38fb0 100644
--- a/drivers/video/msm/mdp4_overlay_dsi_cmd.c
+++ b/drivers/video/msm/mdp4_overlay_dsi_cmd.c
@@ -687,7 +687,10 @@
 		msecs_to_jiffies(VSYNC_PERIOD * 4));
 	if (ret <= 0) {
 		vctrl->wait_vsync_cnt = 0;
-		return -EBUSY;
+		vsync_tick = ktime_to_ns(ktime_get());
+		ret = snprintf(buf, PAGE_SIZE, "VSYNC=%llu", vsync_tick);
+		buf[strlen(buf) + 1] = '\0';
+		return ret;
 	}
 
 	spin_lock_irqsave(&vctrl->spin_lock, flags);
diff --git a/drivers/video/msm/mdp4_overlay_dsi_video.c b/drivers/video/msm/mdp4_overlay_dsi_video.c
index a4d2b77..e22fb6d 100644
--- a/drivers/video/msm/mdp4_overlay_dsi_video.c
+++ b/drivers/video/msm/mdp4_overlay_dsi_video.c
@@ -390,7 +390,10 @@
 		msecs_to_jiffies(VSYNC_PERIOD * 4));
 	if (ret <= 0) {
 		vctrl->wait_vsync_cnt = 0;
-		return -EBUSY;
+		vsync_tick = ktime_to_ns(ktime_get());
+		ret = snprintf(buf, PAGE_SIZE, "VSYNC=%llu", vsync_tick);
+		buf[strlen(buf) + 1] = '\0';
+		return ret;
 	}
 
 	spin_lock_irqsave(&vctrl->spin_lock, flags);
diff --git a/drivers/video/msm/mdp4_overlay_dtv.c b/drivers/video/msm/mdp4_overlay_dtv.c
index b13239c..6ee1efa 100644
--- a/drivers/video/msm/mdp4_overlay_dtv.c
+++ b/drivers/video/msm/mdp4_overlay_dtv.c
@@ -376,7 +376,10 @@
 		msecs_to_jiffies(VSYNC_PERIOD * 4));
 	if (ret <= 0) {
 		vctrl->wait_vsync_cnt = 0;
-		return -EBUSY;
+		vsync_tick = ktime_to_ns(ktime_get());
+		ret = snprintf(buf, PAGE_SIZE, "VSYNC=%llu", vsync_tick);
+		buf[strlen(buf) + 1] = '\0';
+		return ret;
 	}
 
 	spin_lock_irqsave(&vctrl->spin_lock, flags);
diff --git a/drivers/video/msm/mdp4_overlay_lcdc.c b/drivers/video/msm/mdp4_overlay_lcdc.c
index 4a46d72..7c751ff 100644
--- a/drivers/video/msm/mdp4_overlay_lcdc.c
+++ b/drivers/video/msm/mdp4_overlay_lcdc.c
@@ -386,7 +386,10 @@
 		msecs_to_jiffies(VSYNC_PERIOD * 4));
 	if (ret <= 0) {
 		vctrl->wait_vsync_cnt = 0;
-		return -EBUSY;
+		vsync_tick = ktime_to_ns(ktime_get());
+		ret = snprintf(buf, PAGE_SIZE, "VSYNC=%llu", vsync_tick);
+		buf[strlen(buf) + 1] = '\0';
+		return ret;
 	}
 
 	spin_lock_irqsave(&vctrl->spin_lock, flags);
diff --git a/drivers/video/msm/mdp_ppp.c b/drivers/video/msm/mdp_ppp.c
index 8999395..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;
@@ -1698,12 +1701,19 @@
 	return 0;
 }
 
-int mdp_ppp_v4l2_overlay_play(struct fb_info *info,
+int mdp_ppp_v4l2_overlay_play(struct fb_info *info, bool bUserPtr,
 	unsigned long srcp0_addr, unsigned long srcp0_size,
 	unsigned long srcp1_addr, unsigned long srcp1_size)
 {
 	int ret;
+	unsigned long srcp0_start = 0, srcp1_start = 0;
+	unsigned long srcp0_len = 0, srcp1_len = 0;
 
+	struct ion_handle *srcp0_ihdl = NULL;
+	struct ion_handle *srcp1_ihdl = NULL;
+	struct msm_fb_data_type *mfd = info->par;
+
+	ppp_display_iclient = mfd->iclient;
 	if (!mdp_overlay_req_set) {
 		pr_err("mdp_ppp:v4l2:No overlay set, ignore play req\n");
 		return -EINVAL;
@@ -1712,6 +1722,31 @@
 	overlay_req.dst.width = info->var.xres;
 	overlay_req.dst.height = info->var.yres;
 
+	if (bUserPtr) {
+		overlay_req.src.memory_id = srcp0_addr;
+		get_img(&overlay_req.src, &overlay_req, info, &srcp0_start,
+					&srcp0_len, NULL, &srcp0_ihdl);
+		if (srcp0_len == 0) {
+			pr_err("%s: could not retrieve source image0"
+						, __func__);
+			return -EINVAL;
+		}
+		srcp0_addr = srcp0_start + srcp0_size;
+		srcp0_size = srcp0_len;
+
+		if (srcp1_addr) {
+			overlay_req.src.memory_id = srcp1_addr;
+			get_img(&overlay_req.src, &overlay_req, info,
+				&srcp1_start, &srcp1_len, NULL, &srcp1_ihdl);
+			if (srcp1_len == 0) {
+				pr_err("%s: could not retrieve source image1"
+					, __func__);
+				return -EINVAL;
+			}
+			srcp1_addr = srcp1_start + srcp1_size;
+			srcp1_size = srcp1_len;
+		}
+	}
 	ret = mdp_ppp_blit_addr(info, &overlay_req,
 		srcp0_addr, srcp0_size, srcp1_addr, srcp1_size,
 		info->fix.smem_start, info->fix.smem_len, NULL, NULL,
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/mdss_fb.c b/drivers/video/msm/mdss/mdss_fb.c
index 0db47f4..50723e7 100644
--- a/drivers/video/msm/mdss/mdss_fb.c
+++ b/drivers/video/msm/mdss/mdss_fb.c
@@ -40,6 +40,9 @@
 #include <linux/uaccess.h>
 #include <linux/version.h>
 #include <linux/vmalloc.h>
+#include <linux/sync.h>
+#include <linux/sw_sync.h>
+#include <linux/file.h>
 
 #include <mach/board.h>
 #include <mach/memory.h>
@@ -80,6 +83,10 @@
 static int mdss_fb_ioctl(struct fb_info *info, unsigned int cmd,
 			 unsigned long arg);
 static int mdss_fb_mmap(struct fb_info *info, struct vm_area_struct *vma);
+static void mdss_fb_release_fences(struct msm_fb_data_type *mfd);
+
+static void mdss_fb_commit_wq_handler(struct work_struct *work);
+static void mdss_fb_pan_idle(struct msm_fb_data_type *mfd);
 
 void mdss_fb_no_update_notify_timer_cb(unsigned long data)
 {
@@ -278,6 +285,19 @@
 
 	mdss_fb_create_sysfs(mfd);
 
+	if (mfd->timeline == NULL) {
+		char timeline_name[16];
+		snprintf(timeline_name, sizeof(timeline_name),
+			"mdss_fb_%d", mfd->index);
+		mfd->timeline = sw_sync_timeline_create(timeline_name);
+		if (mfd->timeline == NULL) {
+			pr_err("%s: cannot create time line", __func__);
+			return -ENOMEM;
+		} else {
+			mfd->timeline_value = 0;
+		}
+	}
+
 	return 0;
 }
 
@@ -340,6 +360,7 @@
 
 	pr_debug("mdss_fb suspend index=%d\n", mfd->index);
 
+	mdss_fb_pan_idle(mfd);
 	ret = mdss_fb_send_panel_event(mfd, MDSS_EVENT_SUSPEND, NULL);
 	if (ret) {
 		pr_warn("unable to suspend fb%d (%d)\n", mfd->index, ret);
@@ -372,8 +393,11 @@
 	if ((!mfd) || (mfd->key != MFD_KEY))
 		return 0;
 
+	INIT_COMPLETION(mfd->power_set_comp);
+	mfd->is_power_setting = true;
 	pr_debug("mdss_fb resume index=%d\n", mfd->index);
 
+	mdss_fb_pan_idle(mfd);
 	ret = mdss_fb_send_panel_event(mfd, MDSS_EVENT_RESUME, NULL);
 	if (ret) {
 		pr_warn("unable to resume fb%d (%d)\n", mfd->index, ret);
@@ -392,6 +416,8 @@
 		if (mfd->vsync_pending)
 			mdss_mdp_overlay_vsync_ctrl(mfd, mfd->vsync_pending);
 	}
+	mfd->is_power_setting = false;
+	complete_all(&mfd->power_set_comp);
 
 	return ret;
 }
@@ -562,9 +588,10 @@
 
 			msleep(20);
 			ret = mfd->off_fnc(mfd);
-			if (ret)
+			if (ret) {
 				mfd->panel_power_on = curr_pwr_state;
-
+				mdss_fb_release_fences(mfd);
+			}
 			mfd->op_enable = true;
 		}
 		break;
@@ -576,6 +603,14 @@
 static int mdss_fb_blank(int blank_mode, struct fb_info *info)
 {
 	struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
+	mdss_fb_pan_idle(mfd);
+	if (mfd->op_enable == 0) {
+		if (blank_mode == FB_BLANK_UNBLANK)
+			mfd->suspend.panel_power_on = true;
+		else
+			mfd->suspend.panel_power_on = false;
+		return 0;
+	}
 	return mdss_fb_blank_sub(blank_mode, info, mfd->op_enable);
 }
 
@@ -592,6 +627,7 @@
 	unsigned long off = vma->vm_pgoff << PAGE_SHIFT;
 	struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
 
+	mdss_fb_pan_idle(mfd);
 	if (off >= len) {
 		/* memory mapped io */
 		off -= len;
@@ -889,12 +925,21 @@
 	mfd->op_enable = true;
 
 	mutex_init(&mfd->no_update.lock);
+	mutex_init(&mfd->sync_mutex);
 	init_timer(&mfd->no_update.timer);
 	mfd->no_update.timer.function = mdss_fb_no_update_notify_timer_cb;
 	mfd->no_update.timer.data = (unsigned long)mfd;
 	init_completion(&mfd->update.comp);
 	init_completion(&mfd->no_update.comp);
-
+	init_completion(&mfd->commit_comp);
+	init_completion(&mfd->power_set_comp);
+	INIT_WORK(&mfd->commit_work, mdss_fb_commit_wq_handler);
+	mfd->msm_fb_backup = kzalloc(sizeof(struct msm_fb_backup_type),
+		GFP_KERNEL);
+	if (mfd->msm_fb_backup == 0) {
+		pr_err("error: not enough memory!\n");
+		return -ENOMEM;
+	}
 	if (mfd->lut_update) {
 		ret = fb_alloc_cmap(&fbi->cmap, 256, 0);
 		if (ret)
@@ -952,6 +997,7 @@
 		return -EINVAL;
 	}
 
+	mdss_fb_pan_idle(mfd);
 	mfd->ref_cnt--;
 
 	if (!mfd->ref_cnt) {
@@ -967,7 +1013,140 @@
 	return ret;
 }
 
+static void mdss_fb_power_setting_idle(struct msm_fb_data_type *mfd)
+{
+	int ret;
+
+	if (mfd->is_power_setting) {
+		ret = wait_for_completion_timeout(
+				&mfd->power_set_comp,
+			msecs_to_jiffies(WAIT_DISP_OP_TIMEOUT));
+		if (ret < 0)
+			ret = -ERESTARTSYS;
+		else if (!ret)
+			pr_err("%s wait for power_set_comp timeout %d %d",
+				__func__, ret, mfd->is_power_setting);
+		if (ret <= 0) {
+			mfd->is_power_setting = false;
+			complete_all(&mfd->power_set_comp);
+		}
+	}
+}
+
+void mdss_fb_wait_for_fence(struct msm_fb_data_type *mfd)
+{
+	int i, ret;
+	/* buf sync */
+	for (i = 0; i < mfd->acq_fen_cnt; i++) {
+		ret = sync_fence_wait(mfd->acq_fen[i], WAIT_FENCE_TIMEOUT);
+		sync_fence_put(mfd->acq_fen[i]);
+		if (ret < 0) {
+			pr_err("%s: sync_fence_wait failed! ret = %x\n",
+				__func__, ret);
+			break;
+		}
+	}
+	mfd->acq_fen_cnt = 0;
+}
+
+void mdss_fb_signal_timeline(struct msm_fb_data_type *mfd)
+{
+	mutex_lock(&mfd->sync_mutex);
+	if (mfd->timeline) {
+		sw_sync_timeline_inc(mfd->timeline, 1);
+		mfd->timeline_value++;
+	}
+	mfd->last_rel_fence = mfd->cur_rel_fence;
+	mfd->cur_rel_fence = 0;
+	mutex_unlock(&mfd->sync_mutex);
+}
+
+static void mdss_fb_release_fences(struct msm_fb_data_type *mfd)
+{
+	mutex_lock(&mfd->sync_mutex);
+	if (mfd->timeline) {
+		sw_sync_timeline_inc(mfd->timeline, 2);
+		mfd->timeline_value += 2;
+	}
+	mfd->last_rel_fence = 0;
+	mfd->cur_rel_fence = 0;
+	mutex_unlock(&mfd->sync_mutex);
+}
+
+static void mdss_fb_pan_idle(struct msm_fb_data_type *mfd)
+{
+	int ret;
+
+	if (mfd->is_committing) {
+		ret = wait_for_completion_timeout(
+				&mfd->commit_comp,
+			msecs_to_jiffies(WAIT_DISP_OP_TIMEOUT));
+		if (ret < 0)
+			ret = -ERESTARTSYS;
+		else if (!ret)
+			pr_err("%s wait for commit_comp timeout %d %d",
+				__func__, ret, mfd->is_committing);
+		if (ret <= 0) {
+			mutex_lock(&mfd->sync_mutex);
+			mfd->is_committing = 0;
+			complete_all(&mfd->commit_comp);
+			mutex_unlock(&mfd->sync_mutex);
+		}
+	}
+}
+
+static int mdss_fb_pan_display_ex(struct fb_info *info,
+		struct mdp_display_commit *disp_commit)
+{
+	struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
+	struct msm_fb_backup_type *fb_backup;
+	struct fb_var_screeninfo *var = &disp_commit->var;
+	u32 wait_for_finish = disp_commit->wait_for_finish;
+	int ret = 0;
+
+	if ((!mfd->op_enable) || (!mfd->panel_power_on))
+		return -EPERM;
+
+	if (var->xoffset > (info->var.xres_virtual - info->var.xres))
+		return -EINVAL;
+
+	if (var->yoffset > (info->var.yres_virtual - info->var.yres))
+		return -EINVAL;
+
+	mdss_fb_pan_idle(mfd);
+
+	mutex_lock(&mfd->sync_mutex);
+	if (info->fix.xpanstep)
+		info->var.xoffset =
+		(var->xoffset / info->fix.xpanstep) * info->fix.xpanstep;
+
+	if (info->fix.ypanstep)
+		info->var.yoffset =
+		(var->yoffset / info->fix.ypanstep) * info->fix.ypanstep;
+
+	fb_backup = (struct msm_fb_backup_type *)mfd->msm_fb_backup;
+	memcpy(&fb_backup->info, info, sizeof(struct fb_info));
+	memcpy(&fb_backup->disp_commit, disp_commit,
+		sizeof(struct mdp_display_commit));
+	INIT_COMPLETION(mfd->commit_comp);
+	mfd->is_committing = 1;
+	schedule_work(&mfd->commit_work);
+	mutex_unlock(&mfd->sync_mutex);
+	if (wait_for_finish)
+		mdss_fb_pan_idle(mfd);
+	return ret;
+}
+
 static int mdss_fb_pan_display(struct fb_var_screeninfo *var,
+		struct fb_info *info)
+{
+	struct mdp_display_commit disp_commit;
+	memset(&disp_commit, 0, sizeof(disp_commit));
+	disp_commit.wait_for_finish = true;
+	return mdss_fb_pan_display_ex(info, &disp_commit);
+}
+
+static int mdss_fb_pan_display_sub(struct fb_var_screeninfo *var,
 			       struct fb_info *info)
 {
 	struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
@@ -989,12 +1168,13 @@
 		info->var.yoffset =
 		(var->yoffset / info->fix.ypanstep) * info->fix.ypanstep;
 
+	mdss_fb_wait_for_fence(mfd);
 	if (mfd->dma_fnc)
 		mfd->dma_fnc(mfd);
 	else
 		pr_warn("dma function not set for panel type=%d\n",
 				mfd->panel.type);
-
+	mdss_fb_signal_timeline(mfd);
 	mdss_fb_update_backlight(mfd);
 	return 0;
 }
@@ -1015,6 +1195,34 @@
 	pinfo->vic = var->reserved[3];
 }
 
+static void mdss_fb_commit_wq_handler(struct work_struct *work)
+{
+	struct msm_fb_data_type *mfd;
+	struct fb_var_screeninfo *var;
+	struct fb_info *info;
+	struct msm_fb_backup_type *fb_backup;
+	int ret;
+
+	mfd = container_of(work, struct msm_fb_data_type, commit_work);
+	fb_backup = (struct msm_fb_backup_type *)mfd->msm_fb_backup;
+	info = &fb_backup->info;
+	if (fb_backup->disp_commit.flags &
+		MDP_DISPLAY_COMMIT_OVERLAY) {
+		mdss_fb_wait_for_fence(mfd);
+		mdss_mdp_overlay_kickoff(mfd->ctl);
+		mdss_fb_signal_timeline(mfd);
+	} else {
+		var = &fb_backup->disp_commit.var;
+		ret = mdss_fb_pan_display_sub(var, info);
+		if (ret)
+			pr_err("%s fails: ret = %x", __func__, ret);
+	}
+	mutex_lock(&mfd->sync_mutex);
+	mfd->is_committing = 0;
+	complete_all(&mfd->commit_comp);
+	mutex_unlock(&mfd->sync_mutex);
+}
+
 static int mdss_fb_check_var(struct fb_var_screeninfo *var,
 			     struct fb_info *info)
 {
@@ -1135,6 +1343,7 @@
 	struct fb_var_screeninfo *var = &info->var;
 	int old_imgType;
 
+	mdss_fb_pan_idle(mfd);
 	old_imgType = mfd->fb_imgType;
 	switch (var->bits_per_pixel) {
 	case 16:
@@ -1280,6 +1489,105 @@
 		ret = copy_to_user(argp, &mdp_pp, sizeof(struct msmfb_mdp_pp));
 	return ret;
 }
+static int mdss_fb_handle_buf_sync_ioctl(struct msm_fb_data_type *mfd,
+						struct mdp_buf_sync *buf_sync)
+{
+	int i, fence_cnt = 0, ret = 0;
+	int acq_fen_fd[MDP_MAX_FENCE_FD];
+	struct sync_fence *fence;
+
+	if ((buf_sync->acq_fen_fd_cnt > MDP_MAX_FENCE_FD) ||
+		(mfd->timeline == NULL))
+		return -EINVAL;
+
+	if ((!mfd->op_enable) || (!mfd->panel_power_on))
+		return -EPERM;
+
+	if (buf_sync->acq_fen_fd_cnt)
+		ret = copy_from_user(acq_fen_fd, buf_sync->acq_fen_fd,
+				buf_sync->acq_fen_fd_cnt * sizeof(int));
+	if (ret) {
+		pr_err("%s:copy_from_user failed", __func__);
+		return ret;
+	}
+	mutex_lock(&mfd->sync_mutex);
+	for (i = 0; i < buf_sync->acq_fen_fd_cnt; i++) {
+		fence = sync_fence_fdget(acq_fen_fd[i]);
+		if (fence == NULL) {
+			pr_info("%s: null fence! i=%d fd=%d\n", __func__, i,
+				acq_fen_fd[i]);
+			ret = -EINVAL;
+			break;
+		}
+		mfd->acq_fen[i] = fence;
+	}
+	fence_cnt = i;
+	if (ret)
+		goto buf_sync_err_1;
+	mfd->acq_fen_cnt = fence_cnt;
+	if (buf_sync->flags & MDP_BUF_SYNC_FLAG_WAIT)
+		mdss_fb_wait_for_fence(mfd);
+
+	mfd->cur_rel_sync_pt = sw_sync_pt_create(mfd->timeline,
+			mfd->timeline_value + 2);
+	if (mfd->cur_rel_sync_pt == NULL) {
+		pr_err("%s: cannot create sync point", __func__);
+		ret = -ENOMEM;
+		goto buf_sync_err_1;
+	}
+	/* create fence */
+	mfd->cur_rel_fence = sync_fence_create("mdp-fence",
+			mfd->cur_rel_sync_pt);
+	if (mfd->cur_rel_fence == NULL) {
+		sync_pt_free(mfd->cur_rel_sync_pt);
+		mfd->cur_rel_sync_pt = NULL;
+		pr_err("%s: cannot create fence", __func__);
+		ret = -ENOMEM;
+		goto buf_sync_err_1;
+	}
+	/* create fd */
+	mfd->cur_rel_fen_fd = get_unused_fd_flags(0);
+	if (mfd->cur_rel_fen_fd < 0) {
+		pr_err("%s: get_unused_fd_flags failed", __func__);
+		ret  = -EIO;
+		goto buf_sync_err_2;
+	}
+	sync_fence_install(mfd->cur_rel_fence, mfd->cur_rel_fen_fd);
+	ret = copy_to_user(buf_sync->rel_fen_fd,
+		&mfd->cur_rel_fen_fd, sizeof(int));
+	if (ret) {
+		pr_err("%s:copy_to_user failed", __func__);
+		goto buf_sync_err_3;
+	}
+	mutex_unlock(&mfd->sync_mutex);
+	return ret;
+buf_sync_err_3:
+	put_unused_fd(mfd->cur_rel_fen_fd);
+buf_sync_err_2:
+	sync_fence_put(mfd->cur_rel_fence);
+	mfd->cur_rel_fence = NULL;
+	mfd->cur_rel_fen_fd = 0;
+buf_sync_err_1:
+	for (i = 0; i < fence_cnt; i++)
+		sync_fence_put(mfd->acq_fen[i]);
+	mfd->acq_fen_cnt = 0;
+	mutex_unlock(&mfd->sync_mutex);
+	return ret;
+}
+static int mdss_fb_display_commit(struct fb_info *info,
+						unsigned long *argp)
+{
+	int ret;
+	struct mdp_display_commit disp_commit;
+	ret = copy_from_user(&disp_commit, argp,
+			sizeof(disp_commit));
+	if (ret) {
+		pr_err("%s:copy_from_user failed", __func__);
+		return ret;
+	}
+	ret = mdss_fb_pan_display_ex(info, &disp_commit);
+	return ret;
+}
 
 static int mdss_fb_ioctl(struct fb_info *info, unsigned int cmd,
 			 unsigned long arg)
@@ -1291,6 +1599,11 @@
 	u32 block, hist_data_addr = 0;
 	struct mdp_page_protection fb_page_protection;
 	int ret = -ENOSYS;
+	struct mdp_buf_sync buf_sync;
+
+	mdss_fb_power_setting_idle(mfd);
+
+	mdss_fb_pan_idle(mfd);
 
 	switch (cmd) {
 	case MSMFB_CURSOR:
@@ -1351,10 +1664,25 @@
 		ret = mdss_fb_handle_pp_ioctl(mfd, argp);
 		break;
 
+	case MSMFB_BUFFER_SYNC:
+		ret = copy_from_user(&buf_sync, argp, sizeof(buf_sync));
+		if (ret)
+			return ret;
+
+		ret = mdss_fb_handle_buf_sync_ioctl(mfd, &buf_sync);
+
+		if (!ret)
+			ret = copy_to_user(argp, &buf_sync, sizeof(buf_sync));
+		break;
+
 	case MSMFB_NOTIFY_UPDATE:
 		ret = mdss_fb_notify_update(mfd, argp);
 		break;
 
+	case MSMFB_DISPLAY_COMMIT:
+		ret = mdss_fb_display_commit(info, argp);
+		break;
+
 	default:
 		if (mfd->ioctl_handler)
 			ret = mfd->ioctl_handler(mfd, cmd, argp);
diff --git a/drivers/video/msm/mdss/mdss_fb.h b/drivers/video/msm/mdss/mdss_fb.h
index 11bb859..f651b44 100644
--- a/drivers/video/msm/mdss/mdss_fb.h
+++ b/drivers/video/msm/mdss/mdss_fb.h
@@ -27,6 +27,10 @@
 #define MSM_FB_MAX_DEV_LIST 32
 
 #define MSM_FB_ENABLE_DBGFS
+/* 900 ms for fence time out */
+#define WAIT_FENCE_TIMEOUT 900
+/* 950 ms for display operation time out */
+#define WAIT_DISP_OP_TIMEOUT 950
 
 #ifndef MAX
 #define  MAX(x, y) (((x) > (y)) ? (x) : (y))
@@ -69,6 +73,7 @@
 	ktime_t vsync_time;
 	struct completion vsync_comp;
 	spinlock_t vsync_lock;
+	int borderfill_enable;
 
 	int hw_refresh;
 
@@ -111,6 +116,30 @@
 	struct list_head pipes_cleanup;
 	struct disp_info_notify update;
 	struct disp_info_notify no_update;
+
+	u32 acq_fen_cnt;
+	struct sync_fence *acq_fen[MDP_MAX_FENCE_FD];
+	int cur_rel_fen_fd;
+	struct sync_pt *cur_rel_sync_pt;
+	struct sync_fence *cur_rel_fence;
+	struct sync_fence *last_rel_fence;
+	struct sw_sync_timeline *timeline;
+	int timeline_value;
+	u32 last_acq_fen_cnt;
+	struct sync_fence *last_acq_fen[MDP_MAX_FENCE_FD];
+	struct mutex sync_mutex;
+	/* for non-blocking */
+	struct completion commit_comp;
+	u32 is_committing;
+	struct work_struct commit_work;
+	void *msm_fb_backup;
+	struct completion power_set_comp;
+	u32 is_power_setting;
+};
+
+struct msm_fb_backup_type {
+	struct fb_info info;
+	struct mdp_display_commit disp_commit;
 };
 
 int mdss_fb_get_phys_info(unsigned long *start, unsigned long *len, int fb_num);
@@ -118,4 +147,7 @@
 void mdss_fb_update_backlight(struct msm_fb_data_type *mfd);
 int mdss_fb_suspend_all(void);
 int mdss_fb_resume_all(void);
+void mdss_fb_wait_for_fence(struct msm_fb_data_type *mfd);
+void mdss_fb_signal_timeline(struct msm_fb_data_type *mfd);
+
 #endif /* MDSS_FB_H */
diff --git a/drivers/video/msm/mdss/mdss_mdp.h b/drivers/video/msm/mdss/mdss_mdp.h
index d273201..9503489 100644
--- a/drivers/video/msm/mdss/mdss_mdp.h
+++ b/drivers/video/msm/mdss/mdss_mdp.h
@@ -129,7 +129,6 @@
 
 	u32 bus_ab_quota;
 	u32 bus_ib_quota;
-	u32 bus_quota;
 	u32 clk_rate;
 
 	struct msm_fb_data_type *mfd;
@@ -291,6 +290,7 @@
 int mdss_mdp_overlay_vsync_ctrl(struct msm_fb_data_type *mfd, int en);
 int mdss_mdp_video_start(struct mdss_mdp_ctl *ctl);
 int mdss_mdp_writeback_start(struct mdss_mdp_ctl *ctl);
+int mdss_mdp_overlay_kickoff(struct mdss_mdp_ctl *ctl);
 
 int mdss_mdp_ctl_on(struct msm_fb_data_type *mfd);
 int mdss_mdp_ctl_off(struct msm_fb_data_type *mfd);
diff --git a/drivers/video/msm/mdss/mdss_mdp_ctl.c b/drivers/video/msm/mdss/mdss_mdp_ctl.c
index bd0f6c9..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
@@ -599,6 +599,9 @@
 	mutex_lock(&ctl->lock);
 
 	ctl->power_on = true;
+	ctl->bus_ab_quota = 0;
+	ctl->bus_ib_quota = 0;
+	ctl->clk_rate = 0;
 
 	mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_ON, false);
 	ret = mdss_mdp_ctl_intf_event(ctl, MDSS_EVENT_RESET, NULL);
@@ -781,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 5b6d009..c9c6a12 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
@@ -27,10 +27,12 @@
 #include "mdss_mdp_rotator.h"
 
 #define VSYNC_PERIOD 16
+#define BORDERFILL_NDX	0x0BF000BF
 #define CHECK_BOUNDS(offset, size, max_size) \
 	(((size) > (max_size)) || ((offset) > ((max_size) - (size))))
 
 static atomic_t ov_active_panels = ATOMIC_INIT(0);
+static int mdss_mdp_overlay_free_fb_pipe(struct msm_fb_data_type *mfd);
 
 static int mdss_mdp_overlay_get(struct msm_fb_data_type *mfd,
 				struct mdp_overlay *req)
@@ -359,7 +361,7 @@
 static int mdss_mdp_overlay_set(struct msm_fb_data_type *mfd,
 				struct mdp_overlay *req)
 {
-	int ret;
+	int ret = 0;
 
 	ret = mutex_lock_interruptible(&mfd->ov_lock);
 	if (ret)
@@ -372,6 +374,8 @@
 
 	if (req->flags & MDSS_MDP_ROT_ONLY) {
 		ret = mdss_mdp_overlay_rotator_setup(mfd, req);
+	} else if (req->src.format == MDP_RGB_BORDERFILL) {
+		req->id = BORDERFILL_NDX;
 	} else {
 		struct mdss_mdp_pipe *pipe;
 
@@ -452,7 +456,7 @@
 	return 0;
 }
 
-static int mdss_mdp_overlay_kickoff(struct mdss_mdp_ctl *ctl)
+int mdss_mdp_overlay_kickoff(struct mdss_mdp_ctl *ctl)
 {
 	struct msm_fb_data_type *mfd = ctl->mfd;
 	int ret;
@@ -520,6 +524,12 @@
 	if (ret)
 		return ret;
 
+	if (ndx == BORDERFILL_NDX) {
+		pr_debug("borderfill disable\n");
+		mfd->borderfill_enable = false;
+		return 0;
+	}
+
 	if (!mfd->panel_power_on) {
 		mutex_unlock(&mfd->ov_lock);
 		return -EPERM;
@@ -677,6 +687,10 @@
 
 	if (req->id & MDSS_MDP_ROT_SESSION_MASK) {
 		ret = mdss_mdp_overlay_rotate(mfd, req);
+	} else if (req->id == BORDERFILL_NDX) {
+		pr_debug("borderfill enable\n");
+		mfd->borderfill_enable = true;
+		ret = mdss_mdp_overlay_free_fb_pipe(mfd);
 	} else {
 		ret = mdss_mdp_overlay_queue(mfd, req);
 
@@ -692,6 +706,29 @@
 	return ret;
 }
 
+static int mdss_mdp_overlay_free_fb_pipe(struct msm_fb_data_type *mfd)
+{
+	struct mdss_mdp_pipe *pipe;
+	u32 fb_ndx = 0;
+
+	pipe = mdss_mdp_mixer_stage_pipe(mfd->ctl, MDSS_MDP_MIXER_MUX_LEFT,
+					 MDSS_MDP_STAGE_BASE);
+	if (pipe)
+		fb_ndx |= pipe->ndx;
+
+	pipe = mdss_mdp_mixer_stage_pipe(mfd->ctl, MDSS_MDP_MIXER_MUX_RIGHT,
+					 MDSS_MDP_STAGE_BASE);
+	if (pipe)
+		fb_ndx |= pipe->ndx;
+
+	if (fb_ndx) {
+		pr_debug("unstaging framebuffer pipes %x\n", fb_ndx);
+		mdss_mdp_overlay_unset(mfd, fb_ndx);
+		mdss_mdp_overlay_kickoff(mfd->ctl);
+	}
+	return 0;
+}
+
 static int mdss_mdp_overlay_get_fb_pipe(struct msm_fb_data_type *mfd,
 					struct mdss_mdp_pipe **ppipe,
 					int mixer_mux)
@@ -767,7 +804,7 @@
 
 	fbi = mfd->fbi;
 
-	if (fbi->fix.smem_len == 0) {
+	if (fbi->fix.smem_len == 0 || mfd->borderfill_enable) {
 		mdss_mdp_overlay_kickoff(mfd->ctl);
 		return;
 	}
@@ -864,10 +901,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;
 	}
 
@@ -888,6 +930,8 @@
 		rc = ctl->set_vsync_handler(ctl, NULL);
 	mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_OFF, false);
 
+	mutex_unlock(&ctl->lock);
+
 	return rc;
 }
 
@@ -898,13 +942,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);
@@ -1162,7 +1213,9 @@
 		}
 		break;
 	case MSMFB_OVERLAY_COMMIT:
+		mdss_fb_wait_for_fence(mfd);
 		ret = mdss_mdp_overlay_kickoff(mfd->ctl);
+		mdss_fb_signal_timeline(mfd);
 		break;
 	default:
 		if (mfd->panel.type == WRITEBACK_PANEL)
@@ -1192,6 +1245,9 @@
 
 	rc = mdss_mdp_ctl_off(mfd);
 	if (rc == 0) {
+		if (!mfd->ref_cnt)
+			mfd->borderfill_enable = false;
+
 		if (atomic_dec_return(&ov_active_panels) == 0)
 			mdss_mdp_rotator_release_all();
 	}
diff --git a/drivers/video/msm/mdss/mdss_mdp_pp.c b/drivers/video/msm/mdss/mdss_mdp_pp.c
index c90ae82..1482935 100644
--- a/drivers/video/msm/mdss/mdss_mdp_pp.c
+++ b/drivers/video/msm/mdss/mdss_mdp_pp.c
@@ -420,19 +420,19 @@
 	pp_sts = &mdss_pp_res->pp_dspp_sts[dspp_num];
 	if (flags & PP_FLAGS_DIRTY_PA) {
 		pa_config = &mdss_pp_res->pa_disp_cfg[disp_num];
-		if (pa_config->flags & MDP_PP_OPS_WRITE) {
+		if (pa_config->pa_data.flags & MDP_PP_OPS_WRITE) {
 			offset = base + MDSS_MDP_REG_DSPP_PA_BASE;
-			MDSS_MDP_REG_WRITE(offset, pa_config->hue_adj);
+			MDSS_MDP_REG_WRITE(offset, pa_config->pa_data.hue_adj);
 			offset += 4;
-			MDSS_MDP_REG_WRITE(offset, pa_config->sat_adj);
+			MDSS_MDP_REG_WRITE(offset, pa_config->pa_data.sat_adj);
 			offset += 4;
-			MDSS_MDP_REG_WRITE(offset, pa_config->val_adj);
+			MDSS_MDP_REG_WRITE(offset, pa_config->pa_data.val_adj);
 			offset += 4;
-			MDSS_MDP_REG_WRITE(offset, pa_config->cont_adj);
+			MDSS_MDP_REG_WRITE(offset, pa_config->pa_data.cont_adj);
 		}
-		if (pa_config->flags & MDP_PP_OPS_DISABLE)
+		if (pa_config->pa_data.flags & MDP_PP_OPS_DISABLE)
 			pp_sts->pa_sts &= ~PP_STS_ENABLE;
-		else if (pa_config->flags & MDP_PP_OPS_ENABLE)
+		else if (pa_config->pa_data.flags & MDP_PP_OPS_ENABLE)
 			pp_sts->pa_sts |= PP_STS_ENABLE;
 	}
 	if (pp_sts->pa_sts & PP_STS_ENABLE)
@@ -636,7 +636,7 @@
 	mutex_lock(&mdss_pp_mutex);
 	disp_num = config->block - MDP_LOGICAL_BLOCK_DISP_0;
 
-	if (config->flags & MDP_PP_OPS_READ) {
+	if (config->pa_data.flags & MDP_PP_OPS_READ) {
 		ret = pp_get_dspp_num(disp_num, &dspp_num);
 		if (ret) {
 			pr_err("%s, no dspp connects to disp %d",
@@ -646,13 +646,13 @@
 		mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_ON, false);
 		pa_offset = MDSS_MDP_REG_DSPP_OFFSET(dspp_num) +
 			  MDSS_MDP_REG_DSPP_PA_BASE;
-		config->hue_adj = MDSS_MDP_REG_READ(pa_offset);
+		config->pa_data.hue_adj = MDSS_MDP_REG_READ(pa_offset);
 		pa_offset += 4;
-		config->sat_adj = MDSS_MDP_REG_READ(pa_offset);
+		config->pa_data.sat_adj = MDSS_MDP_REG_READ(pa_offset);
 		pa_offset += 4;
-		config->val_adj = MDSS_MDP_REG_READ(pa_offset);
+		config->pa_data.val_adj = MDSS_MDP_REG_READ(pa_offset);
 		pa_offset += 4;
-		config->cont_adj = MDSS_MDP_REG_READ(pa_offset);
+		config->pa_data.cont_adj = MDSS_MDP_REG_READ(pa_offset);
 		*copyback = 1;
 		mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_OFF, false);
 	} else {
diff --git a/drivers/video/msm/mdss/mhl_sii8334.c b/drivers/video/msm/mdss/mhl_sii8334.c
index aa3a827..f3be983 100644
--- a/drivers/video/msm/mdss/mhl_sii8334.c
+++ b/drivers/video/msm/mdss/mhl_sii8334.c
@@ -30,6 +30,7 @@
 
 #define MHL_DRIVER_NAME "sii8334"
 #define COMPATIBLE_NAME "qcom,mhl-sii8334"
+#define MAX_CURRENT 700000
 
 #define pr_debug_intr(...) pr_debug("\n")
 
@@ -62,6 +63,10 @@
 	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;
 };
 
 
@@ -203,11 +208,29 @@
 	return 0;
 }
 
+
+static int mhl_sii_wait_for_rgnd(struct mhl_tx_ctrl *mhl_ctrl)
+{
+	int timeout;
+	/* let isr handle RGND interrupt */
+	pr_debug("%s:%u\n", __func__, __LINE__);
+	INIT_COMPLETION(mhl_ctrl->rgnd_done);
+	timeout = wait_for_completion_interruptible_timeout
+		(&mhl_ctrl->rgnd_done, HZ/2);
+	if (!timeout) {
+		/* most likely nothing plugged in USB */
+		/* USB HOST connected or already in USB mode */
+		pr_warn("%s:%u timedout\n", __func__, __LINE__);
+		return -ENODEV;
+	}
+	return mhl_ctrl->mhl_mode ? 0 : 1;
+}
+
 /*  USB_HANDSHAKING FUNCTIONS */
 static int mhl_sii_device_discovery(void *data, int id,
 			     void (*usb_notify_cb)(int online))
 {
-	int timeout, rc;
+	int rc;
 	struct mhl_tx_ctrl *mhl_ctrl = data;
 
 	if (id) {
@@ -227,33 +250,86 @@
 	if (!mhl_ctrl->notify_usb_online)
 		mhl_ctrl->notify_usb_online = usb_notify_cb;
 
-	mhl_sii_reset_pin(mhl_ctrl, 0);
-	msleep(50);
-	mhl_sii_reset_pin(mhl_ctrl, 1);
-	/* TX PR-guide requires a 100 ms wait here */
-
-	msleep(100);
-	mhl_init_reg_settings(mhl_ctrl, true);
-
-	if (mhl_ctrl->cur_state == POWER_STATE_D3) {
-		/* give MHL driver chance to handle RGND interrupt */
-		INIT_COMPLETION(mhl_ctrl->rgnd_done);
-		timeout = wait_for_completion_interruptible_timeout
-			(&mhl_ctrl->rgnd_done, HZ/2);
-		if (!timeout) {
-			/* most likely nothing plugged in USB */
-			/* USB HOST connected or already in USB mode */
-			pr_debug("Timedout Returning from discovery mode\n");
-			return 0;
-		}
-		rc = mhl_ctrl->mhl_mode ? 0 : 1;
+	if (!mhl_ctrl->disc_enabled) {
+		mhl_sii_reset_pin(mhl_ctrl, 0);
+		msleep(50);
+		mhl_sii_reset_pin(mhl_ctrl, 1);
+		/* TX PR-guide requires a 100 ms wait here */
+		msleep(100);
+		mhl_init_reg_settings(mhl_ctrl, true);
+		rc = mhl_sii_wait_for_rgnd(mhl_ctrl);
 	} else {
-		/* not in D3. already in MHL mode */
-		rc = 0;
+		if (mhl_ctrl->cur_state == POWER_STATE_D3) {
+			rc = mhl_sii_wait_for_rgnd(mhl_ctrl);
+		} else {
+			/* in MHL mode */
+			pr_debug("%s:%u\n", __func__, __LINE__);
+			rc = 0;
+		}
 	}
+	pr_debug("%s: ret result: %s\n", __func__, rc ? "usb" : " mhl");
 	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;
@@ -506,7 +582,8 @@
 		 */
 		MHL_SII_REG_NAME_WR(REG_MHLTX_CTL1, 0xD0);
 		msleep(50);
-		MHL_SII_REG_NAME_MOD(REG_DISC_CTRL1, BIT1 | BIT0, 0x00);
+		if (!mhl_ctrl->disc_enabled)
+			MHL_SII_REG_NAME_MOD(REG_DISC_CTRL1, BIT1 | BIT0, 0x00);
 		MHL_SII_PAGE3_MOD(0x003D, BIT0, 0x00);
 		mhl_ctrl->cur_state = POWER_STATE_D3;
 		break;
@@ -606,6 +683,7 @@
 	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 {
@@ -704,9 +782,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) {
@@ -716,6 +794,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);
 	}
@@ -1216,6 +1295,7 @@
 	 * Other initializations
 	 * such tx specific
 	 */
+	mhl_ctrl->disc_enabled = false;
 	rc = mhl_tx_chip_init(mhl_ctrl);
 	if (rc) {
 		pr_err("%s: tx chip init failed [%d]\n",
@@ -1240,6 +1320,24 @@
 	} 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);
@@ -1257,6 +1355,8 @@
 	mhl_ctrl->mhl_info = mhl_info;
 	return 0;
 failed_probe:
+	mhl_gpio_config(mhl_ctrl, 0);
+	mhl_vreg_config(mhl_ctrl, 0);
 	/* do not deep-free */
 	if (mhl_info)
 		devm_kfree(&client->dev, mhl_info);
diff --git a/drivers/video/msm/mipi_dsi.c b/drivers/video/msm/mipi_dsi.c
index 35b6ae6..82d82c4 100644
--- a/drivers/video/msm/mipi_dsi.c
+++ b/drivers/video/msm/mipi_dsi.c
@@ -319,6 +319,11 @@
 	return ret;
 }
 
+static int mipi_dsi_late_init(struct platform_device *pdev)
+{
+	return panel_next_late_init(pdev);
+}
+
 
 static int mipi_dsi_resource_initialized;
 
@@ -463,6 +468,7 @@
 	pdata = mdp_dev->dev.platform_data;
 	pdata->on = mipi_dsi_on;
 	pdata->off = mipi_dsi_off;
+	pdata->late_init = mipi_dsi_late_init;
 	pdata->next = pdev;
 
 	/*
diff --git a/drivers/video/msm/mipi_novatek.c b/drivers/video/msm/mipi_novatek.c
index 7e0a46e..8f8a525 100644
--- a/drivers/video/msm/mipi_novatek.c
+++ b/drivers/video/msm/mipi_novatek.c
@@ -451,6 +451,11 @@
 	return 0;
 }
 
+static int mipi_novatek_lcd_late_init(struct platform_device *pdev)
+{
+	return 0;
+}
+
 DEFINE_LED_TRIGGER(bkl_led_trigger);
 
 static char led_pwm1[2] = {0x51, 0x0};	/* DTYPE_DCS_WRITE1 */
@@ -555,6 +560,7 @@
 static struct msm_fb_panel_data novatek_panel_data = {
 	.on		= mipi_novatek_lcd_on,
 	.off		= mipi_novatek_lcd_off,
+	.late_init	= mipi_novatek_lcd_late_init,
 	.set_backlight = mipi_novatek_set_backlight,
 };
 
diff --git a/drivers/video/msm/mipi_toshiba.c b/drivers/video/msm/mipi_toshiba.c
index 63504c9..b97077a 100644
--- a/drivers/video/msm/mipi_toshiba.c
+++ b/drivers/video/msm/mipi_toshiba.c
@@ -238,6 +238,11 @@
 	return 0;
 }
 
+static int mipi_toshiba_lcd_late_init(struct platform_device *pdev)
+{
+	return 0;
+}
+
 void mipi_bklight_pwm_cfg(void)
 {
 	if (mipi_toshiba_pdata && mipi_toshiba_pdata->dsi_pwm_cfg)
@@ -310,6 +315,7 @@
 static struct msm_fb_panel_data toshiba_panel_data = {
 	.on		= mipi_toshiba_lcd_on,
 	.off		= mipi_toshiba_lcd_off,
+	.late_init	= mipi_toshiba_lcd_late_init,
 	.set_backlight  = mipi_toshiba_set_backlight,
 };
 
diff --git a/drivers/video/msm/msm_fb.c b/drivers/video/msm/msm_fb.c
index b7e0bbf..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);
@@ -3877,7 +3853,7 @@
 EXPORT_SYMBOL(msm_fb_v4l2_enable);
 
 /* Called by v4l2 driver to provide a frame for display */
-int msm_fb_v4l2_update(void *par,
+int msm_fb_v4l2_update(void *par, bool bUserPtr,
 	unsigned long srcp0_addr, unsigned long srcp0_size,
 	unsigned long srcp1_addr, unsigned long srcp1_size,
 	unsigned long srcp2_addr, unsigned long srcp2_size)
@@ -3889,9 +3865,14 @@
 		srcp2_addr);
 #else
 #ifdef CONFIG_FB_MSM_MDP30
-	return mdp_ppp_v4l2_overlay_play(fbi_list[0],
-		srcp0_addr, srcp0_size,
-		srcp1_addr, srcp1_size);
+	if (bUserPtr)
+		return mdp_ppp_v4l2_overlay_play(fbi_list[0], true,
+				srcp0_addr, srcp0_size,
+				srcp1_addr, srcp1_size);
+	else
+		return mdp_ppp_v4l2_overlay_play(fbi_list[0], false,
+			srcp0_addr, srcp0_size,
+			srcp1_addr, srcp1_size);
 #else
 	return -EINVAL;
 #endif
diff --git a/drivers/video/msm/msm_fb_panel.c b/drivers/video/msm/msm_fb_panel.c
index 8640116..c604f02 100644
--- a/drivers/video/msm/msm_fb_panel.c
+++ b/drivers/video/msm/msm_fb_panel.c
@@ -78,6 +78,28 @@
 	return ret;
 }
 
+int panel_next_late_init(struct platform_device *pdev)
+{
+	int ret = 0;
+	struct msm_fb_panel_data *pdata;
+	struct msm_fb_panel_data *next_pdata;
+	struct platform_device *next_pdev;
+
+	pdata = (struct msm_fb_panel_data *)pdev->dev.platform_data;
+
+	if (pdata) {
+		next_pdev = pdata->next;
+		if (next_pdev) {
+			next_pdata = (struct msm_fb_panel_data *)
+					next_pdev->dev.platform_data;
+			if ((next_pdata) && (next_pdata->late_init))
+				ret = next_pdata->late_init(next_pdev);
+		}
+	}
+
+	return ret;
+}
+
 struct platform_device *msm_fb_device_alloc(struct msm_fb_panel_data *pdata,
 						u32 type, u32 id)
 {
diff --git a/drivers/video/msm/msm_fb_panel.h b/drivers/video/msm/msm_fb_panel.h
index 505928e..9e08405 100644
--- a/drivers/video/msm/msm_fb_panel.h
+++ b/drivers/video/msm/msm_fb_panel.h
@@ -200,6 +200,7 @@
 	/* function entry chain */
 	int (*on) (struct platform_device *pdev);
 	int (*off) (struct platform_device *pdev);
+	int (*late_init) (struct platform_device *pdev);
 	int (*power_ctrl) (boolean enable);
 	struct platform_device *next;
 	int (*clk_func) (int enable);
@@ -224,6 +225,7 @@
 						u32 type, u32 id);
 int panel_next_on(struct platform_device *pdev);
 int panel_next_off(struct platform_device *pdev);
+int panel_next_late_init(struct platform_device *pdev);
 
 int lcdc_device_register(struct msm_panel_info *pinfo);
 
diff --git a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl.c b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl.c
index a82feb9..91cf3ae 100644
--- a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl.c
+++ b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl.c
@@ -88,7 +88,7 @@
 			ddl_context->dram_base_a.align_virtual_addr;
 	}
 	if (!status) {
-		ddl_context->metadata_shared_input.mem_type = DDL_FW_MEM;
+		ddl_context->metadata_shared_input.mem_type = DDL_CMD_MEM;
 		ptr = ddl_pmem_alloc(&ddl_context->metadata_shared_input,
 			DDL_METADATA_TOTAL_INPUTBUFSIZE,
 			DDL_LINEAR_BUFFER_ALIGN_BYTES);
@@ -280,6 +280,25 @@
 		return VCD_ERR_ILLEGAL_OP;
 	}
 	encoder = &ddl->codec_data.encoder;
+	if (DDL_IS_LTR_ENABLED(encoder)) {
+		DDL_MSG_HIGH("LTR enabled, mode %u count %u",
+			(u32)encoder->ltr_control.ltrmode.ltr_mode,
+			(u32)encoder->ltr_control.ltr_count);
+		status = ddl_allocate_ltr_list(&encoder->ltr_control);
+		if (status) {
+			DDL_MSG_ERROR("%s: allocate ltr list failed",
+				__func__);
+			return status;
+		} else {
+			ddl_clear_ltr_list(&encoder->ltr_control, false);
+		}
+		encoder->num_references_for_p_frame = 2;
+		encoder->ltr_control.callback_reqd = false;
+		encoder->ltr_control.curr_ltr_id = (u32)DDL_LTR_FRAME_START_ID;
+		DDL_MSG_HIGH("num_ref_for_p_frames %u, curr_ltr_id = %u",
+			(u32)encoder->num_references_for_p_frame,
+			(u32)encoder->ltr_control.curr_ltr_id);
+	}
 	status = ddl_allocate_enc_hw_buffers(ddl);
 	if (status)
 		return status;
@@ -393,7 +412,7 @@
 		(struct ddl_client_context *) ddl_handle;
 	struct ddl_context *ddl_context;
 	struct ddl_decoder_data *decoder;
-	DDL_MSG_HIGH("ddl_decode_frame");
+	DDL_MSG_MED("ddl_decode_frame");
 	ddl_context = ddl_get_context();
 	if (!DDL_IS_INITIALIZED(ddl_context)) {
 		DDL_MSG_ERROR("ddl_dec_frame:Not_inited");
diff --git a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl.h b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl.h
index 8836b33..248ad57 100644
--- a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl.h
+++ b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl.h
@@ -52,6 +52,19 @@
 #define DDLCLIENT_STATE_IS(ddl, state) \
 	(state == (ddl)->client_state)
 
+#define DDL_IS_LTR_ENABLED(encoder) \
+	((encoder->ltr_control.ltrmode.ltr_mode == \
+		VCD_LTR_MODE_AUTO || \
+	encoder->ltr_control.ltrmode.ltr_mode == \
+		VCD_LTR_MODE_MANUAL) && \
+	(encoder->ltr_control.ltr_count > 0))
+
+#define DDL_IS_LTR_IN_AUTO_MODE(encoder) \
+	((encoder->ltr_control.ltrmode.ltr_mode == \
+		VCD_LTR_MODE_AUTO) && \
+	(encoder->ltr_control.ltr_count > 0) && \
+	(encoder->ltr_control.ltr_period > 0))
+
 #define DDL_DPB_OP_INIT       1
 #define DDL_DPB_OP_MARK_FREE  2
 #define DDL_DPB_OP_MARK_BUSY  3
@@ -72,6 +85,7 @@
 #define DDL_ENC_CHANGE_BITRATE    0x04
 #define DDL_ENC_CHANGE_FRAMERATE  0x08
 #define DDL_ENC_CHANGE_CIR        0x10
+#define DDL_ENC_LTR_USE_FRAME     0x20
 
 #define DDL_DEC_REQ_OUTPUT_FLUSH  0x1
 
@@ -86,6 +100,9 @@
 
 #define MDP_MIN_TILE_HEIGHT			96
 
+#define DDL_MAX_NUM_LTR_FRAMES                  2
+#define DDL_LTR_FRAME_START_ID                  1
+
 enum ddl_mem_area {
 	DDL_FW_MEM	= 0x0,
 	DDL_MM_MEM	= 0x1,
@@ -188,6 +205,7 @@
 	struct ddl_buf_addr h264_nb_ip;
 	struct ddl_buf_addr context;
 	struct ddl_buf_addr extnuserdata;
+	struct ddl_buf_addr meta_hdr[DDL_MAX_BUFFER_COUNT];
 };
 struct ddl_enc_buffer_size{
 	u32  sz_cur_y;
@@ -242,6 +260,43 @@
 	u32 seqdisp_extdump_enable;
 	u32 seq_extdump_enable;
 };
+
+
+struct ddl_ltrlist {
+	bool ltr_in_use;
+	u32 ltr_id;
+};
+
+struct ddl_ltr_encoding_type {
+	struct vcd_property_ltrmode_type  ltrmode;
+	struct vcd_property_ltruse_type  failed_use_cmd;
+	struct ddl_ltrlist *ltr_list;
+	u32 ltr_count;
+	u32 ltr_period;
+	u32 ltr_use_frames;
+	u32 curr_ltr_id;
+	u32 storing_idx;
+	u32 out_frame_cnt_to_use_this_ltr;
+	u32 out_frame_cnt_before_next_idr;
+	bool storing;
+	bool callback_reqd;
+	bool meta_data_reqd;
+	bool using;
+	bool first_ltr_use_arvd;
+	bool use_ltr_reqd;
+	bool store_for_intraframe_insertion;
+	bool pending_chg_ltr_useframes; /* True if
+		 * corresponding driver context of
+		 * out_frame_cnt_to_use_this_ltr
+		 * is pending to be changed with
+		 * client settings
+		 */
+	bool store_ltr0;
+	bool store_ltr1;
+	bool use_ltr0;
+	bool use_ltr1;
+};
+
 struct ddl_encoder_data{
 	struct ddl_codec_data_hdr   hdr;
 	struct vcd_property_codec   codec;
@@ -275,6 +330,7 @@
 	struct ddl_enc_buffers  hw_bufs;
 	struct ddl_yuv_buffer_size  input_buf_size;
 	struct vidc_1080p_enc_frame_info enc_frame_info;
+	struct ddl_ltr_encoding_type  ltr_control;
 	u32  plusptype_enable;
 	u32  meta_data_enable_flag;
 	u32  suffix;
@@ -291,6 +347,7 @@
 	u32  num_references_for_p_frame;
 	u32  closed_gop;
 	u32  num_slices_comp;
+	bool  intra_period_changed;
 	struct vcd_property_slice_delivery_info slice_delivery_info;
 	struct ddl_batch_frame_data batch_frame;
 	u32 avc_delimiter_enable;
@@ -496,7 +553,7 @@
 #ifdef DDL_BUF_LOG
 void ddl_list_buffers(struct ddl_client_context *ddl);
 #endif
-#ifdef DDL_MSG_LOG
+#if DDL_MSG_LOG
 s8 *ddl_get_state_string(enum ddl_client_state client_state);
 #endif
 extern unsigned char *vidc_video_codec_fw;
@@ -510,4 +567,21 @@
 void ddl_vidc_decode_reset_avg_time(struct ddl_client_context *ddl);
 void ddl_calc_core_proc_time(const char *func_name, u32 index,
 		struct ddl_client_context *ddl);
+s32 ddl_encoder_ltr_control(struct ddl_client_context *ddl);
+void ddl_encoder_use_ltr_fail_callback(
+	struct ddl_client_context *ddl);
+void ddl_handle_ltr_in_framedone(struct ddl_client_context *ddl);
+s32 ddl_clear_ltr_list(struct ddl_ltr_encoding_type *ltr_control,
+	bool only_use_flag);
+s32 ddl_find_oldest_ltr_not_in_use(
+	struct ddl_ltr_encoding_type *ltr_control);
+s32 ddl_find_ltr_in_use(struct ddl_ltr_encoding_type *ltr_control);
+s32 ddl_find_ltr_from_list(struct ddl_ltr_encoding_type *ltr_control,
+	u32 ltr_id);
+s32 ddl_use_ltr_from_list(struct ddl_ltr_encoding_type *ltr_control,
+	u32 ltr_idx);
+s32 ddl_allocate_ltr_list(struct ddl_ltr_encoding_type *ltr_control);
+s32 ddl_free_ltr_list(struct ddl_ltr_encoding_type *ltr_control);
+void ddl_print_ltr_list(struct ddl_ltr_encoding_type *ltr_control);
+
 #endif
diff --git a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_core.h b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_core.h
index db8a777..ddfd7e8 100644
--- a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_core.h
+++ b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_core.h
@@ -154,4 +154,10 @@
 #define VIDC_SM_ERR_CONCEALMENT_INTER_SLICE_MB_COPY		2
 #define VIDC_SM_ERR_CONCEALMENT_INTRA_SLICE_COLOR_CONCEALMENT	1
 
+#define DDL_MAX_P_FRAMES_IN_INTRA_INTERVAL      0xffff
+
+#define DDL_SATURATE_P_FRAMES_IN_INTRA_INTERVAL(p_rames) \
+	(((p_rames) > (DDL_MAX_P_FRAMES_IN_INTRA_INTERVAL - 1)) ? \
+	(DDL_MAX_P_FRAMES_IN_INTRA_INTERVAL) : (p_rames))
+
 #endif
diff --git a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_helper.c b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_helper.c
index 1782fd2..729fb2e 100644
--- a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_helper.c
+++ b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_helper.c
@@ -22,7 +22,7 @@
 	return &ddl_context;
 }
 
-#ifdef DDL_MSG_LOG
+#if DDL_MSG_LOG
 s8 *ddl_get_state_string(enum ddl_client_state client_state)
 {
 	s8 *ptr;
@@ -265,7 +265,7 @@
 	luma_size = ddl_get_yuv_buf_size(decoder->frame_size.width,
 			decoder->frame_size.height, DDL_YUV_BUF_TYPE_TILE);
 	dpb = decoder->dp_buf.no_of_dec_pic_buf;
-	DDL_MSG_LOW("%s Decoder num DPB buffers = %u Luma Size = %u"
+	DDL_MSG_LOW("%s Decoder num DPB buffers = %u Luma Size = %u",
 				 __func__, dpb, luma_size);
 	if (dpb > DDL_MAX_BUFFER_COUNT)
 		dpb = DDL_MAX_BUFFER_COUNT;
@@ -298,7 +298,7 @@
 		luma[i] = DDL_OFFSET(ddl_context->dram_base_a.
 			align_physical_addr, frame[i].vcd_frm.physical);
 		chroma[i] = luma[i] + luma_size;
-		DDL_MSG_LOW("%s Decoder Luma address = %x Chroma address = %x"
+		DDL_MSG_LOW("%s Decoder Luma address = %x Chroma address = %x",
 					__func__, luma[i], chroma[i]);
 	}
 	switch (decoder->codec.codec) {
@@ -403,6 +403,7 @@
 		ddl_vidc_encode_dynamic_property(ddl, false);
 		encoder->dynamic_prop_change = 0;
 		ddl_free_enc_hw_buffers(ddl);
+		ddl_free_ltr_list(&encoder->ltr_control);
 	}
 	ddl_pmem_free(&ddl->shared_mem[0]);
 	ddl_pmem_free(&ddl->shared_mem[1]);
@@ -780,7 +781,7 @@
 		}
 	}
 	if (buf_size.sz_extnuserdata > 0) {
-		dec_bufs->extnuserdata.mem_type = DDL_FW_MEM;
+		dec_bufs->extnuserdata.mem_type = DDL_CMD_MEM;
 		ptr = ddl_pmem_alloc(&dec_bufs->extnuserdata,
 				buf_size.sz_extnuserdata, DDL_KILO_BYTE(2));
 		if (!ptr)
@@ -999,7 +1000,7 @@
 	u32 luma_size, i, dpb;
 	luma_size = decoder->dpb_buf_size.size_y;
 	dpb = decoder->dp_buf.no_of_dec_pic_buf;
-	DDL_MSG_HIGH("%s Decoder num DPB buffers = %u Luma Size = %u"
+	DDL_MSG_HIGH("%s Decoder num DPB buffers = %u Luma Size = %u",
 			 __func__, dpb, luma_size);
 	if (dpb > DDL_MAX_BUFFER_COUNT)
 		dpb = DDL_MAX_BUFFER_COUNT;
@@ -1137,8 +1138,295 @@
 				vidc_time_out = temp;
 		}
 	}
-	DDL_MSG_HIGH("%s Video core time out value = 0x%x",
+	DDL_MSG_LOW("%s Video core time out value = 0x%x",
 		 __func__, vidc_time_out);
 	vidc_sm_set_video_core_timeout_value(
 		&ddl->shared_mem[ddl->command_channel], vidc_time_out);
 }
+
+void ddl_handle_ltr_in_framedone(struct ddl_client_context *ddl)
+{
+	struct ddl_ltr_encoding_type *ltr_control =
+		&ddl->codec_data.encoder.ltr_control;
+	DDL_MSG_LOW("%s:", __func__);
+	if (ltr_control->storing) {
+		ltr_control->ltr_list[ltr_control->storing_idx].ltr_id =
+			ltr_control->curr_ltr_id;
+		DDL_MSG_MED("Encoder output stores LTR ID %d into entry %d",
+			ltr_control->curr_ltr_id, ltr_control->storing_idx);
+		ltr_control->meta_data_reqd = true;
+		ltr_control->storing = false;
+	}
+	ltr_control->out_frame_cnt_before_next_idr++;
+	if (ltr_control->out_frame_cnt_to_use_this_ltr) {
+		ltr_control->out_frame_cnt_to_use_this_ltr--;
+		if (!ltr_control->out_frame_cnt_to_use_this_ltr)
+			ddl_clear_ltr_list(ltr_control, true);
+	}
+}
+
+s32 ddl_encoder_ltr_control(struct ddl_client_context *ddl)
+{
+	s32 vcd_status = VCD_S_SUCCESS;
+	struct ddl_encoder_data *encoder = &ddl->codec_data.encoder;
+	struct ddl_ltr_encoding_type *ltr_ctrl = &encoder->ltr_control;
+	bool intra_period_reached = false;
+
+	DDL_MSG_LOW("%s:", __func__);
+	ddl_print_ltr_list(ltr_ctrl);
+
+	if (DDL_IS_LTR_IN_AUTO_MODE(encoder)) {
+		bool finite_i_period, infinite_i_period;
+		DDL_MSG_LOW("%s: before LTR encoding: output "\
+			"count before next IDR %d", __func__,
+			ltr_ctrl->out_frame_cnt_before_next_idr);
+		finite_i_period =
+			(DDL_MAX_P_FRAMES_IN_INTRA_INTERVAL !=
+			encoder->i_period.p_frames) &&
+			(!(ltr_ctrl->out_frame_cnt_before_next_idr %
+			(encoder->i_period.p_frames + 1)));
+		infinite_i_period =
+			((DDL_MAX_P_FRAMES_IN_INTRA_INTERVAL ==
+			encoder->i_period.p_frames) &&
+			(!ltr_ctrl->out_frame_cnt_before_next_idr));
+		if (finite_i_period || infinite_i_period) {
+			DDL_MSG_HIGH("%s: Intra period reached. "\
+			"finite_i_period (%u), infinite_i_period (%u)",
+			__func__, (u32)finite_i_period,
+			(u32)infinite_i_period);
+			intra_period_reached = true;
+		}
+		if (intra_period_reached ||
+			ltr_ctrl->store_for_intraframe_insertion ||
+			encoder->intra_period_changed) {
+			ddl_clear_ltr_list(ltr_ctrl, false);
+			ltr_ctrl->out_frame_cnt_before_next_idr = 0;
+			ltr_ctrl->first_ltr_use_arvd = false;
+			ltr_ctrl->store_for_intraframe_insertion = false;
+		} else {
+			if (ltr_ctrl->first_ltr_use_arvd == false) {
+				ddl_use_ltr_from_list(ltr_ctrl, 0);
+				ltr_ctrl->out_frame_cnt_to_use_this_ltr =
+					0xFFFFFFFF;
+				ltr_ctrl->use_ltr_reqd = true;
+			}
+		}
+		if (!(ltr_ctrl->out_frame_cnt_before_next_idr %
+			ltr_ctrl->ltr_period)) {
+			s32 idx;
+			DDL_MSG_HIGH("%s: reached LTR period "\
+				"out_frame_cnt_before_next_idr %d",
+				__func__, ltr_ctrl->\
+				out_frame_cnt_before_next_idr);
+			idx = ddl_find_oldest_ltr_not_in_use(
+					ltr_ctrl);
+			if (idx >= 0) {
+				ltr_ctrl->storing = true;
+				ltr_ctrl->storing_idx = idx;
+				if (idx == 0)
+					ltr_ctrl->store_ltr0 = true;
+				else if (idx == 1)
+					ltr_ctrl->store_ltr1 = true;
+			}
+		}
+	}
+	if (encoder->intra_frame_insertion) {
+		DDL_MSG_HIGH("%s: I-frame insertion requested, "\
+			"delay LTR store for one frame", __func__);
+		ltr_ctrl->store_for_intraframe_insertion = true;
+	}
+	if (ltr_ctrl->pending_chg_ltr_useframes) {
+		ltr_ctrl->out_frame_cnt_to_use_this_ltr =
+			ltr_ctrl->ltr_use_frames;
+		ltr_ctrl->pending_chg_ltr_useframes = false;
+	}
+	if (ltr_ctrl->out_frame_cnt_to_use_this_ltr)
+		ltr_ctrl->use_ltr_reqd = true;
+	if (ltr_ctrl->use_ltr_reqd) {
+		s32 idx;
+		idx = ddl_find_ltr_in_use(ltr_ctrl);
+		if (idx == 0)
+			ltr_ctrl->use_ltr0 = true;
+		else if (idx == 1)
+			ltr_ctrl->use_ltr1 = true;
+		ltr_ctrl->using = true;
+		ltr_ctrl->use_ltr_reqd = false;
+	} else {
+		DDL_MSG_HIGH("%s: use_ltr_reqd skipped", __func__);
+	}
+
+	return vcd_status;
+}
+
+
+s32 ddl_allocate_ltr_list(struct ddl_ltr_encoding_type *ltr_control)
+{
+	s32 vcd_status = VCD_S_SUCCESS;
+
+	DDL_MSG_LOW("%s: lrr_cout = %u", __func__, ltr_control->ltr_count);
+	if (!ltr_control->ltr_list) {
+		if (ltr_control->ltr_count) {
+			ltr_control->ltr_list = (struct ddl_ltrlist *)
+				kmalloc(sizeof(struct ddl_ltrlist)*
+					ltr_control->ltr_count, GFP_KERNEL);
+			if (!ltr_control->ltr_list) {
+				DDL_MSG_ERROR("ddl_allocate_ltr_list failed");
+				vcd_status = VCD_ERR_ALLOC_FAIL;
+			}
+		} else {
+			DDL_MSG_ERROR("%s: failed, zero LTR count", __func__);
+			vcd_status = VCD_ERR_FAIL;
+		}
+	} else {
+		DDL_MSG_HIGH("WARN: ltr_list already allocated");
+	}
+
+	return vcd_status;
+}
+
+s32 ddl_free_ltr_list(struct ddl_ltr_encoding_type *ltr_control)
+{
+	s32 vcd_status = VCD_S_SUCCESS;
+
+	DDL_MSG_LOW("%s:", __func__);
+	kfree(ltr_control->ltr_list);
+	ltr_control->ltr_list = NULL;
+
+	return vcd_status;
+}
+
+s32 ddl_clear_ltr_list(struct ddl_ltr_encoding_type *ltr_control,
+	bool only_use_flag)
+{
+	s32 vcd_status = VCD_S_SUCCESS;
+	u32 i;
+
+	DDL_MSG_LOW("%s:", __func__);
+	for (i = 0; i < ltr_control->ltr_count; i++) {
+		ltr_control->ltr_list[i].ltr_in_use = false;
+		if (!only_use_flag)
+			ltr_control->ltr_list[i].ltr_id = 0;
+	}
+
+	return vcd_status;
+}
+
+s32 ddl_find_oldest_ltr_not_in_use(struct ddl_ltr_encoding_type *ltr_control)
+{
+	s32 found_idx = -1;
+	u32 i;
+
+	if (ltr_control->ltr_list) {
+		if (ltr_control->ltr_count == 1)
+			found_idx = 0;
+		else {
+			for (i = 0; i < ltr_control->ltr_count; i++) {
+				if ((ltr_control->ltr_list[i].ltr_in_use ==
+					false) && (found_idx < 0)) {
+					found_idx = i;
+				}
+				if ((found_idx >= 0) &&
+					(ltr_control->ltr_list[i].\
+					ltr_in_use == false) &&
+					(ltr_control->ltr_list[i].ltr_id <
+					ltr_control->ltr_list[found_idx].\
+					ltr_id)) {
+					found_idx = i;
+				}
+			}
+		}
+	}
+
+	DDL_MSG_LOW("%s: found_idx = %d", __func__, found_idx);
+	return found_idx;
+}
+
+s32 ddl_find_ltr_in_use(struct ddl_ltr_encoding_type *ltr_control)
+{
+	s32 found_idx = -1;
+	u32 i;
+
+	if (ltr_control->ltr_list) {
+		for (i = 0; i < ltr_control->ltr_count; i++) {
+			if (ltr_control->ltr_list[i].ltr_in_use == true)
+				found_idx = i;
+		}
+	}
+
+	DDL_MSG_LOW("%s: found_idx = %d", __func__, found_idx);
+	return found_idx;
+}
+
+s32 ddl_find_ltr_from_list(struct ddl_ltr_encoding_type *ltr_control,
+	u32 ltr_id)
+{
+	s32 found_idx = -1;
+	u32 i;
+
+	if (ltr_control->ltr_list) {
+		for (i = 0; i < ltr_control->ltr_count; i++) {
+			if (ltr_control->ltr_list[i].ltr_id == ltr_id) {
+				found_idx = i;
+				break;
+			}
+		}
+	} else {
+		DDL_MSG_ERROR("%s: ltr_list is NULL", __func__);
+	}
+
+	DDL_MSG_LOW("%s: found_idx = %d", __func__, found_idx);
+	return found_idx;
+}
+
+s32 ddl_use_ltr_from_list(struct ddl_ltr_encoding_type *ltr_control,
+	u32 ltr_idx)
+{
+	s32 vcd_status = VCD_S_SUCCESS;
+	u32 i;
+
+	DDL_MSG_LOW("%s: ltr_idx = %u", __func__, ltr_idx);
+	if (ltr_idx > ltr_control->ltr_count) {
+		DDL_MSG_ERROR("%s: fail, idx %d larger than "\
+			"the list array count %d", __func__,
+			ltr_idx, ltr_control->ltr_count);
+		vcd_status = VCD_ERR_FAIL;
+	} else {
+		for (i = 0; i < ltr_control->ltr_count; i++) {
+			if (i == ltr_idx)
+				ltr_control->ltr_list[ltr_idx].ltr_in_use =
+					true;
+			else
+				ltr_control->ltr_list[i].ltr_in_use = false;
+		}
+	}
+
+	return vcd_status;
+}
+
+void ddl_encoder_use_ltr_fail_callback(struct ddl_client_context *ddl)
+{
+	struct ddl_encoder_data *encoder = &(ddl->codec_data.encoder);
+	struct ddl_context *ddl_context = ddl->ddl_context;
+
+	DDL_MSG_ERROR("%s: LTR use failed, callback "\
+		"requested with LTR ID %d", __func__,
+		encoder->ltr_control.failed_use_cmd.ltr_id);
+
+	ddl_context->ddl_callback(VCD_EVT_IND_INFO_LTRUSE_FAILED,
+			VCD_ERR_ILLEGAL_PARM,
+			&(encoder->ltr_control.failed_use_cmd),
+			sizeof(struct vcd_property_ltruse_type),
+			(u32 *)ddl,
+			ddl->client_data);
+}
+
+void ddl_print_ltr_list(struct ddl_ltr_encoding_type *ltr_control)
+{
+	u32 i;
+
+	for (i = 0; i < ltr_control->ltr_count; i++) {
+		DDL_MSG_MED("%s: ltr_id: %d, ltr_in_use: %d",
+			__func__, ltr_control->ltr_list[i].ltr_id,
+			ltr_control->ltr_list[i].ltr_in_use);
+	}
+}
diff --git a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_interrupt_handler.c b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_interrupt_handler.c
index d189408..163af21 100644
--- a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_interrupt_handler.c
+++ b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_interrupt_handler.c
@@ -822,13 +822,13 @@
 			pixel_cache_stats;
 			vidc_pix_cache_get_statistics(&pixel_cache_stats);
 
-			DDL_MSG_HIGH(" pixel cache hits = %d,"
+			DDL_MSG_LOW(" pixel cache hits = %d,"
 				"miss = %d", pixel_cache_stats.access_hit,
 				pixel_cache_stats.access_miss);
-			DDL_MSG_HIGH(" pixel cache core reqs = %d,"
+			DDL_MSG_LOW(" pixel cache core reqs = %d,"
 				"axi reqs = %d", pixel_cache_stats.core_req,
 				pixel_cache_stats.axi_req);
-			DDL_MSG_HIGH(" pixel cache core bus stats = %d,"
+			DDL_MSG_LOW(" pixel cache core bus stats = %d,"
 			"axi bus stats = %d", pixel_cache_stats.core_bus,
 				pixel_cache_stats.axi_bus);
 		}
@@ -1313,7 +1313,7 @@
 			DDL_MSG_LOW("%s y_cb_cr_size = %u "
 				"actual_output_buf_req.sz = %u"
 				"min_output_buf_req.sz = %u\n",
-				decoder->y_cb_cr_size,
+				__func__, decoder->y_cb_cr_size,
 				decoder->actual_output_buf_req.sz,
 				decoder->min_output_buf_req.sz);
 			vidc_sm_set_chroma_addr_change(
@@ -1474,7 +1474,7 @@
 		}
 	} else
 		status = false;
-	DDL_MSG_HIGH("Enc Frame Type %u", (u32)frame->frame);
+	DDL_MSG_LOW("Enc Frame Type %u", (u32)frame->frame);
 	return status;
 }
 
@@ -1764,7 +1764,17 @@
 			(unsigned long) output_frame->alloc_len,
 			ION_IOC_INV_CACHES);
 	}
-	ddl_process_encoder_metadata(ddl);
+
+	if ((VIDC_1080P_ENCODE_FRAMETYPE_SKIPPED !=
+		encoder->enc_frame_info.enc_frame) &&
+		(VIDC_1080P_ENCODE_FRAMETYPE_NOT_CODED !=
+		encoder->enc_frame_info.enc_frame)) {
+		if (DDL_IS_LTR_ENABLED(encoder))
+			ddl_handle_ltr_in_framedone(ddl);
+		ddl_process_encoder_metadata(ddl);
+		encoder->ltr_control.meta_data_reqd = false;
+	}
+	encoder->ltr_control.using = false;
 	ddl_vidc_encode_dynamic_property(ddl, false);
 	ddl->input_frame.frm_trans_end = false;
 	input_buffer_address = ddl_context->dram_base_a.align_physical_addr +
@@ -1828,9 +1838,9 @@
 			encoder->batch_frame.output_frame[actual_idx].vcd_frm);
 		DDL_MSG_LOW("OutBfr: vcd_frm 0x%x frmbfr(virtual) 0x%x"
 			"frmbfr(physical) 0x%x\n",
-			&output_frame,
-			output_frame.virtual_base_addr,
-			output_frame.physical_base_addr);
+			(u32)output_frame,
+			(u32)output_frame->virtual,
+			(u32)output_frame->physical);
 		vidc_1080p_get_encode_frame_info(&encoder->enc_frame_info);
 		vidc_sm_get_frame_tags(&ddl->shared_mem
 			[ddl->command_channel],
@@ -1908,17 +1918,17 @@
 		actual_idx =
 			slice_output->slice_info[start_bfr_idx+index]. \
 			stream_buffer_idx;
-		DDL_MSG_LOW("Slice Info: OutBfrIndex %d SliceSize %d",
+		DDL_MSG_LOW("Slice Info: OutBfrIndex %u SliceSize %u",
 			actual_idx,
 			slice_output->slice_info[start_bfr_idx+index]. \
-			stream_buffer_size, 0);
+			stream_buffer_size);
 		output_frame =
 		&(encoder->batch_frame.output_frame[actual_idx].vcd_frm);
 		DDL_MSG_LOW("OutBfr: vcd_frm 0x%x frmbfr(virtual) 0x%x"
 				"frmbfr(physical) 0x%x",
-				&output_frame,
-				output_frame.virtual_base_addr,
-				output_frame.physical_base_addr);
+				(u32)output_frame,
+				(u32)output_frame->virtual,
+				(u32)output_frame->physical);
 		vidc_1080p_get_encode_frame_info(
 			&encoder->enc_frame_info);
 		vidc_sm_get_frame_tags(&ddl->shared_mem
@@ -1936,8 +1946,8 @@
 			slice_output->slice_info[actual_idx].stream_buffer_size;
 		ddl->output_frame =
 			encoder->batch_frame.output_frame[actual_idx];
-		DDL_MSG_LOW(" %s actual_idx = %d"
-		"encoder->batch_frame.num_output_frames = %d\n", __func__,
+		DDL_MSG_LOW("%s: actual_idx = %u "\
+		"encoder->batch_frame.num_output_frames = %u\n", __func__,
 		actual_idx, encoder->batch_frame.num_output_frames);
 		if (encoder->batch_frame.num_output_frames == (actual_idx+1)) {
 			output_frame->flags |= VCD_FRAME_FLAG_ENDOFFRAME;
diff --git a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_metadata.c b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_metadata.c
index f70c47c..803af02 100644
--- a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_metadata.c
+++ b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_metadata.c
@@ -75,6 +75,9 @@
 		case VCD_METADATA_QCOMFILLER:
 			skip_words = 6;
 		break;
+		case VCD_METADATA_LTR_INFO:
+			skip_words = 9;
+		break;
 		}
 	}
 	buffer += skip_words;
@@ -146,19 +149,24 @@
 		hdr_entry[DDL_METADATA_HDR_VERSION_INDEX] = 0x00000101;
 		hdr_entry[DDL_METADATA_HDR_PORT_INDEX] = 1;
 		hdr_entry[DDL_METADATA_HDR_TYPE_INDEX] = VCD_METADATA_ENC_SLICE;
+
+		hdr_entry = ddl_metadata_hdr_entry(ddl, VCD_METADATA_LTR_INFO);
+		hdr_entry[DDL_METADATA_HDR_VERSION_INDEX] = 0x00000101;
+		hdr_entry[DDL_METADATA_HDR_PORT_INDEX] = 1;
+		hdr_entry[DDL_METADATA_HDR_TYPE_INDEX] = VCD_METADATA_LTR_INFO;
 	}
 }
 
 static u32 ddl_supported_metadata_flag(struct ddl_client_context *ddl)
 {
 	u32 flag = 0;
+	enum vcd_codec codec =
+		ddl->codec_data.decoder.codec.codec;
 
 	if (ddl->decoding) {
-		enum vcd_codec codec =
-			ddl->codec_data.decoder.codec.codec;
-
 		flag |= (VCD_METADATA_CONCEALMB | VCD_METADATA_PASSTHROUGH |
-				VCD_METADATA_QPARRAY);
+				VCD_METADATA_QPARRAY |
+				VCD_METADATA_SEPARATE_BUF);
 		if (codec == VCD_CODEC_H264)
 			flag |= (VCD_METADATA_SEI | VCD_METADATA_VUI);
 		else if (codec == VCD_CODEC_VC1 ||
@@ -167,8 +175,12 @@
 		else if (codec == VCD_CODEC_MPEG2)
 			flag |= (VCD_METADATA_USER_DATA |
 				VCD_METADATA_EXT_DATA);
-	} else
-		flag |= VCD_METADATA_ENC_SLICE;
+	} else {
+		if (codec == VCD_CODEC_H264)
+			flag |= VCD_METADATA_ENC_SLICE | VCD_METADATA_LTR_INFO;
+		else
+			flag |= VCD_METADATA_ENC_SLICE;
+	}
 	return flag;
 }
 
@@ -249,6 +261,9 @@
 	DDL_METADATA_ALIGNSIZE(suffix);
 	decoder->suffix = suffix;
 	output_buf_req->sz += suffix;
+	output_buf_req->meta_buffer_size = suffix;
+	output_buf_req->meta_buffer_size =
+		(output_buf_req->meta_buffer_size + 8191) & (~8191);
 	decoder->meta_data_offset = 0;
 	DDL_MSG_LOW("metadata output buf size : %d", suffix);
 }
@@ -272,6 +287,12 @@
 		DDL_METADATA_ALIGNSIZE(size);
 		suffix += size;
 	}
+	if (flag & VCD_METADATA_LTR_INFO) {
+		size = DDL_METADATA_HDR_SIZE;
+		size += DDL_METADATA_LTR_INFO_PAYLOAD_SIZE;
+		DDL_METADATA_ALIGNSIZE(size);
+		suffix += size;
+	}
 	size = DDL_METADATA_EXTRADATANONE_SIZE;
 	DDL_METADATA_ALIGNSIZE(size);
 	suffix += (size);
@@ -464,13 +485,14 @@
 void ddl_vidc_decode_set_metadata_output(struct ddl_decoder_data *decoder)
 {
 	struct ddl_context *ddl_context;
-	u32 loopc, yuv_size;
+	u32 loopc, yuv_size, dpb;
 	u32 *buffer;
-
+	struct ddl_dec_buffers *dec_buffers = &decoder->hw_bufs;
 	if (!decoder->meta_data_enable_flag) {
 		decoder->meta_data_offset = 0;
 		return;
 	}
+	dpb = decoder->dp_buf.no_of_dec_pic_buf;
 	ddl_context = ddl_get_context();
 	yuv_size = ddl_get_yuv_buffer_size(&decoder->client_frame_size,
 		&decoder->buf_format, !decoder->progressive_only,
@@ -478,15 +500,22 @@
 	decoder->meta_data_offset = DDL_ALIGN_SIZE(yuv_size,
 		DDL_LINEAR_BUF_ALIGN_GUARD_BYTES, DDL_LINEAR_BUF_ALIGN_MASK);
 	buffer = (u32 *) decoder->meta_data_input.align_virtual_addr;
-	*buffer++ = decoder->suffix;
 	DDL_MSG_LOW("Metadata offset & size : %d/%d",
 		decoder->meta_data_offset, decoder->suffix);
-	for (loopc = 0; loopc < decoder->dp_buf.no_of_dec_pic_buf;
-		++loopc) {
-		*buffer++ = (u32)(decoder->meta_data_offset + (u8 *)
+	if (!(decoder->meta_data_enable_flag & VCD_METADATA_SEPARATE_BUF)) {
+		*buffer++ = decoder->suffix;
+		for (loopc = 0; loopc < dpb; ++loopc) {
+			*buffer++ = (u32)(decoder->meta_data_offset + (u8 *)
 			DDL_OFFSET(ddl_context->dram_base_a.
 			align_physical_addr, decoder->dp_buf.
 			dec_pic_buffers[loopc].vcd_frm.physical));
+		}
+	} else {
+		*buffer++ = decoder->actual_output_buf_req.meta_buffer_size;
+		for (loopc = 0; loopc < dpb; ++loopc) {
+			*buffer++ = DDL_ADDR_OFFSET(ddl_context->dram_base_a,
+					dec_buffers->meta_hdr[loopc]);
+		}
 	}
 }
 
@@ -497,27 +526,92 @@
 		&(ddl->output_frame.vcd_frm);
 	u32 *qfiller_hdr, *qfiller, start_addr;
 	u32 qfiller_size;
+	u8 *extradata_addr;
+	u32 metadata_available = false;
+
+	out_frame->flags &= ~(VCD_FRAME_FLAG_EXTRADATA);
 	if (!encoder->meta_data_enable_flag) {
-		out_frame->flags &= ~(VCD_FRAME_FLAG_EXTRADATA);
-		return;
+		DDL_MSG_HIGH("meta_data is not enabled");
+		goto exit;
 	}
-	if (!encoder->enc_frame_info.meta_data_exists) {
-		out_frame->flags &= ~(VCD_FRAME_FLAG_EXTRADATA);
-		return;
-	}
-	out_frame->flags |= VCD_FRAME_FLAG_EXTRADATA;
-	DDL_MSG_LOW("processing metadata for encoder");
 	start_addr = (u32) ((u8 *)out_frame->virtual + out_frame->offset);
-	qfiller = (u32 *)((out_frame->data_len +
+	extradata_addr = (u8 *)((out_frame->data_len +
 				start_addr + 3) & ~3);
+	qfiller = (u32 *)extradata_addr;
 	qfiller_size = (u32)((encoder->meta_data_offset +
 		(u8 *) out_frame->virtual) - (u8 *) qfiller);
+	if (qfiller_size & 3) {
+		DDL_MSG_ERROR("qfiller_size is not 4 bytes aligned");
+		goto exit;
+	}
 	qfiller_hdr = ddl_metadata_hdr_entry(ddl, VCD_METADATA_QCOMFILLER);
 	*qfiller++ = qfiller_size;
 	*qfiller++ = qfiller_hdr[DDL_METADATA_HDR_VERSION_INDEX];
 	*qfiller++ = qfiller_hdr[DDL_METADATA_HDR_PORT_INDEX];
 	*qfiller++ = qfiller_hdr[DDL_METADATA_HDR_TYPE_INDEX];
 	*qfiller = (u32)(qfiller_size - DDL_METADATA_HDR_SIZE);
+	extradata_addr += qfiller_size;
+	if ((u32)extradata_addr !=
+		(u32)((u8 *)start_addr + encoder->meta_data_offset)) {
+		DDL_MSG_ERROR("wrong qfiller size");
+		goto exit;
+	}
+	if (encoder->meta_data_enable_flag & VCD_METADATA_ENC_SLICE) {
+		u32 *sliceinfo = (u32 *)extradata_addr;
+		if (sliceinfo[3] != VCD_METADATA_ENC_SLICE) {
+			DDL_MSG_ERROR("wrong slice info extradata. " \
+				"data: 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x",
+				sliceinfo[0], sliceinfo[1],	sliceinfo[2],
+				sliceinfo[3], sliceinfo[4],	sliceinfo[5]);
+			goto metadata_end;
+		}
+		extradata_addr += sliceinfo[0];
+		metadata_available = true;
+		DDL_MSG_HIGH("%s: Send %u slices info in metadata",
+			__func__, sliceinfo[5]);
+	}
+	if ((encoder->meta_data_enable_flag & VCD_METADATA_LTR_INFO) &&
+		(encoder->ltr_control.meta_data_reqd == true)) {
+		u32 *ltrinfo_hdr = ddl_metadata_hdr_entry(ddl,
+				VCD_METADATA_LTR_INFO);
+		u32 *ltrinfo = (u32 *)extradata_addr;
+		if ((u32)extradata_addr > (u32)((u8 *)out_frame->virtual +
+			out_frame->alloc_len)) {
+			metadata_available = false;
+			DDL_MSG_ERROR("Error: extradata_addr = 0x%p, "\
+				"buffer_start = 0x%p, size = %u",
+				extradata_addr, out_frame->virtual,
+				out_frame->alloc_len);
+			goto metadata_end;
+		}
+		ltrinfo[0] = DDL_METADATA_LTR_INFO_PAYLOAD_SIZE +
+				DDL_METADATA_HDR_SIZE;
+		ltrinfo[1] = ltrinfo_hdr[DDL_METADATA_HDR_VERSION_INDEX];
+		ltrinfo[2] = ltrinfo_hdr[DDL_METADATA_HDR_PORT_INDEX];
+		ltrinfo[3] = ltrinfo_hdr[DDL_METADATA_HDR_TYPE_INDEX];
+		ltrinfo[4] = DDL_METADATA_LTR_INFO_PAYLOAD_SIZE;
+		ltrinfo[5] = encoder->ltr_control.curr_ltr_id;
+		extradata_addr += ltrinfo[0];
+		encoder->ltr_control.curr_ltr_id++;
+		metadata_available = true;
+		DDL_MSG_HIGH("%s: Send curr_ltr_id = %u in metadata",
+			__func__, (u32)encoder->ltr_control.curr_ltr_id);
+	}
+metadata_end:
+	if (metadata_available == true) {
+		u32 *data_none_hdr = ddl_metadata_hdr_entry(ddl,
+				VCD_METADATA_DATANONE);
+		u32 *data_none = (u32 *)extradata_addr;
+		DDL_MSG_LOW("prepare metadata_none header");
+		data_none[0] = DDL_METADATA_EXTRADATANONE_SIZE;
+		data_none[1] = data_none_hdr[DDL_METADATA_HDR_VERSION_INDEX];
+		data_none[2] = data_none_hdr[DDL_METADATA_HDR_PORT_INDEX];
+		data_none[3] = data_none_hdr[DDL_METADATA_HDR_TYPE_INDEX];
+		data_none[4] = 0;
+		out_frame->flags |= VCD_FRAME_FLAG_EXTRADATA;
+	}
+exit:
+	return;
 }
 
 void ddl_process_decoder_metadata(struct ddl_client_context *ddl)
@@ -545,7 +639,8 @@
 	DDL_MSG_LOW("data_len/metadata_offset : %d/%d",
 		output_frame->data_len, decoder->meta_data_offset);
 	output_frame->flags |= VCD_FRAME_FLAG_EXTRADATA;
-	if (output_frame->data_len != decoder->meta_data_offset) {
+	if (!(decoder->meta_data_enable_flag & VCD_METADATA_SEPARATE_BUF)
+		&& (output_frame->data_len != decoder->meta_data_offset)) {
 		qfiller = (u32 *)((u32)((output_frame->data_len +
 			output_frame->offset  +
 				(u8 *) output_frame->virtual) + 3) & ~3);
diff --git a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_metadata.h b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_metadata.h
index e03a9b7..4426828 100644
--- a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_metadata.h
+++ b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_metadata.h
@@ -26,6 +26,7 @@
 #define DDL_METADATA_SEI_PAYLOAD_SIZE          100
 #define DDL_METADATA_SEI_MAX                     5
 #define DDL_METADATA_VUI_PAYLOAD_SIZE          256
+#define DDL_METADATA_LTR_INFO_PAYLOAD_SIZE     (4)
 #define DDL_METADATA_PASSTHROUGH_PAYLOAD_SIZE   68
 #define DDL_METADATA_EXT_PAYLOAD_SIZE         (640)
 #define DDL_METADATA_USER_PAYLOAD_SIZE        (2048)
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 2b65d7e..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
@@ -163,6 +163,28 @@
 		DDL_MSG_ERROR("H264BaseLineCABAC!!");
 		return false;
 	}
+	if (DDL_IS_LTR_ENABLED(encoder)) {
+		if ((encoder->codec.codec != VCD_CODEC_H264) ||
+			(encoder->i_period.b_frames)) {
+			DDL_MSG_ERROR("%s: Only support LTR encoding "\
+				"for H264 without B frame. Current "\
+				"codec %d, B-frame %d", __func__,
+				encoder->codec.codec,
+				encoder->i_period.b_frames);
+			return false;
+		}
+		if (encoder->ltr_control.ltrmode.ltr_mode ==
+				VCD_LTR_MODE_MANUAL) {
+			DDL_MSG_ERROR("%s: Manual LTR mode not supported!",
+				__func__);
+			return false;
+		}
+		DDL_MSG_HIGH("%s: LTR: mode = %u, count = %u, period = %u",
+			__func__, (u32)encoder->ltr_control.ltrmode.ltr_mode,
+			encoder->ltr_control.ltr_count,
+			encoder->ltr_control.ltr_period);
+	}
+
 	return true;
 }
 
@@ -319,6 +341,61 @@
 		}
 	}
 	break;
+	case VCD_I_SET_EXT_METABUFFER:
+	{
+		int index, buffer_size;
+		u8 *phys_addr;
+		u8 *virt_addr;
+		struct vcd_property_meta_buffer *meta_buffer =
+			(struct vcd_property_meta_buffer *) property_value;
+		DDL_MSG_LOW("Entered VCD_I_SET_EXT_METABUFFER Virt: %p,"\
+					"Phys %p, fd: %d size: %d count: %d",
+					meta_buffer->kernel_virtual_addr,
+					meta_buffer->physical_addr,
+					meta_buffer->pmem_fd,
+					meta_buffer->size, meta_buffer->count);
+		if ((property_hdr->sz == sizeof(struct
+			vcd_property_meta_buffer)) &&
+			(DDLCLIENT_STATE_IS(ddl,
+			DDL_CLIENT_WAIT_FOR_INITCODEC) ||
+			DDLCLIENT_STATE_IS(ddl, DDL_CLIENT_WAIT_FOR_DPB) ||
+			DDLCLIENT_STATE_IS(ddl, DDL_CLIENT_OPEN))) {
+			phys_addr = meta_buffer->dev_addr;
+			virt_addr = meta_buffer->kernel_virtual_addr;
+			buffer_size = meta_buffer->size/meta_buffer->count;
+
+			for (index = 0; index < meta_buffer->count; index++) {
+				ddl->codec_data.decoder.hw_bufs.
+					meta_hdr[index].align_physical_addr
+					= phys_addr;
+				ddl->codec_data.decoder.hw_bufs.
+					meta_hdr[index].align_virtual_addr
+					= virt_addr;
+				ddl->codec_data.decoder.hw_bufs.
+					meta_hdr[index].buffer_size
+					= buffer_size;
+				ddl->codec_data.decoder.hw_bufs.
+					meta_hdr[index].physical_base_addr
+					= phys_addr;
+				ddl->codec_data.decoder.hw_bufs.
+					meta_hdr[index].virtual_base_addr
+					= virt_addr;
+
+				DDL_MSG_LOW("Meta Buffer: "\
+							"Assigned %d buffer for "
+							"virt: %p, phys %p for "
+							"meta_buffers "
+							"of size: %d\n",
+							index, virt_addr,
+							phys_addr, buffer_size);
+
+				phys_addr += buffer_size;
+				virt_addr += buffer_size;
+			}
+			vcd_status = VCD_S_SUCCESS;
+		}
+	}
+	break;
 	case VCD_I_H264_MV_BUFFER:
 	{
 		int index, buffer_size;
@@ -379,6 +456,13 @@
 			vcd_status = VCD_S_SUCCESS;
 		}
 		break;
+	case VCD_I_FREE_EXT_METABUFFER:
+		{
+			memset(&decoder->hw_bufs.meta_hdr, 0, sizeof(struct
+					ddl_buf_addr) * DDL_MAX_BUFFER_COUNT);
+			vcd_status = VCD_S_SUCCESS;
+		}
+		break;
 	case VCD_I_OUTPUT_ORDER:
 		{
 			if (sizeof(u32) == property_hdr->sz &&
@@ -617,8 +701,9 @@
 		struct vcd_property_multi_slice *multi_slice =
 			(struct vcd_property_multi_slice *)
 				property_value;
-		DDL_MSG_HIGH("VCD_I_MULTI_SLICE eMSliceSel %d  nMSliceSize %d"
-				"Tot#of MB %d encoder->frame_size.width = %d"
+		DDL_MSG_HIGH("VCD_I_MULTI_SLICE eMSliceSel %d  "\
+				"nMSliceSize %d Tot#of MB %d "\
+				"encoder->frame_size.width = %d "\
 				"encoder->frame_size.height = %d",
 				(int)multi_slice->m_slice_sel,
 				multi_slice->m_slice_size,
@@ -1030,20 +1115,62 @@
 				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;
 			}
 		}
 		break;
 	}
+	case VCD_I_LTR_MODE:
+		if (sizeof(struct vcd_property_ltrmode_type) ==
+			property_hdr->sz && encoder->codec.codec ==
+			VCD_CODEC_H264) {
+			struct vcd_property_ltrmode_type *ltrmode =
+				(struct vcd_property_ltrmode_type *)
+				property_value;
+			encoder->ltr_control.ltrmode.ltr_mode =
+				ltrmode->ltr_mode;
+			DDL_MSG_HIGH("%s: set LTR mode = %u", __func__,
+				(u32)encoder->ltr_control.ltrmode.ltr_mode);
+			vcd_status = VCD_S_SUCCESS;
+		}
+	break;
+	case VCD_I_LTR_COUNT:
+		if (sizeof(struct vcd_property_ltrcount_type) ==
+			property_hdr->sz && encoder->codec.codec ==
+			VCD_CODEC_H264) {
+			struct vcd_property_ltrcount_type *ltrcount =
+				(struct vcd_property_ltrcount_type *)
+				property_value;
+			if (ltrcount->ltr_count > DDL_MAX_NUM_LTR_FRAMES) {
+				DDL_MSG_ERROR("%s: set LTR count failed. "\
+					"LTR count %u beyond maximum of %u",
+					__func__, ltrcount->ltr_count,
+					(u32)DDL_MAX_NUM_LTR_FRAMES);
+			} else {
+				encoder->ltr_control.ltr_count =
+					ltrcount->ltr_count;
+				DDL_MSG_HIGH("%s: set LTR count = %u", __func__,
+					encoder->ltr_control.ltr_count);
+				vcd_status = VCD_S_SUCCESS;
+			}
+		}
+	break;
 	case VCD_REQ_PERF_LEVEL:
 		vcd_status = VCD_S_SUCCESS;
 		break;
@@ -1091,7 +1218,8 @@
 		break;
 	}
 	default:
-		DDL_MSG_ERROR("INVALID ID %d\n", (int)property_hdr->prop_id);
+		DDL_MSG_ERROR("%s: unknown prop_id = 0x%x", __func__,
+			property_hdr->prop_id);
 		vcd_status = VCD_ERR_ILLEGAL_OP;
 	break;
 	}
@@ -1552,7 +1680,7 @@
 	break;
 	case VCD_I_METADATA_ENABLE:
 	case VCD_I_METADATA_HEADER:
-		DDL_MSG_ERROR("Meta Data Interface is Requested");
+		DDL_MSG_HIGH("Meta Data Interface is Requested");
 		vcd_status = ddl_get_metadata_params(ddl, property_hdr,
 			property_value);
 		vcd_status = VCD_S_SUCCESS;
@@ -1591,7 +1719,67 @@
 			vcd_status = VCD_S_SUCCESS;
 		}
 		break;
+	case VCD_I_CAPABILITY_LTR_COUNT:
+		if (sizeof(struct vcd_property_range_type) ==
+			property_hdr->sz) {
+			struct vcd_property_range_type capability_ltr_range;
+			capability_ltr_range.max = DDL_MAX_NUM_LTR_FRAMES;
+			capability_ltr_range.min = 1;
+			capability_ltr_range.step_size = 1;
+			*(struct vcd_property_range_type *)property_value =
+				capability_ltr_range;
+			DDL_MSG_HIGH("%s: capability_ltr_count = %u",
+				__func__, ((struct vcd_property_range_type *)
+				property_value)->max);
+			vcd_status = VCD_S_SUCCESS;
+		}
+	break;
+	case VCD_I_LTR_MODE:
+		if (sizeof(struct vcd_property_ltrmode_type) ==
+			property_hdr->sz) {
+			((struct vcd_property_ltrmode_type *)
+			property_value)->ltr_mode =
+				encoder->ltr_control.ltrmode.ltr_mode;
+			DDL_MSG_HIGH("%s: ltr_mode = %u", __func__,
+				(u32)(((struct vcd_property_ltrmode_type *)
+				property_value)->ltr_mode));
+			vcd_status = VCD_S_SUCCESS;
+		}
+	break;
+	case VCD_I_LTR_COUNT:
+		if (sizeof(struct vcd_property_ltrcount_type) ==
+			property_hdr->sz) {
+			struct vcd_property_ltrcount_type ltr_count;
+			ltr_count.ltr_count =
+				encoder->ltr_control.ltr_count;
+			*(struct vcd_property_ltrcount_type *)property_value =
+				ltr_count;
+			DDL_MSG_HIGH("%s: ltr_count = %u", __func__,
+				((struct vcd_property_ltrcount_type *)
+				property_value)->ltr_count);
+			vcd_status = VCD_S_SUCCESS;
+		}
+	break;
+	case VCD_I_LTR_PERIOD:
+		if (sizeof(struct vcd_property_ltrperiod_type) ==
+			property_hdr->sz) {
+			struct vcd_property_ltrperiod_type ltr_period;
+			if (!encoder->ltr_control.ltr_period)
+				ltr_period.ltr_period = 0;
+			else
+				ltr_period.ltr_period =
+					encoder->ltr_control.ltr_period - 1;
+			*(struct vcd_property_ltrperiod_type *)property_value =
+				ltr_period;
+			DDL_MSG_HIGH("%s: ltr_period = %u", __func__,
+				((struct vcd_property_ltrperiod_type *)
+				property_value)->ltr_period);
+			vcd_status = VCD_S_SUCCESS;
+		}
+	break;
 	default:
+		DDL_MSG_ERROR("%s: unknown prop_id = 0x%x", __func__,
+			property_hdr->prop_id);
 		vcd_status = VCD_ERR_ILLEGAL_OP;
 		break;
 	}
@@ -1680,6 +1868,77 @@
 		}
 	}
 	break;
+	case VCD_I_LTR_PERIOD:
+	{
+		if (sizeof(struct vcd_property_ltrperiod_type) ==
+			property_hdr->sz) {
+			struct vcd_property_ltrperiod_type *ltrperiod =
+				(struct vcd_property_ltrperiod_type *)
+				property_value;
+			encoder->ltr_control.ltr_period =
+				(ltrperiod->ltr_period == 0xFFFFFFFF) ?
+				0xFFFFFFFF : (ltrperiod->ltr_period + 1);
+			DDL_MSG_HIGH("%s: set ltr_period = %u", __func__,
+				encoder->ltr_control.ltr_period);
+			vcd_status = VCD_S_SUCCESS;
+		}
+	}
+	break;
+	case VCD_I_LTR_USE:
+	{
+		if (sizeof(struct vcd_property_ltruse_type) ==
+			property_hdr->sz) {
+			struct vcd_property_ltruse_type *ltruse =
+				(struct vcd_property_ltruse_type *)
+				property_value;
+			if (ltruse->ltr_id >= DDL_LTR_FRAME_START_ID) {
+				struct ddl_ltr_encoding_type *ltr_ctrl =
+					&encoder->ltr_control;
+				s32 idx;
+				idx = ddl_find_ltr_from_list(ltr_ctrl,
+					ltruse->ltr_id);
+				if (idx < 0) {
+					ltr_ctrl->callback_reqd = true;
+					ltr_ctrl->failed_use_cmd.ltr_id =
+						ltruse->ltr_id;
+					ltr_ctrl->failed_use_cmd.ltr_frames =
+						ltruse->ltr_frames;
+					DDL_MSG_ERROR("%s: index (%d) "\
+					"not found. Callback requested. "\
+					"ltr_id = %u, ltr_frames = %u",
+					__func__, idx, ltruse->ltr_id,
+					ltruse->ltr_frames);
+				} else {
+					ddl_use_ltr_from_list(ltr_ctrl, idx);
+					ltr_ctrl->ltr_use_frames =
+						ltruse->ltr_frames;
+					if (ltr_ctrl->using == false)
+						ltr_ctrl->\
+						out_frame_cnt_to_use_this_ltr =
+							ltruse->ltr_frames;
+					else
+						ltr_ctrl->\
+						pending_chg_ltr_useframes =
+							true;
+					ltr_ctrl->first_ltr_use_arvd = true;
+					ltr_ctrl->use_ltr_reqd = true;
+					DDL_MSG_HIGH("%s: index (%d) found. "\
+					"num frames to use this ltr_id (%u) "\
+					"is %u", __func__, idx,
+					ltruse->ltr_id, ltruse->ltr_frames);
+				}
+				dynamic_prop_change = DDL_ENC_LTR_USE_FRAME;
+				vcd_status = VCD_S_SUCCESS;
+			} else {
+				DDL_MSG_ERROR("%s: LTRUse ID %d failed. "\
+					"LTR ID starts from %d", __func__,
+					ltruse->ltr_id,
+					(u32)DDL_LTR_FRAME_START_ID);
+				vcd_status = VCD_ERR_ILLEGAL_OP;
+			}
+		}
+	}
+	break;
 	default:
 		vcd_status = VCD_ERR_ILLEGAL_OP;
 		break;
@@ -1747,6 +2006,9 @@
 	encoder->num_references_for_p_frame = DDL_MIN_NUM_REF_FOR_P_FRAME;
 	if (encoder->codec.codec == VCD_CODEC_MPEG4)
 		encoder->closed_gop = true;
+	encoder->intra_period_changed = false;
+	memset(&encoder->ltr_control, 0,
+		sizeof(struct ddl_ltr_encoding_type));
 	ddl_set_default_metadata_flag(ddl);
 	ddl_set_default_encoder_buffer_req(encoder);
 	encoder->slice_delivery_info.enable = 0;
diff --git a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_shared_mem.c b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_shared_mem.c
index de3fc4f..4c73bef 100644
--- a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_shared_mem.c
+++ b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_shared_mem.c
@@ -87,6 +87,8 @@
 #define VIDC_SM_ENC_EXT_CTRL_TIMING_INFO_EN_SHFT     14
 #define VIDC_SM_ENC_EXT_CTRL_AU_DELIMITER_EN_BMSK    0x00000800
 #define VIDC_SM_ENC_EXT_CTRL_AU_DELIMITER_EN_SHFT    11
+#define VIDC_SM_ENC_EXT_CTRL_LONG_TERM_REF_ENABLE_BMSK      0x00000400
+#define VIDC_SM_ENC_EXT_CTRL_LONG_TERM_REF_ENABLE_SHFT      10
 #define VIDC_SM_ENC_EXT_CTRL_H263_CPCFC_ENABLE_BMSK  0x80
 #define VIDC_SM_ENC_EXT_CTRL_H263_CPCFC_ENABLE_SHFT  7
 #define VIDC_SM_ENC_EXT_CTRL_SPS_PPS_CONTROL_BMSK    0X100
@@ -458,8 +460,8 @@
 	enum VIDC_SM_frame_skip frame_skip_mode,
 	u32 seq_hdr_in_band, u32 vbv_buffer_size, u32 cpcfc_enable,
 	u32 sps_pps_control, u32 closed_gop_enable,
-	u32 au_delim_enable,
-	u32 vui_timing_info_enable)
+	u32 au_delim_enable, u32 vui_timing_info_enable,
+	u32 ltr_enable)
 {
 	u32 enc_ctrl;
 	enc_ctrl = VIDC_SETFIELD((hec_enable) ? 1 : 0,
@@ -488,8 +490,10 @@
 			VIDC_SM_ENC_EXT_CTRL_AU_DELIMITER_EN_BMSK) |
 			VIDC_SETFIELD((vui_timing_info_enable) ? 1 : 0,
 			VIDC_SM_ENC_EXT_CTRL_TIMING_INFO_EN_SHFT,
-			VIDC_SM_ENC_EXT_CTRL_TIMING_INFO_EN_BMSK);
-
+			VIDC_SM_ENC_EXT_CTRL_TIMING_INFO_EN_BMSK) |
+			VIDC_SETFIELD((ltr_enable) ? 1 : 0,
+			VIDC_SM_ENC_EXT_CTRL_LONG_TERM_REF_ENABLE_SHFT,
+			VIDC_SM_ENC_EXT_CTRL_LONG_TERM_REF_ENABLE_BMSK);
 	DDL_MEM_WRITE_32(shared_mem, VIDC_SM_ENC_EXT_CTRL_ADDR, enc_ctrl);
 }
 
diff --git a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_shared_mem.h b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_shared_mem.h
index 2eef99d..f344460 100644
--- a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_shared_mem.h
+++ b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_shared_mem.h
@@ -106,7 +106,8 @@
 	struct ddl_buf_addr *shared_mem, u32 hec_enable,
 	enum VIDC_SM_frame_skip  frame_skip_mode, u32 seq_hdr_in_band,
 	u32 vbv_buffer_size, u32 cpcfc_enable, u32 sps_pps_control,
-	u32 closed_gop_enable, u32 au_delim_enable, u32 vui_timing_info_enable);
+	u32 closed_gop_enable, u32 au_delim_enable, u32 vui_timing_info_enable,
+	u32 ltr_enable);
 void vidc_sm_set_encoder_param_change(struct ddl_buf_addr *shared_mem,
 	u32 bit_rate_chg, u32 frame_rate_chg, u32 i_period_chg);
 void vidc_sm_set_encoder_vop_time(struct ddl_buf_addr *shared_mem,
diff --git a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_utils.h b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_utils.h
index 4963874..a099ade 100644
--- a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_utils.h
+++ b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_utils.h
@@ -34,7 +34,7 @@
 		printk(KERN_DEBUG x); \
 } while (0)
 
-#ifdef DDL_MSG_LOG
+#if DDL_MSG_LOG
 #define DDL_MSG_LOW(x...)    printk(KERN_INFO x)
 #define DDL_MSG_MED(x...)    printk(KERN_INFO x)
 #define DDL_MSG_HIGH(x...)   printk(KERN_INFO x)
diff --git a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_vidc.c b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_vidc.c
index 1bf242d..b84ec66 100644
--- a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_vidc.c
+++ b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_vidc.c
@@ -331,7 +331,7 @@
 {
 	struct ddl_encoder_data *encoder = &(ddl->codec_data.encoder);
 	u32 frame_rate_change = false, bit_rate_change = false;
-	u32 i_period_change = false, reset_req = false;
+	u32 reset_req = false;
 
 	if (!enable) {
 		if (encoder->dynmic_prop_change_req) {
@@ -344,6 +344,17 @@
 			encoder->dynamic_prop_change &=
 				~(DDL_ENC_REQ_IFRAME);
 		}
+		if (encoder->dynamic_prop_change & DDL_ENC_LTR_USE_FRAME) {
+			if (encoder->ltr_control.callback_reqd) {
+				DDL_MSG_ERROR("%s: LTR use failed", __func__);
+				ddl_encoder_use_ltr_fail_callback(ddl);
+				encoder->ltr_control.callback_reqd = false;
+			} else {
+				encoder->ltr_control.use_ltr_reqd = true;
+			}
+			encoder->dynamic_prop_change &=
+				~(DDL_ENC_LTR_USE_FRAME);
+		}
 		if ((encoder->dynamic_prop_change &
 			DDL_ENC_CHANGE_BITRATE)) {
 			bit_rate_change = true;
@@ -355,7 +366,7 @@
 		}
 		if ((encoder->dynamic_prop_change
 			& DDL_ENC_CHANGE_IPERIOD)) {
-			i_period_change = true;
+			encoder->intra_period_changed = true;
 			vidc_sm_set_encoder_new_i_period(
 				&ddl->shared_mem[ddl->command_channel],
 				encoder->i_period.p_frames);
@@ -387,7 +398,7 @@
 		vidc_sm_set_encoder_param_change(
 			&ddl->shared_mem[ddl->command_channel],
 			bit_rate_change, frame_rate_change,
-			i_period_change);
+			encoder->intra_period_changed);
 	}
 }
 
@@ -580,7 +591,7 @@
 	u32 index, luma[4], chroma[4], hdr_ext_control = false;
 	const u32 recon_bufs = 4;
 	u32 h263_cpfc_enable = false;
-	u32 scaled_frame_rate;
+	u32 scaled_frame_rate, ltr_enable;
 
 	ddl_vidc_encode_set_profile_level(ddl);
 	vidc_1080p_set_encode_frame_size(encoder->frame_size.width,
@@ -601,12 +612,14 @@
 		(DDL_FRAMERATE_SCALE(DDL_INITIAL_FRAME_RATE)
 		 != scaled_frame_rate) && encoder->plusptype_enable)
 		h263_cpfc_enable = true;
+	ltr_enable = DDL_IS_LTR_ENABLED(encoder);
+	DDL_MSG_HIGH("ltr_enable = %u", ltr_enable);
 	vidc_sm_set_extended_encoder_control(&ddl->shared_mem
 		[ddl->command_channel], hdr_ext_control,
 		r_cframe_skip, false, 0,
 		h263_cpfc_enable, encoder->sps_pps.sps_pps_for_idr_enable_flag,
 		encoder->closed_gop, encoder->avc_delimiter_enable,
-		encoder->vui_timinginfo_enable);
+		encoder->vui_timinginfo_enable, ltr_enable);
 	if (encoder->vui_timinginfo_enable) {
 		vidc_sm_set_h264_encoder_timing_info(
 			&ddl->shared_mem[ddl->command_channel],
@@ -809,7 +822,8 @@
 		encoder->dynmic_prop_change_req = true;
 		ddl_vidc_encode_dynamic_property(ddl, true);
 	}
-
+	if (DDL_IS_LTR_ENABLED(encoder))
+		ddl_encoder_ltr_control(ddl);
 	vidc_1080p_set_encode_circular_intra_refresh(
 		encoder->intra_refresh.cir_mb_number);
 	ddl_vidc_encode_set_multi_slice_info(encoder);
@@ -824,13 +838,21 @@
 	ddl_context->dram_base_a.align_physical_addr, stream->physical);
 	enc_param.stream_buffer_size =
 		encoder->client_output_buf_req.sz;
-
 	enc_param.intra_frame = encoder->intra_frame_insertion;
-	if (encoder->intra_frame_insertion)
-		encoder->intra_frame_insertion = false;
 	enc_param.input_flush = false;
 	enc_param.slice_enable = false;
-		vidc_sm_set_encoder_vop_time(
+	enc_param.store_ltr0 = encoder->ltr_control.store_ltr0;
+	enc_param.store_ltr1 = encoder->ltr_control.store_ltr1;
+	enc_param.use_ltr0 = encoder->ltr_control.use_ltr0;
+	enc_param.use_ltr1 = encoder->ltr_control.use_ltr1;
+
+	encoder->intra_frame_insertion = false;
+	encoder->intra_period_changed = false;
+	encoder->ltr_control.store_ltr0 = false;
+	encoder->ltr_control.store_ltr1 = false;
+	encoder->ltr_control.use_ltr0 = false;
+	encoder->ltr_control.use_ltr1 = false;
+	vidc_sm_set_encoder_vop_time(
 			&ddl->shared_mem[ddl->command_channel], true,
 			encoder->vop_timing.vop_time_resolution,
 			ddl->input_frame.frm_delta);
diff --git a/drivers/video/msm/vidc/1080p/ddl/vidc.c b/drivers/video/msm/vidc/1080p/ddl/vidc.c
index 3c445bc..396adaf 100644
--- a/drivers/video/msm/vidc/1080p/ddl/vidc.c
+++ b/drivers/video/msm/vidc/1080p/ddl/vidc.c
@@ -83,6 +83,17 @@
 #define VIDC_1080P_SI_RG10_ENCODE_SLICE_IF_ENABLE_SHFT      31
 #define VIDC_1080P_MAX_INTRA_PERIOD 0xffff
 
+#define VIDC_1080P_COMMON_CHX_RG6_I_FRAME_BMASK              0x00000001
+#define VIDC_1080P_COMMON_CHX_RG6_I_FRAME_SHIFT              0
+#define VIDC_1080P_COMMON_CHX_RG6_STORE_LTR0_BMASK           0x00000008
+#define VIDC_1080P_COMMON_CHX_RG6_STORE_LTR0_SHIFT           3
+#define VIDC_1080P_COMMON_CHX_RG6_STORE_LTR1_BMASK           0x00000010
+#define VIDC_1080P_COMMON_CHX_RG6_STORE_LTR1_SHIFT           4
+#define VIDC_1080P_COMMON_CHX_RG6_USE_LTR0_BMASK             0x00000020
+#define VIDC_1080P_COMMON_CHX_RG6_USE_LTR0_SHIFT             5
+#define VIDC_1080P_COMMON_CHX_RG6_USE_LTR1_BMASK             0x00000040
+#define VIDC_1080P_COMMON_CHX_RG6_USE_LTR1_SHIFT             6
+
 u8 *VIDC_BASE_PTR;
 
 void vidc_1080p_do_sw_reset(enum vidc_1080p_reset init_flag)
@@ -787,7 +798,9 @@
 void vidc_1080p_encode_frame_start_ch0(
 	struct vidc_1080p_enc_frame_start_param *param)
 {
-	u32 input_flush;
+	u32 input_flush = 0;
+	u32 frame_insertion = 0;
+
 	VIDC_HWIO_OUT(REG_695082, VIDC_1080P_RISC2HOST_CMD_EMPTY);
 	VIDC_HWIO_OUT(REG_666957, VIDC_1080P_INIT_CH_INST_ID);
 	VIDC_HWIO_OUT(REG_117192,
@@ -798,7 +811,22 @@
 		VIDC_1080P_BASE_OFFSET_SHIFT);
 	VIDC_HWIO_OUT(REG_175608, param->current_c_addr_offset >>
 		VIDC_1080P_BASE_OFFSET_SHIFT);
-	VIDC_HWIO_OUT(REG_190381, param->intra_frame);
+	frame_insertion = VIDC_SETFIELD(param->intra_frame,
+			VIDC_1080P_COMMON_CHX_RG6_I_FRAME_SHIFT,
+			VIDC_1080P_COMMON_CHX_RG6_I_FRAME_BMASK);
+	frame_insertion |= VIDC_SETFIELD(param->store_ltr0,
+			VIDC_1080P_COMMON_CHX_RG6_STORE_LTR0_SHIFT,
+			VIDC_1080P_COMMON_CHX_RG6_STORE_LTR0_BMASK);
+	frame_insertion |= VIDC_SETFIELD(param->store_ltr1,
+			VIDC_1080P_COMMON_CHX_RG6_STORE_LTR1_SHIFT,
+			VIDC_1080P_COMMON_CHX_RG6_STORE_LTR1_BMASK);
+	frame_insertion |= VIDC_SETFIELD(param->use_ltr0,
+			VIDC_1080P_COMMON_CHX_RG6_USE_LTR0_SHIFT,
+			VIDC_1080P_COMMON_CHX_RG6_USE_LTR0_BMASK);
+	frame_insertion |= VIDC_SETFIELD(param->use_ltr1,
+			VIDC_1080P_COMMON_CHX_RG6_USE_LTR1_SHIFT,
+			VIDC_1080P_COMMON_CHX_RG6_USE_LTR1_BMASK);
+	VIDC_HWIO_OUT(REG_190381, frame_insertion);
 	VIDC_HWIO_OUT(REG_889944, param->shared_mem_addr_offset);
 	input_flush = VIDC_SETFIELD(param->input_flush,
 			VIDC_1080P_SI_RG10_ENCODE_INPUT_BUFFER_FLUSH_SHFT,
@@ -816,7 +844,9 @@
 void vidc_1080p_encode_frame_start_ch1(
 	struct vidc_1080p_enc_frame_start_param *param)
 {
-	u32 input_flush;
+	u32 input_flush = 0;
+	u32 frame_insertion = 0;
+
 	VIDC_HWIO_OUT(REG_695082, VIDC_1080P_RISC2HOST_CMD_EMPTY);
 	VIDC_HWIO_OUT(REG_313350, VIDC_1080P_INIT_CH_INST_ID);
 	VIDC_HWIO_OUT(REG_980194,
@@ -827,7 +857,22 @@
 		VIDC_1080P_BASE_OFFSET_SHIFT);
 	VIDC_HWIO_OUT(REG_548308,  param->current_c_addr_offset >>
 		VIDC_1080P_BASE_OFFSET_SHIFT);
-	VIDC_HWIO_OUT(REG_887095, param->intra_frame);
+	frame_insertion = VIDC_SETFIELD(param->intra_frame,
+			VIDC_1080P_COMMON_CHX_RG6_I_FRAME_SHIFT,
+			VIDC_1080P_COMMON_CHX_RG6_I_FRAME_BMASK);
+	frame_insertion |= VIDC_SETFIELD(param->store_ltr0,
+			VIDC_1080P_COMMON_CHX_RG6_STORE_LTR0_SHIFT,
+			VIDC_1080P_COMMON_CHX_RG6_STORE_LTR0_BMASK);
+	frame_insertion |= VIDC_SETFIELD(param->store_ltr1,
+			VIDC_1080P_COMMON_CHX_RG6_STORE_LTR1_SHIFT,
+			VIDC_1080P_COMMON_CHX_RG6_STORE_LTR1_BMASK);
+	frame_insertion |= VIDC_SETFIELD(param->use_ltr0,
+			VIDC_1080P_COMMON_CHX_RG6_USE_LTR0_SHIFT,
+			VIDC_1080P_COMMON_CHX_RG6_USE_LTR0_BMASK);
+	frame_insertion |= VIDC_SETFIELD(param->use_ltr1,
+			VIDC_1080P_COMMON_CHX_RG6_USE_LTR1_SHIFT,
+			VIDC_1080P_COMMON_CHX_RG6_USE_LTR1_BMASK);
+	VIDC_HWIO_OUT(REG_887095, frame_insertion);
 	VIDC_HWIO_OUT(REG_652528, param->shared_mem_addr_offset);
 	input_flush = VIDC_SETFIELD(param->input_flush,
 			VIDC_1080P_SI_RG10_ENCODE_INPUT_BUFFER_FLUSH_SHFT,
diff --git a/drivers/video/msm/vidc/1080p/ddl/vidc.h b/drivers/video/msm/vidc/1080p/ddl/vidc.h
index 117612b..be4c35b 100644
--- a/drivers/video/msm/vidc/1080p/ddl/vidc.h
+++ b/drivers/video/msm/vidc/1080p/ddl/vidc.h
@@ -400,6 +400,10 @@
 	u32 intra_frame;
 	u32 input_flush;
 	u32 slice_enable;
+	u32 store_ltr0;
+	u32 store_ltr1;
+	u32 use_ltr0;
+	u32 use_ltr1;
 	enum vidc_1080p_encode encode;
 };
 struct vidc_1080p_enc_frame_info{
diff --git a/drivers/video/msm/vidc/common/dec/vdec.c b/drivers/video/msm/vidc/common/dec/vdec.c
index 59e19b7..48f127a 100644
--- a/drivers/video/msm/vidc/common/dec/vdec.c
+++ b/drivers/video/msm/vidc/common/dec/vdec.c
@@ -271,6 +271,38 @@
 				      &phy_addr, &pmem_fd, &file,
 				      &buffer_index) ||
 		(vcd_frame_data->flags & VCD_FRAME_FLAG_EOS)) {
+
+		if (res_trk_check_for_sec_session() &&
+				event == VCD_EVT_RESP_OUTPUT_DONE) {
+			DBG("Buffer Index = %d", buffer_index);
+			if (buffer_index != -1) {
+				if (client_ctx->meta_addr_table[buffer_index].
+					kernel_vir_addr_iommu &&
+					client_ctx->
+					meta_addr_table[buffer_index].
+					kernel_vir_addr) {
+
+					memcpy(client_ctx->
+						meta_addr_table[buffer_index].
+						kernel_vir_addr_iommu,
+						client_ctx->
+						meta_addr_table[buffer_index].
+						kernel_vir_addr,
+						client_ctx->meta_buf_size);
+					DBG("Copying Meta Buffer from "\
+						"secure memory"
+						"kernel_virt_iommu = %p "
+						"kernel_virt = %p",
+						client_ctx->
+						meta_addr_table[buffer_index].
+						kernel_vir_addr_iommu,
+						client_ctx->
+						meta_addr_table[buffer_index].
+						kernel_vir_addr);
+				}
+			}
+		}
+
 		/* Buffer address in user space */
 		vdec_msg->vdec_msg_info.msgdata.output_frame.bufferaddr =
 		    (u8 *) user_vaddr;
@@ -838,7 +870,263 @@
 		return false;
 	return true;
 }
+static u32 vid_dec_set_meta_buffers(struct video_client_ctx *client_ctx,
+					struct vdec_meta_buffers *meta_buffers)
+{
+	struct vcd_property_hdr vcd_property_hdr;
+	struct vcd_property_meta_buffer *vcd_meta_buffer = NULL;
+	struct msm_mapped_buffer *mapped_buffer = NULL;
+	struct msm_mapped_buffer *mapped_buffer_iommu = NULL;
+	u32 vcd_status = VCD_ERR_FAIL;
+	u32 len = 0, flags = 0, len_iommu = 0, flags_iommu = 0, buf_size = 0;
+	struct file *file, *file_iommu;
+	int rc = 0;
+	unsigned long ionflag = 0, ionflag_iommu = 0;
+	unsigned long buffer_size = 0, buffer_size_iommu = 0;
+	unsigned long iova = 0, iova_iommu = 0;
+	int index = -1, num_buffers = 0;
+	u8 *ker_vir_addr = NULL, *ker_vir_addr_iommu = NULL;
 
+	if (!client_ctx || !meta_buffers)
+		return false;
+
+	vcd_property_hdr.prop_id = VCD_I_SET_EXT_METABUFFER;
+	vcd_property_hdr.sz = sizeof(struct vcd_property_meta_buffer);
+	vcd_meta_buffer = &client_ctx->vcd_meta_buffer;
+
+	memset(&client_ctx->vcd_meta_buffer, 0,
+		   sizeof(struct vcd_property_meta_buffer));
+	vcd_meta_buffer->size = meta_buffers->size;
+	vcd_meta_buffer->count = meta_buffers->count;
+	vcd_meta_buffer->pmem_fd = meta_buffers->pmem_fd;
+	vcd_meta_buffer->offset = meta_buffers->offset;
+	vcd_meta_buffer->pmem_fd_iommu = meta_buffers->pmem_fd_iommu;
+
+	if (!vcd_get_ion_status()) {
+		if (get_pmem_file(vcd_meta_buffer->pmem_fd,
+				(unsigned long *) (&(vcd_meta_buffer->
+				physical_addr)),
+				(unsigned long *) (&vcd_meta_buffer->
+							kernel_virtual_addr),
+				(unsigned long *) (&len), &file)) {
+				ERR("%s(): get_pmem_file failed\n", __func__);
+				return false;
+			}
+		put_pmem_file(file);
+		flags = MSM_SUBSYSTEM_MAP_IOVA;
+		mapped_buffer = msm_subsystem_map_buffer(
+			(unsigned long)vcd_meta_buffer->physical_addr,
+				len, flags, vidc_mmu_subsystem,
+				sizeof(vidc_mmu_subsystem)/
+				sizeof(unsigned int));
+		if (IS_ERR(mapped_buffer)) {
+			pr_err("buffer map failed");
+			return false;
+		}
+		vcd_meta_buffer->client_data = (void *) mapped_buffer;
+		vcd_meta_buffer->dev_addr =
+			(u8 *)mapped_buffer->iova[0];
+
+		if (get_pmem_file(vcd_meta_buffer->pmem_fd_iommu,
+				(unsigned long *) (&(vcd_meta_buffer->
+				physical_addr_iommu)),
+				(unsigned long *) (&vcd_meta_buffer->
+				kernel_virt_addr_iommu),
+				(unsigned long *) (&len_iommu), &file_iommu)) {
+				ERR("%s(): get_pmem_file failed\n", __func__);
+				return false;
+			}
+		put_pmem_file(file_iommu);
+		flags_iommu = MSM_SUBSYSTEM_MAP_IOVA;
+		mapped_buffer_iommu = msm_subsystem_map_buffer(
+			(unsigned long)vcd_meta_buffer->physical_addr_iommu,
+				len_iommu, flags_iommu, vidc_mmu_subsystem,
+				sizeof(vidc_mmu_subsystem)/
+				sizeof(unsigned int));
+		if (IS_ERR(mapped_buffer_iommu)) {
+			pr_err("buffer map failed");
+			return false;
+		}
+		vcd_meta_buffer->client_data_iommu =
+					(void *) mapped_buffer_iommu;
+		vcd_meta_buffer->dev_addr_iommu =
+					(u8 *)mapped_buffer_iommu->iova[0];
+	} else {
+		client_ctx->meta_buffer_ion_handle = ion_import_dma_buf(
+					client_ctx->user_ion_client,
+					vcd_meta_buffer->pmem_fd);
+		if (IS_ERR_OR_NULL(client_ctx->meta_buffer_ion_handle)) {
+			ERR("%s(): get_ION_handle failed\n", __func__);
+			goto import_ion_error;
+		}
+		rc = ion_handle_get_flags(client_ctx->user_ion_client,
+					client_ctx->meta_buffer_ion_handle,
+					&ionflag);
+		if (rc) {
+			ERR("%s():get_ION_flags fail\n",
+					 __func__);
+			goto import_ion_error;
+		}
+		vcd_meta_buffer->kernel_virtual_addr =
+			(u8 *) ion_map_kernel(
+			client_ctx->user_ion_client,
+			client_ctx->meta_buffer_ion_handle);
+		if (!vcd_meta_buffer->kernel_virtual_addr) {
+			ERR("%s(): get_ION_kernel virtual addr failed\n",
+				 __func__);
+			goto import_ion_error;
+		}
+		if (res_trk_check_for_sec_session() ||
+		   (res_trk_get_core_type() == (u32)VCD_CORE_720P)) {
+			rc = ion_phys(client_ctx->user_ion_client,
+				client_ctx->meta_buffer_ion_handle,
+				(unsigned long *) (&(vcd_meta_buffer->
+				physical_addr)), &len);
+			if (rc) {
+				ERR("%s():get_ION_kernel physical addr fail\n",
+					__func__);
+				goto ion_map_error;
+			}
+			vcd_meta_buffer->client_data = NULL;
+			vcd_meta_buffer->dev_addr = (u8 *)
+				vcd_meta_buffer->physical_addr;
+		} else {
+			rc = ion_map_iommu(client_ctx->user_ion_client,
+				client_ctx->meta_buffer_ion_handle,
+				VIDEO_DOMAIN, VIDEO_MAIN_POOL,
+				SZ_4K, 0, (unsigned long *)&iova,
+				(unsigned long *)&buffer_size,
+				0, 0);
+			if (rc || !iova) {
+				ERR("%s():get_ION_kernel physical addr fail,"\
+					" rc = %d iova = 0x%lx\n",
+					__func__, rc, iova);
+				goto ion_map_error;
+			}
+			vcd_meta_buffer->physical_addr = (u8 *) iova;
+			vcd_meta_buffer->client_data = NULL;
+			vcd_meta_buffer->dev_addr = (u8 *) iova;
+		}
+
+		client_ctx->meta_buffer_iommu_ion_handle = ion_import_dma_buf(
+					client_ctx->user_ion_client,
+					vcd_meta_buffer->pmem_fd_iommu);
+		if (IS_ERR_OR_NULL(client_ctx->meta_buffer_iommu_ion_handle)) {
+			ERR("%s(): get_ION_handle failed\n", __func__);
+			goto import_ion_error;
+		}
+		rc = ion_handle_get_flags(client_ctx->user_ion_client,
+					client_ctx->
+					meta_buffer_iommu_ion_handle,
+					&ionflag_iommu);
+		if (rc) {
+			ERR("%s():get_ION_flags fail\n",
+					 __func__);
+			goto import_ion_error;
+		}
+		vcd_meta_buffer->kernel_virt_addr_iommu =
+			(u8 *) ion_map_kernel(
+			client_ctx->user_ion_client,
+			client_ctx->meta_buffer_iommu_ion_handle);
+		if (!vcd_meta_buffer->kernel_virt_addr_iommu) {
+			ERR("%s(): get_ION_kernel virtual addr failed\n",
+				 __func__);
+			goto import_ion_error;
+		}
+		if (res_trk_get_core_type() == (u32)VCD_CORE_720P) {
+			rc = ion_phys(client_ctx->user_ion_client,
+				client_ctx->meta_buffer_iommu_ion_handle,
+				(unsigned long *) (&(vcd_meta_buffer->
+				physical_addr_iommu)), &len_iommu);
+			if (rc) {
+				ERR("%s():get_ION_kernel physical addr fail\n",
+					__func__);
+				goto ion_map_error_iommu;
+			}
+			vcd_meta_buffer->client_data_iommu = NULL;
+			vcd_meta_buffer->dev_addr_iommu = (u8 *)
+				vcd_meta_buffer->physical_addr_iommu;
+		} else {
+			rc = ion_map_iommu(client_ctx->user_ion_client,
+				client_ctx->meta_buffer_iommu_ion_handle,
+				VIDEO_DOMAIN, VIDEO_MAIN_POOL,
+				SZ_4K, 0, (unsigned long *)&iova_iommu,
+				(unsigned long *)&buffer_size_iommu,
+				0, 0);
+			if (rc || !iova_iommu) {
+				ERR("%s():get_ION_kernel physical addr fail, "\
+					"rc = %d iova = 0x%lx\n",
+					__func__, rc, iova);
+				goto ion_map_error_iommu;
+			}
+			vcd_meta_buffer->physical_addr_iommu =
+						(u8 *) iova_iommu;
+			vcd_meta_buffer->client_data_iommu = NULL;
+			vcd_meta_buffer->dev_addr_iommu = (u8 *) iova_iommu;
+		}
+	}
+
+	/*fill the meta addr table*/
+	num_buffers = vcd_meta_buffer->count;
+	buf_size = vcd_meta_buffer->size/num_buffers;
+	ker_vir_addr = vcd_meta_buffer->kernel_virtual_addr;
+	ker_vir_addr_iommu = vcd_meta_buffer->kernel_virt_addr_iommu;
+	client_ctx->meta_buf_size = buf_size;
+	for (index = 0; index < num_buffers; index++) {
+		client_ctx->meta_addr_table[index].kernel_vir_addr =
+			ker_vir_addr;
+		client_ctx->meta_addr_table[index].kernel_vir_addr_iommu =
+			ker_vir_addr_iommu;
+		DBG("[%d] kernel_virtual = %p kernel_vir_iommu = %p",
+			index, ker_vir_addr, ker_vir_addr_iommu);
+		ker_vir_addr += buf_size;
+		ker_vir_addr_iommu += buf_size;
+	}
+
+	DBG("Meta Buffer: Virt: %p, Phys %p, fd: %d",
+			vcd_meta_buffer->kernel_virtual_addr,
+			vcd_meta_buffer->physical_addr,
+			vcd_meta_buffer->pmem_fd);
+	DBG("IOMMU Meta Buffer: Virt: %p, Phys %p, fd: %d",
+			vcd_meta_buffer->kernel_virt_addr_iommu,
+			vcd_meta_buffer->physical_addr_iommu,
+			vcd_meta_buffer->pmem_fd_iommu);
+	DBG("Meta_buffer: Dev addr %p", vcd_meta_buffer->dev_addr);
+	DBG("IOMMU Meta_buffer: Dev addr %p",
+			vcd_meta_buffer->dev_addr_iommu);
+	vcd_status = vcd_set_property(client_ctx->vcd_handle,
+					  &vcd_property_hdr,
+					  vcd_meta_buffer);
+
+	if (vcd_status)
+		return false;
+	else
+		return true;
+ion_map_error_iommu:
+	if (vcd_meta_buffer->kernel_virt_addr_iommu) {
+		ion_unmap_kernel(client_ctx->user_ion_client,
+				client_ctx->meta_buffer_iommu_ion_handle);
+		vcd_meta_buffer->kernel_virt_addr_iommu = NULL;
+	}
+	if (!IS_ERR_OR_NULL(client_ctx->meta_buffer_iommu_ion_handle)) {
+		ion_free(client_ctx->user_ion_client,
+			client_ctx->meta_buffer_iommu_ion_handle);
+		 client_ctx->meta_buffer_iommu_ion_handle = NULL;
+	}
+ion_map_error:
+	if (vcd_meta_buffer->kernel_virtual_addr) {
+		ion_unmap_kernel(client_ctx->user_ion_client,
+				client_ctx->meta_buffer_ion_handle);
+		vcd_meta_buffer->kernel_virtual_addr = NULL;
+	}
+	if (!IS_ERR_OR_NULL(client_ctx->meta_buffer_ion_handle)) {
+		ion_free(client_ctx->user_ion_client,
+			client_ctx->meta_buffer_ion_handle);
+		 client_ctx->meta_buffer_ion_handle = NULL;
+	}
+import_ion_error:
+	return false;
+}
 static u32 vid_dec_set_h264_mv_buffers(struct video_client_ctx *client_ctx,
 					struct vdec_h264_mv *mv_data)
 {
@@ -1018,6 +1306,65 @@
 		return true;
 }
 
+static u32 vid_dec_free_meta_buffers(struct video_client_ctx *client_ctx)
+{
+	struct vcd_property_hdr vcd_property_hdr;
+	struct vcd_property_buffer_size meta_buffer_size;
+	u32 vcd_status = VCD_ERR_FAIL;
+
+	if (!client_ctx)
+		return false;
+	if (client_ctx->vcd_meta_buffer.client_data)
+		msm_subsystem_unmap_buffer((struct msm_mapped_buffer *)
+		client_ctx->vcd_meta_buffer.client_data);
+
+	if (client_ctx->vcd_meta_buffer.client_data_iommu)
+		msm_subsystem_unmap_buffer((struct msm_mapped_buffer *)
+		client_ctx->vcd_meta_buffer.client_data_iommu);
+
+	vcd_property_hdr.prop_id = VCD_I_FREE_EXT_METABUFFER;
+	vcd_property_hdr.sz = sizeof(struct vcd_property_buffer_size);
+
+	vcd_status = vcd_set_property(client_ctx->vcd_handle,
+				      &vcd_property_hdr, &meta_buffer_size);
+
+	if (!IS_ERR_OR_NULL(client_ctx->meta_buffer_ion_handle)) {
+		ion_unmap_kernel(client_ctx->user_ion_client,
+					client_ctx->meta_buffer_ion_handle);
+		if (!res_trk_check_for_sec_session() &&
+		   (res_trk_get_core_type() != (u32)VCD_CORE_720P)) {
+			ion_unmap_iommu(client_ctx->user_ion_client,
+				client_ctx->meta_buffer_ion_handle,
+				VIDEO_DOMAIN,
+				VIDEO_MAIN_POOL);
+		}
+		ion_free(client_ctx->user_ion_client,
+					client_ctx->meta_buffer_ion_handle);
+		client_ctx->meta_buffer_ion_handle = NULL;
+	}
+
+	if (!IS_ERR_OR_NULL(client_ctx->meta_buffer_iommu_ion_handle)) {
+		ion_unmap_kernel(client_ctx->user_ion_client,
+			client_ctx->meta_buffer_iommu_ion_handle);
+		if (res_trk_check_for_sec_session() &&
+		   (res_trk_get_core_type() != (u32)VCD_CORE_720P)) {
+			ion_unmap_iommu(client_ctx->user_ion_client,
+				client_ctx->meta_buffer_iommu_ion_handle,
+				VIDEO_DOMAIN,
+				VIDEO_MAIN_POOL);
+		}
+		ion_free(client_ctx->user_ion_client,
+				client_ctx->meta_buffer_iommu_ion_handle);
+		client_ctx->meta_buffer_iommu_ion_handle = NULL;
+	}
+
+	if (vcd_status)
+		return false;
+	else
+		return true;
+}
+
+
 static u32 vid_dec_free_h264_mv_buffers(struct video_client_ctx *client_ctx)
 {
 	struct vcd_property_hdr vcd_property_hdr;
@@ -1085,6 +1432,7 @@
 		vdec_buf_req->buffer_size = vcd_buf_req.sz;
 		vdec_buf_req->alignment = vcd_buf_req.align;
 		vdec_buf_req->buf_poolid = vcd_buf_req.buf_pool_id;
+		vdec_buf_req->meta_buffer_size = vcd_buf_req.meta_buffer_size;
 
 		return true;
 	}
@@ -1977,6 +2325,29 @@
 			return -EIO;
 		break;
 	}
+	case VDEC_IOCTL_SET_META_BUFFERS:
+	{
+		struct vdec_meta_buffers meta_buffers;
+		DBG("VDEC_IOCTL_SET_META_BUFFERS\n");
+		if (copy_from_user(&vdec_msg, arg, sizeof(vdec_msg)))
+			return -EFAULT;
+		if (copy_from_user(&meta_buffers, vdec_msg.in,
+						   sizeof(meta_buffers)))
+			return -EFAULT;
+		result = vid_dec_set_meta_buffers(client_ctx, &meta_buffers);
+
+		if (!result)
+			return -EIO;
+		break;
+	}
+	case VDEC_IOCTL_FREE_META_BUFFERS:
+	{
+		DBG("VDEC_IOCTL_FREE_META_BUFFERS\n");
+		result = vid_dec_free_meta_buffers(client_ctx);
+		if (!result)
+			return -EIO;
+		break;
+	}
 	case VDEC_IOCTL_SET_H264_MV_BUFFER:
 	{
 		struct vdec_h264_mv mv_data;
diff --git a/drivers/video/msm/vidc/common/enc/venc.c b/drivers/video/msm/vidc/common/enc/venc.c
index 763fbda..c05e568 100644
--- a/drivers/video/msm/vidc/common/enc/venc.c
+++ b/drivers/video/msm/vidc/common/enc/venc.c
@@ -218,15 +218,15 @@
 
 	switch (event) {
 	case VCD_EVT_RESP_OUTPUT_DONE:
-	   DBG("Send INPUT_DON message to client = %p\n",
+	   DBG("Send OUTPUT_DON message to client = %p\n",
 			client_ctx);
 	   break;
 	case VCD_EVT_RESP_OUTPUT_FLUSHED:
-	   DBG("Send INPUT_FLUSHED message to client = %p\n",
+	   DBG("Send OUTPUT_FLUSHED message to client = %p\n",
 		   client_ctx);
 	   break;
 	default:
-	   ERR("QVD: vid_enc_output_frame_done invalid cmd type: %d\n", event);
+	   ERR("vid_enc_output_frame_done: invalid cmd type: %d\n", event);
 	   venc_msg->venc_msg_info.statuscode = VEN_S_EFATAL;
 	   break;
 	}
@@ -336,6 +336,12 @@
 		venc_msg->venc_msg_info.msgcode =
 			VEN_MSG_PAUSE;
 		break;
+	case VCD_EVT_IND_INFO_LTRUSE_FAILED:
+		INFO("\n msm_vidc_enc: Sending VEN_MSG_LTRUSE_FAILED"\
+			 " to client");
+		venc_msg->venc_msg_info.msgcode =
+			VEN_MSG_LTRUSE_FAILED;
+		break;
 
 	default:
 		ERR("%s() : unknown event type %u\n",
@@ -394,6 +400,7 @@
 	case VCD_EVT_IND_OUTPUT_RECONFIG:
 	case VCD_EVT_IND_HWERRFATAL:
 	case VCD_EVT_IND_RESOURCES_LOST:
+	case VCD_EVT_IND_INFO_LTRUSE_FAILED:
 		vid_enc_lean_event(client_ctx, event, status);
 		break;
 
@@ -790,17 +797,18 @@
 		struct venc_buffer enc_buffer;
 		if (copy_from_user(&venc_msg, arg, sizeof(venc_msg)))
 			return -EFAULT;
-		DBG("VEN_IOCTL_CMD_ENCODE_FRAME"
-			"/VEN_IOCTL_CMD_FILL_OUTPUT_BUFFER\n");
 		if (copy_from_user(&enc_buffer, venc_msg.in,
 						   sizeof(enc_buffer)))
 			return -EFAULT;
-		if (cmd == VEN_IOCTL_CMD_ENCODE_FRAME)
+		if (cmd == VEN_IOCTL_CMD_ENCODE_FRAME) {
+			DBG("VEN_IOCTL_CMD_ENCODE_FRAME\n");
 			result = vid_enc_encode_frame(client_ctx,
 					&enc_buffer);
-		else
+		} else {
+			DBG("VEN_IOCTL_CMD_FILL_OUTPUT_BUFFER\n");
 			result = vid_enc_fill_output_buffer(client_ctx,
 					&enc_buffer);
+		}
 		if (!result) {
 			DBG("\n VEN_IOCTL_CMD_ENCODE_FRAME/"
 				"VEN_IOCTL_CMD_FILL_OUTPUT_BUFFER failed");
@@ -866,19 +874,19 @@
 		if (copy_from_user(&venc_msg, arg, sizeof(venc_msg)))
 			return -EFAULT;
 
-		DBG("VEN_IOCTL_SET_INPUT_BUFFER_REQ"
-			"/VEN_IOCTL_SET_OUTPUT_BUFFER_REQ\n");
-
 		if (copy_from_user(&allocatorproperty, venc_msg.in,
 			sizeof(allocatorproperty)))
 			return -EFAULT;
 
-		if (cmd == VEN_IOCTL_SET_OUTPUT_BUFFER_REQ)
-				result = vid_enc_set_buffer_req(client_ctx,
-						&allocatorproperty, false);
-		else
+		if (cmd == VEN_IOCTL_SET_OUTPUT_BUFFER_REQ) {
+			DBG("VEN_IOCTL_SET_OUTPUT_BUFFER_REQ\n");
+			result = vid_enc_set_buffer_req(client_ctx,
+					&allocatorproperty, false);
+		} else {
+			DBG("VEN_IOCTL_SET_INPUT_BUFFER_REQ\n");
 			result = vid_enc_set_buffer_req(client_ctx,
 					&allocatorproperty, true);
+		}
 		if (!result) {
 			DBG("setting VEN_IOCTL_SET_OUTPUT_BUFFER_REQ/"
 			"VEN_IOCTL_SET_INPUT_BUFFER_REQ failed\n");
@@ -893,15 +901,15 @@
 		if (copy_from_user(&venc_msg, arg, sizeof(venc_msg)))
 			return -EFAULT;
 
-		DBG("VEN_IOCTL_GET_INPUT_BUFFER_REQ/"
-			"VEN_IOCTL_GET_OUTPUT_BUFFER_REQ\n");
-
-		if (cmd == VEN_IOCTL_GET_OUTPUT_BUFFER_REQ)
+		if (cmd == VEN_IOCTL_GET_OUTPUT_BUFFER_REQ) {
+			DBG("VEN_IOCTL_GET_OUTPUT_BUFFER_REQ\n");
 			result = vid_enc_get_buffer_req(client_ctx,
 					&allocatorproperty, false);
-		else
+		} else {
+			DBG("VEN_IOCTL_GET_INPUT_BUFFER_REQ\n");
 			result = vid_enc_get_buffer_req(client_ctx,
 					&allocatorproperty, true);
+		}
 		if (!result)
 			return -EIO;
 		if (copy_to_user(venc_msg.out, &allocatorproperty,
@@ -1342,6 +1350,7 @@
 	}
 	case VEN_IOCTL_CMD_REQUEST_IFRAME:
 	{
+		DBG("VEN_IOCTL_CMD_REQUEST_IFRAME\n");
 		result = vid_enc_request_iframe(client_ctx);
 		if (!result) {
 			ERR("setting VEN_IOCTL_CMD_REQUEST_IFRAME failed\n");
@@ -1565,6 +1574,7 @@
 		struct vcd_property_hdr vcd_property_hdr;
 		struct vcd_property_live live_mode;
 
+		DBG("VEN_IOCTL_SET_METABUFFER_MODE\n");
 		if (copy_from_user(&venc_msg, arg, sizeof(venc_msg)))
 			return -EFAULT;
 		if (copy_from_user(&metabuffer_mode, venc_msg.in,
@@ -1614,6 +1624,7 @@
 		struct vcd_property_hdr vcd_property_hdr;
 		u32 vcd_status = VCD_ERR_FAIL;
 		u32 enable = true;
+		DBG("VEN_IOCTL_SET_SLICE_DELIVERY_MODE\n");
 		vcd_property_hdr.prop_id = VCD_I_SLICE_DELIVERY_MODE;
 		vcd_property_hdr.sz = sizeof(u32);
 		vcd_status = vcd_set_property(client_ctx->vcd_handle,
@@ -1647,6 +1658,143 @@
 		}
 		break;
 	}
+	case VEN_IOCTL_SET_LTRMODE:
+	case VEN_IOCTL_GET_LTRMODE:
+	{
+		struct venc_ltrmode encoder_ltrmode;
+		if (copy_from_user(&venc_msg, arg, sizeof(venc_msg)))
+			return -EFAULT;
+		if (cmd == VEN_IOCTL_SET_LTRMODE) {
+			DBG("VEN_IOCTL_SET_LTRMODE\n");
+			if (copy_from_user(&encoder_ltrmode, venc_msg.in,
+					sizeof(encoder_ltrmode)))
+				return -EFAULT;
+			result = vid_enc_set_get_ltrmode(client_ctx,
+					&encoder_ltrmode, true);
+		} else {
+			DBG("VEN_IOCTL_GET_LTRMODE\n");
+			result = vid_enc_set_get_ltrmode(client_ctx,
+					&encoder_ltrmode, false);
+			if (result) {
+				if (copy_to_user(venc_msg.out, &encoder_ltrmode,
+						sizeof(encoder_ltrmode)))
+					return -EFAULT;
+			}
+		}
+		if (!result) {
+			ERR("VEN_IOCTL_(G)SET_LTRMODE failed\n");
+			return -EIO;
+		}
+		break;
+	}
+	case VEN_IOCTL_SET_LTRCOUNT:
+	case VEN_IOCTL_GET_LTRCOUNT:
+	{
+		struct venc_ltrcount encoder_ltrcount;
+		if (copy_from_user(&venc_msg, arg, sizeof(venc_msg)))
+			return -EFAULT;
+		if (cmd == VEN_IOCTL_SET_LTRCOUNT) {
+			DBG("VEN_IOCTL_SET_LTRCOUNT\n");
+			if (copy_from_user(&encoder_ltrcount, venc_msg.in,
+					sizeof(encoder_ltrcount)))
+				return -EFAULT;
+			result = vid_enc_set_get_ltrcount(client_ctx,
+					&encoder_ltrcount, true);
+		} else {
+			DBG("VEN_IOCTL_GET_LTRCOUNT\n");
+			result = vid_enc_set_get_ltrcount(client_ctx,
+					&encoder_ltrcount, false);
+			if (result) {
+				if (copy_to_user(venc_msg.out,
+					&encoder_ltrcount,
+					sizeof(encoder_ltrcount)))
+					return -EFAULT;
+			}
+		}
+		if (!result) {
+			ERR("VEN_IOCTL_(G)SET_LTRCOUNT failed\n");
+			return -EIO;
+		}
+		break;
+	}
+	case VEN_IOCTL_SET_LTRPERIOD:
+	case VEN_IOCTL_GET_LTRPERIOD:
+	{
+		struct venc_ltrperiod encoder_ltrperiod;
+		if (copy_from_user(&venc_msg, arg, sizeof(venc_msg)))
+			return -EFAULT;
+		if (cmd == VEN_IOCTL_SET_LTRPERIOD) {
+			DBG("VEN_IOCTL_SET_LTRPERIOD\n");
+			if (copy_from_user(&encoder_ltrperiod, venc_msg.in,
+					sizeof(encoder_ltrperiod)))
+				return -EFAULT;
+			result = vid_enc_set_get_ltrperiod(client_ctx,
+					&encoder_ltrperiod, true);
+		} else {
+			DBG("VEN_IOCTL_GET_LTRPERIOD\n");
+			result = vid_enc_set_get_ltrperiod(client_ctx,
+					&encoder_ltrperiod, false);
+			if (result) {
+				if (copy_to_user(venc_msg.out,
+					&encoder_ltrperiod,
+					sizeof(encoder_ltrperiod)))
+					return -EFAULT;
+			}
+		}
+		if (!result) {
+			ERR("VEN_IOCTL_(G)SET_LTRPERIOD failed\n");
+			return -EIO;
+		}
+		break;
+	}
+	case VEN_IOCTL_GET_CAPABILITY_LTRCOUNT:
+	{
+		struct venc_range venc_capltrcount;
+		if (copy_from_user(&venc_msg, arg, sizeof(venc_msg)))
+			return -EFAULT;
+		DBG("VEN_IOCTL_GET_CAPABILITY_LTRCOUNT\n");
+		result = vid_enc_get_capability_ltrcount(client_ctx,
+					&venc_capltrcount);
+		if (result) {
+			if (copy_to_user(venc_msg.out, &venc_capltrcount,
+					sizeof(venc_capltrcount)))
+				return -EFAULT;
+		} else {
+			ERR("VEN_IOCTL_GET_CAPABILITY_LTRCOUNT failed\n");
+			return -EIO;
+		}
+		break;
+	}
+	case VEN_IOCTL_SET_LTRUSE:
+	case VEN_IOCTL_GET_LTRUSE:
+	{
+		struct venc_ltruse encoder_ltruse;
+		if (copy_from_user(&venc_msg, arg, sizeof(venc_msg)))
+			return -EFAULT;
+		if (cmd == VEN_IOCTL_SET_LTRUSE) {
+			DBG("VEN_IOCTL_SET_LTRUSE\n");
+			if (copy_from_user(&encoder_ltruse, venc_msg.in,
+					sizeof(encoder_ltruse)))
+				return -EFAULT;
+			result = vid_enc_set_get_ltruse(client_ctx,
+						&encoder_ltruse, true);
+		} else {
+			DBG("VEN_IOCTL_GET_LTRUSE\n");
+			result = vid_enc_set_get_ltruse(client_ctx,
+						&encoder_ltruse, false);
+			if (result) {
+				if (copy_to_user(venc_msg.out,
+					&encoder_ltruse,
+					sizeof(encoder_ltruse)))
+					return -EFAULT;
+			}
+		}
+		if (!result) {
+			ERR("VEN_IOCTL_(G)SET_LTRUSE failed\n");
+			return -EIO;
+		}
+		break;
+	}
 	case VEN_IOCTL_SET_AC_PREDICTION:
 	case VEN_IOCTL_GET_AC_PREDICTION:
 	case VEN_IOCTL_SET_RVLC:
diff --git a/drivers/video/msm/vidc/common/enc/venc_internal.c b/drivers/video/msm/vidc/common/enc/venc_internal.c
index 8779432..7a26d2e 100644
--- a/drivers/video/msm/vidc/common/enc/venc_internal.c
+++ b/drivers/video/msm/vidc/common/enc/venc_internal.c
@@ -328,6 +328,42 @@
 	vcd_property_hdr.prop_id = VCD_I_METADATA_ENABLE;
 	vcd_property_hdr.sz = sizeof(struct vcd_property_meta_data_enable);
 	if (set_flag) {
+		DBG("vcd_set_property: VCD_I_METADATA_ENABLE = %x\n",
+				(u32)*extradata_flag);
+		vcd_meta_data.meta_data_enable_flag = *extradata_flag;
+		vcd_status = vcd_set_property(client_ctx->vcd_handle,
+					&vcd_property_hdr, &vcd_meta_data);
+		if (vcd_status) {
+			ERR("%s(): Set VCD_I_METADATA_ENABLE Failed\n",
+				__func__);
+			return false;
+		}
+	} else {
+		vcd_status = vcd_get_property(client_ctx->vcd_handle,
+					&vcd_property_hdr, &vcd_meta_data);
+		if (vcd_status) {
+			ERR("%s(): Get VCD_I_METADATA_ENABLE Failed\n",
+				__func__);
+			return false;
+		}
+		*extradata_flag = vcd_meta_data.meta_data_enable_flag;
+		DBG("vcd_get_property: VCD_I_METADATA_ENABLE = 0x%x\n",
+				(u32)*extradata_flag);
+	}
+	return true;
+}
+
+u32 vid_enc_set_get_extradata_cfg(struct video_client_ctx *client_ctx,
+		u32 *extradata_flag, u32 set_flag)
+{
+	struct vcd_property_hdr vcd_property_hdr;
+	struct vcd_property_meta_data_enable vcd_meta_data;
+	u32 vcd_status = VCD_ERR_FAIL;
+	if (!client_ctx || !extradata_flag)
+		return false;
+	vcd_property_hdr.prop_id = VCD_I_METADATA_ENABLE;
+	vcd_property_hdr.sz = sizeof(struct vcd_property_meta_data_enable);
+	if (set_flag) {
 		DBG("vcd_set_property: VCD_I_METADATA_ENABLE = %d\n",
 				*extradata_flag);
 		vcd_meta_data.meta_data_enable_flag = *extradata_flag;
@@ -1995,3 +2031,215 @@
 			return false;
 		}
 }
+
+u32 vid_enc_set_get_ltrmode(struct video_client_ctx *client_ctx,
+		struct venc_ltrmode *venc_ltrmode, u32 set_flag)
+{
+	struct vcd_property_ltrmode_type vcd_property_ltrmode;
+	struct vcd_property_hdr vcd_property_hdr;
+	u32 vcd_status = VCD_ERR_FAIL;
+
+	if (!client_ctx || !venc_ltrmode)
+		return false;
+
+	vcd_property_hdr.prop_id = VCD_I_LTR_MODE;
+	vcd_property_hdr.sz =
+		sizeof(struct vcd_property_ltrmode_type);
+
+	if (set_flag) {
+		vcd_property_ltrmode.ltr_mode = (enum vcd_property_ltrmode)
+			venc_ltrmode->ltr_mode;
+		DBG("%s: Set ltr_mode = %u", __func__,
+			(u32)vcd_property_ltrmode.ltr_mode);
+		vcd_status = vcd_set_property(client_ctx->vcd_handle,
+				&vcd_property_hdr, &vcd_property_ltrmode);
+		if (vcd_status) {
+			ERR("%s(): Set VCD_I_LTR_MODE Failed\n",
+					__func__);
+			return false;
+		}
+	} else {
+		vcd_status = vcd_get_property(client_ctx->vcd_handle,
+				&vcd_property_hdr, &vcd_property_ltrmode);
+		if (vcd_status) {
+			ERR("%s(): Get VCD_I_LTR_MODE Failed\n",
+					__func__);
+			return false;
+		} else {
+			venc_ltrmode->ltr_mode = (unsigned long)
+				vcd_property_ltrmode.ltr_mode;
+			DBG("%s: Got ltr_mode = %u", __func__,
+				(u32)vcd_property_ltrmode.ltr_mode);
+		}
+	}
+
+	return true;
+}
+
+u32 vid_enc_set_get_ltrcount(struct video_client_ctx *client_ctx,
+		struct venc_ltrcount *venc_ltrcount, u32 set_flag)
+{
+	struct vcd_property_ltrcount_type vcd_property_ltrcount;
+	struct vcd_property_hdr vcd_property_hdr;
+	u32 vcd_status = VCD_ERR_FAIL;
+
+	if (!client_ctx || !venc_ltrcount)
+		return false;
+
+	vcd_property_hdr.prop_id = VCD_I_LTR_COUNT;
+	vcd_property_hdr.sz =
+		sizeof(struct vcd_property_ltrcount_type);
+
+	if (set_flag) {
+		vcd_property_ltrcount.ltr_count = (u32)
+			venc_ltrcount->ltr_count;
+		DBG("%s: Set ltr_count = %u", __func__,
+			(u32)vcd_property_ltrcount.ltr_count);
+		vcd_status = vcd_set_property(client_ctx->vcd_handle,
+				&vcd_property_hdr, &vcd_property_ltrcount);
+		if (vcd_status) {
+			ERR("%s(): Set VCD_I_LTR_COUNT Failed\n",
+					__func__);
+			return false;
+		}
+	} else {
+		vcd_status = vcd_get_property(client_ctx->vcd_handle,
+				&vcd_property_hdr, &vcd_property_ltrcount);
+		if (vcd_status) {
+			ERR("%s(): Get VCD_I_LTR_COUNT Failed\n",
+					__func__);
+			return false;
+		} else {
+			venc_ltrcount->ltr_count = (unsigned long)
+				vcd_property_ltrcount.ltr_count;
+			DBG("%s: Got ltr_count = %u", __func__,
+				(u32)vcd_property_ltrcount.ltr_count);
+		}
+	}
+
+	return true;
+}
+
+u32 vid_enc_set_get_ltrperiod(struct video_client_ctx *client_ctx,
+		struct venc_ltrperiod *venc_ltrperiod, u32 set_flag)
+{
+	struct vcd_property_ltrperiod_type vcd_property_ltrperiod;
+	struct vcd_property_hdr vcd_property_hdr;
+	u32 vcd_status = VCD_ERR_FAIL;
+
+	if (!client_ctx || !venc_ltrperiod)
+		return false;
+
+	vcd_property_hdr.prop_id = VCD_I_LTR_PERIOD;
+	vcd_property_hdr.sz =
+		sizeof(struct vcd_property_ltrperiod_type);
+
+	if (set_flag) {
+		vcd_property_ltrperiod.ltr_period = (u32)
+			venc_ltrperiod->ltr_period;
+		DBG("%s: Set ltr_period = %u", __func__,
+			(u32)vcd_property_ltrperiod.ltr_period);
+		vcd_status = vcd_set_property(client_ctx->vcd_handle,
+				&vcd_property_hdr, &vcd_property_ltrperiod);
+		if (vcd_status) {
+			ERR("%s(): Set VCD_I_LTR_PERIOD Failed\n",
+					__func__);
+			return false;
+		}
+	} else {
+		vcd_status = vcd_get_property(client_ctx->vcd_handle,
+				&vcd_property_hdr, &vcd_property_ltrperiod);
+		if (vcd_status) {
+			ERR("%s(): Get VCD_I_LTR_PERIOD Failed\n",
+					__func__);
+			return false;
+		} else {
+			venc_ltrperiod->ltr_period = (unsigned long)
+				vcd_property_ltrperiod.ltr_period;
+			DBG("%s: Got ltr_period = %u", __func__,
+				(u32)vcd_property_ltrperiod.ltr_period);
+		}
+	}
+
+	return true;
+}
+
+u32 vid_enc_set_get_ltruse(struct video_client_ctx *client_ctx,
+		struct venc_ltruse *venc_ltruse, u32 set_flag)
+{
+	struct vcd_property_ltruse_type vcd_property_ltruse;
+	struct vcd_property_hdr vcd_property_hdr;
+	u32 vcd_status = VCD_ERR_FAIL;
+
+	if (!client_ctx || !venc_ltruse)
+		return false;
+
+	vcd_property_hdr.prop_id = VCD_I_LTR_USE;
+	vcd_property_hdr.sz =
+		sizeof(struct vcd_property_ltruse_type);
+
+	if (set_flag) {
+		vcd_property_ltruse.ltr_id = (u32)
+			venc_ltruse->ltr_id;
+		vcd_property_ltruse.ltr_frames = (u32)
+			venc_ltruse->ltr_frames;
+		DBG("%s: Set ltr_id = %u, ltr_frames = %u",
+			__func__, vcd_property_ltruse.ltr_id,
+			vcd_property_ltruse.ltr_frames);
+		vcd_status = vcd_set_property(client_ctx->vcd_handle,
+				&vcd_property_hdr, &vcd_property_ltruse);
+		if (vcd_status) {
+			ERR("%s(): Set VCD_I_LTR_USE Failed\n",
+					__func__);
+			return false;
+		}
+	} else {
+		vcd_status = vcd_get_property(client_ctx->vcd_handle,
+				&vcd_property_hdr, &vcd_property_ltruse);
+		if (vcd_status) {
+			ERR("%s(): Get VCD_I_LTR_USE Failed\n",
+					__func__);
+			return false;
+		} else {
+			venc_ltruse->ltr_id = (unsigned long)
+				vcd_property_ltruse.ltr_id;
+			venc_ltruse->ltr_frames = (unsigned long)
+				vcd_property_ltruse.ltr_frames;
+			DBG("%s: Got ltr_id = %u, ltr_frames = %u",
+				__func__, vcd_property_ltruse.ltr_id,
+				vcd_property_ltruse.ltr_frames);
+		}
+	}
+
+	return true;
+}
+
+u32 vid_enc_get_capability_ltrcount(struct video_client_ctx *client_ctx,
+		struct venc_range *venc_capltrcount)
+{
+	struct vcd_property_range_type vcd_property_range;
+	struct vcd_property_hdr vcd_property_hdr;
+	u32 vcd_status = VCD_ERR_FAIL;
+
+	if (!client_ctx || !venc_capltrcount)
+		return false;
+
+	vcd_property_hdr.prop_id = VCD_I_CAPABILITY_LTR_COUNT;
+	vcd_property_hdr.sz = sizeof(struct vcd_property_range_type);
+	vcd_status = vcd_get_property(client_ctx->vcd_handle,
+					&vcd_property_hdr, &vcd_property_range);
+	if (vcd_status) {
+		ERR("%s(): Get VCD_I_CAPABILITY_LTR_COUNT Failed\n",
+			__func__);
+		return false;
+	} else {
+		venc_capltrcount->min = vcd_property_range.min;
+		venc_capltrcount->max = vcd_property_range.max;
+		venc_capltrcount->step_size = vcd_property_range.step_size;
+		DBG("%s: Got min: %lu, max: %lu, step_size: %lu", __func__,
+			venc_capltrcount->min, venc_capltrcount->max,
+			venc_capltrcount->step_size);
+	}
+
+	return true;
+}
diff --git a/drivers/video/msm/vidc/common/enc/venc_internal.h b/drivers/video/msm/vidc/common/enc/venc_internal.h
index 8a07fdb..17cefbb 100644
--- a/drivers/video/msm/vidc/common/enc/venc_internal.h
+++ b/drivers/video/msm/vidc/common/enc/venc_internal.h
@@ -151,4 +151,19 @@
 u32 vid_enc_get_recon_buffer_size(struct video_client_ctx *client_ctx,
 		struct venc_recon_buff_size *venc_recon_size);
 
+u32 vid_enc_set_get_ltrmode(struct video_client_ctx *client_ctx,
+		struct venc_ltrmode *encoder_ltrmode, u32 set_flag);
+
+u32 vid_enc_set_get_ltrcount(struct video_client_ctx *client_ctx,
+		struct venc_ltrcount *encoder_ltrcount, u32 set_flag);
+
+u32 vid_enc_set_get_ltrperiod(struct video_client_ctx *client_ctx,
+		struct venc_ltrperiod *encoder_ltrperiod, u32 set_flag);
+
+u32 vid_enc_get_capability_ltrcount(struct video_client_ctx *client_ctx,
+		struct venc_range *venc_capltrcount);
+
+u32 vid_enc_set_get_ltruse(struct video_client_ctx *client_ctx,
+		struct venc_ltruse *encoder_ltruse, u32 set_flag);
+
 #endif
diff --git a/drivers/video/msm/vidc/common/vcd/vcd.h b/drivers/video/msm/vidc/common/vcd/vcd.h
index a22adeb..5b2450e 100644
--- a/drivers/video/msm/vidc/common/vcd/vcd.h
+++ b/drivers/video/msm/vidc/common/vcd/vcd.h
@@ -402,4 +402,7 @@
 struct vcd_transc *vcd_get_first_in_use_trans_for_clnt(
 	struct vcd_clnt_ctxt *cctxt);
 
+u32 vcd_handle_ltr_use_failed(struct vcd_clnt_ctxt *cctxt,
+	void *payload, size_t sz, u32 status);
+
 #endif
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 8f52f83..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
@@ -964,6 +964,12 @@
 			vcd_handle_ind_info_output_reconfig(cctxt, status);
 			break;
 		}
+	case VCD_EVT_IND_INFO_LTRUSE_FAILED:
+		{
+			rc = vcd_handle_ltr_use_failed(cctxt,
+					payload, sz, status);
+			break;
+		}
 	default:
 		{
 			VCD_MSG_ERROR
@@ -1744,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/drivers/video/msm/vidc/common/vcd/vcd_sub.c b/drivers/video/msm/vidc/common/vcd/vcd_sub.c
index a4c44f3..78d77d1 100644
--- a/drivers/video/msm/vidc/common/vcd/vcd_sub.c
+++ b/drivers/video/msm/vidc/common/vcd/vcd_sub.c
@@ -3516,3 +3516,14 @@
 	}
 	return rc;
 }
+
+u32 vcd_handle_ltr_use_failed(struct vcd_clnt_ctxt *cctxt,
+	void *payload, size_t sz, u32 status)
+{
+	u32 rc = VCD_S_SUCCESS;
+	if (payload && cctxt) {
+		cctxt->callback(VCD_EVT_IND_INFO_LTRUSE_FAILED,
+			status, payload, sz, cctxt, cctxt->client_data);
+	}
+	return rc;
+}
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/dvb/dmx.h b/include/linux/dvb/dmx.h
index fd4447f..460cba3 100644
--- a/include/linux/dvb/dmx.h
+++ b/include/linux/dvb/dmx.h
@@ -208,7 +208,10 @@
 	DMX_EVENT_SECTION_CRC_ERROR,
 
 	/* End-of-stream, no more data from this filter */
-	DMX_EVENT_EOS
+	DMX_EVENT_EOS,
+
+	/* New Elementary Stream data is ready */
+	DMX_EVENT_NEW_ES_DATA
 };
 
 /* Flags passed in filter events */
@@ -217,7 +220,7 @@
 #define DMX_FILTER_CC_ERROR			0x01
 
 /* Discontinuity indicator was set */
-#define DMX_FILTER_DISCONTINUITY_INDEICATOR	0x02
+#define DMX_FILTER_DISCONTINUITY_INDICATOR	0x02
 
 /* PES legnth in PES header is not correct */
 #define DMX_FILTER_PES_LENGTH_ERROR		0x04
@@ -296,6 +299,57 @@
 };
 
 /*
+ * Elementary stream data information associated
+ * with DMX_EVENT_NEW_ES_DATA event
+ */
+struct dmx_es_data_event_info {
+	/* Buffer user-space handle */
+	int buf_handle;
+
+	/*
+	 * Cookie to provide when releasing the buffer
+	 * using the DMX_RELEASE_DECODER_BUFFER ioctl command
+	 */
+	int cookie;
+
+	/* Offset of data from the beginning of the buffer */
+	__u32 offset;
+
+	/* Length of data in buffer (in bytes) */
+	__u32 data_len;
+
+	/* Indication whether PTS value is valid */
+	int pts_valid;
+
+	/* PTS value associated with the buffer */
+	__u64 pts;
+
+	/* Indication whether DTS value is valid */
+	int dts_valid;
+
+	/* DTS value associated with the buffer */
+	__u64 dts;
+
+	/*
+	 * Number of TS packets with Transport Error Indicator (TEI) set
+	 * in the TS packet header since last reported event
+	 */
+	__u32 transport_error_indicator_counter;
+
+	/* Number of continuity errors since last reported event */
+	__u32 continuity_error_counter;
+
+	/* Total number of TS packets processed since last reported event */
+	__u32 ts_packets_num;
+
+	/*
+	 * Number of dropped bytes due to insufficient buffer space,
+	 * since last reported event
+	 */
+	__u32 ts_dropped_bytes;
+};
+
+/*
  * Filter's event returned through DMX_GET_EVENT.
  * poll with POLLPRI would block until events are available.
  */
@@ -307,6 +361,7 @@
 		struct dmx_section_event_info section;
 		struct dmx_rec_chunk_event_info recording_chunk;
 		struct dmx_pcr_event_info pcr;
+		struct dmx_es_data_event_info es_data;
 	} params;
 };
 
@@ -525,10 +580,10 @@
 #define DMX_RELEASE_DATA		 _IO('o', 57)
 #define DMX_FEED_DATA			 _IO('o', 58)
 #define DMX_SET_PLAYBACK_MODE	 _IOW('o', 59, enum dmx_playback_mode_t)
-#define DMX_GET_EVENT			 _IOR('o', 60, struct dmx_filter_event)
-#define DMX_SET_BUFFER_MODE		 _IOW('o', 61, enum dmx_buffer_mode)
-#define DMX_SET_BUFFER			 _IOW('o', 62, struct dmx_buffer)
+#define DMX_GET_EVENT		 _IOR('o', 60, struct dmx_filter_event)
+#define DMX_SET_BUFFER_MODE	 _IOW('o', 61, enum dmx_buffer_mode)
+#define DMX_SET_BUFFER		 _IOW('o', 62, struct dmx_buffer)
 #define DMX_SET_DECODER_BUFFER	 _IOW('o', 63, struct dmx_decoder_buffers)
-
+#define DMX_REUSE_DECODER_BUFFER _IO('o', 64)
 
 #endif /*_DVBDMX_H_*/
diff --git a/include/linux/mfd/pm8xxx/ccadc.h b/include/linux/mfd/pm8xxx/ccadc.h
index fc31f89..e4d5a67f 100644
--- a/include/linux/mfd/pm8xxx/ccadc.h
+++ b/include/linux/mfd/pm8xxx/ccadc.h
@@ -17,14 +17,20 @@
 
 #define PM8XXX_CCADC_DEV_NAME "pm8xxx-ccadc"
 
+struct pm8xxx_ccadc_core_data {
+	unsigned int	batt_temp_channel;
+};
+
 /**
  * struct pm8xxx_ccadc_platform_data -
+ * @ccadc_cdata:	core data for the ccadc driver containing channel info
  * @r_sense_uohm:		sense resistor value in (micro Ohms)
  * @calib_delay_ms:	how often should the adc calculate gain and offset
  */
 struct pm8xxx_ccadc_platform_data {
-	int		r_sense_uohm;
-	unsigned int	calib_delay_ms;
+	struct pm8xxx_ccadc_core_data	ccadc_cdata;
+	int				r_sense_uohm;
+	unsigned int			calib_delay_ms;
 };
 
 #define CCADC_READING_RESOLUTION_N	542535
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/mfd/pm8xxx/pm8921-charger.h b/include/linux/mfd/pm8xxx/pm8921-charger.h
index 44f8538..ab52309 100644
--- a/include/linux/mfd/pm8xxx/pm8921-charger.h
+++ b/include/linux/mfd/pm8xxx/pm8921-charger.h
@@ -138,6 +138,10 @@
  *				driver couldn't stop charging when battery
  *				temperature is out of bounds. Used only if
  *				btc_override = 1
+ * stop_chg_upon_expiry:	flag to indicate that the charger driver should
+ *				stop charging the battery when the safety timer
+ *				expires. If not set the charger driver will
+ *				restart charging upon expiry.
  */
 struct pm8921_charger_platform_data {
 	struct pm8xxx_charger_core_data	charger_cdata;
@@ -183,6 +187,7 @@
 	int				btc_override_hot_degc;
 	int				btc_delay_ms;
 	int				btc_panic_if_cant_stop_chg;
+	int				stop_chg_upon_expiry;
 };
 
 enum pm8921_charger_source {
diff --git a/include/linux/mfd/wcd9xxx/core.h b/include/linux/mfd/wcd9xxx/core.h
index 2874a3b..4b2ad66 100644
--- a/include/linux/mfd/wcd9xxx/core.h
+++ b/include/linux/mfd/wcd9xxx/core.h
@@ -83,6 +83,7 @@
 	TABLA_NUM_IRQS = WCD9XXX_NUM_IRQS,
 	SITAR_NUM_IRQS = WCD9XXX_NUM_IRQS,
 	TAIKO_NUM_IRQS = WCD9XXX_NUM_IRQS,
+	TAPAN_NUM_IRQS = WCD9XXX_NUM_IRQS,
 };
 
 
@@ -212,7 +213,8 @@
 void wcd9xxx_disable_irq_sync(struct wcd9xxx *wcd9xxx, int irq);
 #if defined(CONFIG_WCD9310_CODEC) || \
 	defined(CONFIG_WCD9304_CODEC) || \
-	defined(CONFIG_WCD9320_CODEC)
+	defined(CONFIG_WCD9320_CODEC) || \
+	defined(CONFIG_WCD9306_CODEC)
 int __init wcd9xxx_irq_of_init(struct device_node *node,
 			       struct device_node *parent);
 #else
@@ -221,5 +223,5 @@
 {
 	return 0;
 }
-#endif
+#endif	/* CONFIG_OF */
 #endif
diff --git a/include/linux/mfd/wcd9xxx/wcd9306_registers.h b/include/linux/mfd/wcd9xxx/wcd9306_registers.h
new file mode 100644
index 0000000..1254fac
--- /dev/null
+++ b/include/linux/mfd/wcd9xxx/wcd9306_registers.h
@@ -0,0 +1,1015 @@
+/* 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 WCD9306_REGISTERS_H
+#define WCD9306_REGISTERS_H
+
+#include <linux/mfd/wcd9xxx/wcd9xxx_registers.h>
+
+#define TAPAN_A_CHIP_CTL				WCD9XXX_A_CHIP_CTL
+#define TAPAN_A_CHIP_CTL__POR			WCD9XXX_A_CHIP_CTL__POR
+#define TAPAN_A_CHIP_STATUS				WCD9XXX_A_CHIP_STATUS
+#define TAPAN_A_CHIP_STATUS__POR		WCD9XXX_A_CHIP_STATUS__POR
+#define TAPAN_A_CHIP_ID_BYTE_0			WCD9XXX_A_CHIP_ID_BYTE_0
+#define TAPAN_A_CHIP_ID_BYTE_0__POR		WCD9XXX_A_CHIP_ID_BYTE_0__POR
+#define TAPAN_A_CHIP_ID_BYTE_1			WCD9XXX_A_CHIP_ID_BYTE_1
+#define TAPAN_A_CHIP_ID_BYTE_1__POR		WCD9XXX_A_CHIP_ID_BYTE_1__POR
+#define TAPAN_A_CHIP_ID_BYTE_2			WCD9XXX_A_CHIP_ID_BYTE_2
+#define TAPAN_A_CHIP_ID_BYTE_2__POR		WCD9XXX_A_CHIP_ID_BYTE_2__POR
+#define TAPAN_A_CHIP_ID_BYTE_3			WCD9XXX_A_CHIP_ID_BYTE_3
+#define TAPAN_A_CHIP_ID_BYTE_3__POR		WCD9XXX_A_CHIP_ID_BYTE_3__POR
+#define TAPAN_A_CHIP_VERSION			WCD9XXX_A_CHIP_VERSION
+#define TAPAN_A_CHIP_VERSION__POR		WCD9XXX_A_CHIP_VERSION__POR
+#define TAPAN_A_CHIP_DEBUG_CTL			(0x009)
+#define TAPAN_A_CHIP_DEBUG_CTL__POR				(0x00)
+#define TAPAN_A_SLAVE_ID_1			(0x00C)
+#define TAPAN_A_SLAVE_ID_1__POR				(0x77)
+#define TAPAN_A_SLAVE_ID_2			(0x00D)
+#define TAPAN_A_SLAVE_ID_2__POR				(0x66)
+#define TAPAN_A_SLAVE_ID_3			(0x00E)
+#define TAPAN_A_SLAVE_ID_3__POR				(0x55)
+#define TAPAN_A_PIN_CTL_OE0			(0x010)
+#define TAPAN_A_PIN_CTL_OE0__POR				(0x00)
+#define TAPAN_A_PIN_CTL_DATA0			(0x012)
+#define TAPAN_A_PIN_CTL_DATA0__POR				(0x00)
+#define TAPAN_A_HDRIVE_GENERIC			(0x018)
+#define TAPAN_A_HDRIVE_GENERIC__POR				(0x00)
+#define TAPAN_A_HDRIVE_OVERRIDE			(0x019)
+#define TAPAN_A_HDRIVE_OVERRIDE__POR				(0x08)
+#define TAPAN_A_ANA_CSR_WAIT_STATE			(0x020)
+#define TAPAN_A_ANA_CSR_WAIT_STATE__POR				(0x44)
+#define TAPAN_A_PROCESS_MONITOR_CTL0			(0x040)
+#define TAPAN_A_PROCESS_MONITOR_CTL0__POR				(0x80)
+#define TAPAN_A_PROCESS_MONITOR_CTL1			(0x041)
+#define TAPAN_A_PROCESS_MONITOR_CTL1__POR				(0x00)
+#define TAPAN_A_PROCESS_MONITOR_CTL2			(0x042)
+#define TAPAN_A_PROCESS_MONITOR_CTL2__POR				(0x00)
+#define TAPAN_A_PROCESS_MONITOR_CTL3			(0x043)
+#define TAPAN_A_PROCESS_MONITOR_CTL3__POR				(0x01)
+#define TAPAN_A_QFUSE_CTL			(0x048)
+#define TAPAN_A_QFUSE_CTL__POR				(0x00)
+#define TAPAN_A_QFUSE_STATUS			(0x049)
+#define TAPAN_A_QFUSE_STATUS__POR				(0x00)
+#define TAPAN_A_QFUSE_DATA_OUT0			(0x04A)
+#define TAPAN_A_QFUSE_DATA_OUT0__POR				(0x00)
+#define TAPAN_A_QFUSE_DATA_OUT1			(0x04B)
+#define TAPAN_A_QFUSE_DATA_OUT1__POR				(0x00)
+#define TAPAN_A_QFUSE_DATA_OUT2			(0x04C)
+#define TAPAN_A_QFUSE_DATA_OUT2__POR				(0x00)
+#define TAPAN_A_QFUSE_DATA_OUT3			(0x04D)
+#define TAPAN_A_QFUSE_DATA_OUT3__POR				(0x00)
+#define TAPAN_A_QFUSE_DATA_OUT4			(0x04E)
+#define TAPAN_A_QFUSE_DATA_OUT4__POR				(0x00)
+#define TAPAN_A_QFUSE_DATA_OUT5			(0x04F)
+#define TAPAN_A_QFUSE_DATA_OUT5__POR				(0x00)
+#define TAPAN_A_QFUSE_DATA_OUT6			(0x050)
+#define TAPAN_A_QFUSE_DATA_OUT6__POR				(0x00)
+#define TAPAN_A_QFUSE_DATA_OUT7			(0x051)
+#define TAPAN_A_QFUSE_DATA_OUT7__POR				(0x00)
+#define TAPAN_A_CDC_CTL			(0x080)
+#define TAPAN_A_CDC_CTL__POR				(0x00)
+#define TAPAN_A_LEAKAGE_CTL			(0x088)
+#define TAPAN_A_LEAKAGE_CTL__POR				(0x04)
+#define TAPAN_A_INTR_MODE			(0x090)
+#define TAPAN_A_INTR_MODE__POR				(0x00)
+#define TAPAN_A_INTR_MASK0			(0x094)
+#define TAPAN_A_INTR_MASK0__POR				(0xFF)
+#define TAPAN_A_INTR_MASK1			(0x095)
+#define TAPAN_A_INTR_MASK1__POR				(0xFF)
+#define TAPAN_A_INTR_MASK2			(0x096)
+#define TAPAN_A_INTR_MASK2__POR				(0x3F)
+#define TAPAN_A_INTR_MASK3			(0x097)
+#define TAPAN_A_INTR_MASK3__POR				(0x3F)
+#define TAPAN_A_INTR_STATUS0			(0x098)
+#define TAPAN_A_INTR_STATUS0__POR				(0x00)
+#define TAPAN_A_INTR_STATUS1			(0x099)
+#define TAPAN_A_INTR_STATUS1__POR				(0x00)
+#define TAPAN_A_INTR_STATUS2			(0x09A)
+#define TAPAN_A_INTR_STATUS2__POR				(0x00)
+#define TAPAN_A_INTR_STATUS3			(0x09B)
+#define TAPAN_A_INTR_STATUS3__POR				(0x00)
+#define TAPAN_A_INTR_CLEAR0			(0x09C)
+#define TAPAN_A_INTR_CLEAR0__POR				(0x00)
+#define TAPAN_A_INTR_CLEAR1			(0x09D)
+#define TAPAN_A_INTR_CLEAR1__POR				(0x00)
+#define TAPAN_A_INTR_CLEAR2			(0x09E)
+#define TAPAN_A_INTR_CLEAR2__POR				(0x00)
+#define TAPAN_A_INTR_CLEAR3			(0x09F)
+#define TAPAN_A_INTR_CLEAR3__POR				(0x00)
+#define TAPAN_A_INTR_LEVEL0			(0x0A0)
+#define TAPAN_A_INTR_LEVEL0__POR				(0x01)
+#define TAPAN_A_INTR_LEVEL1			(0x0A1)
+#define TAPAN_A_INTR_LEVEL1__POR				(0x00)
+#define TAPAN_A_INTR_LEVEL2			(0x0A2)
+#define TAPAN_A_INTR_LEVEL2__POR				(0x00)
+#define TAPAN_A_INTR_LEVEL3			(0x0A3)
+#define TAPAN_A_INTR_LEVEL3__POR				(0x00)
+#define TAPAN_A_INTR_TEST0			(0x0A4)
+#define TAPAN_A_INTR_TEST0__POR				(0x00)
+#define TAPAN_A_INTR_TEST1			(0x0A5)
+#define TAPAN_A_INTR_TEST1__POR				(0x00)
+#define TAPAN_A_INTR_TEST2			(0x0A6)
+#define TAPAN_A_INTR_TEST2__POR				(0x00)
+#define TAPAN_A_INTR_TEST3			(0x0A7)
+#define TAPAN_A_INTR_TEST3__POR				(0x00)
+#define TAPAN_A_INTR_SET0			(0x0A8)
+#define TAPAN_A_INTR_SET0__POR				(0x00)
+#define TAPAN_A_INTR_SET1			(0x0A9)
+#define TAPAN_A_INTR_SET1__POR				(0x00)
+#define TAPAN_A_INTR_SET2			(0x0AA)
+#define TAPAN_A_INTR_SET2__POR				(0x00)
+#define TAPAN_A_INTR_SET3			(0x0AB)
+#define TAPAN_A_INTR_SET3__POR				(0x00)
+#define TAPAN_A_INTR_DESTN0			(0x0AC)
+#define TAPAN_A_INTR_DESTN0__POR				(0x00)
+#define TAPAN_A_INTR_DESTN1			(0x0AD)
+#define TAPAN_A_INTR_DESTN1__POR				(0x00)
+#define TAPAN_A_INTR_DESTN2			(0x0AE)
+#define TAPAN_A_INTR_DESTN2__POR				(0x00)
+#define TAPAN_A_INTR_DESTN3			(0x0AF)
+#define TAPAN_A_INTR_DESTN3__POR				(0x00)
+#define TAPAN_A_CDC_DMIC_DATA0_MODE			(0x0C0)
+#define TAPAN_A_CDC_DMIC_DATA0_MODE__POR				(0x00)
+#define TAPAN_A_CDC_DMIC_CLK0_MODE			(0x0C1)
+#define TAPAN_A_CDC_DMIC_CLK0_MODE__POR				(0x00)
+#define TAPAN_A_CDC_DMIC_DATA1_MODE			(0x0C2)
+#define TAPAN_A_CDC_DMIC_DATA1_MODE__POR				(0x00)
+#define TAPAN_A_CDC_DMIC_CLK1_MODE			(0x0C3)
+#define TAPAN_A_CDC_DMIC_CLK1_MODE__POR				(0x00)
+#define TAPAN_A_CDC_INTR_MODE			(0x0C4)
+#define TAPAN_A_CDC_INTR_MODE__POR				(0x00)
+#define TAPAN_A_BIAS_REF_CTL			(0x100)
+#define TAPAN_A_BIAS_REF_CTL__POR				(0x1C)
+#define TAPAN_A_BIAS_CENTRAL_BG_CTL			(0x101)
+#define TAPAN_A_BIAS_CENTRAL_BG_CTL__POR				(0x50)
+#define TAPAN_A_BIAS_PRECHRG_CTL			(0x102)
+#define TAPAN_A_BIAS_PRECHRG_CTL__POR				(0x07)
+#define TAPAN_A_BIAS_CURR_CTL_1			(0x103)
+#define TAPAN_A_BIAS_CURR_CTL_1__POR				(0x52)
+#define TAPAN_A_BIAS_CURR_CTL_2			(0x104)
+#define TAPAN_A_BIAS_CURR_CTL_2__POR				(0x00)
+#define TAPAN_A_BIAS_OSC_BG_CTL			(0x105)
+#define TAPAN_A_BIAS_OSC_BG_CTL__POR				(0x16)
+#define TAPAN_A_CLK_BUFF_EN1			(0x108)
+#define TAPAN_A_CLK_BUFF_EN1__POR				(0x04)
+#define TAPAN_A_CLK_BUFF_EN2			(0x109)
+#define TAPAN_A_CLK_BUFF_EN2__POR				(0x02)
+#define TAPAN_A_LDO_H_MODE_1			(0x110)
+#define TAPAN_A_LDO_H_MODE_1__POR				(0x65)
+#define TAPAN_A_LDO_H_MODE_2			(0x111)
+#define TAPAN_A_LDO_H_MODE_2__POR				(0xA8)
+#define TAPAN_A_LDO_H_LOOP_CTL			(0x112)
+#define TAPAN_A_LDO_H_LOOP_CTL__POR				(0x6B)
+#define TAPAN_A_LDO_H_COMP_1			(0x113)
+#define TAPAN_A_LDO_H_COMP_1__POR				(0x84)
+#define TAPAN_A_LDO_H_COMP_2			(0x114)
+#define TAPAN_A_LDO_H_COMP_2__POR				(0xE0)
+#define TAPAN_A_LDO_H_BIAS_1			(0x115)
+#define TAPAN_A_LDO_H_BIAS_1__POR				(0x6D)
+#define TAPAN_A_LDO_H_BIAS_2			(0x116)
+#define TAPAN_A_LDO_H_BIAS_2__POR				(0xA5)
+#define TAPAN_A_LDO_H_BIAS_3			(0x117)
+#define TAPAN_A_LDO_H_BIAS_3__POR				(0x60)
+#define TAPAN_A_MICB_CFILT_1_CTL			(0x128)
+#define TAPAN_A_MICB_CFILT_1_CTL__POR				(0x40)
+#define TAPAN_A_MICB_CFILT_1_VAL			(0x129)
+#define TAPAN_A_MICB_CFILT_1_VAL__POR				(0x80)
+#define TAPAN_A_MICB_CFILT_1_PRECHRG			(0x12A)
+#define TAPAN_A_MICB_CFILT_1_PRECHRG__POR				(0x00)
+#define TAPAN_A_MICB_1_CTL			(0x12B)
+#define TAPAN_A_MICB_1_CTL__POR				(0x02)
+#define TAPAN_A_MICB_1_INT_RBIAS			(0x12C)
+#define TAPAN_A_MICB_1_INT_RBIAS__POR				(0x24)
+#define TAPAN_A_MICB_1_MBHC			(0x12D)
+#define TAPAN_A_MICB_1_MBHC__POR				(0x01)
+#define TAPAN_A_MICB_CFILT_2_CTL			(0x12E)
+#define TAPAN_A_MICB_CFILT_2_CTL__POR				(0x40)
+#define TAPAN_A_MICB_CFILT_2_VAL			(0x12F)
+#define TAPAN_A_MICB_CFILT_2_VAL__POR				(0x80)
+#define TAPAN_A_MICB_CFILT_2_PRECHRG			(0x130)
+#define TAPAN_A_MICB_CFILT_2_PRECHRG__POR				(0x00)
+#define TAPAN_A_MICB_2_CTL			(0x131)
+#define TAPAN_A_MICB_2_CTL__POR				(0x12)
+#define TAPAN_A_MICB_2_INT_RBIAS			(0x132)
+#define TAPAN_A_MICB_2_INT_RBIAS__POR				(0x24)
+#define TAPAN_A_MICB_2_MBHC			(0x133)
+#define TAPAN_A_MICB_2_MBHC__POR				(0x02)
+#define TAPAN_A_MICB_CFILT_3_CTL			(0x134)
+#define TAPAN_A_MICB_CFILT_3_CTL__POR				(0x40)
+#define TAPAN_A_MICB_CFILT_3_VAL			(0x135)
+#define TAPAN_A_MICB_CFILT_3_VAL__POR				(0x80)
+#define TAPAN_A_MICB_CFILT_3_PRECHRG			(0x136)
+#define TAPAN_A_MICB_CFILT_3_PRECHRG__POR				(0x00)
+#define TAPAN_A_MICB_3_CTL			(0x137)
+#define TAPAN_A_MICB_3_CTL__POR				(0x02)
+#define TAPAN_A_MICB_3_INT_RBIAS			(0x138)
+#define TAPAN_A_MICB_3_INT_RBIAS__POR				(0x24)
+#define TAPAN_A_MICB_3_MBHC			(0x139)
+#define TAPAN_A_MICB_3_MBHC__POR				(0x00)
+#define TAPAN_A_MBHC_INSERT_DETECT			(0x14A)
+#define TAPAN_A_MBHC_INSERT_DETECT__POR				(0x00)
+#define TAPAN_A_MBHC_INSERT_DET_STATUS			(0x14B)
+#define TAPAN_A_MBHC_INSERT_DET_STATUS__POR				(0x00)
+#define TAPAN_A_TX_COM_BIAS			(0x14C)
+#define TAPAN_A_TX_COM_BIAS__POR				(0xF0)
+#define TAPAN_A_MBHC_SCALING_MUX_1			(0x14E)
+#define TAPAN_A_MBHC_SCALING_MUX_1__POR				(0x00)
+#define TAPAN_A_MBHC_SCALING_MUX_2			(0x14F)
+#define TAPAN_A_MBHC_SCALING_MUX_2__POR				(0x80)
+#define TAPAN_A_RESERVED_MAD_ANA_CTRL			(0x150)
+#define TAPAN_A_RESERVED_MAD_ANA_CTRL__POR				(0xF1)
+#define TAPAN_A_TX_SUP_SWITCH_CTRL_1			(0x151)
+#define TAPAN_A_TX_SUP_SWITCH_CTRL_1__POR				(0x00)
+#define TAPAN_A_TX_SUP_SWITCH_CTRL_2			(0x152)
+#define TAPAN_A_TX_SUP_SWITCH_CTRL_2__POR				(0x80)
+#define TAPAN_A_TX_1_EN			(0x153)
+#define TAPAN_A_TX_1_EN__POR				(0x02)
+#define TAPAN_A_TX_2_EN			(0x154)
+#define TAPAN_A_TX_2_EN__POR				(0x02)
+#define TAPAN_A_TX_1_2_ADC_CH1			(0x155)
+#define TAPAN_A_TX_1_2_ADC_CH1__POR				(0x44)
+#define TAPAN_A_TX_1_2_ADC_CH2			(0x156)
+#define TAPAN_A_TX_1_2_ADC_CH2__POR				(0x44)
+#define TAPAN_A_TX_1_2_ATEST_REFCTRL			(0x157)
+#define TAPAN_A_TX_1_2_ATEST_REFCTRL__POR				(0x00)
+#define TAPAN_A_TX_1_2_TEST_CTL			(0x158)
+#define TAPAN_A_TX_1_2_TEST_CTL__POR				(0x38)
+#define TAPAN_A_TX_1_2_TEST_BLOCK_EN			(0x159)
+#define TAPAN_A_TX_1_2_TEST_BLOCK_EN__POR				(0xFC)
+#define TAPAN_A_TX_1_2_TXFE_CLKDIV			(0x15A)
+#define TAPAN_A_TX_1_2_TXFE_CLKDIV__POR				(0x55)
+#define TAPAN_A_TX_1_2_SAR_ERR_CH1			(0x15B)
+#define TAPAN_A_TX_1_2_SAR_ERR_CH1__POR				(0x00)
+#define TAPAN_A_TX_1_2_SAR_ERR_CH2			(0x15C)
+#define TAPAN_A_TX_1_2_SAR_ERR_CH2__POR				(0x00)
+#define TAPAN_A_TX_3_EN			(0x15D)
+#define TAPAN_A_TX_3_EN__POR				(0x00)
+#define TAPAN_A_TX_1_2_TEST_EN			(0x15E)
+#define TAPAN_A_TX_1_2_TEST_EN__POR				(0xCC)
+#define TAPAN_A_TX_4_5_TXFE_SC_CTL			(0x15F)
+#define TAPAN_A_TX_4_5_TXFE_SC_CTL__POR				(0x00)
+#define TAPAN_A_TX_4_5_TEST_EN			(0x160)
+#define TAPAN_A_TX_4_5_TEST_EN__POR				(0xCC)
+#define TAPAN_A_TX_4_EN			(0x167)
+#define TAPAN_A_TX_4_EN__POR				(0x02)
+#define TAPAN_A_TX_5_EN			(0x168)
+#define TAPAN_A_TX_5_EN__POR				(0x02)
+#define TAPAN_A_TX_4_5_ADC_CH4			(0x169)
+#define TAPAN_A_TX_4_5_ADC_CH4__POR				(0x44)
+#define TAPAN_A_TX_4_5_ADC_CH5			(0x16A)
+#define TAPAN_A_TX_4_5_ADC_CH5__POR				(0x44)
+#define TAPAN_A_TX_4_5_ATEST_REFCTRL			(0x16B)
+#define TAPAN_A_TX_4_5_ATEST_REFCTRL__POR				(0x00)
+#define TAPAN_A_TX_4_5_TEST_CTL			(0x16C)
+#define TAPAN_A_TX_4_5_TEST_CTL__POR				(0x38)
+#define TAPAN_A_TX_4_5_TEST_BLOCK_EN			(0x16D)
+#define TAPAN_A_TX_4_5_TEST_BLOCK_EN__POR				(0xFC)
+#define TAPAN_A_TX_4_5_TXFE_CKDIV			(0x16E)
+#define TAPAN_A_TX_4_5_TXFE_CKDIV__POR				(0x55)
+#define TAPAN_A_TX_4_5_SAR_ERR_CH4			(0x16F)
+#define TAPAN_A_TX_4_5_SAR_ERR_CH4__POR				(0x00)
+#define TAPAN_A_TX_4_5_SAR_ERR_CH5			(0x170)
+#define TAPAN_A_TX_4_5_SAR_ERR_CH5__POR				(0x00)
+#define TAPAN_A_TX_7_MBHC_EN			(0x171)
+#define TAPAN_A_TX_7_MBHC_EN__POR				(0x0C)
+#define TAPAN_A_TX_7_MBHC_ATEST_REFCTRL			(0x172)
+#define TAPAN_A_TX_7_MBHC_ATEST_REFCTRL__POR				(0x00)
+#define TAPAN_A_TX_7_MBHC_ADC			(0x173)
+#define TAPAN_A_TX_7_MBHC_ADC__POR				(0x44)
+#define TAPAN_A_TX_7_MBHC_TEST_CTL			(0x174)
+#define TAPAN_A_TX_7_MBHC_TEST_CTL__POR				(0x38)
+#define TAPAN_A_TX_7_MBHC_SAR_ERR			(0x175)
+#define TAPAN_A_TX_7_MBHC_SAR_ERR__POR				(0x00)
+#define TAPAN_A_TX_7_TXFE_CLKDIV			(0x176)
+#define TAPAN_A_TX_7_TXFE_CLKDIV__POR				(0x0B)
+#define TAPAN_A_BUCK_MODE_1			(0x181)
+#define TAPAN_A_BUCK_MODE_1__POR				(0x21)
+#define TAPAN_A_BUCK_MODE_2			(0x182)
+#define TAPAN_A_BUCK_MODE_2__POR				(0xFF)
+#define TAPAN_A_BUCK_MODE_3			(0x183)
+#define TAPAN_A_BUCK_MODE_3__POR				(0xCE)
+#define TAPAN_A_BUCK_MODE_4			(0x184)
+#define TAPAN_A_BUCK_MODE_4__POR				(0x3A)
+#define TAPAN_A_BUCK_MODE_5			(0x185)
+#define TAPAN_A_BUCK_MODE_5__POR				(0x00)
+#define TAPAN_A_BUCK_CTRL_VCL_1			(0x186)
+#define TAPAN_A_BUCK_CTRL_VCL_1__POR				(0x08)
+#define TAPAN_A_BUCK_CTRL_VCL_2			(0x187)
+#define TAPAN_A_BUCK_CTRL_VCL_2__POR				(0xA3)
+#define TAPAN_A_BUCK_CTRL_VCL_3			(0x188)
+#define TAPAN_A_BUCK_CTRL_VCL_3__POR				(0x82)
+#define TAPAN_A_BUCK_CTRL_CCL_1			(0x189)
+#define TAPAN_A_BUCK_CTRL_CCL_1__POR				(0x5B)
+#define TAPAN_A_BUCK_CTRL_CCL_2			(0x18A)
+#define TAPAN_A_BUCK_CTRL_CCL_2__POR				(0xDC)
+#define TAPAN_A_BUCK_CTRL_CCL_3			(0x18B)
+#define TAPAN_A_BUCK_CTRL_CCL_3__POR				(0x6A)
+#define TAPAN_A_BUCK_CTRL_CCL_4			(0x18C)
+#define TAPAN_A_BUCK_CTRL_CCL_4__POR				(0x50)
+#define TAPAN_A_BUCK_CTRL_PWM_DRVR_1			(0x18D)
+#define TAPAN_A_BUCK_CTRL_PWM_DRVR_1__POR				(0x50)
+#define TAPAN_A_BUCK_CTRL_PWM_DRVR_2			(0x18E)
+#define TAPAN_A_BUCK_CTRL_PWM_DRVR_2__POR				(0x64)
+#define TAPAN_A_BUCK_CTRL_PWM_DRVR_3			(0x18F)
+#define TAPAN_A_BUCK_CTRL_PWM_DRVR_3__POR				(0x77)
+#define TAPAN_A_BUCK_TMUX_A_D			(0x190)
+#define TAPAN_A_BUCK_TMUX_A_D__POR				(0x00)
+#define TAPAN_A_NCP_BUCKREF			(0x191)
+#define TAPAN_A_NCP_BUCKREF__POR				(0x00)
+#define TAPAN_A_NCP_EN			(0x192)
+#define TAPAN_A_NCP_EN__POR				(0xFE)
+#define TAPAN_A_NCP_CLK			(0x193)
+#define TAPAN_A_NCP_CLK__POR				(0x94)
+#define TAPAN_A_NCP_STATIC			(0x194)
+#define TAPAN_A_NCP_STATIC__POR				(0x28)
+#define TAPAN_A_NCP_VTH_LOW			(0x195)
+#define TAPAN_A_NCP_VTH_LOW__POR				(0x88)
+#define TAPAN_A_NCP_VTH_HIGH			(0x196)
+#define TAPAN_A_NCP_VTH_HIGH__POR				(0xA0)
+#define TAPAN_A_NCP_ATEST			(0x197)
+#define TAPAN_A_NCP_ATEST__POR				(0x00)
+#define TAPAN_A_NCP_DTEST			(0x198)
+#define TAPAN_A_NCP_DTEST__POR				(0x10)
+#define TAPAN_A_NCP_DLY1			(0x199)
+#define TAPAN_A_NCP_DLY1__POR				(0x06)
+#define TAPAN_A_NCP_DLY2			(0x19A)
+#define TAPAN_A_NCP_DLY2__POR				(0x06)
+#define TAPAN_A_RX_AUX_SW_CTL			(0x19B)
+#define TAPAN_A_RX_AUX_SW_CTL__POR				(0x00)
+#define TAPAN_A_RX_PA_AUX_IN_CONN			(0x19C)
+#define TAPAN_A_RX_PA_AUX_IN_CONN__POR				(0x00)
+#define TAPAN_A_RX_COM_TIMER_DIV			(0x19E)
+#define TAPAN_A_RX_COM_TIMER_DIV__POR				(0xE8)
+#define TAPAN_A_RX_COM_OCP_CTL			(0x19F)
+#define TAPAN_A_RX_COM_OCP_CTL__POR				(0x1F)
+#define TAPAN_A_RX_COM_OCP_COUNT			(0x1A0)
+#define TAPAN_A_RX_COM_OCP_COUNT__POR				(0x77)
+#define TAPAN_A_RX_COM_DAC_CTL			(0x1A1)
+#define TAPAN_A_RX_COM_DAC_CTL__POR				(0x00)
+#define TAPAN_A_RX_COM_BIAS			(0x1A2)
+#define TAPAN_A_RX_COM_BIAS__POR				(0x00)
+#define TAPAN_A_RX_HPH_AUTO_CHOP			(0x1A4)
+#define TAPAN_A_RX_HPH_AUTO_CHOP__POR				(0x38)
+#define TAPAN_A_RX_HPH_CHOP_CTL			(0x1A5)
+#define TAPAN_A_RX_HPH_CHOP_CTL__POR				(0xA4)
+#define TAPAN_A_RX_HPH_BIAS_PA			(0x1A6)
+#define TAPAN_A_RX_HPH_BIAS_PA__POR				(0x7A)
+#define TAPAN_A_RX_HPH_BIAS_LDO			(0x1A7)
+#define TAPAN_A_RX_HPH_BIAS_LDO__POR				(0x87)
+#define TAPAN_A_RX_HPH_BIAS_CNP			(0x1A8)
+#define TAPAN_A_RX_HPH_BIAS_CNP__POR				(0x8A)
+#define TAPAN_A_RX_HPH_BIAS_WG_OCP			(0x1A9)
+#define TAPAN_A_RX_HPH_BIAS_WG_OCP__POR				(0x2A)
+#define TAPAN_A_RX_HPH_OCP_CTL			(0x1AA)
+#define TAPAN_A_RX_HPH_OCP_CTL__POR				(0x69)
+#define TAPAN_A_RX_HPH_CNP_EN			(0x1AB)
+#define TAPAN_A_RX_HPH_CNP_EN__POR				(0x80)
+#define TAPAN_A_RX_HPH_CNP_WG_CTL			(0x1AC)
+#define TAPAN_A_RX_HPH_CNP_WG_CTL__POR				(0xDE)
+#define TAPAN_A_RX_HPH_CNP_WG_TIME			(0x1AD)
+#define TAPAN_A_RX_HPH_CNP_WG_TIME__POR				(0x15)
+#define TAPAN_A_RX_HPH_L_GAIN			(0x1AE)
+#define TAPAN_A_RX_HPH_L_GAIN__POR				(0x00)
+#define TAPAN_A_RX_HPH_L_TEST			(0x1AF)
+#define TAPAN_A_RX_HPH_L_TEST__POR				(0x00)
+#define TAPAN_A_RX_HPH_L_PA_CTL			(0x1B0)
+#define TAPAN_A_RX_HPH_L_PA_CTL__POR				(0x40)
+#define TAPAN_A_RX_HPH_L_DAC_CTL			(0x1B1)
+#define TAPAN_A_RX_HPH_L_DAC_CTL__POR				(0x00)
+#define TAPAN_A_RX_HPH_L_ATEST			(0x1B2)
+#define TAPAN_A_RX_HPH_L_ATEST__POR				(0x00)
+#define TAPAN_A_RX_HPH_L_STATUS			(0x1B3)
+#define TAPAN_A_RX_HPH_L_STATUS__POR				(0x00)
+#define TAPAN_A_RX_HPH_R_GAIN			(0x1B4)
+#define TAPAN_A_RX_HPH_R_GAIN__POR				(0x00)
+#define TAPAN_A_RX_HPH_R_TEST			(0x1B5)
+#define TAPAN_A_RX_HPH_R_TEST__POR				(0x00)
+#define TAPAN_A_RX_HPH_R_PA_CTL			(0x1B6)
+#define TAPAN_A_RX_HPH_R_PA_CTL__POR				(0x40)
+#define TAPAN_A_RX_HPH_R_DAC_CTL			(0x1B7)
+#define TAPAN_A_RX_HPH_R_DAC_CTL__POR				(0x00)
+#define TAPAN_A_RX_HPH_R_ATEST			(0x1B8)
+#define TAPAN_A_RX_HPH_R_ATEST__POR				(0x00)
+#define TAPAN_A_RX_HPH_R_STATUS			(0x1B9)
+#define TAPAN_A_RX_HPH_R_STATUS__POR				(0x00)
+#define TAPAN_A_RX_EAR_BIAS_PA			(0x1BA)
+#define TAPAN_A_RX_EAR_BIAS_PA__POR				(0x76)
+#define TAPAN_A_RX_EAR_BIAS_CMBUFF			(0x1BB)
+#define TAPAN_A_RX_EAR_BIAS_CMBUFF__POR				(0xA0)
+#define TAPAN_A_RX_EAR_EN			(0x1BC)
+#define TAPAN_A_RX_EAR_EN__POR				(0x00)
+#define TAPAN_A_RX_EAR_GAIN			(0x1BD)
+#define TAPAN_A_RX_EAR_GAIN__POR				(0x02)
+#define TAPAN_A_RX_EAR_CMBUFF			(0x1BE)
+#define TAPAN_A_RX_EAR_CMBUFF__POR				(0x05)
+#define TAPAN_A_RX_EAR_ICTL			(0x1BF)
+#define TAPAN_A_RX_EAR_ICTL__POR				(0x40)
+#define TAPAN_A_RX_EAR_CCOMP			(0x1C0)
+#define TAPAN_A_RX_EAR_CCOMP__POR				(0x08)
+#define TAPAN_A_RX_EAR_VCM			(0x1C1)
+#define TAPAN_A_RX_EAR_VCM__POR				(0x03)
+#define TAPAN_A_RX_EAR_CNP			(0x1C2)
+#define TAPAN_A_RX_EAR_CNP__POR				(0xF2)
+#define TAPAN_A_RX_EAR_DAC_CTL_ATEST			(0x1C3)
+#define TAPAN_A_RX_EAR_DAC_CTL_ATEST__POR				(0x00)
+#define TAPAN_A_RX_EAR_STATUS			(0x1C5)
+#define TAPAN_A_RX_EAR_STATUS__POR				(0x04)
+#define TAPAN_A_RX_LINE_BIAS_PA			(0x1C6)
+#define TAPAN_A_RX_LINE_BIAS_PA__POR				(0x78)
+#define TAPAN_A_RX_BUCK_BIAS1			(0x1C7)
+#define TAPAN_A_RX_BUCK_BIAS1__POR				(0x42)
+#define TAPAN_A_RX_BUCK_BIAS2			(0x1C8)
+#define TAPAN_A_RX_BUCK_BIAS2__POR				(0x84)
+#define TAPAN_A_RX_LINE_COM			(0x1C9)
+#define TAPAN_A_RX_LINE_COM__POR				(0x80)
+#define TAPAN_A_RX_LINE_CNP_EN			(0x1CA)
+#define TAPAN_A_RX_LINE_CNP_EN__POR				(0x00)
+#define TAPAN_A_RX_LINE_CNP_WG_CTL			(0x1CB)
+#define TAPAN_A_RX_LINE_CNP_WG_CTL__POR				(0x00)
+#define TAPAN_A_RX_LINE_CNP_WG_TIME			(0x1CC)
+#define TAPAN_A_RX_LINE_CNP_WG_TIME__POR				(0x04)
+#define TAPAN_A_RX_LINE_1_GAIN			(0x1CD)
+#define TAPAN_A_RX_LINE_1_GAIN__POR				(0x00)
+#define TAPAN_A_RX_LINE_1_TEST			(0x1CE)
+#define TAPAN_A_RX_LINE_1_TEST__POR				(0x00)
+#define TAPAN_A_RX_LINE_1_DAC_CTL			(0x1CF)
+#define TAPAN_A_RX_LINE_1_DAC_CTL__POR				(0x00)
+#define TAPAN_A_RX_LINE_1_STATUS			(0x1D0)
+#define TAPAN_A_RX_LINE_1_STATUS__POR				(0x00)
+#define TAPAN_A_RX_LINE_2_GAIN			(0x1D1)
+#define TAPAN_A_RX_LINE_2_GAIN__POR				(0x00)
+#define TAPAN_A_RX_LINE_2_TEST			(0x1D2)
+#define TAPAN_A_RX_LINE_2_TEST__POR				(0x00)
+#define TAPAN_A_RX_LINE_2_DAC_CTL			(0x1D3)
+#define TAPAN_A_RX_LINE_2_DAC_CTL__POR				(0x00)
+#define TAPAN_A_RX_LINE_2_STATUS			(0x1D4)
+#define TAPAN_A_RX_LINE_2_STATUS__POR				(0x00)
+#define TAPAN_A_RX_LINE_CNP_DBG			(0x1DD)
+#define TAPAN_A_RX_LINE_CNP_DBG__POR				(0x00)
+#define TAPAN_A_SPKR_DRV_EN			(0x1DF)
+#define TAPAN_A_SPKR_DRV_EN__POR				(0x6F)
+#define TAPAN_A_SPKR_DRV_GAIN			(0x1E0)
+#define TAPAN_A_SPKR_DRV_GAIN__POR				(0x00)
+#define TAPAN_A_SPKR_DRV_DAC_CTL			(0x1E1)
+#define TAPAN_A_SPKR_DRV_DAC_CTL__POR				(0x04)
+#define TAPAN_A_SPKR_DRV_OCP_CTL			(0x1E2)
+#define TAPAN_A_SPKR_DRV_OCP_CTL__POR				(0x98)
+#define TAPAN_A_SPKR_DRV_CLIP_DET			(0x1E3)
+#define TAPAN_A_SPKR_DRV_CLIP_DET__POR				(0x48)
+#define TAPAN_A_SPKR_DRV_IEC			(0x1E4)
+#define TAPAN_A_SPKR_DRV_IEC__POR				(0x28)
+#define TAPAN_A_SPKR_DRV_DBG_DAC			(0x1E5)
+#define TAPAN_A_SPKR_DRV_DBG_DAC__POR				(0x05)
+#define TAPAN_A_SPKR_DRV_DBG_PA			(0x1E6)
+#define TAPAN_A_SPKR_DRV_DBG_PA__POR				(0x18)
+#define TAPAN_A_SPKR_DRV_DBG_PWRSTG			(0x1E7)
+#define TAPAN_A_SPKR_DRV_DBG_PWRSTG__POR				(0x00)
+#define TAPAN_A_SPKR_DRV_BIAS_LDO			(0x1E8)
+#define TAPAN_A_SPKR_DRV_BIAS_LDO__POR				(0x45)
+#define TAPAN_A_SPKR_DRV_BIAS_INT			(0x1E9)
+#define TAPAN_A_SPKR_DRV_BIAS_INT__POR				(0xA5)
+#define TAPAN_A_SPKR_DRV_BIAS_PA			(0x1EA)
+#define TAPAN_A_SPKR_DRV_BIAS_PA__POR				(0x55)
+#define TAPAN_A_SPKR_DRV_STATUS_OCP			(0x1EB)
+#define TAPAN_A_SPKR_DRV_STATUS_OCP__POR				(0x00)
+#define TAPAN_A_SPKR_DRV_STATUS_PA			(0x1EC)
+#define TAPAN_A_SPKR_DRV_STATUS_PA__POR				(0x00)
+#define TAPAN_A_RC_OSC_FREQ			(0x1FA)
+#define TAPAN_A_RC_OSC_FREQ__POR				(0x46)
+#define TAPAN_A_RC_OSC_TEST			(0x1FB)
+#define TAPAN_A_RC_OSC_TEST__POR				(0x0A)
+#define TAPAN_A_RC_OSC_STATUS			(0x1FC)
+#define TAPAN_A_RC_OSC_STATUS__POR				(0x18)
+#define TAPAN_A_RC_OSC_TUNER			(0x1FD)
+#define TAPAN_A_RC_OSC_TUNER__POR				(0x00)
+#define TAPAN_A_MBHC_HPH			(0x1FE)
+#define TAPAN_A_MBHC_HPH__POR				(0x44)
+#define TAPAN_A_CDC_ANC1_B1_CTL			(0x200)
+#define TAPAN_A_CDC_ANC1_B1_CTL__POR				(0x00)
+#define TAPAN_A_CDC_ANC2_B1_CTL			(0x280)
+#define TAPAN_A_CDC_ANC2_B1_CTL__POR				(0x00)
+#define TAPAN_A_CDC_ANC1_SHIFT			(0x201)
+#define TAPAN_A_CDC_ANC1_SHIFT__POR				(0x00)
+#define TAPAN_A_CDC_ANC2_SHIFT			(0x281)
+#define TAPAN_A_CDC_ANC2_SHIFT__POR				(0x00)
+#define TAPAN_A_CDC_ANC1_IIR_B1_CTL			(0x202)
+#define TAPAN_A_CDC_ANC1_IIR_B1_CTL__POR				(0x00)
+#define TAPAN_A_CDC_ANC2_IIR_B1_CTL			(0x282)
+#define TAPAN_A_CDC_ANC2_IIR_B1_CTL__POR				(0x00)
+#define TAPAN_A_CDC_ANC1_IIR_B2_CTL			(0x203)
+#define TAPAN_A_CDC_ANC1_IIR_B2_CTL__POR				(0x00)
+#define TAPAN_A_CDC_ANC2_IIR_B2_CTL			(0x283)
+#define TAPAN_A_CDC_ANC2_IIR_B2_CTL__POR				(0x00)
+#define TAPAN_A_CDC_ANC1_IIR_B3_CTL			(0x204)
+#define TAPAN_A_CDC_ANC1_IIR_B3_CTL__POR				(0x00)
+#define TAPAN_A_CDC_ANC2_IIR_B3_CTL			(0x284)
+#define TAPAN_A_CDC_ANC2_IIR_B3_CTL__POR				(0x00)
+#define TAPAN_A_CDC_ANC1_LPF_B1_CTL			(0x206)
+#define TAPAN_A_CDC_ANC1_LPF_B1_CTL__POR				(0x00)
+#define TAPAN_A_CDC_ANC2_LPF_B1_CTL			(0x286)
+#define TAPAN_A_CDC_ANC2_LPF_B1_CTL__POR				(0x00)
+#define TAPAN_A_CDC_ANC1_LPF_B2_CTL			(0x207)
+#define TAPAN_A_CDC_ANC1_LPF_B2_CTL__POR				(0x00)
+#define TAPAN_A_CDC_ANC2_LPF_B2_CTL			(0x287)
+#define TAPAN_A_CDC_ANC2_LPF_B2_CTL__POR				(0x00)
+#define TAPAN_A_CDC_ANC1_SPARE			(0x209)
+#define TAPAN_A_CDC_ANC1_SPARE__POR				(0x00)
+#define TAPAN_A_CDC_ANC2_SPARE			(0x289)
+#define TAPAN_A_CDC_ANC2_SPARE__POR				(0x00)
+#define TAPAN_A_CDC_ANC1_SMLPF_CTL			(0x20A)
+#define TAPAN_A_CDC_ANC1_SMLPF_CTL__POR				(0x00)
+#define TAPAN_A_CDC_ANC2_SMLPF_CTL			(0x28A)
+#define TAPAN_A_CDC_ANC2_SMLPF_CTL__POR				(0x00)
+#define TAPAN_A_CDC_ANC1_DCFLT_CTL			(0x20B)
+#define TAPAN_A_CDC_ANC1_DCFLT_CTL__POR				(0x00)
+#define TAPAN_A_CDC_ANC2_DCFLT_CTL			(0x28B)
+#define TAPAN_A_CDC_ANC2_DCFLT_CTL__POR				(0x00)
+#define TAPAN_A_CDC_ANC1_GAIN_CTL			(0x20C)
+#define TAPAN_A_CDC_ANC1_GAIN_CTL__POR				(0x00)
+#define TAPAN_A_CDC_ANC2_GAIN_CTL			(0x28C)
+#define TAPAN_A_CDC_ANC2_GAIN_CTL__POR				(0x00)
+#define TAPAN_A_CDC_ANC1_B2_CTL			(0x20D)
+#define TAPAN_A_CDC_ANC1_B2_CTL__POR				(0x00)
+#define TAPAN_A_CDC_ANC2_B2_CTL			(0x28D)
+#define TAPAN_A_CDC_ANC2_B2_CTL__POR				(0x00)
+#define TAPAN_A_CDC_TX1_VOL_CTL_TIMER			(0x220)
+#define TAPAN_A_CDC_TX1_VOL_CTL_TIMER__POR				(0x00)
+#define TAPAN_A_CDC_TX2_VOL_CTL_TIMER			(0x228)
+#define TAPAN_A_CDC_TX2_VOL_CTL_TIMER__POR				(0x00)
+#define TAPAN_A_CDC_TX3_VOL_CTL_TIMER			(0x230)
+#define TAPAN_A_CDC_TX3_VOL_CTL_TIMER__POR				(0x00)
+#define TAPAN_A_CDC_TX4_VOL_CTL_TIMER			(0x238)
+#define TAPAN_A_CDC_TX4_VOL_CTL_TIMER__POR				(0x00)
+#define TAPAN_A_CDC_TX1_VOL_CTL_GAIN			(0x221)
+#define TAPAN_A_CDC_TX1_VOL_CTL_GAIN__POR				(0x00)
+#define TAPAN_A_CDC_TX2_VOL_CTL_GAIN			(0x229)
+#define TAPAN_A_CDC_TX2_VOL_CTL_GAIN__POR				(0x00)
+#define TAPAN_A_CDC_TX3_VOL_CTL_GAIN			(0x231)
+#define TAPAN_A_CDC_TX3_VOL_CTL_GAIN__POR				(0x00)
+#define TAPAN_A_CDC_TX4_VOL_CTL_GAIN			(0x239)
+#define TAPAN_A_CDC_TX4_VOL_CTL_GAIN__POR				(0x00)
+#define TAPAN_A_CDC_TX1_VOL_CTL_CFG			(0x222)
+#define TAPAN_A_CDC_TX1_VOL_CTL_CFG__POR				(0x00)
+#define TAPAN_A_CDC_TX2_VOL_CTL_CFG			(0x22A)
+#define TAPAN_A_CDC_TX2_VOL_CTL_CFG__POR				(0x00)
+#define TAPAN_A_CDC_TX3_VOL_CTL_CFG			(0x232)
+#define TAPAN_A_CDC_TX3_VOL_CTL_CFG__POR				(0x00)
+#define TAPAN_A_CDC_TX4_VOL_CTL_CFG			(0x23A)
+#define TAPAN_A_CDC_TX4_VOL_CTL_CFG__POR				(0x00)
+#define TAPAN_A_CDC_TX1_MUX_CTL			(0x223)
+#define TAPAN_A_CDC_TX1_MUX_CTL__POR				(0x00)
+#define TAPAN_A_CDC_TX2_MUX_CTL			(0x22B)
+#define TAPAN_A_CDC_TX2_MUX_CTL__POR				(0x00)
+#define TAPAN_A_CDC_TX3_MUX_CTL			(0x233)
+#define TAPAN_A_CDC_TX3_MUX_CTL__POR				(0x00)
+#define TAPAN_A_CDC_TX4_MUX_CTL			(0x23B)
+#define TAPAN_A_CDC_TX4_MUX_CTL__POR				(0x00)
+#define TAPAN_A_CDC_TX1_CLK_FS_CTL			(0x224)
+#define TAPAN_A_CDC_TX1_CLK_FS_CTL__POR				(0x00)
+#define TAPAN_A_CDC_TX2_CLK_FS_CTL			(0x22C)
+#define TAPAN_A_CDC_TX2_CLK_FS_CTL__POR				(0x00)
+#define TAPAN_A_CDC_TX3_CLK_FS_CTL			(0x234)
+#define TAPAN_A_CDC_TX3_CLK_FS_CTL__POR				(0x00)
+#define TAPAN_A_CDC_TX4_CLK_FS_CTL			(0x23C)
+#define TAPAN_A_CDC_TX4_CLK_FS_CTL__POR				(0x00)
+#define TAPAN_A_CDC_TX1_DMIC_CTL			(0x225)
+#define TAPAN_A_CDC_TX1_DMIC_CTL__POR				(0x00)
+#define TAPAN_A_CDC_TX2_DMIC_CTL			(0x22D)
+#define TAPAN_A_CDC_TX2_DMIC_CTL__POR				(0x00)
+#define TAPAN_A_CDC_TX3_DMIC_CTL			(0x235)
+#define TAPAN_A_CDC_TX3_DMIC_CTL__POR				(0x00)
+#define TAPAN_A_CDC_TX4_DMIC_CTL			(0x23D)
+#define TAPAN_A_CDC_TX4_DMIC_CTL__POR				(0x00)
+#define TAPAN_A_CDC_DEBUG_B1_CTL			(0x278)
+#define TAPAN_A_CDC_DEBUG_B1_CTL__POR				(0x00)
+#define TAPAN_A_CDC_DEBUG_B2_CTL			(0x279)
+#define TAPAN_A_CDC_DEBUG_B2_CTL__POR				(0x00)
+#define TAPAN_A_CDC_DEBUG_B3_CTL			(0x27A)
+#define TAPAN_A_CDC_DEBUG_B3_CTL__POR				(0x00)
+#define TAPAN_A_CDC_DEBUG_B4_CTL			(0x27B)
+#define TAPAN_A_CDC_DEBUG_B4_CTL__POR				(0x00)
+#define TAPAN_A_CDC_DEBUG_B5_CTL			(0x27C)
+#define TAPAN_A_CDC_DEBUG_B5_CTL__POR				(0x00)
+#define TAPAN_A_CDC_DEBUG_B6_CTL			(0x27D)
+#define TAPAN_A_CDC_DEBUG_B6_CTL__POR				(0x00)
+#define TAPAN_A_CDC_DEBUG_B7_CTL			(0x27E)
+#define TAPAN_A_CDC_DEBUG_B7_CTL__POR				(0x00)
+#define TAPAN_A_CDC_SRC1_PDA_CFG			(0x2A0)
+#define TAPAN_A_CDC_SRC1_PDA_CFG__POR				(0x00)
+#define TAPAN_A_CDC_SRC2_PDA_CFG			(0x2A8)
+#define TAPAN_A_CDC_SRC2_PDA_CFG__POR				(0x00)
+#define TAPAN_A_CDC_SRC1_FS_CTL			(0x2A1)
+#define TAPAN_A_CDC_SRC1_FS_CTL__POR				(0x00)
+#define TAPAN_A_CDC_SRC2_FS_CTL			(0x2A9)
+#define TAPAN_A_CDC_SRC2_FS_CTL__POR				(0x00)
+#define TAPAN_A_CDC_RX1_B1_CTL			(0x2B0)
+#define TAPAN_A_CDC_RX1_B1_CTL__POR				(0x00)
+#define TAPAN_A_CDC_RX2_B1_CTL			(0x2B8)
+#define TAPAN_A_CDC_RX2_B1_CTL__POR				(0x00)
+#define TAPAN_A_CDC_RX3_B1_CTL			(0x2C0)
+#define TAPAN_A_CDC_RX3_B1_CTL__POR				(0x00)
+#define TAPAN_A_CDC_RX4_B1_CTL			(0x2C8)
+#define TAPAN_A_CDC_RX4_B1_CTL__POR				(0x00)
+#define TAPAN_A_CDC_RX1_B2_CTL			(0x2B1)
+#define TAPAN_A_CDC_RX1_B2_CTL__POR				(0x00)
+#define TAPAN_A_CDC_RX2_B2_CTL			(0x2B9)
+#define TAPAN_A_CDC_RX2_B2_CTL__POR				(0x00)
+#define TAPAN_A_CDC_RX3_B2_CTL			(0x2C1)
+#define TAPAN_A_CDC_RX3_B2_CTL__POR				(0x00)
+#define TAPAN_A_CDC_RX4_B2_CTL			(0x2C9)
+#define TAPAN_A_CDC_RX4_B2_CTL__POR				(0x00)
+#define TAPAN_A_CDC_RX1_B3_CTL			(0x2B2)
+#define TAPAN_A_CDC_RX1_B3_CTL__POR				(0x00)
+#define TAPAN_A_CDC_RX2_B3_CTL			(0x2BA)
+#define TAPAN_A_CDC_RX2_B3_CTL__POR				(0x00)
+#define TAPAN_A_CDC_RX3_B3_CTL			(0x2C2)
+#define TAPAN_A_CDC_RX3_B3_CTL__POR				(0x00)
+#define TAPAN_A_CDC_RX4_B3_CTL			(0x2CA)
+#define TAPAN_A_CDC_RX4_B3_CTL__POR				(0x00)
+#define TAPAN_A_CDC_RX1_B4_CTL			(0x2B3)
+#define TAPAN_A_CDC_RX1_B4_CTL__POR				(0x00)
+#define TAPAN_A_CDC_RX2_B4_CTL			(0x2BB)
+#define TAPAN_A_CDC_RX2_B4_CTL__POR				(0x00)
+#define TAPAN_A_CDC_RX3_B4_CTL			(0x2C3)
+#define TAPAN_A_CDC_RX3_B4_CTL__POR				(0x00)
+#define TAPAN_A_CDC_RX4_B4_CTL			(0x2CB)
+#define TAPAN_A_CDC_RX4_B4_CTL__POR				(0x00)
+#define TAPAN_A_CDC_RX1_B5_CTL			(0x2B4)
+#define TAPAN_A_CDC_RX1_B5_CTL__POR				(0x00)
+#define TAPAN_A_CDC_RX2_B5_CTL			(0x2BC)
+#define TAPAN_A_CDC_RX2_B5_CTL__POR				(0x00)
+#define TAPAN_A_CDC_RX3_B5_CTL			(0x2C4)
+#define TAPAN_A_CDC_RX3_B5_CTL__POR				(0x00)
+#define TAPAN_A_CDC_RX4_B5_CTL			(0x2CC)
+#define TAPAN_A_CDC_RX4_B5_CTL__POR				(0x00)
+#define TAPAN_A_CDC_RX1_B6_CTL			(0x2B5)
+#define TAPAN_A_CDC_RX1_B6_CTL__POR				(0x00)
+#define TAPAN_A_CDC_RX2_B6_CTL			(0x2BD)
+#define TAPAN_A_CDC_RX2_B6_CTL__POR				(0x00)
+#define TAPAN_A_CDC_RX3_B6_CTL			(0x2C5)
+#define TAPAN_A_CDC_RX3_B6_CTL__POR				(0x00)
+#define TAPAN_A_CDC_RX4_B6_CTL			(0x2CD)
+#define TAPAN_A_CDC_RX4_B6_CTL__POR				(0x00)
+#define TAPAN_A_CDC_RX1_VOL_CTL_B1_CTL			(0x2B6)
+#define TAPAN_A_CDC_RX1_VOL_CTL_B1_CTL__POR				(0x00)
+#define TAPAN_A_CDC_RX2_VOL_CTL_B1_CTL			(0x2BE)
+#define TAPAN_A_CDC_RX2_VOL_CTL_B1_CTL__POR				(0x00)
+#define TAPAN_A_CDC_RX3_VOL_CTL_B1_CTL			(0x2C6)
+#define TAPAN_A_CDC_RX3_VOL_CTL_B1_CTL__POR				(0x00)
+#define TAPAN_A_CDC_RX4_VOL_CTL_B1_CTL			(0x2CE)
+#define TAPAN_A_CDC_RX4_VOL_CTL_B1_CTL__POR				(0x00)
+#define TAPAN_A_CDC_RX1_VOL_CTL_B2_CTL			(0x2B7)
+#define TAPAN_A_CDC_RX1_VOL_CTL_B2_CTL__POR				(0x00)
+#define TAPAN_A_CDC_RX2_VOL_CTL_B2_CTL			(0x2BF)
+#define TAPAN_A_CDC_RX2_VOL_CTL_B2_CTL__POR				(0x00)
+#define TAPAN_A_CDC_RX3_VOL_CTL_B2_CTL			(0x2C7)
+#define TAPAN_A_CDC_RX3_VOL_CTL_B2_CTL__POR				(0x00)
+#define TAPAN_A_CDC_RX4_VOL_CTL_B2_CTL			(0x2CF)
+#define TAPAN_A_CDC_RX4_VOL_CTL_B2_CTL__POR				(0x00)
+#define TAPAN_A_CDC_CLK_ANC_RESET_CTL			(0x300)
+#define TAPAN_A_CDC_CLK_ANC_RESET_CTL__POR				(0x00)
+#define TAPAN_A_CDC_CLK_RX_RESET_CTL			(0x301)
+#define TAPAN_A_CDC_CLK_RX_RESET_CTL__POR				(0x00)
+#define TAPAN_A_CDC_CLK_TX_RESET_B1_CTL			(0x302)
+#define TAPAN_A_CDC_CLK_TX_RESET_B1_CTL__POR				(0x00)
+#define TAPAN_A_CDC_CLK_TX_RESET_B2_CTL			(0x303)
+#define TAPAN_A_CDC_CLK_TX_RESET_B2_CTL__POR				(0x00)
+#define TAPAN_A_CDC_CLK_DMIC_B1_CTL			(0x304)
+#define TAPAN_A_CDC_CLK_DMIC_B1_CTL__POR				(0x00)
+#define TAPAN_A_CDC_CLK_DMIC_B2_CTL			(0x305)
+#define TAPAN_A_CDC_CLK_DMIC_B2_CTL__POR				(0x00)
+#define TAPAN_A_CDC_CLK_I2S_CTL			(0x306)
+#define TAPAN_A_CDC_CLK_I2S_CTL__POR				(0x03)
+#define TAPAN_A_CDC_CLK_OTHR_RESET_B1_CTL			(0x308)
+#define TAPAN_A_CDC_CLK_OTHR_RESET_B1_CTL__POR				(0x00)
+#define TAPAN_A_CDC_CLK_OTHR_RESET_B2_CTL			(0x309)
+#define TAPAN_A_CDC_CLK_OTHR_RESET_B2_CTL__POR				(0x00)
+#define TAPAN_A_CDC_CLK_TX_CLK_EN_B1_CTL			(0x30A)
+#define TAPAN_A_CDC_CLK_TX_CLK_EN_B1_CTL__POR				(0x00)
+#define TAPAN_A_CDC_CLK_TX_CLK_EN_B2_CTL			(0x30B)
+#define TAPAN_A_CDC_CLK_TX_CLK_EN_B2_CTL__POR				(0x00)
+#define TAPAN_A_CDC_CLK_OTHR_CTL			(0x30C)
+#define TAPAN_A_CDC_CLK_OTHR_CTL__POR				(0x00)
+#define TAPAN_A_CDC_CLK_RDAC_CLK_EN_CTL			(0x30D)
+#define TAPAN_A_CDC_CLK_RDAC_CLK_EN_CTL__POR				(0x00)
+#define TAPAN_A_CDC_CLK_ANC_CLK_EN_CTL			(0x30E)
+#define TAPAN_A_CDC_CLK_ANC_CLK_EN_CTL__POR				(0x00)
+#define TAPAN_A_CDC_CLK_RX_B1_CTL			(0x30F)
+#define TAPAN_A_CDC_CLK_RX_B1_CTL__POR				(0x00)
+#define TAPAN_A_CDC_CLK_RX_B2_CTL			(0x310)
+#define TAPAN_A_CDC_CLK_RX_B2_CTL__POR				(0x00)
+#define TAPAN_A_CDC_CLK_MCLK_CTL			(0x311)
+#define TAPAN_A_CDC_CLK_MCLK_CTL__POR				(0x00)
+#define TAPAN_A_CDC_CLK_PDM_CTL			(0x312)
+#define TAPAN_A_CDC_CLK_PDM_CTL__POR				(0x00)
+#define TAPAN_A_CDC_CLK_SD_CTL			(0x313)
+#define TAPAN_A_CDC_CLK_SD_CTL__POR				(0x00)
+#define TAPAN_A_CDC_CLK_POWER_CTL			(0x314)
+#define TAPAN_A_CDC_CLK_POWER_CTL__POR				(0x03)
+#define TAPAN_A_CDC_CLSH_B1_CTL			(0x320)
+#define TAPAN_A_CDC_CLSH_B1_CTL__POR				(0x22)
+#define TAPAN_A_CDC_CLSH_B2_CTL			(0x321)
+#define TAPAN_A_CDC_CLSH_B2_CTL__POR				(0x35)
+#define TAPAN_A_CDC_CLSH_B3_CTL			(0x322)
+#define TAPAN_A_CDC_CLSH_B3_CTL__POR				(0x3B)
+#define TAPAN_A_CDC_CLSH_BUCK_NCP_VARS			(0x323)
+#define TAPAN_A_CDC_CLSH_BUCK_NCP_VARS__POR				(0x04)
+#define TAPAN_A_CDC_CLSH_IDLE_HPH_THSD			(0x324)
+#define TAPAN_A_CDC_CLSH_IDLE_HPH_THSD__POR				(0x12)
+#define TAPAN_A_CDC_CLSH_IDLE_EAR_THSD			(0x325)
+#define TAPAN_A_CDC_CLSH_IDLE_EAR_THSD__POR				(0x0C)
+#define TAPAN_A_CDC_CLSH_FCLKONLY_HPH_THSD			(0x326)
+#define TAPAN_A_CDC_CLSH_FCLKONLY_HPH_THSD__POR				(0x18)
+#define TAPAN_A_CDC_CLSH_FCLKONLY_EAR_THSD			(0x327)
+#define TAPAN_A_CDC_CLSH_FCLKONLY_EAR_THSD__POR				(0x23)
+#define TAPAN_A_CDC_CLSH_K_ADDR			(0x328)
+#define TAPAN_A_CDC_CLSH_K_ADDR__POR				(0x00)
+#define TAPAN_A_CDC_CLSH_K_DATA			(0x329)
+#define TAPAN_A_CDC_CLSH_K_DATA__POR				(0xA4)
+#define TAPAN_A_CDC_CLSH_I_PA_FACT_HPH_L			(0x32A)
+#define TAPAN_A_CDC_CLSH_I_PA_FACT_HPH_L__POR				(0xD7)
+#define TAPAN_A_CDC_CLSH_I_PA_FACT_HPH_U			(0x32B)
+#define TAPAN_A_CDC_CLSH_I_PA_FACT_HPH_U__POR				(0x05)
+#define TAPAN_A_CDC_CLSH_I_PA_FACT_EAR_L			(0x32C)
+#define TAPAN_A_CDC_CLSH_I_PA_FACT_EAR_L__POR				(0x60)
+#define TAPAN_A_CDC_CLSH_I_PA_FACT_EAR_U			(0x32D)
+#define TAPAN_A_CDC_CLSH_I_PA_FACT_EAR_U__POR				(0x09)
+#define TAPAN_A_CDC_CLSH_V_PA_HD_EAR			(0x32E)
+#define TAPAN_A_CDC_CLSH_V_PA_HD_EAR__POR				(0x0D)
+#define TAPAN_A_CDC_CLSH_V_PA_HD_HPH			(0x32F)
+#define TAPAN_A_CDC_CLSH_V_PA_HD_HPH__POR				(0x0D)
+#define TAPAN_A_CDC_CLSH_V_PA_MIN_EAR			(0x330)
+#define TAPAN_A_CDC_CLSH_V_PA_MIN_EAR__POR				(0x3A)
+#define TAPAN_A_CDC_CLSH_V_PA_MIN_HPH			(0x331)
+#define TAPAN_A_CDC_CLSH_V_PA_MIN_HPH__POR				(0x1D)
+#define TAPAN_A_CDC_IIR1_GAIN_B1_CTL			(0x340)
+#define TAPAN_A_CDC_IIR1_GAIN_B1_CTL__POR				(0x00)
+#define TAPAN_A_CDC_IIR2_GAIN_B1_CTL			(0x350)
+#define TAPAN_A_CDC_IIR2_GAIN_B1_CTL__POR				(0x00)
+#define TAPAN_A_CDC_IIR1_GAIN_B2_CTL			(0x341)
+#define TAPAN_A_CDC_IIR1_GAIN_B2_CTL__POR				(0x00)
+#define TAPAN_A_CDC_IIR2_GAIN_B2_CTL			(0x351)
+#define TAPAN_A_CDC_IIR2_GAIN_B2_CTL__POR				(0x00)
+#define TAPAN_A_CDC_IIR1_GAIN_B3_CTL			(0x342)
+#define TAPAN_A_CDC_IIR1_GAIN_B3_CTL__POR				(0x00)
+#define TAPAN_A_CDC_IIR2_GAIN_B3_CTL			(0x352)
+#define TAPAN_A_CDC_IIR2_GAIN_B3_CTL__POR				(0x00)
+#define TAPAN_A_CDC_IIR1_GAIN_B4_CTL			(0x343)
+#define TAPAN_A_CDC_IIR1_GAIN_B4_CTL__POR				(0x00)
+#define TAPAN_A_CDC_IIR2_GAIN_B4_CTL			(0x353)
+#define TAPAN_A_CDC_IIR2_GAIN_B4_CTL__POR				(0x00)
+#define TAPAN_A_CDC_IIR1_GAIN_B5_CTL			(0x344)
+#define TAPAN_A_CDC_IIR1_GAIN_B5_CTL__POR				(0x00)
+#define TAPAN_A_CDC_IIR2_GAIN_B5_CTL			(0x354)
+#define TAPAN_A_CDC_IIR2_GAIN_B5_CTL__POR				(0x00)
+#define TAPAN_A_CDC_IIR1_GAIN_B6_CTL			(0x345)
+#define TAPAN_A_CDC_IIR1_GAIN_B6_CTL__POR				(0x00)
+#define TAPAN_A_CDC_IIR2_GAIN_B6_CTL			(0x355)
+#define TAPAN_A_CDC_IIR2_GAIN_B6_CTL__POR				(0x00)
+#define TAPAN_A_CDC_IIR1_GAIN_B7_CTL			(0x346)
+#define TAPAN_A_CDC_IIR1_GAIN_B7_CTL__POR				(0x00)
+#define TAPAN_A_CDC_IIR2_GAIN_B7_CTL			(0x356)
+#define TAPAN_A_CDC_IIR2_GAIN_B7_CTL__POR				(0x00)
+#define TAPAN_A_CDC_IIR1_GAIN_B8_CTL			(0x347)
+#define TAPAN_A_CDC_IIR1_GAIN_B8_CTL__POR				(0x00)
+#define TAPAN_A_CDC_IIR2_GAIN_B8_CTL			(0x357)
+#define TAPAN_A_CDC_IIR2_GAIN_B8_CTL__POR				(0x00)
+#define TAPAN_A_CDC_IIR1_CTL			(0x348)
+#define TAPAN_A_CDC_IIR1_CTL__POR				(0x00)
+#define TAPAN_A_CDC_IIR2_CTL			(0x358)
+#define TAPAN_A_CDC_IIR2_CTL__POR				(0x00)
+#define TAPAN_A_CDC_IIR1_GAIN_TIMER_CTL			(0x349)
+#define TAPAN_A_CDC_IIR1_GAIN_TIMER_CTL__POR				(0x00)
+#define TAPAN_A_CDC_IIR2_GAIN_TIMER_CTL			(0x359)
+#define TAPAN_A_CDC_IIR2_GAIN_TIMER_CTL__POR				(0x00)
+#define TAPAN_A_CDC_IIR1_COEF_B1_CTL			(0x34A)
+#define TAPAN_A_CDC_IIR1_COEF_B1_CTL__POR				(0x00)
+#define TAPAN_A_CDC_IIR2_COEF_B1_CTL			(0x35A)
+#define TAPAN_A_CDC_IIR2_COEF_B1_CTL__POR				(0x00)
+#define TAPAN_A_CDC_IIR1_COEF_B2_CTL			(0x34B)
+#define TAPAN_A_CDC_IIR1_COEF_B2_CTL__POR				(0x00)
+#define TAPAN_A_CDC_IIR2_COEF_B2_CTL			(0x35B)
+#define TAPAN_A_CDC_IIR2_COEF_B2_CTL__POR				(0x00)
+#define TAPAN_A_CDC_TOP_GAIN_UPDATE			(0x360)
+#define TAPAN_A_CDC_TOP_GAIN_UPDATE__POR				(0x00)
+#define TAPAN_A_CDC_COMP0_B1_CTL			(0x368)
+#define TAPAN_A_CDC_COMP0_B1_CTL__POR				(0x00)
+#define TAPAN_A_CDC_COMP1_B1_CTL			(0x370)
+#define TAPAN_A_CDC_COMP1_B1_CTL__POR				(0x00)
+#define TAPAN_A_CDC_COMP2_B1_CTL			(0x378)
+#define TAPAN_A_CDC_COMP2_B1_CTL__POR				(0x00)
+#define TAPAN_A_CDC_COMP0_B2_CTL			(0x369)
+#define TAPAN_A_CDC_COMP0_B2_CTL__POR				(0x00)
+#define TAPAN_A_CDC_COMP1_B2_CTL			(0x371)
+#define TAPAN_A_CDC_COMP1_B2_CTL__POR				(0x00)
+#define TAPAN_A_CDC_COMP2_B2_CTL			(0x379)
+#define TAPAN_A_CDC_COMP2_B2_CTL__POR				(0x00)
+#define TAPAN_A_CDC_COMP0_B3_CTL			(0x36A)
+#define TAPAN_A_CDC_COMP0_B3_CTL__POR				(0x00)
+#define TAPAN_A_CDC_COMP1_B3_CTL			(0x372)
+#define TAPAN_A_CDC_COMP1_B3_CTL__POR				(0x00)
+#define TAPAN_A_CDC_COMP2_B3_CTL			(0x37A)
+#define TAPAN_A_CDC_COMP2_B3_CTL__POR				(0x00)
+#define TAPAN_A_CDC_COMP0_B4_CTL			(0x36B)
+#define TAPAN_A_CDC_COMP0_B4_CTL__POR				(0x00)
+#define TAPAN_A_CDC_COMP1_B4_CTL			(0x373)
+#define TAPAN_A_CDC_COMP1_B4_CTL__POR				(0x00)
+#define TAPAN_A_CDC_COMP2_B4_CTL			(0x37B)
+#define TAPAN_A_CDC_COMP2_B4_CTL__POR				(0x00)
+#define TAPAN_A_CDC_COMP0_B5_CTL			(0x36C)
+#define TAPAN_A_CDC_COMP0_B5_CTL__POR				(0x00)
+#define TAPAN_A_CDC_COMP1_B5_CTL			(0x374)
+#define TAPAN_A_CDC_COMP1_B5_CTL__POR				(0x00)
+#define TAPAN_A_CDC_COMP2_B5_CTL			(0x37C)
+#define TAPAN_A_CDC_COMP2_B5_CTL__POR				(0x00)
+#define TAPAN_A_CDC_COMP0_B6_CTL			(0x36D)
+#define TAPAN_A_CDC_COMP0_B6_CTL__POR				(0x00)
+#define TAPAN_A_CDC_COMP1_B6_CTL			(0x375)
+#define TAPAN_A_CDC_COMP1_B6_CTL__POR				(0x00)
+#define TAPAN_A_CDC_COMP2_B6_CTL			(0x37D)
+#define TAPAN_A_CDC_COMP2_B6_CTL__POR				(0x00)
+#define TAPAN_A_CDC_COMP0_SHUT_DOWN_STATUS			(0x36E)
+#define TAPAN_A_CDC_COMP0_SHUT_DOWN_STATUS__POR				(0x00)
+#define TAPAN_A_CDC_COMP1_SHUT_DOWN_STATUS			(0x376)
+#define TAPAN_A_CDC_COMP1_SHUT_DOWN_STATUS__POR				(0x00)
+#define TAPAN_A_CDC_COMP2_SHUT_DOWN_STATUS			(0x37E)
+#define TAPAN_A_CDC_COMP2_SHUT_DOWN_STATUS__POR				(0x00)
+#define TAPAN_A_CDC_COMP0_FS_CFG			(0x36F)
+#define TAPAN_A_CDC_COMP0_FS_CFG__POR				(0x00)
+#define TAPAN_A_CDC_COMP1_FS_CFG			(0x377)
+#define TAPAN_A_CDC_COMP1_FS_CFG__POR				(0x00)
+#define TAPAN_A_CDC_COMP2_FS_CFG			(0x37F)
+#define TAPAN_A_CDC_COMP2_FS_CFG__POR				(0x00)
+#define TAPAN_A_CDC_CONN_RX1_B1_CTL			(0x380)
+#define TAPAN_A_CDC_CONN_RX1_B1_CTL__POR				(0x00)
+#define TAPAN_A_CDC_CONN_RX1_B2_CTL			(0x381)
+#define TAPAN_A_CDC_CONN_RX1_B2_CTL__POR				(0x00)
+#define TAPAN_A_CDC_CONN_RX1_B3_CTL			(0x382)
+#define TAPAN_A_CDC_CONN_RX1_B3_CTL__POR				(0x00)
+#define TAPAN_A_CDC_CONN_RX2_B1_CTL			(0x383)
+#define TAPAN_A_CDC_CONN_RX2_B1_CTL__POR				(0x00)
+#define TAPAN_A_CDC_CONN_RX2_B2_CTL			(0x384)
+#define TAPAN_A_CDC_CONN_RX2_B2_CTL__POR				(0x00)
+#define TAPAN_A_CDC_CONN_RX2_B3_CTL			(0x385)
+#define TAPAN_A_CDC_CONN_RX2_B3_CTL__POR				(0x00)
+#define TAPAN_A_CDC_CONN_RX3_B1_CTL			(0x386)
+#define TAPAN_A_CDC_CONN_RX3_B1_CTL__POR				(0x00)
+#define TAPAN_A_CDC_CONN_RX3_B2_CTL			(0x387)
+#define TAPAN_A_CDC_CONN_RX3_B2_CTL__POR				(0x00)
+#define TAPAN_A_CDC_CONN_RX4_B1_CTL			(0x388)
+#define TAPAN_A_CDC_CONN_RX4_B1_CTL__POR				(0x00)
+#define TAPAN_A_CDC_CONN_RX4_B2_CTL			(0x389)
+#define TAPAN_A_CDC_CONN_RX4_B2_CTL__POR				(0x00)
+#define TAPAN_A_CDC_CONN_RX4_B3_CTL			(0x38A)
+#define TAPAN_A_CDC_CONN_RX4_B3_CTL__POR				(0x00)
+#define TAPAN_A_CDC_CONN_ANC_B1_CTL			(0x391)
+#define TAPAN_A_CDC_CONN_ANC_B1_CTL__POR				(0x00)
+#define TAPAN_A_CDC_CONN_ANC_B2_CTL			(0x392)
+#define TAPAN_A_CDC_CONN_ANC_B2_CTL__POR				(0x00)
+#define TAPAN_A_CDC_CONN_TX_B1_CTL			(0x393)
+#define TAPAN_A_CDC_CONN_TX_B1_CTL__POR				(0x00)
+#define TAPAN_A_CDC_CONN_TX_B2_CTL			(0x394)
+#define TAPAN_A_CDC_CONN_TX_B2_CTL__POR				(0x00)
+#define TAPAN_A_CDC_CONN_TX_B3_CTL			(0x395)
+#define TAPAN_A_CDC_CONN_TX_B3_CTL__POR				(0x00)
+#define TAPAN_A_CDC_CONN_TX_B4_CTL			(0x396)
+#define TAPAN_A_CDC_CONN_TX_B4_CTL__POR				(0x00)
+#define TAPAN_A_CDC_CONN_EQ1_B1_CTL			(0x397)
+#define TAPAN_A_CDC_CONN_EQ1_B1_CTL__POR				(0x00)
+#define TAPAN_A_CDC_CONN_EQ1_B2_CTL			(0x398)
+#define TAPAN_A_CDC_CONN_EQ1_B2_CTL__POR				(0x00)
+#define TAPAN_A_CDC_CONN_EQ1_B3_CTL			(0x399)
+#define TAPAN_A_CDC_CONN_EQ1_B3_CTL__POR				(0x00)
+#define TAPAN_A_CDC_CONN_EQ1_B4_CTL			(0x39A)
+#define TAPAN_A_CDC_CONN_EQ1_B4_CTL__POR				(0x00)
+#define TAPAN_A_CDC_CONN_EQ2_B1_CTL			(0x39B)
+#define TAPAN_A_CDC_CONN_EQ2_B1_CTL__POR				(0x00)
+#define TAPAN_A_CDC_CONN_EQ2_B2_CTL			(0x39C)
+#define TAPAN_A_CDC_CONN_EQ2_B2_CTL__POR				(0x00)
+#define TAPAN_A_CDC_CONN_EQ2_B3_CTL			(0x39D)
+#define TAPAN_A_CDC_CONN_EQ2_B3_CTL__POR				(0x00)
+#define TAPAN_A_CDC_CONN_EQ2_B4_CTL			(0x39E)
+#define TAPAN_A_CDC_CONN_EQ2_B4_CTL__POR				(0x00)
+#define TAPAN_A_CDC_CONN_SRC1_B1_CTL			(0x39F)
+#define TAPAN_A_CDC_CONN_SRC1_B1_CTL__POR				(0x00)
+#define TAPAN_A_CDC_CONN_SRC1_B2_CTL			(0x3A0)
+#define TAPAN_A_CDC_CONN_SRC1_B2_CTL__POR				(0x00)
+#define TAPAN_A_CDC_CONN_SRC2_B1_CTL			(0x3A1)
+#define TAPAN_A_CDC_CONN_SRC2_B1_CTL__POR				(0x00)
+#define TAPAN_A_CDC_CONN_SRC2_B2_CTL			(0x3A2)
+#define TAPAN_A_CDC_CONN_SRC2_B2_CTL__POR				(0x00)
+#define TAPAN_A_CDC_CONN_TX_SB_B1_CTL			(0x3A3)
+#define TAPAN_A_CDC_CONN_TX_SB_B1_CTL__POR				(0x00)
+#define TAPAN_A_CDC_CONN_TX_SB_B2_CTL			(0x3A4)
+#define TAPAN_A_CDC_CONN_TX_SB_B2_CTL__POR				(0x00)
+#define TAPAN_A_CDC_CONN_TX_SB_B3_CTL			(0x3A5)
+#define TAPAN_A_CDC_CONN_TX_SB_B3_CTL__POR				(0x00)
+#define TAPAN_A_CDC_CONN_TX_SB_B4_CTL			(0x3A6)
+#define TAPAN_A_CDC_CONN_TX_SB_B4_CTL__POR				(0x00)
+#define TAPAN_A_CDC_CONN_TX_SB_B5_CTL			(0x3A7)
+#define TAPAN_A_CDC_CONN_TX_SB_B5_CTL__POR				(0x00)
+#define TAPAN_A_CDC_CONN_TX_SB_B11_CTL			(0x3AD)
+#define TAPAN_A_CDC_CONN_TX_SB_B11_CTL__POR				(0x00)
+#define TAPAN_A_CDC_CONN_RX_SB_B1_CTL			(0x3AE)
+#define TAPAN_A_CDC_CONN_RX_SB_B1_CTL__POR				(0x00)
+#define TAPAN_A_CDC_CONN_RX_SB_B2_CTL			(0x3AF)
+#define TAPAN_A_CDC_CONN_RX_SB_B2_CTL__POR				(0x00)
+#define TAPAN_A_CDC_CONN_CLSH_CTL			(0x3B0)
+#define TAPAN_A_CDC_CONN_CLSH_CTL__POR				(0x00)
+#define TAPAN_A_CDC_CONN_MISC			(0x3B1)
+#define TAPAN_A_CDC_CONN_MISC__POR				(0x01)
+#define TAPAN_A_CDC_MBHC_EN_CTL			(0x3C0)
+#define TAPAN_A_CDC_MBHC_EN_CTL__POR				(0x00)
+#define TAPAN_A_CDC_MBHC_FIR_B1_CFG			(0x3C1)
+#define TAPAN_A_CDC_MBHC_FIR_B1_CFG__POR				(0x00)
+#define TAPAN_A_CDC_MBHC_FIR_B2_CFG			(0x3C2)
+#define TAPAN_A_CDC_MBHC_FIR_B2_CFG__POR				(0x06)
+#define TAPAN_A_CDC_MBHC_TIMER_B1_CTL			(0x3C3)
+#define TAPAN_A_CDC_MBHC_TIMER_B1_CTL__POR				(0x03)
+#define TAPAN_A_CDC_MBHC_TIMER_B2_CTL			(0x3C4)
+#define TAPAN_A_CDC_MBHC_TIMER_B2_CTL__POR				(0x09)
+#define TAPAN_A_CDC_MBHC_TIMER_B3_CTL			(0x3C5)
+#define TAPAN_A_CDC_MBHC_TIMER_B3_CTL__POR				(0x1E)
+#define TAPAN_A_CDC_MBHC_TIMER_B4_CTL			(0x3C6)
+#define TAPAN_A_CDC_MBHC_TIMER_B4_CTL__POR				(0x45)
+#define TAPAN_A_CDC_MBHC_TIMER_B5_CTL			(0x3C7)
+#define TAPAN_A_CDC_MBHC_TIMER_B5_CTL__POR				(0x04)
+#define TAPAN_A_CDC_MBHC_TIMER_B6_CTL			(0x3C8)
+#define TAPAN_A_CDC_MBHC_TIMER_B6_CTL__POR				(0x78)
+#define TAPAN_A_CDC_MBHC_B1_STATUS			(0x3C9)
+#define TAPAN_A_CDC_MBHC_B1_STATUS__POR				(0x00)
+#define TAPAN_A_CDC_MBHC_B2_STATUS			(0x3CA)
+#define TAPAN_A_CDC_MBHC_B2_STATUS__POR				(0x00)
+#define TAPAN_A_CDC_MBHC_B3_STATUS			(0x3CB)
+#define TAPAN_A_CDC_MBHC_B3_STATUS__POR				(0x00)
+#define TAPAN_A_CDC_MBHC_B4_STATUS			(0x3CC)
+#define TAPAN_A_CDC_MBHC_B4_STATUS__POR				(0x00)
+#define TAPAN_A_CDC_MBHC_B5_STATUS			(0x3CD)
+#define TAPAN_A_CDC_MBHC_B5_STATUS__POR				(0x00)
+#define TAPAN_A_CDC_MBHC_B1_CTL			(0x3CE)
+#define TAPAN_A_CDC_MBHC_B1_CTL__POR				(0xC0)
+#define TAPAN_A_CDC_MBHC_B2_CTL			(0x3CF)
+#define TAPAN_A_CDC_MBHC_B2_CTL__POR				(0x5D)
+#define TAPAN_A_CDC_MBHC_VOLT_B1_CTL			(0x3D0)
+#define TAPAN_A_CDC_MBHC_VOLT_B1_CTL__POR				(0x00)
+#define TAPAN_A_CDC_MBHC_VOLT_B2_CTL			(0x3D1)
+#define TAPAN_A_CDC_MBHC_VOLT_B2_CTL__POR				(0x00)
+#define TAPAN_A_CDC_MBHC_VOLT_B3_CTL			(0x3D2)
+#define TAPAN_A_CDC_MBHC_VOLT_B3_CTL__POR				(0x00)
+#define TAPAN_A_CDC_MBHC_VOLT_B4_CTL			(0x3D3)
+#define TAPAN_A_CDC_MBHC_VOLT_B4_CTL__POR				(0x00)
+#define TAPAN_A_CDC_MBHC_VOLT_B5_CTL			(0x3D4)
+#define TAPAN_A_CDC_MBHC_VOLT_B5_CTL__POR				(0x00)
+#define TAPAN_A_CDC_MBHC_VOLT_B6_CTL			(0x3D5)
+#define TAPAN_A_CDC_MBHC_VOLT_B6_CTL__POR				(0x00)
+#define TAPAN_A_CDC_MBHC_VOLT_B7_CTL			(0x3D6)
+#define TAPAN_A_CDC_MBHC_VOLT_B7_CTL__POR				(0xFF)
+#define TAPAN_A_CDC_MBHC_VOLT_B8_CTL			(0x3D7)
+#define TAPAN_A_CDC_MBHC_VOLT_B8_CTL__POR				(0x07)
+#define TAPAN_A_CDC_MBHC_VOLT_B9_CTL			(0x3D8)
+#define TAPAN_A_CDC_MBHC_VOLT_B9_CTL__POR				(0xFF)
+#define TAPAN_A_CDC_MBHC_VOLT_B10_CTL			(0x3D9)
+#define TAPAN_A_CDC_MBHC_VOLT_B10_CTL__POR				(0x7F)
+#define TAPAN_A_CDC_MBHC_VOLT_B11_CTL			(0x3DA)
+#define TAPAN_A_CDC_MBHC_VOLT_B11_CTL__POR				(0x00)
+#define TAPAN_A_CDC_MBHC_VOLT_B12_CTL			(0x3DB)
+#define TAPAN_A_CDC_MBHC_VOLT_B12_CTL__POR				(0x80)
+#define TAPAN_A_CDC_MBHC_CLK_CTL			(0x3DC)
+#define TAPAN_A_CDC_MBHC_CLK_CTL__POR				(0x00)
+#define TAPAN_A_CDC_MBHC_INT_CTL			(0x3DD)
+#define TAPAN_A_CDC_MBHC_INT_CTL__POR				(0x00)
+#define TAPAN_A_CDC_MBHC_DEBUG_CTL			(0x3DE)
+#define TAPAN_A_CDC_MBHC_DEBUG_CTL__POR				(0x00)
+#define TAPAN_A_CDC_MBHC_SPARE			(0x3DF)
+#define TAPAN_A_CDC_MBHC_SPARE__POR				(0x00)
+
+
+/* SLIMBUS Slave Registers */
+#define TAPAN_SLIM_PGD_PORT_INT_EN0 (0x30)
+#define TAPAN_SLIM_PGD_PORT_INT_STATUS0 (0x34)
+#define TAPAN_SLIM_PGD_PORT_INT_CLR0 (0x38)
+#define TAPAN_SLIM_PGD_PORT_INT_SOURCE0 (0x60)
+
+/* Macros for Packing Register Writes into a U32 */
+#define TAPAN_PACKED_REG_SIZE sizeof(u32)
+
+#define TAPAN_CODEC_PACK_ENTRY(reg, mask, val) ((val & 0xff)|\
+	((mask & 0xff) << 8)|((reg & 0xffff) << 16))
+
+#define TAPAN_CODEC_UNPACK_ENTRY(packed, reg, mask, val) \
+	do { \
+		((reg) = ((packed >> 16) & (0xffff))); \
+		((mask) = ((packed >> 8) & (0xff))); \
+		((val) = ((packed) & (0xff))); \
+	} while (0);
+
+#endif
diff --git a/include/linux/mmc/card.h b/include/linux/mmc/card.h
index d2f8faf..4d004c2 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,35 +262,39 @@
 /**
  * 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;
 	unsigned int		min_sectors_to_queue_delayed_work;
-	struct mmc_bkops_stats  bkops_stats;    /* BKOPS statistics */
+	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;
 	unsigned int		sectors_changed;
 /*
  * Since canceling the delayed work might have significant effect on the
@@ -297,9 +302,8 @@
  * mmcqd thread is idle.
  * The delayed work for idle BKOPS will be scheduled only after a significant
  * amount of write or discard data.
- * 100MB is chosen based on benchmark tests.
  */
-#define BKOPS_MIN_SECTORS_TO_QUEUE_DELAYED_WORK 204800 /* 100MB */
+#define BKOPS_SIZE_PERCENTAGE_TO_QUEUE_DELAYED_WORK 1 /* 1% */
 };
 
 /**
@@ -350,6 +354,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 */
@@ -524,6 +529,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)
@@ -537,7 +543,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.
  */
diff --git a/include/linux/mmc/core.h b/include/linux/mmc/core.h
index 83cc723..ea48688 100644
--- a/include/linux/mmc/core.h
+++ b/include/linux/mmc/core.h
@@ -96,6 +96,8 @@
  */
 
 	unsigned int		cmd_timeout_ms;	/* in milliseconds */
+	/* Set this flag only for blocking bkops request */
+	bool			bkops_busy;
 
 	struct mmc_data		*data;		/* data segment associated with cmd */
 	struct mmc_request	*mrq;		/* associated request */
@@ -153,7 +155,8 @@
 extern void mmc_start_delayed_bkops(struct mmc_card *card);
 extern void mmc_start_idle_time_bkops(struct work_struct *work);
 extern void mmc_bkops_completion_polling(struct work_struct *work);
-extern int __mmc_switch(struct mmc_card *, u8, u8, u8, unsigned int, bool);
+extern int __mmc_switch(struct mmc_card *, u8, u8, u8, unsigned int, bool,
+			bool);
 extern int mmc_switch(struct mmc_card *, u8, u8, u8, unsigned int);
 extern int mmc_send_ext_csd(struct mmc_card *card, u8 *ext_csd);
 
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_mdp.h b/include/linux/msm_mdp.h
index d3f6792..7e67db0 100644
--- a/include/linux/msm_mdp.h
+++ b/include/linux/msm_mdp.h
@@ -72,6 +72,9 @@
 #define MSMFB_VSYNC_CTRL  _IOW(MSMFB_IOCTL_MAGIC, 161, unsigned int)
 #define MSMFB_METADATA_SET  _IOW(MSMFB_IOCTL_MAGIC, 162, struct msmfb_metadata)
 #define MSMFB_OVERLAY_COMMIT      _IO(MSMFB_IOCTL_MAGIC, 163)
+#define MSMFB_BUFFER_SYNC  _IOW(MSMFB_IOCTL_MAGIC, 164, struct mdp_buf_sync)
+#define MSMFB_DISPLAY_COMMIT      _IOW(MSMFB_IOCTL_MAGIC, 165, \
+						struct mdp_display_commit)
 
 #define FB_TYPE_3D_PANEL 0x10101010
 #define MDP_IMGTYPE2_START 0x10000
@@ -142,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
@@ -295,6 +299,7 @@
 
 #define MDP_OVERLAY_PP_CSC_CFG      0x1
 #define MDP_OVERLAY_PP_QSEED_CFG    0x2
+#define MDP_OVERLAY_PP_PA_CFG      0x4
 
 #define MDP_CSC_FLAG_ENABLE	0x1
 #define MDP_CSC_FLAG_YUV_IN	0x2
@@ -315,10 +320,19 @@
 	struct mdp_csc_cfg csc_data;
 };
 
+struct mdp_pa_cfg {
+	uint32_t flags;
+	uint32_t hue_adj;
+	uint32_t sat_adj;
+	uint32_t val_adj;
+	uint32_t cont_adj;
+};
+
 struct mdp_overlay_pp_params {
 	uint32_t config_ops;
 	struct mdp_csc_cfg csc_cfg;
 	struct mdp_qseed_cfg qseed_cfg[2];
+	struct mdp_pa_cfg pa_cfg;
 };
 
 struct mdp_overlay {
@@ -483,11 +497,7 @@
 
 struct mdp_pa_cfg_data {
 	uint32_t block;
-	uint32_t flags;
-	uint32_t hue_adj;
-	uint32_t sat_adj;
-	uint32_t val_adj;
-	uint32_t cont_adj;
+	struct mdp_pa_cfg pa_data;
 };
 
 struct mdp_dither_cfg_data {
@@ -508,6 +518,12 @@
 	uint16_t *b_tbl[MDP_GAMUT_TABLE_NUM];
 };
 
+struct mdp_calib_config_data {
+	uint32_t ops;
+	uint32_t addr;
+	uint32_t data;
+};
+
 enum {
 	mdp_op_pcc_cfg,
 	mdp_op_csc_cfg,
@@ -517,6 +533,7 @@
 	mdp_op_pa_cfg,
 	mdp_op_dither_cfg,
 	mdp_op_gamut_cfg,
+	mdp_op_calib_cfg,
 	mdp_op_max,
 };
 
@@ -531,6 +548,7 @@
 		struct mdp_pa_cfg_data pa_cfg_data;
 		struct mdp_dither_cfg_data dither_cfg_data;
 		struct mdp_gamut_cfg_data gamut_cfg_data;
+		struct mdp_calib_config_data calib_cfg;
 	} data;
 };
 
@@ -551,6 +569,25 @@
 		struct mdp_blend_cfg blend_cfg;
 	} data;
 };
+
+#define MDP_MAX_FENCE_FD	10
+#define MDP_BUF_SYNC_FLAG_WAIT	1
+
+struct mdp_buf_sync {
+	uint32_t flags;
+	uint32_t acq_fen_fd_cnt;
+	int *acq_fen_fd;
+	int *rel_fen_fd;
+};
+
+#define MDP_DISPLAY_COMMIT_OVERLAY	1
+
+struct mdp_display_commit {
+	uint32_t flags;
+	uint32_t wait_for_finish;
+	struct fb_var_screeninfo var;
+};
+
 struct mdp_page_protection {
 	uint32_t page_protection;
 };
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/msm_vidc_dec.h b/include/linux/msm_vidc_dec.h
index 3c99562..cc864f0 100644
--- a/include/linux/msm_vidc_dec.h
+++ b/include/linux/msm_vidc_dec.h
@@ -78,6 +78,7 @@
 
 #define VDEC_EXTRADATA_EXT_DATA          0x0800
 #define VDEC_EXTRADATA_USER_DATA         0x1000
+#define VDEC_EXTRADATA_EXT_BUFFER        0x2000
 
 #define VDEC_CMDBASE	0x800
 #define VDEC_CMD_SET_INTF_VERSION	(VDEC_CMDBASE)
@@ -213,6 +214,12 @@
 #define VDEC_IOCTL_SET_PERF_CLK \
 	_IOR(VDEC_IOCTL_MAGIC, 38, struct vdec_ioctl_msg)
 
+#define VDEC_IOCTL_SET_META_BUFFERS \
+	_IOW(VDEC_IOCTL_MAGIC, 39, struct vdec_ioctl_msg)
+
+#define VDEC_IOCTL_FREE_META_BUFFERS \
+	_IO(VDEC_IOCTL_MAGIC, 40)
+
 enum vdec_picture {
 	PICTURE_TYPE_I,
 	PICTURE_TYPE_P,
@@ -236,6 +243,7 @@
 	size_t buffer_size;
 	uint32_t alignment;
 	uint32_t buf_poolid;
+	size_t meta_buffer_size;
 };
 
 struct vdec_bufferpayload {
@@ -526,6 +534,11 @@
 	uint32_t par_height;
 };
 
+struct vdec_sep_metadatainfo {
+	void __user *metabufaddr;
+	uint32_t size;
+};
+
 struct vdec_output_frameinfo {
 	void __user *bufferaddr;
 	size_t offset;
@@ -538,6 +551,7 @@
 	struct vdec_framesize framesize;
 	enum vdec_interlaced_format interlaced_format;
 	struct vdec_aspectratioinfo aspect_ratio_info;
+	struct vdec_sep_metadatainfo metadata_info;
 };
 
 union vdec_msgdata {
@@ -571,4 +585,12 @@
 	int alignment;
 };
 
+struct vdec_meta_buffers {
+	size_t size;
+	int count;
+	int pmem_fd;
+	int pmem_fd_iommu;
+	int offset;
+};
+
 #endif /* end of macro _VDECDECODER_H_ */
diff --git a/include/linux/msm_vidc_enc.h b/include/linux/msm_vidc_enc.h
index ea7db81..dde126c 100644
--- a/include/linux/msm_vidc_enc.h
+++ b/include/linux/msm_vidc_enc.h
@@ -44,6 +44,8 @@
 #define VEN_MSG_PAUSE	8
 #define VEN_MSG_RESUME	9
 #define VEN_MSG_STOP_READING_MSG	10
+#define VEN_MSG_LTRUSE_FAILED	    11
+
 
 /*Buffer flags bits masks*/
 #define VEN_BUFFLAG_EOS	0x00000001
@@ -56,6 +58,7 @@
 #define VEN_EXTRADATA_NONE          0x001
 #define VEN_EXTRADATA_QCOMFILLER    0x002
 #define VEN_EXTRADATA_SLICEINFO     0x100
+#define VEN_EXTRADATA_LTRINFO       0x200
 
 /*ENCODER CONFIGURATION CONSTANTS*/
 
@@ -461,6 +464,55 @@
 #define VEN_IOCTL_SET_H263_PLUSPTYPE \
 	_IOW(VEN_IOCTLBASE_ENC, 51, struct venc_ioctl_msg)
 
+/*IOCTL params:SET: InputData - venc_range, OutputData - NULL.*/
+#define VEN_IOCTL_SET_CAPABILITY_LTRCOUNT \
+	_IOW(VEN_IOCTLBASE_ENC, 52, struct venc_ioctl_msg)
+/*IOCTL params:GET: InputData - NULL, OutputData - venc_range.*/
+#define VEN_IOCTL_GET_CAPABILITY_LTRCOUNT \
+	_IOR(VEN_IOCTLBASE_ENC, 53, struct venc_ioctl_msg)
+
+/*IOCTL params:SET: InputData - venc_ltrmode, OutputData - NULL.*/
+#define VEN_IOCTL_SET_LTRMODE \
+	_IOW(VEN_IOCTLBASE_ENC, 54, struct venc_ioctl_msg)
+/*IOCTL params:GET: InputData - NULL, OutputData - venc_ltrmode.*/
+#define VEN_IOCTL_GET_LTRMODE \
+	_IOR(VEN_IOCTLBASE_ENC, 55, struct venc_ioctl_msg)
+
+/*IOCTL params:SET: InputData - venc_ltrcount, OutputData - NULL.*/
+#define VEN_IOCTL_SET_LTRCOUNT \
+	_IOW(VEN_IOCTLBASE_ENC, 56, struct venc_ioctl_msg)
+/*IOCTL params:GET: InputData - NULL, OutputData - venc_ltrcount.*/
+#define VEN_IOCTL_GET_LTRCOUNT \
+	_IOR(VEN_IOCTLBASE_ENC, 57, struct venc_ioctl_msg)
+
+/*IOCTL params:SET: InputData - venc_ltrperiod, OutputData - NULL.*/
+#define VEN_IOCTL_SET_LTRPERIOD \
+	_IOW(VEN_IOCTLBASE_ENC, 58, struct venc_ioctl_msg)
+/*IOCTL params:GET: InputData - NULL, OutputData - venc_ltrperiod.*/
+#define VEN_IOCTL_GET_LTRPERIOD \
+	_IOR(VEN_IOCTLBASE_ENC, 59, struct venc_ioctl_msg)
+
+/*IOCTL params:SET: InputData - venc_ltruse, OutputData - NULL.*/
+#define VEN_IOCTL_SET_LTRUSE \
+	_IOW(VEN_IOCTLBASE_ENC, 60, struct venc_ioctl_msg)
+/*IOCTL params:GET: InputData - NULL, OutputData - venc_ltruse.*/
+#define VEN_IOCTL_GET_LTRUSE \
+	_IOR(VEN_IOCTLBASE_ENC, 61, struct venc_ioctl_msg)
+
+/*IOCTL params:SET: InputData - venc_ltrmark, OutputData - NULL.*/
+#define VEN_IOCTL_SET_LTRMARK \
+	_IOW(VEN_IOCTLBASE_ENC, 62, struct venc_ioctl_msg)
+/*IOCTL params:GET: InputData - NULL, OutputData - venc_ltrmark.*/
+#define VEN_IOCTL_GET_LTRMARK \
+	_IOR(VEN_IOCTLBASE_ENC, 63, struct venc_ioctl_msg)
+
+
+struct venc_range {
+	unsigned long	max;
+	unsigned long	min;
+	unsigned long	step_size;
+};
+
 struct venc_switch{
 	unsigned char	status;
 };
@@ -622,4 +674,21 @@
 	int alignment;
 };
 
+struct venc_ltrmode {
+	unsigned long   ltr_mode;
+};
+
+struct venc_ltrcount {
+	unsigned long   ltr_count;
+};
+
+struct venc_ltrperiod {
+	unsigned long   ltr_period;
+};
+
+struct venc_ltruse {
+	unsigned long   ltr_id;
+	unsigned long   ltr_frames;
+};
+
 #endif /* _MSM_VIDC_ENC_H_ */
diff --git a/include/linux/usb/msm_hsusb.h b/include/linux/usb/msm_hsusb.h
index bcbdec4..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];
 };
 
 /**
@@ -504,6 +505,15 @@
 	void *ctxt;
 };
 
+#ifdef CONFIG_USB_CI13XXX_MSM
+void msm_hw_bam_disable(bool bam_disable);
+
+#else
+static inline void msm_hw_bam_disable(bool bam_disable)
+{
+}
+#endif
+
 #ifdef CONFIG_USB_DWC3_MSM
 int msm_ep_config(struct usb_ep *ep);
 int msm_ep_unconfig(struct usb_ep *ep);
diff --git a/include/linux/usb/msm_hsusb_hw.h b/include/linux/usb/msm_hsusb_hw.h
index c8c2ed1..6e36f56 100644
--- a/include/linux/usb/msm_hsusb_hw.h
+++ b/include/linux/usb/msm_hsusb_hw.h
@@ -18,6 +18,7 @@
 
 #define USB_AHBBURST         (MSM_USB_BASE + 0x0090)
 #define USB_AHBMODE          (MSM_USB_BASE + 0x0098)
+#define USB_GENCONFIG        (MSM_USB_BASE + 0x009C)
 #define USB_CAPLENGTH        (MSM_USB_BASE + 0x0100) /* 8 bit */
 #define USB_HS_GPTIMER_BASE  (MSM_USB_BASE + 0x80)
 
@@ -49,6 +50,8 @@
 #define ULPI_DATA(n)          ((n) & 255)
 #define ULPI_DATA_READ(n)     (((n) >> 8) & 255)
 
+#define GENCONFIG_BAM_DISABLE (1 << 13)
+
 /* synopsys 28nm phy registers */
 #define ULPI_PWR_CLK_MNG_REG	0x88
 #define OTG_COMP_DISABLE	BIT(0)
diff --git a/include/media/msm/vcd_api.h b/include/media/msm/vcd_api.h
index 7104028..e668544 100644
--- a/include/media/msm/vcd_api.h
+++ b/include/media/msm/vcd_api.h
@@ -100,6 +100,7 @@
 	size_t sz;
 	u32 align;
 	u32 buf_pool_id;
+	size_t meta_buffer_size;
 };
 
 struct vcd_init_config {
diff --git a/include/media/msm/vcd_property.h b/include/media/msm/vcd_property.h
index 2ce1a88..85b28e2 100644
--- a/include/media/msm/vcd_property.h
+++ b/include/media/msm/vcd_property.h
@@ -58,7 +58,14 @@
 #define VCD_I_ENABLE_DELIMITER_FLAG (VCD_START_BASE + 0x2A)
 #define VCD_I_ENABLE_VUI_TIMING_INFO (VCD_START_BASE + 0x2B)
 #define VCD_I_H263_PLUSPTYPE (VCD_START_BASE + 0x2C)
-
+#define VCD_I_LTR_MODE (VCD_START_BASE + 0x2D)
+#define VCD_I_LTR_COUNT (VCD_START_BASE + 0x2E)
+#define VCD_I_LTR_PERIOD (VCD_START_BASE + 0x2F)
+#define VCD_I_LTR_USE (VCD_START_BASE + 0x30)
+#define VCD_I_CAPABILITY_LTR_COUNT (VCD_START_BASE + 0x31)
+#define VCD_I_LTR_MARK (VCD_START_BASE + 0x32)
+#define VCD_I_SET_EXT_METABUFFER (VCD_START_BASE + 0x33)
+#define VCD_I_FREE_EXT_METABUFFER (VCD_START_BASE + 0x34)
 
 #define VCD_START_REQ      (VCD_START_BASE + 0x1000)
 #define VCD_I_REQ_IFRAME   (VCD_START_REQ + 0x1)
@@ -116,9 +123,12 @@
 #define VCD_METADATA_VC1            0x040
 #define VCD_METADATA_PASSTHROUGH    0x080
 #define VCD_METADATA_ENC_SLICE      0x100
+#define VCD_METADATA_LTR_INFO       0x200
 
 #define VCD_METADATA_EXT_DATA       0x0800
 #define VCD_METADATA_USER_DATA      0x1000
+#define VCD_METADATA_SEPARATE_BUF   0x2000
+
 
 struct vcd_property_meta_data_enable {
 	u32 meta_data_enable_flag;
@@ -389,4 +399,49 @@
 	u32 vui_timing_info;
 };
 
+struct vcd_property_range_type {
+	u32 min;
+	u32 max;
+	u32 step_size;
+};
+
+enum vcd_property_ltrmode {
+	VCD_LTR_MODE_DISABLE = 0,
+	VCD_LTR_MODE_MANUAL  = 1,
+	VCD_LTR_MODE_AUTO    = 2,
+	VCD_LTR_MODE_MAX     = 0x7fffffff
+};
+
+struct vcd_property_ltrmode_type {
+	enum vcd_property_ltrmode ltr_mode;
+};
+
+struct vcd_property_ltrcount_type {
+	u32 ltr_count;
+};
+
+struct vcd_property_ltrperiod_type {
+	u32 ltr_period;
+};
+
+struct vcd_property_ltruse_type {
+	u32 ltr_id;
+	u32 ltr_frames;
+};
+
+struct vcd_property_meta_buffer {
+	u8 *kernel_virtual_addr;
+	u8 *physical_addr;
+	u32 size;
+	u32 count;
+	int pmem_fd;
+	u32 offset;
+	u8 *dev_addr;
+	void *client_data;
+	u8 *kernel_virt_addr_iommu;
+	u8 *physical_addr_iommu;
+	int pmem_fd_iommu;
+	u8 *dev_addr_iommu;
+	void *client_data_iommu;
+};
 #endif
diff --git a/include/media/msm/vcd_status.h b/include/media/msm/vcd_status.h
index 7e8ec0b..631501d 100644
--- a/include/media/msm/vcd_status.h
+++ b/include/media/msm/vcd_status.h
@@ -33,6 +33,7 @@
 #define VCD_EVT_IND_RESOURCES_LOST        (VCD_EVT_IND_BASE + 0x4)
 #define VCD_EVT_IND_INFO_OUTPUT_RECONFIG  (VCD_EVT_IND_BASE + 0x5)
 #define VCD_EVT_IND_INFO_FIELD_DROPPED    (VCD_EVT_IND_BASE + 0x6)
+#define VCD_EVT_IND_INFO_LTRUSE_FAILED    (VCD_EVT_IND_BASE + 0x7)
 
 #define VCD_S_SUCCESS           0x0
 
diff --git a/include/media/msm/vidc_init.h b/include/media/msm/vidc_init.h
index f7d4e58..aff231d 100644
--- a/include/media/msm/vidc_init.h
+++ b/include/media/msm/vidc_init.h
@@ -19,6 +19,7 @@
 
 #define VIDC_MAX_NUM_CLIENTS 4
 #define MAX_VIDEO_NUM_OF_BUFF 100
+#define MAX_META_BUFFERS 32
 
 enum buffer_dir {
 	BUFFER_TYPE_INPUT,
@@ -37,6 +38,11 @@
 	void *client_data;
 };
 
+struct meta_buffer_addr_table {
+	u8 *kernel_vir_addr;
+	u8 *kernel_vir_addr_iommu;
+};
+
 struct video_client_ctx {
 	void *vcd_handle;
 	u32 num_of_input_buffers;
@@ -49,17 +55,22 @@
 	wait_queue_head_t msg_wait;
 	struct completion event;
 	struct vcd_property_h264_mv_buffer vcd_h264_mv_buffer;
+	struct vcd_property_meta_buffer vcd_meta_buffer;
 	struct vcd_property_enc_recon_buffer recon_buffer[4];
 	u32 event_status;
 	u32 seq_header_set;
 	u32 stop_msg;
 	u32 stop_called;
 	u32 stop_sync_cb;
+	size_t meta_buf_size;
 	struct ion_client *user_ion_client;
 	struct ion_handle *seq_hdr_ion_handle;
 	struct ion_handle *h264_mv_ion_handle;
 	struct ion_handle *recon_buffer_ion_handle[4];
+	struct ion_handle *meta_buffer_ion_handle;
+	struct ion_handle *meta_buffer_iommu_ion_handle;
 	u32 dmx_disable;
+	struct meta_buffer_addr_table meta_addr_table[MAX_META_BUFFERS];
 };
 
 void __iomem *vidc_get_ioaddr(void);
diff --git a/include/media/msm/vidc_type.h b/include/media/msm/vidc_type.h
index d4db0a0..809ec00 100644
--- a/include/media/msm/vidc_type.h
+++ b/include/media/msm/vidc_type.h
@@ -23,8 +23,9 @@
 #include <linux/dma-mapping.h>
 #include <linux/android_pmem.h>
 
-#define DEBUG   0
+#define DDL_MSG_LOG 0
+#define DEBUG 0
 #define VIDC_ENABLE_DBGFS
-
 #define USE_RES_TRACKER
+
 #endif
diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h
index 80f36e0..3a7cd5d 100644
--- a/include/net/bluetooth/hci.h
+++ b/include/net/bluetooth/hci.h
@@ -412,6 +412,11 @@
 	__le16   handle;
 } __packed;
 
+#define HCI_OP_READ_CLOCK_OFFSET	0x041f
+struct hci_cp_read_clock_offset {
+	__le16   handle;
+} __packed;
+
 #define HCI_OP_SETUP_SYNC_CONN		0x0428
 struct hci_cp_setup_sync_conn {
 	__le16   handle;
diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index 544f3bf..d55ec26 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -383,7 +383,7 @@
 
 /* ----- Inquiry cache ----- */
 #define INQUIRY_CACHE_AGE_MAX   (HZ*30)   /* 30 seconds */
-#define INQUIRY_ENTRY_AGE_MAX   (HZ*60)   /* 60 seconds */
+#define INQUIRY_ENTRY_AGE_MAX   (HZ*60*60)   /* 1 Hour */
 
 #define inquiry_cache_lock(c)		spin_lock(&c->lock)
 #define inquiry_cache_unlock(c)		spin_unlock(&c->lock)
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/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/madvise.c b/mm/madvise.c
index 1ccbba5..55f645c 100644
--- a/mm/madvise.c
+++ b/mm/madvise.c
@@ -13,6 +13,7 @@
 #include <linux/hugetlb.h>
 #include <linux/sched.h>
 #include <linux/ksm.h>
+#include <linux/file.h>
 
 /*
  * Any behaviour which results in changes to the vma->vm_flags needs to
@@ -203,14 +204,16 @@
 	struct address_space *mapping;
 	loff_t offset, endoff;
 	int error;
+	struct file *f;
 
 	*prev = NULL;	/* tell sys_madvise we drop mmap_sem */
 
 	if (vma->vm_flags & (VM_LOCKED|VM_NONLINEAR|VM_HUGETLB))
 		return -EINVAL;
 
-	if (!vma->vm_file || !vma->vm_file->f_mapping
-		|| !vma->vm_file->f_mapping->host) {
+	f = vma->vm_file;
+
+	if (!f || !f->f_mapping || !f->f_mapping->host) {
 			return -EINVAL;
 	}
 
@@ -224,9 +227,16 @@
 	endoff = (loff_t)(end - vma->vm_start - 1)
 			+ ((loff_t)vma->vm_pgoff << PAGE_SHIFT);
 
-	/* vmtruncate_range needs to take i_mutex */
+	/*
+	 * vmtruncate_range may need to take i_mutex.  We need to
+	 * explicitly grab a reference because the vma (and hence the
+	 * vma's reference to the file) can go away as soon as we drop
+	 * mmap_sem.
+	 */
+	get_file(f);
 	up_read(&current->mm->mmap_sem);
 	error = vmtruncate_range(mapping->host, offset, endoff);
+	fput(f);
 	down_read(&current->mm->mmap_sem);
 	return error;
 }
diff --git a/net/bluetooth/bnep/core.c b/net/bluetooth/bnep/core.c
index 5ac5c52..f504921 100644
--- a/net/bluetooth/bnep/core.c
+++ b/net/bluetooth/bnep/core.c
@@ -56,9 +56,6 @@
 #include "bnep.h"
 
 #define VERSION "1.3"
-/* As this feature is dummy for BNEP net device
-** disabling support */
-#undef CONFIG_BT_BNEP_MC_FILTER
 
 static bool compress_src = 1;
 static bool compress_dst = 1;
diff --git a/net/bluetooth/bnep/netdev.c b/net/bluetooth/bnep/netdev.c
index a8e5449..155ff74 100644
--- a/net/bluetooth/bnep/netdev.c
+++ b/net/bluetooth/bnep/netdev.c
@@ -44,9 +44,6 @@
 #include "bnep.h"
 
 #define BNEP_TX_QUEUE_LEN 20
-/* As this feature is dummy for BNEP net device
-** disabling support */
-#undef CONFIG_BT_BNEP_MC_FILTER
 
 static int bnep_net_open(struct net_device *dev)
 {
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/hci_event.c b/net/bluetooth/hci_event.c
index ea116e9..15d3585 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -1,6 +1,6 @@
 /*
    BlueZ - Bluetooth protocol stack for Linux
-   Copyright (c) 2000-2001, 2010-2012, Code Aurora Forum. All rights reserved.
+   Copyright (c) 2000-2001, 2010-2012 The Linux Foundation. All rights reserved.
 
    Written 2000,2001 by Maxim Krasnyansky <maxk@qualcomm.com>
 
@@ -1669,6 +1669,8 @@
 		if (conn->type == ACL_LINK) {
 			struct hci_cp_read_remote_version cp;
 			cp.handle = ev->handle;
+			hci_send_cmd(hdev, HCI_OP_READ_CLOCK_OFFSET,
+				sizeof(cp), &cp);
 			hci_send_cmd(hdev, HCI_OP_READ_REMOTE_VERSION,
 				sizeof(cp), &cp);
 		}
@@ -2667,12 +2669,6 @@
 		BT_DBG("Conn pending sec level is %d, ssp is %d, key len is %d",
 			conn->pending_sec_level, conn->ssp_mode, key->pin_len);
 	}
-	if (conn && (conn->ssp_mode == 0) &&
-		(conn->pending_sec_level == BT_SECURITY_HIGH) &&
-		(key->pin_len != 16)) {
-		BT_DBG("Security is high ignoring this key");
-		goto not_found;
-	}
 
 	if (key->key_type == 0x04 && conn && conn->auth_type != 0xff &&
 						(conn->auth_type & 0x01)) {
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/Kconfig b/sound/soc/codecs/Kconfig
index 1b46499..df34213 100644
--- a/sound/soc/codecs/Kconfig
+++ b/sound/soc/codecs/Kconfig
@@ -295,6 +295,9 @@
 config SND_SOC_WCD9320
         tristate
 
+config SND_SOC_WCD9306
+        tristate
+
 config SND_SOC_WL1273
 	tristate
 
diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile
index 42121fe..11338aa 100644
--- a/sound/soc/codecs/Makefile
+++ b/sound/soc/codecs/Makefile
@@ -52,6 +52,7 @@
 snd-soc-wcd9310-objs := wcd9310.o wcd9310-tables.o
 snd-soc-cs8427-objs := cs8427.o
 snd-soc-wcd9320-objs := wcd9xxx-resmgr.o wcd9320.o wcd9320-tables.o wcd9xxx-mbhc.o
+snd-soc-wcd9306-objs := wcd9xxx-resmgr.o wcd9306.o wcd9306-tables.o wcd9xxx-mbhc.o
 snd-soc-wl1273-objs := wl1273.o
 snd-soc-wm1250-ev1-objs := wm1250-ev1.o
 snd-soc-wm2000-objs := wm2000.o
@@ -162,6 +163,7 @@
 obj-$(CONFIG_SND_SOC_WCD9310)	+= snd-soc-wcd9310.o
 obj-$(CONFIG_SND_SOC_CS8427)	+= snd-soc-cs8427.o
 obj-$(CONFIG_SND_SOC_WCD9320)	+= snd-soc-wcd9320.o
+obj-$(CONFIG_SND_SOC_WCD9306)	+= snd-soc-wcd9306.o
 obj-$(CONFIG_SND_SOC_WL1273)	+= snd-soc-wl1273.o
 obj-$(CONFIG_SND_SOC_WM1250_EV1) += snd-soc-wm1250-ev1.o
 obj-$(CONFIG_SND_SOC_WM2000)	+= snd-soc-wm2000.o
diff --git a/sound/soc/codecs/wcd9304.c b/sound/soc/codecs/wcd9304.c
index 3fc3f32..0d5771b 100644
--- a/sound/soc/codecs/wcd9304.c
+++ b/sound/soc/codecs/wcd9304.c
@@ -1919,7 +1919,7 @@
 				     int mask)
 {
 	/* XXX: wake_lock_timeout()? */
-	snd_soc_jack_report(jack, status, mask);
+	snd_soc_jack_report_no_dapm(jack, status, mask);
 }
 
 static void hphocp_off_report(struct sitar_priv *sitar,
diff --git a/sound/soc/codecs/wcd9306-tables.c b/sound/soc/codecs/wcd9306-tables.c
new file mode 100644
index 0000000..21c5636
--- /dev/null
+++ b/sound/soc/codecs/wcd9306-tables.c
@@ -0,0 +1,1015 @@
+/* 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/mfd/wcd9xxx/wcd9306_registers.h>
+#include "wcd9306.h"
+
+const u8 tapan_reg_readable[TAPAN_CACHE_SIZE] = {
+	[TAPAN_A_CHIP_CTL] = 1,
+	[TAPAN_A_CHIP_STATUS] = 1,
+	[TAPAN_A_CHIP_ID_BYTE_0] = 1,
+	[TAPAN_A_CHIP_ID_BYTE_1] = 1,
+	[TAPAN_A_CHIP_ID_BYTE_2] = 1,
+	[TAPAN_A_CHIP_ID_BYTE_3] = 1,
+	[TAPAN_A_CHIP_VERSION] = 1,
+	[TAPAN_A_CHIP_DEBUG_CTL] = 1,
+	[TAPAN_A_SLAVE_ID_1] = 1,
+	[TAPAN_A_SLAVE_ID_2] = 1,
+	[TAPAN_A_SLAVE_ID_3] = 1,
+	[TAPAN_A_PIN_CTL_OE0] = 1,
+	[TAPAN_A_PIN_CTL_DATA0] = 1,
+	[TAPAN_A_HDRIVE_GENERIC] = 1,
+	[TAPAN_A_HDRIVE_OVERRIDE] = 1,
+	[TAPAN_A_ANA_CSR_WAIT_STATE] = 1,
+	[TAPAN_A_PROCESS_MONITOR_CTL0] = 1,
+	[TAPAN_A_PROCESS_MONITOR_CTL1] = 1,
+	[TAPAN_A_PROCESS_MONITOR_CTL2] = 1,
+	[TAPAN_A_PROCESS_MONITOR_CTL3] = 1,
+	[TAPAN_A_QFUSE_CTL] = 1,
+	[TAPAN_A_QFUSE_STATUS] = 1,
+	[TAPAN_A_QFUSE_DATA_OUT0] = 1,
+	[TAPAN_A_QFUSE_DATA_OUT1] = 1,
+	[TAPAN_A_QFUSE_DATA_OUT2] = 1,
+	[TAPAN_A_QFUSE_DATA_OUT3] = 1,
+	[TAPAN_A_QFUSE_DATA_OUT4] = 1,
+	[TAPAN_A_QFUSE_DATA_OUT5] = 1,
+	[TAPAN_A_QFUSE_DATA_OUT6] = 1,
+	[TAPAN_A_QFUSE_DATA_OUT7] = 1,
+	[TAPAN_A_CDC_CTL] = 1,
+	[TAPAN_A_LEAKAGE_CTL] = 1,
+	[TAPAN_A_INTR_MODE] = 1,
+	[TAPAN_A_INTR_MASK0] = 1,
+	[TAPAN_A_INTR_MASK1] = 1,
+	[TAPAN_A_INTR_MASK2] = 1,
+	[TAPAN_A_INTR_MASK3] = 1,
+	[TAPAN_A_INTR_STATUS0] = 1,
+	[TAPAN_A_INTR_STATUS1] = 1,
+	[TAPAN_A_INTR_STATUS2] = 1,
+	[TAPAN_A_INTR_STATUS3] = 1,
+	[TAPAN_A_INTR_CLEAR0] = 0,
+	[TAPAN_A_INTR_CLEAR1] = 0,
+	[TAPAN_A_INTR_CLEAR2] = 0,
+	[TAPAN_A_INTR_CLEAR3] = 0,
+	[TAPAN_A_INTR_LEVEL0] = 1,
+	[TAPAN_A_INTR_LEVEL1] = 1,
+	[TAPAN_A_INTR_LEVEL2] = 1,
+	[TAPAN_A_INTR_LEVEL3] = 1,
+	[TAPAN_A_INTR_TEST0] = 1,
+	[TAPAN_A_INTR_TEST1] = 1,
+	[TAPAN_A_INTR_TEST2] = 1,
+	[TAPAN_A_INTR_TEST3] = 1,
+	[TAPAN_A_INTR_SET0] = 1,
+	[TAPAN_A_INTR_SET1] = 1,
+	[TAPAN_A_INTR_SET2] = 1,
+	[TAPAN_A_INTR_SET3] = 1,
+	[TAPAN_A_INTR_DESTN0] = 1,
+	[TAPAN_A_INTR_DESTN1] = 1,
+	[TAPAN_A_INTR_DESTN2] = 1,
+	[TAPAN_A_INTR_DESTN3] = 1,
+	[TAPAN_A_CDC_DMIC_DATA0_MODE] = 1,
+	[TAPAN_A_CDC_DMIC_CLK0_MODE] = 1,
+	[TAPAN_A_CDC_DMIC_DATA1_MODE] = 1,
+	[TAPAN_A_CDC_DMIC_CLK1_MODE] = 1,
+	[TAPAN_A_CDC_INTR_MODE] = 1,
+	[TAPAN_A_BIAS_REF_CTL] = 1,
+	[TAPAN_A_BIAS_CENTRAL_BG_CTL] = 1,
+	[TAPAN_A_BIAS_PRECHRG_CTL] = 1,
+	[TAPAN_A_BIAS_CURR_CTL_1] = 1,
+	[TAPAN_A_BIAS_CURR_CTL_2] = 1,
+	[TAPAN_A_BIAS_OSC_BG_CTL] = 1,
+	[TAPAN_A_CLK_BUFF_EN1] = 1,
+	[TAPAN_A_CLK_BUFF_EN2] = 1,
+	[TAPAN_A_LDO_H_MODE_1] = 1,
+	[TAPAN_A_LDO_H_MODE_2] = 1,
+	[TAPAN_A_LDO_H_LOOP_CTL] = 1,
+	[TAPAN_A_LDO_H_COMP_1] = 1,
+	[TAPAN_A_LDO_H_COMP_2] = 1,
+	[TAPAN_A_LDO_H_BIAS_1] = 1,
+	[TAPAN_A_LDO_H_BIAS_2] = 1,
+	[TAPAN_A_LDO_H_BIAS_3] = 1,
+	[TAPAN_A_MICB_CFILT_1_CTL] = 1,
+	[TAPAN_A_MICB_CFILT_1_VAL] = 1,
+	[TAPAN_A_MICB_CFILT_1_PRECHRG] = 1,
+	[TAPAN_A_MICB_1_CTL] = 1,
+	[TAPAN_A_MICB_1_INT_RBIAS] = 1,
+	[TAPAN_A_MICB_1_MBHC] = 1,
+	[TAPAN_A_MICB_CFILT_2_CTL] = 1,
+	[TAPAN_A_MICB_CFILT_2_VAL] = 1,
+	[TAPAN_A_MICB_CFILT_2_PRECHRG] = 1,
+	[TAPAN_A_MICB_2_CTL] = 1,
+	[TAPAN_A_MICB_2_INT_RBIAS] = 1,
+	[TAPAN_A_MICB_2_MBHC] = 1,
+	[TAPAN_A_MICB_CFILT_3_CTL] = 1,
+	[TAPAN_A_MICB_CFILT_3_VAL] = 1,
+	[TAPAN_A_MICB_CFILT_3_PRECHRG] = 1,
+	[TAPAN_A_MICB_3_CTL] = 1,
+	[TAPAN_A_MICB_3_INT_RBIAS] = 1,
+	[TAPAN_A_MICB_3_MBHC] = 1,
+	[TAPAN_A_MBHC_INSERT_DETECT] = 1,
+	[TAPAN_A_MBHC_INSERT_DET_STATUS] = 1,
+	[TAPAN_A_TX_COM_BIAS] = 1,
+	[TAPAN_A_MBHC_SCALING_MUX_1] = 1,
+	[TAPAN_A_MBHC_SCALING_MUX_2] = 1,
+	[TAPAN_A_RESERVED_MAD_ANA_CTRL] = 1,
+	[TAPAN_A_TX_SUP_SWITCH_CTRL_1] = 1,
+	[TAPAN_A_TX_SUP_SWITCH_CTRL_2] = 1,
+	[TAPAN_A_TX_1_EN] = 1,
+	[TAPAN_A_TX_2_EN] = 1,
+	[TAPAN_A_TX_1_2_ADC_CH1] = 1,
+	[TAPAN_A_TX_1_2_ADC_CH2] = 1,
+	[TAPAN_A_TX_1_2_ATEST_REFCTRL] = 1,
+	[TAPAN_A_TX_1_2_TEST_CTL] = 1,
+	[TAPAN_A_TX_1_2_TEST_BLOCK_EN] = 1,
+	[TAPAN_A_TX_1_2_TXFE_CLKDIV] = 1,
+	[TAPAN_A_TX_1_2_SAR_ERR_CH1] = 1,
+	[TAPAN_A_TX_1_2_SAR_ERR_CH2] = 1,
+	[TAPAN_A_TX_3_EN] = 1,
+	[TAPAN_A_TX_1_2_TEST_EN] = 1,
+	[TAPAN_A_TX_4_5_TXFE_SC_CTL] = 1,
+	[TAPAN_A_TX_4_5_TEST_EN] = 1,
+	[TAPAN_A_TX_4_EN] = 1,
+	[TAPAN_A_TX_5_EN] = 1,
+	[TAPAN_A_TX_4_5_ADC_CH4] = 1,
+	[TAPAN_A_TX_4_5_ADC_CH5] = 1,
+	[TAPAN_A_TX_4_5_ATEST_REFCTRL] = 1,
+	[TAPAN_A_TX_4_5_TEST_CTL] = 1,
+	[TAPAN_A_TX_4_5_TEST_BLOCK_EN] = 1,
+	[TAPAN_A_TX_4_5_TXFE_CKDIV] = 1,
+	[TAPAN_A_TX_4_5_SAR_ERR_CH4] = 1,
+	[TAPAN_A_TX_4_5_SAR_ERR_CH5] = 1,
+	[TAPAN_A_TX_7_MBHC_EN] = 1,
+	[TAPAN_A_TX_7_MBHC_ATEST_REFCTRL] = 1,
+	[TAPAN_A_TX_7_MBHC_ADC] = 1,
+	[TAPAN_A_TX_7_MBHC_TEST_CTL] = 1,
+	[TAPAN_A_TX_7_MBHC_SAR_ERR] = 1,
+	[TAPAN_A_TX_7_TXFE_CLKDIV] = 1,
+	[TAPAN_A_BUCK_MODE_1] = 1,
+	[TAPAN_A_BUCK_MODE_2] = 1,
+	[TAPAN_A_BUCK_MODE_3] = 1,
+	[TAPAN_A_BUCK_MODE_4] = 1,
+	[TAPAN_A_BUCK_MODE_5] = 1,
+	[TAPAN_A_BUCK_CTRL_VCL_1] = 1,
+	[TAPAN_A_BUCK_CTRL_VCL_2] = 1,
+	[TAPAN_A_BUCK_CTRL_VCL_3] = 1,
+	[TAPAN_A_BUCK_CTRL_CCL_1] = 1,
+	[TAPAN_A_BUCK_CTRL_CCL_2] = 1,
+	[TAPAN_A_BUCK_CTRL_CCL_3] = 1,
+	[TAPAN_A_BUCK_CTRL_CCL_4] = 1,
+	[TAPAN_A_BUCK_CTRL_PWM_DRVR_1] = 1,
+	[TAPAN_A_BUCK_CTRL_PWM_DRVR_2] = 1,
+	[TAPAN_A_BUCK_CTRL_PWM_DRVR_3] = 1,
+	[TAPAN_A_BUCK_TMUX_A_D] = 1,
+	[TAPAN_A_NCP_BUCKREF] = 1,
+	[TAPAN_A_NCP_EN] = 1,
+	[TAPAN_A_NCP_CLK] = 1,
+	[TAPAN_A_NCP_STATIC] = 1,
+	[TAPAN_A_NCP_VTH_LOW] = 1,
+	[TAPAN_A_NCP_VTH_HIGH] = 1,
+	[TAPAN_A_NCP_ATEST] = 1,
+	[TAPAN_A_NCP_DTEST] = 1,
+	[TAPAN_A_NCP_DLY1] = 1,
+	[TAPAN_A_NCP_DLY2] = 1,
+	[TAPAN_A_RX_AUX_SW_CTL] = 1,
+	[TAPAN_A_RX_PA_AUX_IN_CONN] = 1,
+	[TAPAN_A_RX_COM_TIMER_DIV] = 1,
+	[TAPAN_A_RX_COM_OCP_CTL] = 1,
+	[TAPAN_A_RX_COM_OCP_COUNT] = 1,
+	[TAPAN_A_RX_COM_DAC_CTL] = 1,
+	[TAPAN_A_RX_COM_BIAS] = 1,
+	[TAPAN_A_RX_HPH_AUTO_CHOP] = 1,
+	[TAPAN_A_RX_HPH_CHOP_CTL] = 1,
+	[TAPAN_A_RX_HPH_BIAS_PA] = 1,
+	[TAPAN_A_RX_HPH_BIAS_LDO] = 1,
+	[TAPAN_A_RX_HPH_BIAS_CNP] = 1,
+	[TAPAN_A_RX_HPH_BIAS_WG_OCP] = 1,
+	[TAPAN_A_RX_HPH_OCP_CTL] = 1,
+	[TAPAN_A_RX_HPH_CNP_EN] = 1,
+	[TAPAN_A_RX_HPH_CNP_WG_CTL] = 1,
+	[TAPAN_A_RX_HPH_CNP_WG_TIME] = 1,
+	[TAPAN_A_RX_HPH_L_GAIN] = 1,
+	[TAPAN_A_RX_HPH_L_TEST] = 1,
+	[TAPAN_A_RX_HPH_L_PA_CTL] = 1,
+	[TAPAN_A_RX_HPH_L_DAC_CTL] = 1,
+	[TAPAN_A_RX_HPH_L_ATEST] = 1,
+	[TAPAN_A_RX_HPH_L_STATUS] = 1,
+	[TAPAN_A_RX_HPH_R_GAIN] = 1,
+	[TAPAN_A_RX_HPH_R_TEST] = 1,
+	[TAPAN_A_RX_HPH_R_PA_CTL] = 1,
+	[TAPAN_A_RX_HPH_R_DAC_CTL] = 1,
+	[TAPAN_A_RX_HPH_R_ATEST] = 1,
+	[TAPAN_A_RX_HPH_R_STATUS] = 1,
+	[TAPAN_A_RX_EAR_BIAS_PA] = 1,
+	[TAPAN_A_RX_EAR_BIAS_CMBUFF] = 1,
+	[TAPAN_A_RX_EAR_EN] = 1,
+	[TAPAN_A_RX_EAR_GAIN] = 1,
+	[TAPAN_A_RX_EAR_CMBUFF] = 1,
+	[TAPAN_A_RX_EAR_ICTL] = 1,
+	[TAPAN_A_RX_EAR_CCOMP] = 1,
+	[TAPAN_A_RX_EAR_VCM] = 1,
+	[TAPAN_A_RX_EAR_CNP] = 1,
+	[TAPAN_A_RX_EAR_DAC_CTL_ATEST] = 1,
+	[TAPAN_A_RX_EAR_STATUS] = 1,
+	[TAPAN_A_RX_LINE_BIAS_PA] = 1,
+	[TAPAN_A_RX_BUCK_BIAS1] = 1,
+	[TAPAN_A_RX_BUCK_BIAS2] = 1,
+	[TAPAN_A_RX_LINE_COM] = 1,
+	[TAPAN_A_RX_LINE_CNP_EN] = 1,
+	[TAPAN_A_RX_LINE_CNP_WG_CTL] = 1,
+	[TAPAN_A_RX_LINE_CNP_WG_TIME] = 1,
+	[TAPAN_A_RX_LINE_1_GAIN] = 1,
+	[TAPAN_A_RX_LINE_1_TEST] = 1,
+	[TAPAN_A_RX_LINE_1_DAC_CTL] = 1,
+	[TAPAN_A_RX_LINE_1_STATUS] = 1,
+	[TAPAN_A_RX_LINE_2_GAIN] = 1,
+	[TAPAN_A_RX_LINE_2_TEST] = 1,
+	[TAPAN_A_RX_LINE_2_DAC_CTL] = 1,
+	[TAPAN_A_RX_LINE_2_STATUS] = 1,
+	[TAPAN_A_RX_LINE_CNP_DBG] = 1,
+	[TAPAN_A_SPKR_DRV_EN] = 1,
+	[TAPAN_A_SPKR_DRV_GAIN] = 1,
+	[TAPAN_A_SPKR_DRV_DAC_CTL] = 1,
+	[TAPAN_A_SPKR_DRV_OCP_CTL] = 1,
+	[TAPAN_A_SPKR_DRV_CLIP_DET] = 1,
+	[TAPAN_A_SPKR_DRV_IEC] = 1,
+	[TAPAN_A_SPKR_DRV_DBG_DAC] = 1,
+	[TAPAN_A_SPKR_DRV_DBG_PA] = 1,
+	[TAPAN_A_SPKR_DRV_DBG_PWRSTG] = 1,
+	[TAPAN_A_SPKR_DRV_BIAS_LDO] = 1,
+	[TAPAN_A_SPKR_DRV_BIAS_INT] = 1,
+	[TAPAN_A_SPKR_DRV_BIAS_PA] = 1,
+	[TAPAN_A_SPKR_DRV_STATUS_OCP] = 1,
+	[TAPAN_A_SPKR_DRV_STATUS_PA] = 1,
+	[TAPAN_A_RC_OSC_FREQ] = 1,
+	[TAPAN_A_RC_OSC_TEST] = 1,
+	[TAPAN_A_RC_OSC_STATUS] = 1,
+	[TAPAN_A_RC_OSC_TUNER] = 1,
+	[TAPAN_A_MBHC_HPH] = 1,
+	[TAPAN_A_CDC_ANC1_B1_CTL] = 1,
+	[TAPAN_A_CDC_ANC2_B1_CTL] = 1,
+	[TAPAN_A_CDC_ANC1_SHIFT] = 1,
+	[TAPAN_A_CDC_ANC2_SHIFT] = 1,
+	[TAPAN_A_CDC_ANC1_IIR_B1_CTL] = 1,
+	[TAPAN_A_CDC_ANC2_IIR_B1_CTL] = 1,
+	[TAPAN_A_CDC_ANC1_IIR_B2_CTL] = 1,
+	[TAPAN_A_CDC_ANC2_IIR_B2_CTL] = 1,
+	[TAPAN_A_CDC_ANC1_IIR_B3_CTL] = 1,
+	[TAPAN_A_CDC_ANC2_IIR_B3_CTL] = 1,
+	[TAPAN_A_CDC_ANC1_LPF_B1_CTL] = 1,
+	[TAPAN_A_CDC_ANC2_LPF_B1_CTL] = 1,
+	[TAPAN_A_CDC_ANC1_LPF_B2_CTL] = 1,
+	[TAPAN_A_CDC_ANC2_LPF_B2_CTL] = 1,
+	[TAPAN_A_CDC_ANC1_SPARE] = 1,
+	[TAPAN_A_CDC_ANC2_SPARE] = 1,
+	[TAPAN_A_CDC_ANC1_SMLPF_CTL] = 1,
+	[TAPAN_A_CDC_ANC2_SMLPF_CTL] = 1,
+	[TAPAN_A_CDC_ANC1_DCFLT_CTL] = 1,
+	[TAPAN_A_CDC_ANC2_DCFLT_CTL] = 1,
+	[TAPAN_A_CDC_ANC1_GAIN_CTL] = 1,
+	[TAPAN_A_CDC_ANC2_GAIN_CTL] = 1,
+	[TAPAN_A_CDC_ANC1_B2_CTL] = 1,
+	[TAPAN_A_CDC_ANC2_B2_CTL] = 1,
+	[TAPAN_A_CDC_TX1_VOL_CTL_TIMER] = 1,
+	[TAPAN_A_CDC_TX2_VOL_CTL_TIMER] = 1,
+	[TAPAN_A_CDC_TX3_VOL_CTL_TIMER] = 1,
+	[TAPAN_A_CDC_TX4_VOL_CTL_TIMER] = 1,
+	[TAPAN_A_CDC_TX1_VOL_CTL_GAIN] = 1,
+	[TAPAN_A_CDC_TX2_VOL_CTL_GAIN] = 1,
+	[TAPAN_A_CDC_TX3_VOL_CTL_GAIN] = 1,
+	[TAPAN_A_CDC_TX4_VOL_CTL_GAIN] = 1,
+	[TAPAN_A_CDC_TX1_VOL_CTL_CFG] = 1,
+	[TAPAN_A_CDC_TX2_VOL_CTL_CFG] = 1,
+	[TAPAN_A_CDC_TX3_VOL_CTL_CFG] = 1,
+	[TAPAN_A_CDC_TX4_VOL_CTL_CFG] = 1,
+	[TAPAN_A_CDC_TX1_MUX_CTL] = 1,
+	[TAPAN_A_CDC_TX2_MUX_CTL] = 1,
+	[TAPAN_A_CDC_TX3_MUX_CTL] = 1,
+	[TAPAN_A_CDC_TX4_MUX_CTL] = 1,
+	[TAPAN_A_CDC_TX1_CLK_FS_CTL] = 1,
+	[TAPAN_A_CDC_TX2_CLK_FS_CTL] = 1,
+	[TAPAN_A_CDC_TX3_CLK_FS_CTL] = 1,
+	[TAPAN_A_CDC_TX4_CLK_FS_CTL] = 1,
+	[TAPAN_A_CDC_TX1_DMIC_CTL] = 1,
+	[TAPAN_A_CDC_TX2_DMIC_CTL] = 1,
+	[TAPAN_A_CDC_TX3_DMIC_CTL] = 1,
+	[TAPAN_A_CDC_TX4_DMIC_CTL] = 1,
+	[TAPAN_A_CDC_DEBUG_B1_CTL] = 1,
+	[TAPAN_A_CDC_DEBUG_B2_CTL] = 1,
+	[TAPAN_A_CDC_DEBUG_B3_CTL] = 1,
+	[TAPAN_A_CDC_DEBUG_B4_CTL] = 1,
+	[TAPAN_A_CDC_DEBUG_B5_CTL] = 1,
+	[TAPAN_A_CDC_DEBUG_B6_CTL] = 1,
+	[TAPAN_A_CDC_DEBUG_B7_CTL] = 1,
+	[TAPAN_A_CDC_SRC1_PDA_CFG] = 1,
+	[TAPAN_A_CDC_SRC2_PDA_CFG] = 1,
+	[TAPAN_A_CDC_SRC1_FS_CTL] = 1,
+	[TAPAN_A_CDC_SRC2_FS_CTL] = 1,
+	[TAPAN_A_CDC_RX1_B1_CTL] = 1,
+	[TAPAN_A_CDC_RX2_B1_CTL] = 1,
+	[TAPAN_A_CDC_RX3_B1_CTL] = 1,
+	[TAPAN_A_CDC_RX4_B1_CTL] = 1,
+	[TAPAN_A_CDC_RX1_B2_CTL] = 1,
+	[TAPAN_A_CDC_RX2_B2_CTL] = 1,
+	[TAPAN_A_CDC_RX3_B2_CTL] = 1,
+	[TAPAN_A_CDC_RX4_B2_CTL] = 1,
+	[TAPAN_A_CDC_RX1_B3_CTL] = 1,
+	[TAPAN_A_CDC_RX2_B3_CTL] = 1,
+	[TAPAN_A_CDC_RX3_B3_CTL] = 1,
+	[TAPAN_A_CDC_RX4_B3_CTL] = 1,
+	[TAPAN_A_CDC_RX1_B4_CTL] = 1,
+	[TAPAN_A_CDC_RX2_B4_CTL] = 1,
+	[TAPAN_A_CDC_RX3_B4_CTL] = 1,
+	[TAPAN_A_CDC_RX4_B4_CTL] = 1,
+	[TAPAN_A_CDC_RX1_B5_CTL] = 1,
+	[TAPAN_A_CDC_RX2_B5_CTL] = 1,
+	[TAPAN_A_CDC_RX3_B5_CTL] = 1,
+	[TAPAN_A_CDC_RX4_B5_CTL] = 1,
+	[TAPAN_A_CDC_RX1_B6_CTL] = 1,
+	[TAPAN_A_CDC_RX2_B6_CTL] = 1,
+	[TAPAN_A_CDC_RX3_B6_CTL] = 1,
+	[TAPAN_A_CDC_RX4_B6_CTL] = 1,
+	[TAPAN_A_CDC_RX1_VOL_CTL_B1_CTL] = 1,
+	[TAPAN_A_CDC_RX2_VOL_CTL_B1_CTL] = 1,
+	[TAPAN_A_CDC_RX3_VOL_CTL_B1_CTL] = 1,
+	[TAPAN_A_CDC_RX4_VOL_CTL_B1_CTL] = 1,
+	[TAPAN_A_CDC_RX1_VOL_CTL_B2_CTL] = 1,
+	[TAPAN_A_CDC_RX2_VOL_CTL_B2_CTL] = 1,
+	[TAPAN_A_CDC_RX3_VOL_CTL_B2_CTL] = 1,
+	[TAPAN_A_CDC_RX4_VOL_CTL_B2_CTL] = 1,
+	[TAPAN_A_CDC_CLK_ANC_RESET_CTL] = 1,
+	[TAPAN_A_CDC_CLK_RX_RESET_CTL] = 1,
+	[TAPAN_A_CDC_CLK_TX_RESET_B1_CTL] = 1,
+	[TAPAN_A_CDC_CLK_TX_RESET_B2_CTL] = 1,
+	[TAPAN_A_CDC_CLK_DMIC_B1_CTL] = 1,
+	[TAPAN_A_CDC_CLK_DMIC_B2_CTL] = 1,
+	[TAPAN_A_CDC_CLK_I2S_CTL] = 1,
+	[TAPAN_A_CDC_CLK_OTHR_RESET_B1_CTL] = 1,
+	[TAPAN_A_CDC_CLK_OTHR_RESET_B2_CTL] = 1,
+	[TAPAN_A_CDC_CLK_TX_CLK_EN_B1_CTL] = 1,
+	[TAPAN_A_CDC_CLK_TX_CLK_EN_B2_CTL] = 1,
+	[TAPAN_A_CDC_CLK_OTHR_CTL] = 1,
+	[TAPAN_A_CDC_CLK_RDAC_CLK_EN_CTL] = 1,
+	[TAPAN_A_CDC_CLK_ANC_CLK_EN_CTL] = 1,
+	[TAPAN_A_CDC_CLK_RX_B1_CTL] = 1,
+	[TAPAN_A_CDC_CLK_RX_B2_CTL] = 1,
+	[TAPAN_A_CDC_CLK_MCLK_CTL] = 1,
+	[TAPAN_A_CDC_CLK_PDM_CTL] = 1,
+	[TAPAN_A_CDC_CLK_SD_CTL] = 1,
+	[TAPAN_A_CDC_CLK_POWER_CTL] = 1,
+	[TAPAN_A_CDC_CLSH_B1_CTL] = 1,
+	[TAPAN_A_CDC_CLSH_B2_CTL] = 1,
+	[TAPAN_A_CDC_CLSH_B3_CTL] = 1,
+	[TAPAN_A_CDC_CLSH_BUCK_NCP_VARS] = 1,
+	[TAPAN_A_CDC_CLSH_IDLE_HPH_THSD] = 1,
+	[TAPAN_A_CDC_CLSH_IDLE_EAR_THSD] = 1,
+	[TAPAN_A_CDC_CLSH_FCLKONLY_HPH_THSD] = 1,
+	[TAPAN_A_CDC_CLSH_FCLKONLY_EAR_THSD] = 1,
+	[TAPAN_A_CDC_CLSH_K_ADDR] = 1,
+	[TAPAN_A_CDC_CLSH_K_DATA] = 1,
+	[TAPAN_A_CDC_CLSH_I_PA_FACT_HPH_L] = 1,
+	[TAPAN_A_CDC_CLSH_I_PA_FACT_HPH_U] = 1,
+	[TAPAN_A_CDC_CLSH_I_PA_FACT_EAR_L] = 1,
+	[TAPAN_A_CDC_CLSH_I_PA_FACT_EAR_U] = 1,
+	[TAPAN_A_CDC_CLSH_V_PA_HD_EAR] = 1,
+	[TAPAN_A_CDC_CLSH_V_PA_HD_HPH] = 1,
+	[TAPAN_A_CDC_CLSH_V_PA_MIN_EAR] = 1,
+	[TAPAN_A_CDC_CLSH_V_PA_MIN_HPH] = 1,
+	[TAPAN_A_CDC_IIR1_GAIN_B1_CTL] = 1,
+	[TAPAN_A_CDC_IIR2_GAIN_B1_CTL] = 1,
+	[TAPAN_A_CDC_IIR1_GAIN_B2_CTL] = 1,
+	[TAPAN_A_CDC_IIR2_GAIN_B2_CTL] = 1,
+	[TAPAN_A_CDC_IIR1_GAIN_B3_CTL] = 1,
+	[TAPAN_A_CDC_IIR2_GAIN_B3_CTL] = 1,
+	[TAPAN_A_CDC_IIR1_GAIN_B4_CTL] = 1,
+	[TAPAN_A_CDC_IIR2_GAIN_B4_CTL] = 1,
+	[TAPAN_A_CDC_IIR1_GAIN_B5_CTL] = 1,
+	[TAPAN_A_CDC_IIR2_GAIN_B5_CTL] = 1,
+	[TAPAN_A_CDC_IIR1_GAIN_B6_CTL] = 1,
+	[TAPAN_A_CDC_IIR2_GAIN_B6_CTL] = 1,
+	[TAPAN_A_CDC_IIR1_GAIN_B7_CTL] = 1,
+	[TAPAN_A_CDC_IIR2_GAIN_B7_CTL] = 1,
+	[TAPAN_A_CDC_IIR1_GAIN_B8_CTL] = 1,
+	[TAPAN_A_CDC_IIR2_GAIN_B8_CTL] = 1,
+	[TAPAN_A_CDC_IIR1_CTL] = 1,
+	[TAPAN_A_CDC_IIR2_CTL] = 1,
+	[TAPAN_A_CDC_IIR1_GAIN_TIMER_CTL] = 1,
+	[TAPAN_A_CDC_IIR2_GAIN_TIMER_CTL] = 1,
+	[TAPAN_A_CDC_IIR1_COEF_B1_CTL] = 1,
+	[TAPAN_A_CDC_IIR2_COEF_B1_CTL] = 1,
+	[TAPAN_A_CDC_IIR1_COEF_B2_CTL] = 1,
+	[TAPAN_A_CDC_IIR2_COEF_B2_CTL] = 1,
+	[TAPAN_A_CDC_TOP_GAIN_UPDATE] = 1,
+	[TAPAN_A_CDC_COMP0_B1_CTL] = 1,
+	[TAPAN_A_CDC_COMP1_B1_CTL] = 1,
+	[TAPAN_A_CDC_COMP2_B1_CTL] = 1,
+	[TAPAN_A_CDC_COMP0_B2_CTL] = 1,
+	[TAPAN_A_CDC_COMP1_B2_CTL] = 1,
+	[TAPAN_A_CDC_COMP2_B2_CTL] = 1,
+	[TAPAN_A_CDC_COMP0_B3_CTL] = 1,
+	[TAPAN_A_CDC_COMP1_B3_CTL] = 1,
+	[TAPAN_A_CDC_COMP2_B3_CTL] = 1,
+	[TAPAN_A_CDC_COMP0_B4_CTL] = 1,
+	[TAPAN_A_CDC_COMP1_B4_CTL] = 1,
+	[TAPAN_A_CDC_COMP2_B4_CTL] = 1,
+	[TAPAN_A_CDC_COMP0_B5_CTL] = 1,
+	[TAPAN_A_CDC_COMP1_B5_CTL] = 1,
+	[TAPAN_A_CDC_COMP2_B5_CTL] = 1,
+	[TAPAN_A_CDC_COMP0_B6_CTL] = 1,
+	[TAPAN_A_CDC_COMP1_B6_CTL] = 1,
+	[TAPAN_A_CDC_COMP2_B6_CTL] = 1,
+	[TAPAN_A_CDC_COMP0_SHUT_DOWN_STATUS] = 1,
+	[TAPAN_A_CDC_COMP1_SHUT_DOWN_STATUS] = 1,
+	[TAPAN_A_CDC_COMP2_SHUT_DOWN_STATUS] = 1,
+	[TAPAN_A_CDC_COMP0_FS_CFG] = 1,
+	[TAPAN_A_CDC_COMP1_FS_CFG] = 1,
+	[TAPAN_A_CDC_COMP2_FS_CFG] = 1,
+	[TAPAN_A_CDC_CONN_RX1_B1_CTL] = 1,
+	[TAPAN_A_CDC_CONN_RX1_B2_CTL] = 1,
+	[TAPAN_A_CDC_CONN_RX1_B3_CTL] = 1,
+	[TAPAN_A_CDC_CONN_RX2_B1_CTL] = 1,
+	[TAPAN_A_CDC_CONN_RX2_B2_CTL] = 1,
+	[TAPAN_A_CDC_CONN_RX2_B3_CTL] = 1,
+	[TAPAN_A_CDC_CONN_RX3_B1_CTL] = 1,
+	[TAPAN_A_CDC_CONN_RX3_B2_CTL] = 1,
+	[TAPAN_A_CDC_CONN_RX4_B1_CTL] = 1,
+	[TAPAN_A_CDC_CONN_RX4_B2_CTL] = 1,
+	[TAPAN_A_CDC_CONN_RX4_B3_CTL] = 1,
+	[TAPAN_A_CDC_CONN_ANC_B1_CTL] = 1,
+	[TAPAN_A_CDC_CONN_ANC_B2_CTL] = 1,
+	[TAPAN_A_CDC_CONN_TX_B1_CTL] = 1,
+	[TAPAN_A_CDC_CONN_TX_B2_CTL] = 1,
+	[TAPAN_A_CDC_CONN_TX_B3_CTL] = 1,
+	[TAPAN_A_CDC_CONN_TX_B4_CTL] = 1,
+	[TAPAN_A_CDC_CONN_EQ1_B1_CTL] = 1,
+	[TAPAN_A_CDC_CONN_EQ1_B2_CTL] = 1,
+	[TAPAN_A_CDC_CONN_EQ1_B3_CTL] = 1,
+	[TAPAN_A_CDC_CONN_EQ1_B4_CTL] = 1,
+	[TAPAN_A_CDC_CONN_EQ2_B1_CTL] = 1,
+	[TAPAN_A_CDC_CONN_EQ2_B2_CTL] = 1,
+	[TAPAN_A_CDC_CONN_EQ2_B3_CTL] = 1,
+	[TAPAN_A_CDC_CONN_EQ2_B4_CTL] = 1,
+	[TAPAN_A_CDC_CONN_SRC1_B1_CTL] = 1,
+	[TAPAN_A_CDC_CONN_SRC1_B2_CTL] = 1,
+	[TAPAN_A_CDC_CONN_SRC2_B1_CTL] = 1,
+	[TAPAN_A_CDC_CONN_SRC2_B2_CTL] = 1,
+	[TAPAN_A_CDC_CONN_TX_SB_B1_CTL] = 1,
+	[TAPAN_A_CDC_CONN_TX_SB_B2_CTL] = 1,
+	[TAPAN_A_CDC_CONN_TX_SB_B3_CTL] = 1,
+	[TAPAN_A_CDC_CONN_TX_SB_B4_CTL] = 1,
+	[TAPAN_A_CDC_CONN_TX_SB_B5_CTL] = 1,
+	[TAPAN_A_CDC_CONN_TX_SB_B11_CTL] = 1,
+	[TAPAN_A_CDC_CONN_RX_SB_B1_CTL] = 1,
+	[TAPAN_A_CDC_CONN_RX_SB_B2_CTL] = 1,
+	[TAPAN_A_CDC_CONN_CLSH_CTL] = 1,
+	[TAPAN_A_CDC_CONN_MISC] = 1,
+	[TAPAN_A_CDC_MBHC_EN_CTL] = 1,
+	[TAPAN_A_CDC_MBHC_FIR_B1_CFG] = 1,
+	[TAPAN_A_CDC_MBHC_FIR_B2_CFG] = 1,
+	[TAPAN_A_CDC_MBHC_TIMER_B1_CTL] = 1,
+	[TAPAN_A_CDC_MBHC_TIMER_B2_CTL] = 1,
+	[TAPAN_A_CDC_MBHC_TIMER_B3_CTL] = 1,
+	[TAPAN_A_CDC_MBHC_TIMER_B4_CTL] = 1,
+	[TAPAN_A_CDC_MBHC_TIMER_B5_CTL] = 1,
+	[TAPAN_A_CDC_MBHC_TIMER_B6_CTL] = 1,
+	[TAPAN_A_CDC_MBHC_B1_STATUS] = 1,
+	[TAPAN_A_CDC_MBHC_B2_STATUS] = 1,
+	[TAPAN_A_CDC_MBHC_B3_STATUS] = 1,
+	[TAPAN_A_CDC_MBHC_B4_STATUS] = 1,
+	[TAPAN_A_CDC_MBHC_B5_STATUS] = 1,
+	[TAPAN_A_CDC_MBHC_B1_CTL] = 1,
+	[TAPAN_A_CDC_MBHC_B2_CTL] = 1,
+	[TAPAN_A_CDC_MBHC_VOLT_B1_CTL] = 1,
+	[TAPAN_A_CDC_MBHC_VOLT_B2_CTL] = 1,
+	[TAPAN_A_CDC_MBHC_VOLT_B3_CTL] = 1,
+	[TAPAN_A_CDC_MBHC_VOLT_B4_CTL] = 1,
+	[TAPAN_A_CDC_MBHC_VOLT_B5_CTL] = 1,
+	[TAPAN_A_CDC_MBHC_VOLT_B6_CTL] = 1,
+	[TAPAN_A_CDC_MBHC_VOLT_B7_CTL] = 1,
+	[TAPAN_A_CDC_MBHC_VOLT_B8_CTL] = 1,
+	[TAPAN_A_CDC_MBHC_VOLT_B9_CTL] = 1,
+	[TAPAN_A_CDC_MBHC_VOLT_B10_CTL] = 1,
+	[TAPAN_A_CDC_MBHC_VOLT_B11_CTL] = 1,
+	[TAPAN_A_CDC_MBHC_VOLT_B12_CTL] = 1,
+	[TAPAN_A_CDC_MBHC_CLK_CTL] = 1,
+	[TAPAN_A_CDC_MBHC_INT_CTL] = 1,
+	[TAPAN_A_CDC_MBHC_DEBUG_CTL] = 1,
+	[TAPAN_A_CDC_MBHC_SPARE] = 1,
+};
+
+const u8 tapan_reset_reg_defaults[TAPAN_CACHE_SIZE] = {
+	[TAPAN_A_CHIP_CTL] = TAPAN_A_CHIP_CTL__POR,
+	[TAPAN_A_CHIP_STATUS] = TAPAN_A_CHIP_STATUS__POR,
+	[TAPAN_A_CHIP_ID_BYTE_0] = TAPAN_A_CHIP_ID_BYTE_0__POR,
+	[TAPAN_A_CHIP_ID_BYTE_1] = TAPAN_A_CHIP_ID_BYTE_1__POR,
+	[TAPAN_A_CHIP_ID_BYTE_2] = TAPAN_A_CHIP_ID_BYTE_2__POR,
+	[TAPAN_A_CHIP_ID_BYTE_3] = TAPAN_A_CHIP_ID_BYTE_3__POR,
+	[TAPAN_A_CHIP_VERSION] = TAPAN_A_CHIP_VERSION__POR,
+	[TAPAN_A_CHIP_DEBUG_CTL] = TAPAN_A_CHIP_DEBUG_CTL__POR,
+	[TAPAN_A_SLAVE_ID_1] = TAPAN_A_SLAVE_ID_1__POR,
+	[TAPAN_A_SLAVE_ID_2] = TAPAN_A_SLAVE_ID_2__POR,
+	[TAPAN_A_SLAVE_ID_3] = TAPAN_A_SLAVE_ID_3__POR,
+	[TAPAN_A_PIN_CTL_OE0] = TAPAN_A_PIN_CTL_OE0__POR,
+	[TAPAN_A_PIN_CTL_DATA0] = TAPAN_A_PIN_CTL_DATA0__POR,
+	[TAPAN_A_HDRIVE_GENERIC] = TAPAN_A_HDRIVE_GENERIC__POR,
+	[TAPAN_A_HDRIVE_OVERRIDE] = TAPAN_A_HDRIVE_OVERRIDE__POR,
+	[TAPAN_A_ANA_CSR_WAIT_STATE] = TAPAN_A_ANA_CSR_WAIT_STATE__POR,
+	[TAPAN_A_PROCESS_MONITOR_CTL0] = TAPAN_A_PROCESS_MONITOR_CTL0__POR,
+	[TAPAN_A_PROCESS_MONITOR_CTL1] = TAPAN_A_PROCESS_MONITOR_CTL1__POR,
+	[TAPAN_A_PROCESS_MONITOR_CTL2] = TAPAN_A_PROCESS_MONITOR_CTL2__POR,
+	[TAPAN_A_PROCESS_MONITOR_CTL3] = TAPAN_A_PROCESS_MONITOR_CTL3__POR,
+	[TAPAN_A_QFUSE_CTL] = TAPAN_A_QFUSE_CTL__POR,
+	[TAPAN_A_QFUSE_STATUS] = TAPAN_A_QFUSE_STATUS__POR,
+	[TAPAN_A_QFUSE_DATA_OUT0] = TAPAN_A_QFUSE_DATA_OUT0__POR,
+	[TAPAN_A_QFUSE_DATA_OUT1] = TAPAN_A_QFUSE_DATA_OUT1__POR,
+	[TAPAN_A_QFUSE_DATA_OUT2] = TAPAN_A_QFUSE_DATA_OUT2__POR,
+	[TAPAN_A_QFUSE_DATA_OUT3] = TAPAN_A_QFUSE_DATA_OUT3__POR,
+	[TAPAN_A_QFUSE_DATA_OUT4] = TAPAN_A_QFUSE_DATA_OUT4__POR,
+	[TAPAN_A_QFUSE_DATA_OUT5] = TAPAN_A_QFUSE_DATA_OUT5__POR,
+	[TAPAN_A_QFUSE_DATA_OUT6] = TAPAN_A_QFUSE_DATA_OUT6__POR,
+	[TAPAN_A_QFUSE_DATA_OUT7] = TAPAN_A_QFUSE_DATA_OUT7__POR,
+	[TAPAN_A_CDC_CTL] = TAPAN_A_CDC_CTL__POR,
+	[TAPAN_A_LEAKAGE_CTL] = TAPAN_A_LEAKAGE_CTL__POR,
+	[TAPAN_A_INTR_MODE] = TAPAN_A_INTR_MODE__POR,
+	[TAPAN_A_INTR_MASK0] = TAPAN_A_INTR_MASK0__POR,
+	[TAPAN_A_INTR_MASK1] = TAPAN_A_INTR_MASK1__POR,
+	[TAPAN_A_INTR_MASK2] = TAPAN_A_INTR_MASK2__POR,
+	[TAPAN_A_INTR_MASK3] = TAPAN_A_INTR_MASK3__POR,
+	[TAPAN_A_INTR_STATUS0] = TAPAN_A_INTR_STATUS0__POR,
+	[TAPAN_A_INTR_STATUS1] = TAPAN_A_INTR_STATUS1__POR,
+	[TAPAN_A_INTR_STATUS2] = TAPAN_A_INTR_STATUS2__POR,
+	[TAPAN_A_INTR_STATUS3] = TAPAN_A_INTR_STATUS3__POR,
+	[TAPAN_A_INTR_CLEAR0] = TAPAN_A_INTR_CLEAR0__POR,
+	[TAPAN_A_INTR_CLEAR1] = TAPAN_A_INTR_CLEAR1__POR,
+	[TAPAN_A_INTR_CLEAR2] = TAPAN_A_INTR_CLEAR2__POR,
+	[TAPAN_A_INTR_CLEAR3] = TAPAN_A_INTR_CLEAR3__POR,
+	[TAPAN_A_INTR_LEVEL0] = TAPAN_A_INTR_LEVEL0__POR,
+	[TAPAN_A_INTR_LEVEL1] = TAPAN_A_INTR_LEVEL1__POR,
+	[TAPAN_A_INTR_LEVEL2] = TAPAN_A_INTR_LEVEL2__POR,
+	[TAPAN_A_INTR_LEVEL3] = TAPAN_A_INTR_LEVEL3__POR,
+	[TAPAN_A_INTR_TEST0] = TAPAN_A_INTR_TEST0__POR,
+	[TAPAN_A_INTR_TEST1] = TAPAN_A_INTR_TEST1__POR,
+	[TAPAN_A_INTR_TEST2] = TAPAN_A_INTR_TEST2__POR,
+	[TAPAN_A_INTR_TEST3] = TAPAN_A_INTR_TEST3__POR,
+	[TAPAN_A_INTR_SET0] = TAPAN_A_INTR_SET0__POR,
+	[TAPAN_A_INTR_SET1] = TAPAN_A_INTR_SET1__POR,
+	[TAPAN_A_INTR_SET2] = TAPAN_A_INTR_SET2__POR,
+	[TAPAN_A_INTR_SET3] = TAPAN_A_INTR_SET3__POR,
+	[TAPAN_A_INTR_DESTN0] = TAPAN_A_INTR_DESTN0__POR,
+	[TAPAN_A_INTR_DESTN1] = TAPAN_A_INTR_DESTN1__POR,
+	[TAPAN_A_INTR_DESTN2] = TAPAN_A_INTR_DESTN2__POR,
+	[TAPAN_A_INTR_DESTN3] = TAPAN_A_INTR_DESTN3__POR,
+	[TAPAN_A_CDC_DMIC_DATA0_MODE] = TAPAN_A_CDC_DMIC_DATA0_MODE__POR,
+	[TAPAN_A_CDC_DMIC_CLK0_MODE] = TAPAN_A_CDC_DMIC_CLK0_MODE__POR,
+	[TAPAN_A_CDC_DMIC_DATA1_MODE] = TAPAN_A_CDC_DMIC_DATA1_MODE__POR,
+	[TAPAN_A_CDC_DMIC_CLK1_MODE] = TAPAN_A_CDC_DMIC_CLK1_MODE__POR,
+	[TAPAN_A_CDC_INTR_MODE] = TAPAN_A_CDC_INTR_MODE__POR,
+	[TAPAN_A_BIAS_REF_CTL] = TAPAN_A_BIAS_REF_CTL__POR,
+	[TAPAN_A_BIAS_CENTRAL_BG_CTL] = TAPAN_A_BIAS_CENTRAL_BG_CTL__POR,
+	[TAPAN_A_BIAS_PRECHRG_CTL] = TAPAN_A_BIAS_PRECHRG_CTL__POR,
+	[TAPAN_A_BIAS_CURR_CTL_1] = TAPAN_A_BIAS_CURR_CTL_1__POR,
+	[TAPAN_A_BIAS_CURR_CTL_2] = TAPAN_A_BIAS_CURR_CTL_2__POR,
+	[TAPAN_A_BIAS_OSC_BG_CTL] = TAPAN_A_BIAS_OSC_BG_CTL__POR,
+	[TAPAN_A_CLK_BUFF_EN1] = TAPAN_A_CLK_BUFF_EN1__POR,
+	[TAPAN_A_CLK_BUFF_EN2] = TAPAN_A_CLK_BUFF_EN2__POR,
+	[TAPAN_A_LDO_H_MODE_1] = TAPAN_A_LDO_H_MODE_1__POR,
+	[TAPAN_A_LDO_H_MODE_2] = TAPAN_A_LDO_H_MODE_2__POR,
+	[TAPAN_A_LDO_H_LOOP_CTL] = TAPAN_A_LDO_H_LOOP_CTL__POR,
+	[TAPAN_A_LDO_H_COMP_1] = TAPAN_A_LDO_H_COMP_1__POR,
+	[TAPAN_A_LDO_H_COMP_2] = TAPAN_A_LDO_H_COMP_2__POR,
+	[TAPAN_A_LDO_H_BIAS_1] = TAPAN_A_LDO_H_BIAS_1__POR,
+	[TAPAN_A_LDO_H_BIAS_2] = TAPAN_A_LDO_H_BIAS_2__POR,
+	[TAPAN_A_LDO_H_BIAS_3] = TAPAN_A_LDO_H_BIAS_3__POR,
+	[TAPAN_A_MICB_CFILT_1_CTL] = TAPAN_A_MICB_CFILT_1_CTL__POR,
+	[TAPAN_A_MICB_CFILT_1_VAL] = TAPAN_A_MICB_CFILT_1_VAL__POR,
+	[TAPAN_A_MICB_CFILT_1_PRECHRG] = TAPAN_A_MICB_CFILT_1_PRECHRG__POR,
+	[TAPAN_A_MICB_1_CTL] = TAPAN_A_MICB_1_CTL__POR,
+	[TAPAN_A_MICB_1_INT_RBIAS] = TAPAN_A_MICB_1_INT_RBIAS__POR,
+	[TAPAN_A_MICB_1_MBHC] = TAPAN_A_MICB_1_MBHC__POR,
+	[TAPAN_A_MICB_CFILT_2_CTL] = TAPAN_A_MICB_CFILT_2_CTL__POR,
+	[TAPAN_A_MICB_CFILT_2_VAL] = TAPAN_A_MICB_CFILT_2_VAL__POR,
+	[TAPAN_A_MICB_CFILT_2_PRECHRG] = TAPAN_A_MICB_CFILT_2_PRECHRG__POR,
+	[TAPAN_A_MICB_2_CTL] = TAPAN_A_MICB_2_CTL__POR,
+	[TAPAN_A_MICB_2_INT_RBIAS] = TAPAN_A_MICB_2_INT_RBIAS__POR,
+	[TAPAN_A_MICB_2_MBHC] = TAPAN_A_MICB_2_MBHC__POR,
+	[TAPAN_A_MICB_CFILT_3_CTL] = TAPAN_A_MICB_CFILT_3_CTL__POR,
+	[TAPAN_A_MICB_CFILT_3_VAL] = TAPAN_A_MICB_CFILT_3_VAL__POR,
+	[TAPAN_A_MICB_CFILT_3_PRECHRG] = TAPAN_A_MICB_CFILT_3_PRECHRG__POR,
+	[TAPAN_A_MICB_3_CTL] = TAPAN_A_MICB_3_CTL__POR,
+	[TAPAN_A_MICB_3_INT_RBIAS] = TAPAN_A_MICB_3_INT_RBIAS__POR,
+	[TAPAN_A_MICB_3_MBHC] = TAPAN_A_MICB_3_MBHC__POR,
+	[TAPAN_A_MBHC_INSERT_DETECT] = TAPAN_A_MBHC_INSERT_DETECT__POR,
+	[TAPAN_A_MBHC_INSERT_DET_STATUS] = TAPAN_A_MBHC_INSERT_DET_STATUS__POR,
+	[TAPAN_A_TX_COM_BIAS] = TAPAN_A_TX_COM_BIAS__POR,
+	[TAPAN_A_MBHC_SCALING_MUX_1] = TAPAN_A_MBHC_SCALING_MUX_1__POR,
+	[TAPAN_A_MBHC_SCALING_MUX_2] = TAPAN_A_MBHC_SCALING_MUX_2__POR,
+	[TAPAN_A_RESERVED_MAD_ANA_CTRL] = TAPAN_A_RESERVED_MAD_ANA_CTRL__POR,
+	[TAPAN_A_TX_SUP_SWITCH_CTRL_1] = TAPAN_A_TX_SUP_SWITCH_CTRL_1__POR,
+	[TAPAN_A_TX_SUP_SWITCH_CTRL_2] = TAPAN_A_TX_SUP_SWITCH_CTRL_2__POR,
+	[TAPAN_A_TX_1_EN] = TAPAN_A_TX_1_EN__POR,
+	[TAPAN_A_TX_2_EN] = TAPAN_A_TX_2_EN__POR,
+	[TAPAN_A_TX_1_2_ADC_CH1] = TAPAN_A_TX_1_2_ADC_CH1__POR,
+	[TAPAN_A_TX_1_2_ADC_CH2] = TAPAN_A_TX_1_2_ADC_CH2__POR,
+	[TAPAN_A_TX_1_2_ATEST_REFCTRL] = TAPAN_A_TX_1_2_ATEST_REFCTRL__POR,
+	[TAPAN_A_TX_1_2_TEST_CTL] = TAPAN_A_TX_1_2_TEST_CTL__POR,
+	[TAPAN_A_TX_1_2_TEST_BLOCK_EN] = TAPAN_A_TX_1_2_TEST_BLOCK_EN__POR,
+	[TAPAN_A_TX_1_2_TXFE_CLKDIV] = TAPAN_A_TX_1_2_TXFE_CLKDIV__POR,
+	[TAPAN_A_TX_1_2_SAR_ERR_CH1] = TAPAN_A_TX_1_2_SAR_ERR_CH1__POR,
+	[TAPAN_A_TX_1_2_SAR_ERR_CH2] = TAPAN_A_TX_1_2_SAR_ERR_CH2__POR,
+	[TAPAN_A_TX_3_EN] = TAPAN_A_TX_3_EN__POR,
+	[TAPAN_A_TX_1_2_TEST_EN] = TAPAN_A_TX_1_2_TEST_EN__POR,
+	[TAPAN_A_TX_4_5_TXFE_SC_CTL] = TAPAN_A_TX_4_5_TXFE_SC_CTL__POR,
+	[TAPAN_A_TX_4_5_TEST_EN] = TAPAN_A_TX_4_5_TEST_EN__POR,
+	[TAPAN_A_TX_4_EN] = TAPAN_A_TX_4_EN__POR,
+	[TAPAN_A_TX_5_EN] = TAPAN_A_TX_5_EN__POR,
+	[TAPAN_A_TX_4_5_ADC_CH4] = TAPAN_A_TX_4_5_ADC_CH4__POR,
+	[TAPAN_A_TX_4_5_ADC_CH5] = TAPAN_A_TX_4_5_ADC_CH5__POR,
+	[TAPAN_A_TX_4_5_ATEST_REFCTRL] = TAPAN_A_TX_4_5_ATEST_REFCTRL__POR,
+	[TAPAN_A_TX_4_5_TEST_CTL] = TAPAN_A_TX_4_5_TEST_CTL__POR,
+	[TAPAN_A_TX_4_5_TEST_BLOCK_EN] = TAPAN_A_TX_4_5_TEST_BLOCK_EN__POR,
+	[TAPAN_A_TX_4_5_TXFE_CKDIV] = TAPAN_A_TX_4_5_TXFE_CKDIV__POR,
+	[TAPAN_A_TX_4_5_SAR_ERR_CH4] = TAPAN_A_TX_4_5_SAR_ERR_CH4__POR,
+	[TAPAN_A_TX_4_5_SAR_ERR_CH5] = TAPAN_A_TX_4_5_SAR_ERR_CH5__POR,
+	[TAPAN_A_TX_7_MBHC_EN] = TAPAN_A_TX_7_MBHC_EN__POR,
+	[TAPAN_A_TX_7_MBHC_ATEST_REFCTRL] =
+			TAPAN_A_TX_7_MBHC_ATEST_REFCTRL__POR,
+	[TAPAN_A_TX_7_MBHC_ADC] = TAPAN_A_TX_7_MBHC_ADC__POR,
+	[TAPAN_A_TX_7_MBHC_TEST_CTL] = TAPAN_A_TX_7_MBHC_TEST_CTL__POR,
+	[TAPAN_A_TX_7_MBHC_SAR_ERR] = TAPAN_A_TX_7_MBHC_SAR_ERR__POR,
+	[TAPAN_A_TX_7_TXFE_CLKDIV] = TAPAN_A_TX_7_TXFE_CLKDIV__POR,
+	[TAPAN_A_BUCK_MODE_1] = TAPAN_A_BUCK_MODE_1__POR,
+	[TAPAN_A_BUCK_MODE_2] = TAPAN_A_BUCK_MODE_2__POR,
+	[TAPAN_A_BUCK_MODE_3] = TAPAN_A_BUCK_MODE_3__POR,
+	[TAPAN_A_BUCK_MODE_4] = TAPAN_A_BUCK_MODE_4__POR,
+	[TAPAN_A_BUCK_MODE_5] = TAPAN_A_BUCK_MODE_5__POR,
+	[TAPAN_A_BUCK_CTRL_VCL_1] = TAPAN_A_BUCK_CTRL_VCL_1__POR,
+	[TAPAN_A_BUCK_CTRL_VCL_2] = TAPAN_A_BUCK_CTRL_VCL_2__POR,
+	[TAPAN_A_BUCK_CTRL_VCL_3] = TAPAN_A_BUCK_CTRL_VCL_3__POR,
+	[TAPAN_A_BUCK_CTRL_CCL_1] = TAPAN_A_BUCK_CTRL_CCL_1__POR,
+	[TAPAN_A_BUCK_CTRL_CCL_2] = TAPAN_A_BUCK_CTRL_CCL_2__POR,
+	[TAPAN_A_BUCK_CTRL_CCL_3] = TAPAN_A_BUCK_CTRL_CCL_3__POR,
+	[TAPAN_A_BUCK_CTRL_CCL_4] = TAPAN_A_BUCK_CTRL_CCL_4__POR,
+	[TAPAN_A_BUCK_CTRL_PWM_DRVR_1] = TAPAN_A_BUCK_CTRL_PWM_DRVR_1__POR,
+	[TAPAN_A_BUCK_CTRL_PWM_DRVR_2] = TAPAN_A_BUCK_CTRL_PWM_DRVR_2__POR,
+	[TAPAN_A_BUCK_CTRL_PWM_DRVR_3] = TAPAN_A_BUCK_CTRL_PWM_DRVR_3__POR,
+	[TAPAN_A_BUCK_TMUX_A_D] = TAPAN_A_BUCK_TMUX_A_D__POR,
+	[TAPAN_A_NCP_BUCKREF] = TAPAN_A_NCP_BUCKREF__POR,
+	[TAPAN_A_NCP_EN] = TAPAN_A_NCP_EN__POR,
+	[TAPAN_A_NCP_CLK] = TAPAN_A_NCP_CLK__POR,
+	[TAPAN_A_NCP_STATIC] = TAPAN_A_NCP_STATIC__POR,
+	[TAPAN_A_NCP_VTH_LOW] = TAPAN_A_NCP_VTH_LOW__POR,
+	[TAPAN_A_NCP_VTH_HIGH] = TAPAN_A_NCP_VTH_HIGH__POR,
+	[TAPAN_A_NCP_ATEST] = TAPAN_A_NCP_ATEST__POR,
+	[TAPAN_A_NCP_DTEST] = TAPAN_A_NCP_DTEST__POR,
+	[TAPAN_A_NCP_DLY1] = TAPAN_A_NCP_DLY1__POR,
+	[TAPAN_A_NCP_DLY2] = TAPAN_A_NCP_DLY2__POR,
+	[TAPAN_A_RX_AUX_SW_CTL] = TAPAN_A_RX_AUX_SW_CTL__POR,
+	[TAPAN_A_RX_PA_AUX_IN_CONN] = TAPAN_A_RX_PA_AUX_IN_CONN__POR,
+	[TAPAN_A_RX_COM_TIMER_DIV] = TAPAN_A_RX_COM_TIMER_DIV__POR,
+	[TAPAN_A_RX_COM_OCP_CTL] = TAPAN_A_RX_COM_OCP_CTL__POR,
+	[TAPAN_A_RX_COM_OCP_COUNT] = TAPAN_A_RX_COM_OCP_COUNT__POR,
+	[TAPAN_A_RX_COM_DAC_CTL] = TAPAN_A_RX_COM_DAC_CTL__POR,
+	[TAPAN_A_RX_COM_BIAS] = TAPAN_A_RX_COM_BIAS__POR,
+	[TAPAN_A_RX_HPH_AUTO_CHOP] = TAPAN_A_RX_HPH_AUTO_CHOP__POR,
+	[TAPAN_A_RX_HPH_CHOP_CTL] = TAPAN_A_RX_HPH_CHOP_CTL__POR,
+	[TAPAN_A_RX_HPH_BIAS_PA] = TAPAN_A_RX_HPH_BIAS_PA__POR,
+	[TAPAN_A_RX_HPH_BIAS_LDO] = TAPAN_A_RX_HPH_BIAS_LDO__POR,
+	[TAPAN_A_RX_HPH_BIAS_CNP] = TAPAN_A_RX_HPH_BIAS_CNP__POR,
+	[TAPAN_A_RX_HPH_BIAS_WG_OCP] = TAPAN_A_RX_HPH_BIAS_WG_OCP__POR,
+	[TAPAN_A_RX_HPH_OCP_CTL] = TAPAN_A_RX_HPH_OCP_CTL__POR,
+	[TAPAN_A_RX_HPH_CNP_EN] = TAPAN_A_RX_HPH_CNP_EN__POR,
+	[TAPAN_A_RX_HPH_CNP_WG_CTL] = TAPAN_A_RX_HPH_CNP_WG_CTL__POR,
+	[TAPAN_A_RX_HPH_CNP_WG_TIME] = TAPAN_A_RX_HPH_CNP_WG_TIME__POR,
+	[TAPAN_A_RX_HPH_L_GAIN] = TAPAN_A_RX_HPH_L_GAIN__POR,
+	[TAPAN_A_RX_HPH_L_TEST] = TAPAN_A_RX_HPH_L_TEST__POR,
+	[TAPAN_A_RX_HPH_L_PA_CTL] = TAPAN_A_RX_HPH_L_PA_CTL__POR,
+	[TAPAN_A_RX_HPH_L_DAC_CTL] = TAPAN_A_RX_HPH_L_DAC_CTL__POR,
+	[TAPAN_A_RX_HPH_L_ATEST] = TAPAN_A_RX_HPH_L_ATEST__POR,
+	[TAPAN_A_RX_HPH_L_STATUS] = TAPAN_A_RX_HPH_L_STATUS__POR,
+	[TAPAN_A_RX_HPH_R_GAIN] = TAPAN_A_RX_HPH_R_GAIN__POR,
+	[TAPAN_A_RX_HPH_R_TEST] = TAPAN_A_RX_HPH_R_TEST__POR,
+	[TAPAN_A_RX_HPH_R_PA_CTL] = TAPAN_A_RX_HPH_R_PA_CTL__POR,
+	[TAPAN_A_RX_HPH_R_DAC_CTL] = TAPAN_A_RX_HPH_R_DAC_CTL__POR,
+	[TAPAN_A_RX_HPH_R_ATEST] = TAPAN_A_RX_HPH_R_ATEST__POR,
+	[TAPAN_A_RX_HPH_R_STATUS] = TAPAN_A_RX_HPH_R_STATUS__POR,
+	[TAPAN_A_RX_EAR_BIAS_PA] = TAPAN_A_RX_EAR_BIAS_PA__POR,
+	[TAPAN_A_RX_EAR_BIAS_CMBUFF] = TAPAN_A_RX_EAR_BIAS_CMBUFF__POR,
+	[TAPAN_A_RX_EAR_EN] = TAPAN_A_RX_EAR_EN__POR,
+	[TAPAN_A_RX_EAR_GAIN] = TAPAN_A_RX_EAR_GAIN__POR,
+	[TAPAN_A_RX_EAR_CMBUFF] = TAPAN_A_RX_EAR_CMBUFF__POR,
+	[TAPAN_A_RX_EAR_ICTL] = TAPAN_A_RX_EAR_ICTL__POR,
+	[TAPAN_A_RX_EAR_CCOMP] = TAPAN_A_RX_EAR_CCOMP__POR,
+	[TAPAN_A_RX_EAR_VCM] = TAPAN_A_RX_EAR_VCM__POR,
+	[TAPAN_A_RX_EAR_CNP] = TAPAN_A_RX_EAR_CNP__POR,
+	[TAPAN_A_RX_EAR_DAC_CTL_ATEST] = TAPAN_A_RX_EAR_DAC_CTL_ATEST__POR,
+	[TAPAN_A_RX_EAR_STATUS] = TAPAN_A_RX_EAR_STATUS__POR,
+	[TAPAN_A_RX_LINE_BIAS_PA] = TAPAN_A_RX_LINE_BIAS_PA__POR,
+	[TAPAN_A_RX_BUCK_BIAS1] = TAPAN_A_RX_BUCK_BIAS1__POR,
+	[TAPAN_A_RX_BUCK_BIAS2] = TAPAN_A_RX_BUCK_BIAS2__POR,
+	[TAPAN_A_RX_LINE_COM] = TAPAN_A_RX_LINE_COM__POR,
+	[TAPAN_A_RX_LINE_CNP_EN] = TAPAN_A_RX_LINE_CNP_EN__POR,
+	[TAPAN_A_RX_LINE_CNP_WG_CTL] = TAPAN_A_RX_LINE_CNP_WG_CTL__POR,
+	[TAPAN_A_RX_LINE_CNP_WG_TIME] = TAPAN_A_RX_LINE_CNP_WG_TIME__POR,
+	[TAPAN_A_RX_LINE_1_GAIN] = TAPAN_A_RX_LINE_1_GAIN__POR,
+	[TAPAN_A_RX_LINE_1_TEST] = TAPAN_A_RX_LINE_1_TEST__POR,
+	[TAPAN_A_RX_LINE_1_DAC_CTL] = TAPAN_A_RX_LINE_1_DAC_CTL__POR,
+	[TAPAN_A_RX_LINE_1_STATUS] = TAPAN_A_RX_LINE_1_STATUS__POR,
+	[TAPAN_A_RX_LINE_2_GAIN] = TAPAN_A_RX_LINE_2_GAIN__POR,
+	[TAPAN_A_RX_LINE_2_TEST] = TAPAN_A_RX_LINE_2_TEST__POR,
+	[TAPAN_A_RX_LINE_2_DAC_CTL] = TAPAN_A_RX_LINE_2_DAC_CTL__POR,
+	[TAPAN_A_RX_LINE_2_STATUS] = TAPAN_A_RX_LINE_2_STATUS__POR,
+	[TAPAN_A_RX_LINE_CNP_DBG] = TAPAN_A_RX_LINE_CNP_DBG__POR,
+	[TAPAN_A_SPKR_DRV_EN] = TAPAN_A_SPKR_DRV_EN__POR,
+	[TAPAN_A_SPKR_DRV_GAIN] = TAPAN_A_SPKR_DRV_GAIN__POR,
+	[TAPAN_A_SPKR_DRV_DAC_CTL] = TAPAN_A_SPKR_DRV_DAC_CTL__POR,
+	[TAPAN_A_SPKR_DRV_OCP_CTL] = TAPAN_A_SPKR_DRV_OCP_CTL__POR,
+	[TAPAN_A_SPKR_DRV_CLIP_DET] = TAPAN_A_SPKR_DRV_CLIP_DET__POR,
+	[TAPAN_A_SPKR_DRV_IEC] = TAPAN_A_SPKR_DRV_IEC__POR,
+	[TAPAN_A_SPKR_DRV_DBG_DAC] = TAPAN_A_SPKR_DRV_DBG_DAC__POR,
+	[TAPAN_A_SPKR_DRV_DBG_PA] = TAPAN_A_SPKR_DRV_DBG_PA__POR,
+	[TAPAN_A_SPKR_DRV_DBG_PWRSTG] = TAPAN_A_SPKR_DRV_DBG_PWRSTG__POR,
+	[TAPAN_A_SPKR_DRV_BIAS_LDO] = TAPAN_A_SPKR_DRV_BIAS_LDO__POR,
+	[TAPAN_A_SPKR_DRV_BIAS_INT] = TAPAN_A_SPKR_DRV_BIAS_INT__POR,
+	[TAPAN_A_SPKR_DRV_BIAS_PA] = TAPAN_A_SPKR_DRV_BIAS_PA__POR,
+	[TAPAN_A_SPKR_DRV_STATUS_OCP] = TAPAN_A_SPKR_DRV_STATUS_OCP__POR,
+	[TAPAN_A_SPKR_DRV_STATUS_PA] = TAPAN_A_SPKR_DRV_STATUS_PA__POR,
+	[TAPAN_A_RC_OSC_FREQ] = TAPAN_A_RC_OSC_FREQ__POR,
+	[TAPAN_A_RC_OSC_TEST] = TAPAN_A_RC_OSC_TEST__POR,
+	[TAPAN_A_RC_OSC_STATUS] = TAPAN_A_RC_OSC_STATUS__POR,
+	[TAPAN_A_RC_OSC_TUNER] = TAPAN_A_RC_OSC_TUNER__POR,
+	[TAPAN_A_MBHC_HPH] = TAPAN_A_MBHC_HPH__POR,
+	[TAPAN_A_CDC_ANC1_B1_CTL] = TAPAN_A_CDC_ANC1_B1_CTL__POR,
+	[TAPAN_A_CDC_ANC2_B1_CTL] = TAPAN_A_CDC_ANC2_B1_CTL__POR,
+	[TAPAN_A_CDC_ANC1_SHIFT] = TAPAN_A_CDC_ANC1_SHIFT__POR,
+	[TAPAN_A_CDC_ANC2_SHIFT] = TAPAN_A_CDC_ANC2_SHIFT__POR,
+	[TAPAN_A_CDC_ANC1_IIR_B1_CTL] = TAPAN_A_CDC_ANC1_IIR_B1_CTL__POR,
+	[TAPAN_A_CDC_ANC2_IIR_B1_CTL] = TAPAN_A_CDC_ANC2_IIR_B1_CTL__POR,
+	[TAPAN_A_CDC_ANC1_IIR_B2_CTL] = TAPAN_A_CDC_ANC1_IIR_B2_CTL__POR,
+	[TAPAN_A_CDC_ANC2_IIR_B2_CTL] = TAPAN_A_CDC_ANC2_IIR_B2_CTL__POR,
+	[TAPAN_A_CDC_ANC1_IIR_B3_CTL] = TAPAN_A_CDC_ANC1_IIR_B3_CTL__POR,
+	[TAPAN_A_CDC_ANC2_IIR_B3_CTL] = TAPAN_A_CDC_ANC2_IIR_B3_CTL__POR,
+	[TAPAN_A_CDC_ANC1_LPF_B1_CTL] = TAPAN_A_CDC_ANC1_LPF_B1_CTL__POR,
+	[TAPAN_A_CDC_ANC2_LPF_B1_CTL] = TAPAN_A_CDC_ANC2_LPF_B1_CTL__POR,
+	[TAPAN_A_CDC_ANC1_LPF_B2_CTL] = TAPAN_A_CDC_ANC1_LPF_B2_CTL__POR,
+	[TAPAN_A_CDC_ANC2_LPF_B2_CTL] = TAPAN_A_CDC_ANC2_LPF_B2_CTL__POR,
+	[TAPAN_A_CDC_ANC1_SPARE] = TAPAN_A_CDC_ANC1_SPARE__POR,
+	[TAPAN_A_CDC_ANC2_SPARE] = TAPAN_A_CDC_ANC2_SPARE__POR,
+	[TAPAN_A_CDC_ANC1_SMLPF_CTL] = TAPAN_A_CDC_ANC1_SMLPF_CTL__POR,
+	[TAPAN_A_CDC_ANC2_SMLPF_CTL] = TAPAN_A_CDC_ANC2_SMLPF_CTL__POR,
+	[TAPAN_A_CDC_ANC1_DCFLT_CTL] = TAPAN_A_CDC_ANC1_DCFLT_CTL__POR,
+	[TAPAN_A_CDC_ANC2_DCFLT_CTL] = TAPAN_A_CDC_ANC2_DCFLT_CTL__POR,
+	[TAPAN_A_CDC_ANC1_GAIN_CTL] = TAPAN_A_CDC_ANC1_GAIN_CTL__POR,
+	[TAPAN_A_CDC_ANC2_GAIN_CTL] = TAPAN_A_CDC_ANC2_GAIN_CTL__POR,
+	[TAPAN_A_CDC_ANC1_B2_CTL] = TAPAN_A_CDC_ANC1_B2_CTL__POR,
+	[TAPAN_A_CDC_ANC2_B2_CTL] = TAPAN_A_CDC_ANC2_B2_CTL__POR,
+	[TAPAN_A_CDC_TX1_VOL_CTL_TIMER] = TAPAN_A_CDC_TX1_VOL_CTL_TIMER__POR,
+	[TAPAN_A_CDC_TX2_VOL_CTL_TIMER] = TAPAN_A_CDC_TX2_VOL_CTL_TIMER__POR,
+	[TAPAN_A_CDC_TX3_VOL_CTL_TIMER] = TAPAN_A_CDC_TX3_VOL_CTL_TIMER__POR,
+	[TAPAN_A_CDC_TX4_VOL_CTL_TIMER] = TAPAN_A_CDC_TX4_VOL_CTL_TIMER__POR,
+	[TAPAN_A_CDC_TX1_VOL_CTL_GAIN] = TAPAN_A_CDC_TX1_VOL_CTL_GAIN__POR,
+	[TAPAN_A_CDC_TX2_VOL_CTL_GAIN] = TAPAN_A_CDC_TX2_VOL_CTL_GAIN__POR,
+	[TAPAN_A_CDC_TX3_VOL_CTL_GAIN] = TAPAN_A_CDC_TX3_VOL_CTL_GAIN__POR,
+	[TAPAN_A_CDC_TX4_VOL_CTL_GAIN] = TAPAN_A_CDC_TX4_VOL_CTL_GAIN__POR,
+	[TAPAN_A_CDC_TX1_VOL_CTL_CFG] = TAPAN_A_CDC_TX1_VOL_CTL_CFG__POR,
+	[TAPAN_A_CDC_TX2_VOL_CTL_CFG] = TAPAN_A_CDC_TX2_VOL_CTL_CFG__POR,
+	[TAPAN_A_CDC_TX3_VOL_CTL_CFG] = TAPAN_A_CDC_TX3_VOL_CTL_CFG__POR,
+	[TAPAN_A_CDC_TX4_VOL_CTL_CFG] = TAPAN_A_CDC_TX4_VOL_CTL_CFG__POR,
+	[TAPAN_A_CDC_TX1_MUX_CTL] = TAPAN_A_CDC_TX1_MUX_CTL__POR,
+	[TAPAN_A_CDC_TX2_MUX_CTL] = TAPAN_A_CDC_TX2_MUX_CTL__POR,
+	[TAPAN_A_CDC_TX3_MUX_CTL] = TAPAN_A_CDC_TX3_MUX_CTL__POR,
+	[TAPAN_A_CDC_TX4_MUX_CTL] = TAPAN_A_CDC_TX4_MUX_CTL__POR,
+	[TAPAN_A_CDC_TX1_CLK_FS_CTL] = TAPAN_A_CDC_TX1_CLK_FS_CTL__POR,
+	[TAPAN_A_CDC_TX2_CLK_FS_CTL] = TAPAN_A_CDC_TX2_CLK_FS_CTL__POR,
+	[TAPAN_A_CDC_TX3_CLK_FS_CTL] = TAPAN_A_CDC_TX3_CLK_FS_CTL__POR,
+	[TAPAN_A_CDC_TX4_CLK_FS_CTL] = TAPAN_A_CDC_TX4_CLK_FS_CTL__POR,
+	[TAPAN_A_CDC_TX1_DMIC_CTL] = TAPAN_A_CDC_TX1_DMIC_CTL__POR,
+	[TAPAN_A_CDC_TX2_DMIC_CTL] = TAPAN_A_CDC_TX2_DMIC_CTL__POR,
+	[TAPAN_A_CDC_TX3_DMIC_CTL] = TAPAN_A_CDC_TX3_DMIC_CTL__POR,
+	[TAPAN_A_CDC_TX4_DMIC_CTL] = TAPAN_A_CDC_TX4_DMIC_CTL__POR,
+	[TAPAN_A_CDC_DEBUG_B1_CTL] = TAPAN_A_CDC_DEBUG_B1_CTL__POR,
+	[TAPAN_A_CDC_DEBUG_B2_CTL] = TAPAN_A_CDC_DEBUG_B2_CTL__POR,
+	[TAPAN_A_CDC_DEBUG_B3_CTL] = TAPAN_A_CDC_DEBUG_B3_CTL__POR,
+	[TAPAN_A_CDC_DEBUG_B4_CTL] = TAPAN_A_CDC_DEBUG_B4_CTL__POR,
+	[TAPAN_A_CDC_DEBUG_B5_CTL] = TAPAN_A_CDC_DEBUG_B5_CTL__POR,
+	[TAPAN_A_CDC_DEBUG_B6_CTL] = TAPAN_A_CDC_DEBUG_B6_CTL__POR,
+	[TAPAN_A_CDC_DEBUG_B7_CTL] = TAPAN_A_CDC_DEBUG_B7_CTL__POR,
+	[TAPAN_A_CDC_SRC1_PDA_CFG] = TAPAN_A_CDC_SRC1_PDA_CFG__POR,
+	[TAPAN_A_CDC_SRC2_PDA_CFG] = TAPAN_A_CDC_SRC2_PDA_CFG__POR,
+	[TAPAN_A_CDC_SRC1_FS_CTL] = TAPAN_A_CDC_SRC1_FS_CTL__POR,
+	[TAPAN_A_CDC_SRC2_FS_CTL] = TAPAN_A_CDC_SRC2_FS_CTL__POR,
+	[TAPAN_A_CDC_RX1_B1_CTL] = TAPAN_A_CDC_RX1_B1_CTL__POR,
+	[TAPAN_A_CDC_RX2_B1_CTL] = TAPAN_A_CDC_RX2_B1_CTL__POR,
+	[TAPAN_A_CDC_RX3_B1_CTL] = TAPAN_A_CDC_RX3_B1_CTL__POR,
+	[TAPAN_A_CDC_RX4_B1_CTL] = TAPAN_A_CDC_RX4_B1_CTL__POR,
+	[TAPAN_A_CDC_RX1_B2_CTL] = TAPAN_A_CDC_RX1_B2_CTL__POR,
+	[TAPAN_A_CDC_RX2_B2_CTL] = TAPAN_A_CDC_RX2_B2_CTL__POR,
+	[TAPAN_A_CDC_RX3_B2_CTL] = TAPAN_A_CDC_RX3_B2_CTL__POR,
+	[TAPAN_A_CDC_RX4_B2_CTL] = TAPAN_A_CDC_RX4_B2_CTL__POR,
+	[TAPAN_A_CDC_RX1_B3_CTL] = TAPAN_A_CDC_RX1_B3_CTL__POR,
+	[TAPAN_A_CDC_RX2_B3_CTL] = TAPAN_A_CDC_RX2_B3_CTL__POR,
+	[TAPAN_A_CDC_RX3_B3_CTL] = TAPAN_A_CDC_RX3_B3_CTL__POR,
+	[TAPAN_A_CDC_RX4_B3_CTL] = TAPAN_A_CDC_RX4_B3_CTL__POR,
+	[TAPAN_A_CDC_RX1_B4_CTL] = TAPAN_A_CDC_RX1_B4_CTL__POR,
+	[TAPAN_A_CDC_RX2_B4_CTL] = TAPAN_A_CDC_RX2_B4_CTL__POR,
+	[TAPAN_A_CDC_RX3_B4_CTL] = TAPAN_A_CDC_RX3_B4_CTL__POR,
+	[TAPAN_A_CDC_RX4_B4_CTL] = TAPAN_A_CDC_RX4_B4_CTL__POR,
+	[TAPAN_A_CDC_RX1_B5_CTL] = TAPAN_A_CDC_RX1_B5_CTL__POR,
+	[TAPAN_A_CDC_RX2_B5_CTL] = TAPAN_A_CDC_RX2_B5_CTL__POR,
+	[TAPAN_A_CDC_RX3_B5_CTL] = TAPAN_A_CDC_RX3_B5_CTL__POR,
+	[TAPAN_A_CDC_RX4_B5_CTL] = TAPAN_A_CDC_RX4_B5_CTL__POR,
+	[TAPAN_A_CDC_RX1_B6_CTL] = TAPAN_A_CDC_RX1_B6_CTL__POR,
+	[TAPAN_A_CDC_RX2_B6_CTL] = TAPAN_A_CDC_RX2_B6_CTL__POR,
+	[TAPAN_A_CDC_RX3_B6_CTL] = TAPAN_A_CDC_RX3_B6_CTL__POR,
+	[TAPAN_A_CDC_RX4_B6_CTL] = TAPAN_A_CDC_RX4_B6_CTL__POR,
+	[TAPAN_A_CDC_RX1_VOL_CTL_B1_CTL] = TAPAN_A_CDC_RX1_VOL_CTL_B1_CTL__POR,
+	[TAPAN_A_CDC_RX2_VOL_CTL_B1_CTL] = TAPAN_A_CDC_RX2_VOL_CTL_B1_CTL__POR,
+	[TAPAN_A_CDC_RX3_VOL_CTL_B1_CTL] = TAPAN_A_CDC_RX3_VOL_CTL_B1_CTL__POR,
+	[TAPAN_A_CDC_RX4_VOL_CTL_B1_CTL] = TAPAN_A_CDC_RX4_VOL_CTL_B1_CTL__POR,
+	[TAPAN_A_CDC_RX1_VOL_CTL_B2_CTL] = TAPAN_A_CDC_RX1_VOL_CTL_B2_CTL__POR,
+	[TAPAN_A_CDC_RX2_VOL_CTL_B2_CTL] = TAPAN_A_CDC_RX2_VOL_CTL_B2_CTL__POR,
+	[TAPAN_A_CDC_RX3_VOL_CTL_B2_CTL] = TAPAN_A_CDC_RX3_VOL_CTL_B2_CTL__POR,
+	[TAPAN_A_CDC_RX4_VOL_CTL_B2_CTL] = TAPAN_A_CDC_RX4_VOL_CTL_B2_CTL__POR,
+	[TAPAN_A_CDC_CLK_ANC_RESET_CTL] = TAPAN_A_CDC_CLK_ANC_RESET_CTL__POR,
+	[TAPAN_A_CDC_CLK_RX_RESET_CTL] = TAPAN_A_CDC_CLK_RX_RESET_CTL__POR,
+	[TAPAN_A_CDC_CLK_TX_RESET_B1_CTL] =
+			TAPAN_A_CDC_CLK_TX_RESET_B1_CTL__POR,
+	[TAPAN_A_CDC_CLK_TX_RESET_B2_CTL] =
+			TAPAN_A_CDC_CLK_TX_RESET_B2_CTL__POR,
+	[TAPAN_A_CDC_CLK_DMIC_B1_CTL] = TAPAN_A_CDC_CLK_DMIC_B1_CTL__POR,
+	[TAPAN_A_CDC_CLK_DMIC_B2_CTL] = TAPAN_A_CDC_CLK_DMIC_B2_CTL__POR,
+	[TAPAN_A_CDC_CLK_I2S_CTL] = TAPAN_A_CDC_CLK_I2S_CTL__POR,
+	[TAPAN_A_CDC_CLK_OTHR_RESET_B1_CTL] =
+			TAPAN_A_CDC_CLK_OTHR_RESET_B1_CTL__POR,
+	[TAPAN_A_CDC_CLK_OTHR_RESET_B2_CTL] =
+			TAPAN_A_CDC_CLK_OTHR_RESET_B2_CTL__POR,
+	[TAPAN_A_CDC_CLK_TX_CLK_EN_B1_CTL] =
+			TAPAN_A_CDC_CLK_TX_CLK_EN_B1_CTL__POR,
+	[TAPAN_A_CDC_CLK_TX_CLK_EN_B2_CTL] =
+			TAPAN_A_CDC_CLK_TX_CLK_EN_B2_CTL__POR,
+	[TAPAN_A_CDC_CLK_OTHR_CTL] = TAPAN_A_CDC_CLK_OTHR_CTL__POR,
+	[TAPAN_A_CDC_CLK_RDAC_CLK_EN_CTL] =
+			TAPAN_A_CDC_CLK_RDAC_CLK_EN_CTL__POR,
+	[TAPAN_A_CDC_CLK_ANC_CLK_EN_CTL] = TAPAN_A_CDC_CLK_ANC_CLK_EN_CTL__POR,
+	[TAPAN_A_CDC_CLK_RX_B1_CTL] = TAPAN_A_CDC_CLK_RX_B1_CTL__POR,
+	[TAPAN_A_CDC_CLK_RX_B2_CTL] = TAPAN_A_CDC_CLK_RX_B2_CTL__POR,
+	[TAPAN_A_CDC_CLK_MCLK_CTL] = TAPAN_A_CDC_CLK_MCLK_CTL__POR,
+	[TAPAN_A_CDC_CLK_PDM_CTL] = TAPAN_A_CDC_CLK_PDM_CTL__POR,
+	[TAPAN_A_CDC_CLK_SD_CTL] = TAPAN_A_CDC_CLK_SD_CTL__POR,
+	[TAPAN_A_CDC_CLK_POWER_CTL] = TAPAN_A_CDC_CLK_POWER_CTL__POR,
+	[TAPAN_A_CDC_CLSH_B1_CTL] = TAPAN_A_CDC_CLSH_B1_CTL__POR,
+	[TAPAN_A_CDC_CLSH_B2_CTL] = TAPAN_A_CDC_CLSH_B2_CTL__POR,
+	[TAPAN_A_CDC_CLSH_B3_CTL] = TAPAN_A_CDC_CLSH_B3_CTL__POR,
+	[TAPAN_A_CDC_CLSH_BUCK_NCP_VARS] = TAPAN_A_CDC_CLSH_BUCK_NCP_VARS__POR,
+	[TAPAN_A_CDC_CLSH_IDLE_HPH_THSD] = TAPAN_A_CDC_CLSH_IDLE_HPH_THSD__POR,
+	[TAPAN_A_CDC_CLSH_IDLE_EAR_THSD] = TAPAN_A_CDC_CLSH_IDLE_EAR_THSD__POR,
+	[TAPAN_A_CDC_CLSH_FCLKONLY_HPH_THSD] =
+			TAPAN_A_CDC_CLSH_FCLKONLY_HPH_THSD__POR,
+	[TAPAN_A_CDC_CLSH_FCLKONLY_EAR_THSD] =
+			TAPAN_A_CDC_CLSH_FCLKONLY_EAR_THSD__POR,
+	[TAPAN_A_CDC_CLSH_K_ADDR] = TAPAN_A_CDC_CLSH_K_ADDR__POR,
+	[TAPAN_A_CDC_CLSH_K_DATA] = TAPAN_A_CDC_CLSH_K_DATA__POR,
+	[TAPAN_A_CDC_CLSH_I_PA_FACT_HPH_L] =
+			TAPAN_A_CDC_CLSH_I_PA_FACT_HPH_L__POR,
+	[TAPAN_A_CDC_CLSH_I_PA_FACT_HPH_U] =
+			TAPAN_A_CDC_CLSH_I_PA_FACT_HPH_U__POR,
+	[TAPAN_A_CDC_CLSH_I_PA_FACT_EAR_L] =
+			TAPAN_A_CDC_CLSH_I_PA_FACT_EAR_L__POR,
+	[TAPAN_A_CDC_CLSH_I_PA_FACT_EAR_U] =
+			TAPAN_A_CDC_CLSH_I_PA_FACT_EAR_U__POR,
+	[TAPAN_A_CDC_CLSH_V_PA_HD_EAR] = TAPAN_A_CDC_CLSH_V_PA_HD_EAR__POR,
+	[TAPAN_A_CDC_CLSH_V_PA_HD_HPH] = TAPAN_A_CDC_CLSH_V_PA_HD_HPH__POR,
+	[TAPAN_A_CDC_CLSH_V_PA_MIN_EAR] = TAPAN_A_CDC_CLSH_V_PA_MIN_EAR__POR,
+	[TAPAN_A_CDC_CLSH_V_PA_MIN_HPH] = TAPAN_A_CDC_CLSH_V_PA_MIN_HPH__POR,
+	[TAPAN_A_CDC_IIR1_GAIN_B1_CTL] = TAPAN_A_CDC_IIR1_GAIN_B1_CTL__POR,
+	[TAPAN_A_CDC_IIR2_GAIN_B1_CTL] = TAPAN_A_CDC_IIR2_GAIN_B1_CTL__POR,
+	[TAPAN_A_CDC_IIR1_GAIN_B2_CTL] = TAPAN_A_CDC_IIR1_GAIN_B2_CTL__POR,
+	[TAPAN_A_CDC_IIR2_GAIN_B2_CTL] = TAPAN_A_CDC_IIR2_GAIN_B2_CTL__POR,
+	[TAPAN_A_CDC_IIR1_GAIN_B3_CTL] = TAPAN_A_CDC_IIR1_GAIN_B3_CTL__POR,
+	[TAPAN_A_CDC_IIR2_GAIN_B3_CTL] = TAPAN_A_CDC_IIR2_GAIN_B3_CTL__POR,
+	[TAPAN_A_CDC_IIR1_GAIN_B4_CTL] = TAPAN_A_CDC_IIR1_GAIN_B4_CTL__POR,
+	[TAPAN_A_CDC_IIR2_GAIN_B4_CTL] = TAPAN_A_CDC_IIR2_GAIN_B4_CTL__POR,
+	[TAPAN_A_CDC_IIR1_GAIN_B5_CTL] = TAPAN_A_CDC_IIR1_GAIN_B5_CTL__POR,
+	[TAPAN_A_CDC_IIR2_GAIN_B5_CTL] = TAPAN_A_CDC_IIR2_GAIN_B5_CTL__POR,
+	[TAPAN_A_CDC_IIR1_GAIN_B6_CTL] = TAPAN_A_CDC_IIR1_GAIN_B6_CTL__POR,
+	[TAPAN_A_CDC_IIR2_GAIN_B6_CTL] = TAPAN_A_CDC_IIR2_GAIN_B6_CTL__POR,
+	[TAPAN_A_CDC_IIR1_GAIN_B7_CTL] = TAPAN_A_CDC_IIR1_GAIN_B7_CTL__POR,
+	[TAPAN_A_CDC_IIR2_GAIN_B7_CTL] = TAPAN_A_CDC_IIR2_GAIN_B7_CTL__POR,
+	[TAPAN_A_CDC_IIR1_GAIN_B8_CTL] = TAPAN_A_CDC_IIR1_GAIN_B8_CTL__POR,
+	[TAPAN_A_CDC_IIR2_GAIN_B8_CTL] = TAPAN_A_CDC_IIR2_GAIN_B8_CTL__POR,
+	[TAPAN_A_CDC_IIR1_CTL] = TAPAN_A_CDC_IIR1_CTL__POR,
+	[TAPAN_A_CDC_IIR2_CTL] = TAPAN_A_CDC_IIR2_CTL__POR,
+	[TAPAN_A_CDC_IIR1_GAIN_TIMER_CTL] =
+			TAPAN_A_CDC_IIR1_GAIN_TIMER_CTL__POR,
+	[TAPAN_A_CDC_IIR2_GAIN_TIMER_CTL] =
+			TAPAN_A_CDC_IIR2_GAIN_TIMER_CTL__POR,
+	[TAPAN_A_CDC_IIR1_COEF_B1_CTL] = TAPAN_A_CDC_IIR1_COEF_B1_CTL__POR,
+	[TAPAN_A_CDC_IIR2_COEF_B1_CTL] = TAPAN_A_CDC_IIR2_COEF_B1_CTL__POR,
+	[TAPAN_A_CDC_IIR1_COEF_B2_CTL] = TAPAN_A_CDC_IIR1_COEF_B2_CTL__POR,
+	[TAPAN_A_CDC_IIR2_COEF_B2_CTL] = TAPAN_A_CDC_IIR2_COEF_B2_CTL__POR,
+	[TAPAN_A_CDC_TOP_GAIN_UPDATE] = TAPAN_A_CDC_TOP_GAIN_UPDATE__POR,
+	[TAPAN_A_CDC_COMP0_B1_CTL] = TAPAN_A_CDC_COMP0_B1_CTL__POR,
+	[TAPAN_A_CDC_COMP1_B1_CTL] = TAPAN_A_CDC_COMP1_B1_CTL__POR,
+	[TAPAN_A_CDC_COMP2_B1_CTL] = TAPAN_A_CDC_COMP2_B1_CTL__POR,
+	[TAPAN_A_CDC_COMP0_B2_CTL] = TAPAN_A_CDC_COMP0_B2_CTL__POR,
+	[TAPAN_A_CDC_COMP1_B2_CTL] = TAPAN_A_CDC_COMP1_B2_CTL__POR,
+	[TAPAN_A_CDC_COMP2_B2_CTL] = TAPAN_A_CDC_COMP2_B2_CTL__POR,
+	[TAPAN_A_CDC_COMP0_B3_CTL] = TAPAN_A_CDC_COMP0_B3_CTL__POR,
+	[TAPAN_A_CDC_COMP1_B3_CTL] = TAPAN_A_CDC_COMP1_B3_CTL__POR,
+	[TAPAN_A_CDC_COMP2_B3_CTL] = TAPAN_A_CDC_COMP2_B3_CTL__POR,
+	[TAPAN_A_CDC_COMP0_B4_CTL] = TAPAN_A_CDC_COMP0_B4_CTL__POR,
+	[TAPAN_A_CDC_COMP1_B4_CTL] = TAPAN_A_CDC_COMP1_B4_CTL__POR,
+	[TAPAN_A_CDC_COMP2_B4_CTL] = TAPAN_A_CDC_COMP2_B4_CTL__POR,
+	[TAPAN_A_CDC_COMP0_B5_CTL] = TAPAN_A_CDC_COMP0_B5_CTL__POR,
+	[TAPAN_A_CDC_COMP1_B5_CTL] = TAPAN_A_CDC_COMP1_B5_CTL__POR,
+	[TAPAN_A_CDC_COMP2_B5_CTL] = TAPAN_A_CDC_COMP2_B5_CTL__POR,
+	[TAPAN_A_CDC_COMP0_B6_CTL] = TAPAN_A_CDC_COMP0_B6_CTL__POR,
+	[TAPAN_A_CDC_COMP1_B6_CTL] = TAPAN_A_CDC_COMP1_B6_CTL__POR,
+	[TAPAN_A_CDC_COMP2_B6_CTL] = TAPAN_A_CDC_COMP2_B6_CTL__POR,
+	[TAPAN_A_CDC_COMP0_SHUT_DOWN_STATUS] =
+			TAPAN_A_CDC_COMP0_SHUT_DOWN_STATUS__POR,
+	[TAPAN_A_CDC_COMP1_SHUT_DOWN_STATUS] =
+			TAPAN_A_CDC_COMP1_SHUT_DOWN_STATUS__POR,
+	[TAPAN_A_CDC_COMP2_SHUT_DOWN_STATUS] =
+			TAPAN_A_CDC_COMP2_SHUT_DOWN_STATUS__POR,
+	[TAPAN_A_CDC_COMP0_FS_CFG] = TAPAN_A_CDC_COMP0_FS_CFG__POR,
+	[TAPAN_A_CDC_COMP1_FS_CFG] = TAPAN_A_CDC_COMP1_FS_CFG__POR,
+	[TAPAN_A_CDC_COMP2_FS_CFG] = TAPAN_A_CDC_COMP2_FS_CFG__POR,
+	[TAPAN_A_CDC_CONN_RX1_B1_CTL] = TAPAN_A_CDC_CONN_RX1_B1_CTL__POR,
+	[TAPAN_A_CDC_CONN_RX1_B2_CTL] = TAPAN_A_CDC_CONN_RX1_B2_CTL__POR,
+	[TAPAN_A_CDC_CONN_RX1_B3_CTL] = TAPAN_A_CDC_CONN_RX1_B3_CTL__POR,
+	[TAPAN_A_CDC_CONN_RX2_B1_CTL] = TAPAN_A_CDC_CONN_RX2_B1_CTL__POR,
+	[TAPAN_A_CDC_CONN_RX2_B2_CTL] = TAPAN_A_CDC_CONN_RX2_B2_CTL__POR,
+	[TAPAN_A_CDC_CONN_RX2_B3_CTL] = TAPAN_A_CDC_CONN_RX2_B3_CTL__POR,
+	[TAPAN_A_CDC_CONN_RX3_B1_CTL] = TAPAN_A_CDC_CONN_RX3_B1_CTL__POR,
+	[TAPAN_A_CDC_CONN_RX3_B2_CTL] = TAPAN_A_CDC_CONN_RX3_B2_CTL__POR,
+	[TAPAN_A_CDC_CONN_RX4_B1_CTL] = TAPAN_A_CDC_CONN_RX4_B1_CTL__POR,
+	[TAPAN_A_CDC_CONN_RX4_B2_CTL] = TAPAN_A_CDC_CONN_RX4_B2_CTL__POR,
+	[TAPAN_A_CDC_CONN_RX4_B3_CTL] = TAPAN_A_CDC_CONN_RX4_B3_CTL__POR,
+	[TAPAN_A_CDC_CONN_ANC_B1_CTL] = TAPAN_A_CDC_CONN_ANC_B1_CTL__POR,
+	[TAPAN_A_CDC_CONN_ANC_B2_CTL] = TAPAN_A_CDC_CONN_ANC_B2_CTL__POR,
+	[TAPAN_A_CDC_CONN_TX_B1_CTL] = TAPAN_A_CDC_CONN_TX_B1_CTL__POR,
+	[TAPAN_A_CDC_CONN_TX_B2_CTL] = TAPAN_A_CDC_CONN_TX_B2_CTL__POR,
+	[TAPAN_A_CDC_CONN_TX_B3_CTL] = TAPAN_A_CDC_CONN_TX_B3_CTL__POR,
+	[TAPAN_A_CDC_CONN_TX_B4_CTL] = TAPAN_A_CDC_CONN_TX_B4_CTL__POR,
+	[TAPAN_A_CDC_CONN_EQ1_B1_CTL] = TAPAN_A_CDC_CONN_EQ1_B1_CTL__POR,
+	[TAPAN_A_CDC_CONN_EQ1_B2_CTL] = TAPAN_A_CDC_CONN_EQ1_B2_CTL__POR,
+	[TAPAN_A_CDC_CONN_EQ1_B3_CTL] = TAPAN_A_CDC_CONN_EQ1_B3_CTL__POR,
+	[TAPAN_A_CDC_CONN_EQ1_B4_CTL] = TAPAN_A_CDC_CONN_EQ1_B4_CTL__POR,
+	[TAPAN_A_CDC_CONN_EQ2_B1_CTL] = TAPAN_A_CDC_CONN_EQ2_B1_CTL__POR,
+	[TAPAN_A_CDC_CONN_EQ2_B2_CTL] = TAPAN_A_CDC_CONN_EQ2_B2_CTL__POR,
+	[TAPAN_A_CDC_CONN_EQ2_B3_CTL] = TAPAN_A_CDC_CONN_EQ2_B3_CTL__POR,
+	[TAPAN_A_CDC_CONN_EQ2_B4_CTL] = TAPAN_A_CDC_CONN_EQ2_B4_CTL__POR,
+	[TAPAN_A_CDC_CONN_SRC1_B1_CTL] = TAPAN_A_CDC_CONN_SRC1_B1_CTL__POR,
+	[TAPAN_A_CDC_CONN_SRC1_B2_CTL] = TAPAN_A_CDC_CONN_SRC1_B2_CTL__POR,
+	[TAPAN_A_CDC_CONN_SRC2_B1_CTL] = TAPAN_A_CDC_CONN_SRC2_B1_CTL__POR,
+	[TAPAN_A_CDC_CONN_SRC2_B2_CTL] = TAPAN_A_CDC_CONN_SRC2_B2_CTL__POR,
+	[TAPAN_A_CDC_CONN_TX_SB_B1_CTL] = TAPAN_A_CDC_CONN_TX_SB_B1_CTL__POR,
+	[TAPAN_A_CDC_CONN_TX_SB_B2_CTL] = TAPAN_A_CDC_CONN_TX_SB_B2_CTL__POR,
+	[TAPAN_A_CDC_CONN_TX_SB_B3_CTL] = TAPAN_A_CDC_CONN_TX_SB_B3_CTL__POR,
+	[TAPAN_A_CDC_CONN_TX_SB_B4_CTL] = TAPAN_A_CDC_CONN_TX_SB_B4_CTL__POR,
+	[TAPAN_A_CDC_CONN_TX_SB_B5_CTL] = TAPAN_A_CDC_CONN_TX_SB_B5_CTL__POR,
+	[TAPAN_A_CDC_CONN_TX_SB_B11_CTL] = TAPAN_A_CDC_CONN_TX_SB_B11_CTL__POR,
+	[TAPAN_A_CDC_CONN_RX_SB_B1_CTL] = TAPAN_A_CDC_CONN_RX_SB_B1_CTL__POR,
+	[TAPAN_A_CDC_CONN_RX_SB_B2_CTL] = TAPAN_A_CDC_CONN_RX_SB_B2_CTL__POR,
+	[TAPAN_A_CDC_CONN_CLSH_CTL] = TAPAN_A_CDC_CONN_CLSH_CTL__POR,
+	[TAPAN_A_CDC_CONN_MISC] = TAPAN_A_CDC_CONN_MISC__POR,
+	[TAPAN_A_CDC_MBHC_EN_CTL] = TAPAN_A_CDC_MBHC_EN_CTL__POR,
+	[TAPAN_A_CDC_MBHC_FIR_B1_CFG] = TAPAN_A_CDC_MBHC_FIR_B1_CFG__POR,
+	[TAPAN_A_CDC_MBHC_FIR_B2_CFG] = TAPAN_A_CDC_MBHC_FIR_B2_CFG__POR,
+	[TAPAN_A_CDC_MBHC_TIMER_B1_CTL] = TAPAN_A_CDC_MBHC_TIMER_B1_CTL__POR,
+	[TAPAN_A_CDC_MBHC_TIMER_B2_CTL] = TAPAN_A_CDC_MBHC_TIMER_B2_CTL__POR,
+	[TAPAN_A_CDC_MBHC_TIMER_B3_CTL] = TAPAN_A_CDC_MBHC_TIMER_B3_CTL__POR,
+	[TAPAN_A_CDC_MBHC_TIMER_B4_CTL] = TAPAN_A_CDC_MBHC_TIMER_B4_CTL__POR,
+	[TAPAN_A_CDC_MBHC_TIMER_B5_CTL] = TAPAN_A_CDC_MBHC_TIMER_B5_CTL__POR,
+	[TAPAN_A_CDC_MBHC_TIMER_B6_CTL] = TAPAN_A_CDC_MBHC_TIMER_B6_CTL__POR,
+	[TAPAN_A_CDC_MBHC_B1_STATUS] = TAPAN_A_CDC_MBHC_B1_STATUS__POR,
+	[TAPAN_A_CDC_MBHC_B2_STATUS] = TAPAN_A_CDC_MBHC_B2_STATUS__POR,
+	[TAPAN_A_CDC_MBHC_B3_STATUS] = TAPAN_A_CDC_MBHC_B3_STATUS__POR,
+	[TAPAN_A_CDC_MBHC_B4_STATUS] = TAPAN_A_CDC_MBHC_B4_STATUS__POR,
+	[TAPAN_A_CDC_MBHC_B5_STATUS] = TAPAN_A_CDC_MBHC_B5_STATUS__POR,
+	[TAPAN_A_CDC_MBHC_B1_CTL] = TAPAN_A_CDC_MBHC_B1_CTL__POR,
+	[TAPAN_A_CDC_MBHC_B2_CTL] = TAPAN_A_CDC_MBHC_B2_CTL__POR,
+	[TAPAN_A_CDC_MBHC_VOLT_B1_CTL] = TAPAN_A_CDC_MBHC_VOLT_B1_CTL__POR,
+	[TAPAN_A_CDC_MBHC_VOLT_B2_CTL] = TAPAN_A_CDC_MBHC_VOLT_B2_CTL__POR,
+	[TAPAN_A_CDC_MBHC_VOLT_B3_CTL] = TAPAN_A_CDC_MBHC_VOLT_B3_CTL__POR,
+	[TAPAN_A_CDC_MBHC_VOLT_B4_CTL] = TAPAN_A_CDC_MBHC_VOLT_B4_CTL__POR,
+	[TAPAN_A_CDC_MBHC_VOLT_B5_CTL] = TAPAN_A_CDC_MBHC_VOLT_B5_CTL__POR,
+	[TAPAN_A_CDC_MBHC_VOLT_B6_CTL] = TAPAN_A_CDC_MBHC_VOLT_B6_CTL__POR,
+	[TAPAN_A_CDC_MBHC_VOLT_B7_CTL] = TAPAN_A_CDC_MBHC_VOLT_B7_CTL__POR,
+	[TAPAN_A_CDC_MBHC_VOLT_B8_CTL] = TAPAN_A_CDC_MBHC_VOLT_B8_CTL__POR,
+	[TAPAN_A_CDC_MBHC_VOLT_B9_CTL] = TAPAN_A_CDC_MBHC_VOLT_B9_CTL__POR,
+	[TAPAN_A_CDC_MBHC_VOLT_B10_CTL] = TAPAN_A_CDC_MBHC_VOLT_B10_CTL__POR,
+	[TAPAN_A_CDC_MBHC_VOLT_B11_CTL] = TAPAN_A_CDC_MBHC_VOLT_B11_CTL__POR,
+	[TAPAN_A_CDC_MBHC_VOLT_B12_CTL] = TAPAN_A_CDC_MBHC_VOLT_B12_CTL__POR,
+	[TAPAN_A_CDC_MBHC_CLK_CTL] = TAPAN_A_CDC_MBHC_CLK_CTL__POR,
+	[TAPAN_A_CDC_MBHC_INT_CTL] = TAPAN_A_CDC_MBHC_INT_CTL__POR,
+	[TAPAN_A_CDC_MBHC_DEBUG_CTL] = TAPAN_A_CDC_MBHC_DEBUG_CTL__POR,
+	[TAPAN_A_CDC_MBHC_SPARE] = TAPAN_A_CDC_MBHC_SPARE__POR,
+};
diff --git a/sound/soc/codecs/wcd9306.c b/sound/soc/codecs/wcd9306.c
new file mode 100644
index 0000000..b0cf27b
--- /dev/null
+++ b/sound/soc/codecs/wcd9306.c
@@ -0,0 +1,3856 @@
+/* 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/init.h>
+#include <linux/firmware.h>
+#include <linux/slab.h>
+#include <linux/platform_device.h>
+#include <linux/device.h>
+#include <linux/printk.h>
+#include <linux/ratelimit.h>
+#include <linux/debugfs.h>
+#include <linux/mfd/wcd9xxx/core.h>
+#include <linux/mfd/wcd9xxx/wcd9xxx_registers.h>
+#include <linux/mfd/wcd9xxx/wcd9306_registers.h>
+#include <linux/mfd/wcd9xxx/pdata.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+#include <sound/tlv.h>
+#include <linux/bitops.h>
+#include <linux/delay.h>
+#include <linux/pm_runtime.h>
+#include <linux/kernel.h>
+#include <linux/gpio.h>
+#include "wcd9306.h"
+#include "wcd9xxx-resmgr.h"
+
+#define WCD9306_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 |\
+			SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_48000 |\
+			SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_192000)
+
+#define NUM_DECIMATORS 4
+#define NUM_INTERPOLATORS 4
+#define BITS_PER_REG 8
+#define TAPAN_TX_PORT_NUMBER	16
+
+#define TAPAN_I2S_MASTER_MODE_MASK 0x08
+
+enum {
+	AIF1_PB = 0,
+	AIF1_CAP,
+	AIF2_PB,
+	AIF2_CAP,
+	AIF3_PB,
+	AIF3_CAP,
+	NUM_CODEC_DAIS,
+};
+
+enum {
+	RX_MIX1_INP_SEL_ZERO = 0,
+	RX_MIX1_INP_SEL_SRC1,
+	RX_MIX1_INP_SEL_SRC2,
+	RX_MIX1_INP_SEL_IIR1,
+	RX_MIX1_INP_SEL_IIR2,
+	RX_MIX1_INP_SEL_RX1,
+	RX_MIX1_INP_SEL_RX2,
+	RX_MIX1_INP_SEL_RX3,
+	RX_MIX1_INP_SEL_RX4,
+	RX_MIX1_INP_SEL_RX5,
+	RX_MIX1_INP_SEL_RX6,
+	RX_MIX1_INP_SEL_RX7,
+	RX_MIX1_INP_SEL_AUXRX,
+};
+
+#define TAPAN_COMP_DIGITAL_GAIN_OFFSET 3
+
+static const DECLARE_TLV_DB_SCALE(digital_gain, 0, 1, 0);
+static const DECLARE_TLV_DB_SCALE(line_gain, 0, 7, 1);
+static const DECLARE_TLV_DB_SCALE(analog_gain, 0, 25, 1);
+static struct snd_soc_dai_driver tapan_dai[];
+static const DECLARE_TLV_DB_SCALE(aux_pga_gain, 0, 2, 0);
+
+/* Codec supports 2 IIR filters */
+enum {
+	IIR1 = 0,
+	IIR2,
+	IIR_MAX,
+};
+/* Codec supports 5 bands */
+enum {
+	BAND1 = 0,
+	BAND2,
+	BAND3,
+	BAND4,
+	BAND5,
+	BAND_MAX,
+};
+
+enum {
+	COMPANDER_1 = 0,
+	COMPANDER_2,
+	COMPANDER_MAX,
+};
+
+enum {
+	COMPANDER_FS_8KHZ = 0,
+	COMPANDER_FS_16KHZ,
+	COMPANDER_FS_32KHZ,
+	COMPANDER_FS_48KHZ,
+	COMPANDER_FS_96KHZ,
+	COMPANDER_FS_192KHZ,
+	COMPANDER_FS_MAX,
+};
+
+struct comp_sample_dependent_params {
+	u32 peak_det_timeout;
+	u32 rms_meter_div_fact;
+	u32 rms_meter_resamp_fact;
+};
+
+struct hpf_work {
+	struct tapan_priv *tapan;
+	u32 decimator;
+	u8 tx_hpf_cut_of_freq;
+	struct delayed_work dwork;
+};
+
+static struct hpf_work tx_hpf_work[NUM_DECIMATORS];
+
+static const struct wcd9xxx_ch tapan_rx_chs[TAPAN_RX_MAX] = {
+	WCD9XXX_CH(16, 0),
+	WCD9XXX_CH(17, 1),
+	WCD9XXX_CH(18, 2),
+	WCD9XXX_CH(19, 3),
+	WCD9XXX_CH(20, 4),
+};
+
+static const struct wcd9xxx_ch tapan_tx_chs[TAPAN_TX_MAX] = {
+	WCD9XXX_CH(0, 0),
+	WCD9XXX_CH(1, 1),
+	WCD9XXX_CH(2, 2),
+	WCD9XXX_CH(3, 3),
+	WCD9XXX_CH(4, 4),
+};
+
+static const u32 vport_check_table[NUM_CODEC_DAIS] = {
+	0,					/* AIF1_PB */
+	(1 << AIF2_CAP) | (1 << AIF3_CAP),	/* AIF1_CAP */
+	0,					/* AIF2_PB */
+	(1 << AIF1_CAP) | (1 << AIF3_CAP),	/* AIF2_CAP */
+	0,					/* AIF2_PB */
+	(1 << AIF1_CAP) | (1 << AIF2_CAP),	/* AIF2_CAP */
+};
+
+struct tapan_priv {
+	struct snd_soc_codec *codec;
+	u32 adc_count;
+	u32 rx_bias_count;
+	s32 dmic_1_2_clk_cnt;
+	s32 dmic_3_4_clk_cnt;
+	s32 dmic_5_6_clk_cnt;
+
+	u32 anc_slot;
+
+	/*track tapan interface type*/
+	u8 intf_type;
+
+	/* num of slim ports required */
+	struct wcd9xxx_codec_dai_data  dai[NUM_CODEC_DAIS];
+
+	/* Maintain the status of AUX PGA */
+	int aux_pga_cnt;
+	u8 aux_l_gain;
+	u8 aux_r_gain;
+
+	/* resmgr module */
+	struct wcd9xxx_resmgr resmgr;
+	/* mbhc module */
+	struct wcd9xxx_mbhc mbhc;
+};
+
+static const u32 comp_shift[] = {
+	0,
+	2,
+};
+
+static unsigned short rx_digital_gain_reg[] = {
+	TAPAN_A_CDC_RX1_VOL_CTL_B2_CTL,
+	TAPAN_A_CDC_RX2_VOL_CTL_B2_CTL,
+	TAPAN_A_CDC_RX3_VOL_CTL_B2_CTL,
+	TAPAN_A_CDC_RX4_VOL_CTL_B2_CTL,
+};
+
+static unsigned short tx_digital_gain_reg[] = {
+	TAPAN_A_CDC_TX1_VOL_CTL_GAIN,
+	TAPAN_A_CDC_TX2_VOL_CTL_GAIN,
+	TAPAN_A_CDC_TX3_VOL_CTL_GAIN,
+	TAPAN_A_CDC_TX4_VOL_CTL_GAIN,
+};
+
+static int tapan_codec_enable_class_h_clk(struct snd_soc_dapm_widget *w,
+		struct snd_kcontrol *kcontrol, int event)
+{
+	struct snd_soc_codec *codec = w->codec;
+
+	dev_dbg(codec->dev, "%s %s  %d\n", __func__, w->name, event);
+
+	switch (event) {
+	case SND_SOC_DAPM_PRE_PMU:
+		snd_soc_update_bits(codec, TAPAN_A_CDC_CLSH_B1_CTL, 0x01, 0x01);
+		break;
+	case SND_SOC_DAPM_PRE_PMD:
+		snd_soc_update_bits(codec, TAPAN_A_BUCK_MODE_1, 0x80, 0x00);
+		snd_soc_update_bits(codec, TAPAN_A_CDC_CLSH_B1_CTL, 0x01, 0x00);
+		break;
+	}
+	return 0;
+}
+
+static int tapan_codec_enable_class_h(struct snd_soc_dapm_widget *w,
+		struct snd_kcontrol *kcontrol, int event)
+{
+	struct snd_soc_codec *codec = w->codec;
+
+	dev_dbg(codec->dev, "%s %s  %d\n", __func__, w->name, event);
+
+	switch (event) {
+	case SND_SOC_DAPM_POST_PMU:
+		snd_soc_update_bits(codec, TAPAN_A_BUCK_MODE_5, 0x02, 0x02);
+		snd_soc_update_bits(codec, TAPAN_A_BUCK_MODE_4, 0xFF, 0xFF);
+		snd_soc_update_bits(codec, TAPAN_A_BUCK_MODE_1, 0x04, 0x04);
+		snd_soc_update_bits(codec, TAPAN_A_BUCK_MODE_1, 0x04, 0x00);
+		snd_soc_update_bits(codec, TAPAN_A_BUCK_MODE_3, 0x04, 0x00);
+		snd_soc_update_bits(codec, TAPAN_A_BUCK_MODE_3, 0x08, 0x00);
+		snd_soc_update_bits(codec, TAPAN_A_BUCK_MODE_1, 0x80, 0x80);
+		usleep_range(1000, 1000);
+		break;
+	}
+	return 0;
+}
+
+static int tapan_codec_enable_charge_pump(struct snd_soc_dapm_widget *w,
+		struct snd_kcontrol *kcontrol, int event)
+{
+	struct snd_soc_codec *codec = w->codec;
+
+	dev_dbg(codec->dev, "%s %s %d\n", __func__, w->name, event);
+
+	switch (event) {
+	case SND_SOC_DAPM_PRE_PMU:
+		snd_soc_update_bits(codec, w->reg, 0x01, 0x01);
+		snd_soc_update_bits(codec, w->reg, 0x40, 0x00);
+		snd_soc_update_bits(codec, TAPAN_A_NCP_STATIC, 0x0f, 0x01);
+		break;
+
+	case SND_SOC_DAPM_POST_PMU:
+		usleep_range(1000, 1000);
+		break;
+
+	case SND_SOC_DAPM_PRE_PMD:
+	    snd_soc_update_bits(codec, w->reg, 0x01, 0x00);
+		snd_soc_update_bits(codec, w->reg, 0x40, 0x40);
+		snd_soc_update_bits(codec, TAPAN_A_NCP_STATIC, 0x0f, 0x08);
+		break;
+	}
+	return 0;
+}
+
+static int tapan_pa_gain_get(struct snd_kcontrol *kcontrol,
+				struct snd_ctl_elem_value *ucontrol)
+{
+	u8 ear_pa_gain;
+	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+
+	ear_pa_gain = snd_soc_read(codec, TAPAN_A_RX_EAR_GAIN);
+
+	ear_pa_gain = ear_pa_gain >> 5;
+
+	if (ear_pa_gain == 0x00) {
+		ucontrol->value.integer.value[0] = 0;
+	} else if (ear_pa_gain == 0x04) {
+		ucontrol->value.integer.value[0] = 1;
+	} else  {
+		pr_err("%s: ERROR: Unsupported Ear Gain = 0x%x\n",
+				__func__, ear_pa_gain);
+		return -EINVAL;
+	}
+
+	dev_dbg(codec->dev, "%s: ear_pa_gain = 0x%x\n", __func__, ear_pa_gain);
+
+	return 0;
+}
+
+static int tapan_pa_gain_put(struct snd_kcontrol *kcontrol,
+				struct snd_ctl_elem_value *ucontrol)
+{
+	u8 ear_pa_gain;
+	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+
+	dev_dbg(codec->dev, "%s: ucontrol->value.integer.value[0]  = %ld\n",
+			 __func__, ucontrol->value.integer.value[0]);
+
+	switch (ucontrol->value.integer.value[0]) {
+	case 0:
+		ear_pa_gain = 0x00;
+		break;
+	case 1:
+		ear_pa_gain = 0x80;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	snd_soc_update_bits(codec, TAPAN_A_RX_EAR_GAIN, 0xE0, ear_pa_gain);
+	return 0;
+}
+
+static int tapan_get_iir_enable_audio_mixer(
+					struct snd_kcontrol *kcontrol,
+					struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+	int iir_idx = ((struct soc_multi_mixer_control *)
+					kcontrol->private_value)->reg;
+	int band_idx = ((struct soc_multi_mixer_control *)
+					kcontrol->private_value)->shift;
+
+	ucontrol->value.integer.value[0] =
+		snd_soc_read(codec, (TAPAN_A_CDC_IIR1_CTL + 16 * iir_idx)) &
+		(1 << band_idx);
+
+	dev_dbg(codec->dev, "%s: IIR #%d band #%d enable %d\n", __func__,
+		iir_idx, band_idx,
+		(uint32_t)ucontrol->value.integer.value[0]);
+	return 0;
+}
+
+static int tapan_put_iir_enable_audio_mixer(
+					struct snd_kcontrol *kcontrol,
+					struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+	int iir_idx = ((struct soc_multi_mixer_control *)
+					kcontrol->private_value)->reg;
+	int band_idx = ((struct soc_multi_mixer_control *)
+					kcontrol->private_value)->shift;
+	int value = ucontrol->value.integer.value[0];
+
+	/* Mask first 5 bits, 6-8 are reserved */
+	snd_soc_update_bits(codec, (TAPAN_A_CDC_IIR1_CTL + 16 * iir_idx),
+		(1 << band_idx), (value << band_idx));
+
+	dev_dbg(codec->dev, "%s: IIR #%d band #%d enable %d\n", __func__,
+		iir_idx, band_idx, value);
+	return 0;
+}
+static uint32_t get_iir_band_coeff(struct snd_soc_codec *codec,
+				int iir_idx, int band_idx,
+				int coeff_idx)
+{
+	/* Address does not automatically update if reading */
+	snd_soc_write(codec,
+		(TAPAN_A_CDC_IIR1_COEF_B1_CTL + 16 * iir_idx),
+		(band_idx * BAND_MAX + coeff_idx) & 0x1F);
+
+	/* Mask bits top 2 bits since they are reserved */
+	return ((snd_soc_read(codec,
+		(TAPAN_A_CDC_IIR1_COEF_B2_CTL + 16 * iir_idx)) << 24)) &
+		0x3FFFFFFF;
+}
+
+static int tapan_get_iir_band_audio_mixer(
+					struct snd_kcontrol *kcontrol,
+					struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+	int iir_idx = ((struct soc_multi_mixer_control *)
+					kcontrol->private_value)->reg;
+	int band_idx = ((struct soc_multi_mixer_control *)
+					kcontrol->private_value)->shift;
+
+	ucontrol->value.integer.value[0] =
+		get_iir_band_coeff(codec, iir_idx, band_idx, 0);
+	ucontrol->value.integer.value[1] =
+		get_iir_band_coeff(codec, iir_idx, band_idx, 1);
+	ucontrol->value.integer.value[2] =
+		get_iir_band_coeff(codec, iir_idx, band_idx, 2);
+	ucontrol->value.integer.value[3] =
+		get_iir_band_coeff(codec, iir_idx, band_idx, 3);
+	ucontrol->value.integer.value[4] =
+		get_iir_band_coeff(codec, iir_idx, band_idx, 4);
+
+	dev_dbg(codec->dev, "%s: IIR #%d band #%d b0 = 0x%x\n"
+		"%s: IIR #%d band #%d b1 = 0x%x\n"
+		"%s: IIR #%d band #%d b2 = 0x%x\n"
+		"%s: IIR #%d band #%d a1 = 0x%x\n"
+		"%s: IIR #%d band #%d a2 = 0x%x\n",
+		__func__, iir_idx, band_idx,
+		(uint32_t)ucontrol->value.integer.value[0],
+		__func__, iir_idx, band_idx,
+		(uint32_t)ucontrol->value.integer.value[1],
+		__func__, iir_idx, band_idx,
+		(uint32_t)ucontrol->value.integer.value[2],
+		__func__, iir_idx, band_idx,
+		(uint32_t)ucontrol->value.integer.value[3],
+		__func__, iir_idx, band_idx,
+		(uint32_t)ucontrol->value.integer.value[4]);
+	return 0;
+}
+
+static void set_iir_band_coeff(struct snd_soc_codec *codec,
+				int iir_idx, int band_idx,
+				int coeff_idx, uint32_t value)
+{
+	/* Mask top 3 bits, 6-8 are reserved */
+	/* Update address manually each time */
+	snd_soc_write(codec,
+		(TAPAN_A_CDC_IIR1_COEF_B1_CTL + 16 * iir_idx),
+		(band_idx * BAND_MAX + coeff_idx) & 0x1F);
+
+	/* Mask top 2 bits, 7-8 are reserved */
+	snd_soc_write(codec,
+		(TAPAN_A_CDC_IIR1_COEF_B2_CTL + 16 * iir_idx),
+		(value >> 24) & 0x3F);
+
+}
+
+static int tapan_put_iir_band_audio_mixer(
+					struct snd_kcontrol *kcontrol,
+					struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+	int iir_idx = ((struct soc_multi_mixer_control *)
+					kcontrol->private_value)->reg;
+	int band_idx = ((struct soc_multi_mixer_control *)
+					kcontrol->private_value)->shift;
+
+	set_iir_band_coeff(codec, iir_idx, band_idx, 0,
+				ucontrol->value.integer.value[0]);
+	set_iir_band_coeff(codec, iir_idx, band_idx, 1,
+				ucontrol->value.integer.value[1]);
+	set_iir_band_coeff(codec, iir_idx, band_idx, 2,
+				ucontrol->value.integer.value[2]);
+	set_iir_band_coeff(codec, iir_idx, band_idx, 3,
+				ucontrol->value.integer.value[3]);
+	set_iir_band_coeff(codec, iir_idx, band_idx, 4,
+				ucontrol->value.integer.value[4]);
+
+	dev_dbg(codec->dev, "%s: IIR #%d band #%d b0 = 0x%x\n"
+		"%s: IIR #%d band #%d b1 = 0x%x\n"
+		"%s: IIR #%d band #%d b2 = 0x%x\n"
+		"%s: IIR #%d band #%d a1 = 0x%x\n"
+		"%s: IIR #%d band #%d a2 = 0x%x\n",
+		__func__, iir_idx, band_idx,
+		get_iir_band_coeff(codec, iir_idx, band_idx, 0),
+		__func__, iir_idx, band_idx,
+		get_iir_band_coeff(codec, iir_idx, band_idx, 1),
+		__func__, iir_idx, band_idx,
+		get_iir_band_coeff(codec, iir_idx, band_idx, 2),
+		__func__, iir_idx, band_idx,
+		get_iir_band_coeff(codec, iir_idx, band_idx, 3),
+		__func__, iir_idx, band_idx,
+		get_iir_band_coeff(codec, iir_idx, band_idx, 4));
+	return 0;
+}
+
+static const char * const tapan_ear_pa_gain_text[] = {"POS_6_DB", "POS_2_DB"};
+static const struct soc_enum tapan_ear_pa_gain_enum[] = {
+		SOC_ENUM_SINGLE_EXT(2, tapan_ear_pa_gain_text),
+};
+
+/*cut of frequency for high pass filter*/
+static const char * const cf_text[] = {
+	"MIN_3DB_4Hz", "MIN_3DB_75Hz", "MIN_3DB_150Hz"
+};
+
+static const struct soc_enum cf_dec1_enum =
+	SOC_ENUM_SINGLE(TAPAN_A_CDC_TX1_MUX_CTL, 4, 3, cf_text);
+
+static const struct soc_enum cf_dec2_enum =
+	SOC_ENUM_SINGLE(TAPAN_A_CDC_TX2_MUX_CTL, 4, 3, cf_text);
+
+static const struct soc_enum cf_dec3_enum =
+	SOC_ENUM_SINGLE(TAPAN_A_CDC_TX3_MUX_CTL, 4, 3, cf_text);
+
+static const struct soc_enum cf_dec4_enum =
+	SOC_ENUM_SINGLE(TAPAN_A_CDC_TX4_MUX_CTL, 4, 3, cf_text);
+
+static const struct soc_enum cf_rxmix1_enum =
+	SOC_ENUM_SINGLE(TAPAN_A_CDC_RX1_B4_CTL, 1, 3, cf_text);
+
+static const struct soc_enum cf_rxmix2_enum =
+	SOC_ENUM_SINGLE(TAPAN_A_CDC_RX2_B4_CTL, 1, 3, cf_text);
+
+static const struct soc_enum cf_rxmix3_enum =
+	SOC_ENUM_SINGLE(TAPAN_A_CDC_RX3_B4_CTL, 1, 3, cf_text);
+
+static const struct soc_enum cf_rxmix4_enum =
+	SOC_ENUM_SINGLE(TAPAN_A_CDC_RX4_B4_CTL, 1, 3, cf_text);
+
+static const struct snd_kcontrol_new tapan_snd_controls[] = {
+
+	SOC_ENUM_EXT("EAR PA Gain", tapan_ear_pa_gain_enum[0],
+		tapan_pa_gain_get, tapan_pa_gain_put),
+
+	SOC_SINGLE_TLV("LINEOUT1 Volume", TAPAN_A_RX_LINE_1_GAIN, 0, 12, 1,
+		line_gain),
+	SOC_SINGLE_TLV("LINEOUT2 Volume", TAPAN_A_RX_LINE_2_GAIN, 0, 12, 1,
+		line_gain),
+
+	SOC_SINGLE_TLV("HPHL Volume", TAPAN_A_RX_HPH_L_GAIN, 0, 12, 1,
+		line_gain),
+	SOC_SINGLE_TLV("HPHR Volume", TAPAN_A_RX_HPH_R_GAIN, 0, 12, 1,
+		line_gain),
+
+	SOC_SINGLE_S8_TLV("RX1 Digital Volume", TAPAN_A_CDC_RX1_VOL_CTL_B2_CTL,
+		-84, 40, digital_gain),
+	SOC_SINGLE_S8_TLV("RX2 Digital Volume", TAPAN_A_CDC_RX2_VOL_CTL_B2_CTL,
+		-84, 40, digital_gain),
+	SOC_SINGLE_S8_TLV("RX3 Digital Volume", TAPAN_A_CDC_RX3_VOL_CTL_B2_CTL,
+		-84, 40, digital_gain),
+	SOC_SINGLE_S8_TLV("RX4 Digital Volume", TAPAN_A_CDC_RX4_VOL_CTL_B2_CTL,
+		-84, 40, digital_gain),
+
+	SOC_SINGLE_S8_TLV("DEC1 Volume", TAPAN_A_CDC_TX1_VOL_CTL_GAIN, -84, 40,
+		digital_gain),
+	SOC_SINGLE_S8_TLV("DEC2 Volume", TAPAN_A_CDC_TX2_VOL_CTL_GAIN, -84, 40,
+		digital_gain),
+	SOC_SINGLE_S8_TLV("DEC3 Volume", TAPAN_A_CDC_TX3_VOL_CTL_GAIN, -84, 40,
+		digital_gain),
+	SOC_SINGLE_S8_TLV("DEC4 Volume", TAPAN_A_CDC_TX4_VOL_CTL_GAIN, -84, 40,
+		digital_gain),
+
+	SOC_SINGLE_S8_TLV("IIR1 INP1 Volume", TAPAN_A_CDC_IIR1_GAIN_B1_CTL, -84,
+		40, digital_gain),
+	SOC_SINGLE_S8_TLV("IIR1 INP2 Volume", TAPAN_A_CDC_IIR1_GAIN_B2_CTL, -84,
+		40, digital_gain),
+	SOC_SINGLE_S8_TLV("IIR1 INP3 Volume", TAPAN_A_CDC_IIR1_GAIN_B3_CTL, -84,
+		40, digital_gain),
+	SOC_SINGLE_S8_TLV("IIR1 INP4 Volume", TAPAN_A_CDC_IIR1_GAIN_B4_CTL, -84,
+		40, digital_gain),
+
+	SOC_SINGLE("MICBIAS1 CAPLESS Switch", TAPAN_A_MICB_1_CTL, 4, 1, 1),
+	SOC_SINGLE("MICBIAS2 CAPLESS Switch", TAPAN_A_MICB_2_CTL, 4, 1, 1),
+	SOC_SINGLE("MICBIAS3 CAPLESS Switch", TAPAN_A_MICB_3_CTL, 4, 1, 1),
+
+	SOC_ENUM("TX1 HPF cut off", cf_dec1_enum),
+	SOC_ENUM("TX2 HPF cut off", cf_dec2_enum),
+	SOC_ENUM("TX3 HPF cut off", cf_dec3_enum),
+	SOC_ENUM("TX4 HPF cut off", cf_dec4_enum),
+
+	SOC_SINGLE("TX1 HPF Switch", TAPAN_A_CDC_TX1_MUX_CTL, 3, 1, 0),
+	SOC_SINGLE("TX2 HPF Switch", TAPAN_A_CDC_TX2_MUX_CTL, 3, 1, 0),
+	SOC_SINGLE("TX3 HPF Switch", TAPAN_A_CDC_TX3_MUX_CTL, 3, 1, 0),
+	SOC_SINGLE("TX4 HPF Switch", TAPAN_A_CDC_TX4_MUX_CTL, 3, 1, 0),
+
+	SOC_SINGLE("RX1 HPF Switch", TAPAN_A_CDC_RX1_B5_CTL, 2, 1, 0),
+	SOC_SINGLE("RX2 HPF Switch", TAPAN_A_CDC_RX2_B5_CTL, 2, 1, 0),
+	SOC_SINGLE("RX3 HPF Switch", TAPAN_A_CDC_RX3_B5_CTL, 2, 1, 0),
+	SOC_SINGLE("RX4 HPF Switch", TAPAN_A_CDC_RX4_B5_CTL, 2, 1, 0),
+
+	SOC_ENUM("RX1 HPF cut off", cf_rxmix1_enum),
+	SOC_ENUM("RX2 HPF cut off", cf_rxmix2_enum),
+	SOC_ENUM("RX3 HPF cut off", cf_rxmix3_enum),
+	SOC_ENUM("RX4 HPF cut off", cf_rxmix4_enum),
+
+	SOC_SINGLE_EXT("IIR1 Enable Band1", IIR1, BAND1, 1, 0,
+	tapan_get_iir_enable_audio_mixer, tapan_put_iir_enable_audio_mixer),
+	SOC_SINGLE_EXT("IIR1 Enable Band2", IIR1, BAND2, 1, 0,
+	tapan_get_iir_enable_audio_mixer, tapan_put_iir_enable_audio_mixer),
+	SOC_SINGLE_EXT("IIR1 Enable Band3", IIR1, BAND3, 1, 0,
+	tapan_get_iir_enable_audio_mixer, tapan_put_iir_enable_audio_mixer),
+	SOC_SINGLE_EXT("IIR1 Enable Band4", IIR1, BAND4, 1, 0,
+	tapan_get_iir_enable_audio_mixer, tapan_put_iir_enable_audio_mixer),
+	SOC_SINGLE_EXT("IIR1 Enable Band5", IIR1, BAND5, 1, 0,
+	tapan_get_iir_enable_audio_mixer, tapan_put_iir_enable_audio_mixer),
+	SOC_SINGLE_EXT("IIR2 Enable Band1", IIR2, BAND1, 1, 0,
+	tapan_get_iir_enable_audio_mixer, tapan_put_iir_enable_audio_mixer),
+	SOC_SINGLE_EXT("IIR2 Enable Band2", IIR2, BAND2, 1, 0,
+	tapan_get_iir_enable_audio_mixer, tapan_put_iir_enable_audio_mixer),
+	SOC_SINGLE_EXT("IIR2 Enable Band3", IIR2, BAND3, 1, 0,
+	tapan_get_iir_enable_audio_mixer, tapan_put_iir_enable_audio_mixer),
+	SOC_SINGLE_EXT("IIR2 Enable Band4", IIR2, BAND4, 1, 0,
+	tapan_get_iir_enable_audio_mixer, tapan_put_iir_enable_audio_mixer),
+	SOC_SINGLE_EXT("IIR2 Enable Band5", IIR2, BAND5, 1, 0,
+	tapan_get_iir_enable_audio_mixer, tapan_put_iir_enable_audio_mixer),
+
+	SOC_SINGLE_MULTI_EXT("IIR1 Band1", IIR1, BAND1, 255, 0, 5,
+	tapan_get_iir_band_audio_mixer, tapan_put_iir_band_audio_mixer),
+	SOC_SINGLE_MULTI_EXT("IIR1 Band2", IIR1, BAND2, 255, 0, 5,
+	tapan_get_iir_band_audio_mixer, tapan_put_iir_band_audio_mixer),
+	SOC_SINGLE_MULTI_EXT("IIR1 Band3", IIR1, BAND3, 255, 0, 5,
+	tapan_get_iir_band_audio_mixer, tapan_put_iir_band_audio_mixer),
+	SOC_SINGLE_MULTI_EXT("IIR1 Band4", IIR1, BAND4, 255, 0, 5,
+	tapan_get_iir_band_audio_mixer, tapan_put_iir_band_audio_mixer),
+	SOC_SINGLE_MULTI_EXT("IIR1 Band5", IIR1, BAND5, 255, 0, 5,
+	tapan_get_iir_band_audio_mixer, tapan_put_iir_band_audio_mixer),
+	SOC_SINGLE_MULTI_EXT("IIR2 Band1", IIR2, BAND1, 255, 0, 5,
+	tapan_get_iir_band_audio_mixer, tapan_put_iir_band_audio_mixer),
+	SOC_SINGLE_MULTI_EXT("IIR2 Band2", IIR2, BAND2, 255, 0, 5,
+	tapan_get_iir_band_audio_mixer, tapan_put_iir_band_audio_mixer),
+	SOC_SINGLE_MULTI_EXT("IIR2 Band3", IIR2, BAND3, 255, 0, 5,
+	tapan_get_iir_band_audio_mixer, tapan_put_iir_band_audio_mixer),
+	SOC_SINGLE_MULTI_EXT("IIR2 Band4", IIR2, BAND4, 255, 0, 5,
+	tapan_get_iir_band_audio_mixer, tapan_put_iir_band_audio_mixer),
+	SOC_SINGLE_MULTI_EXT("IIR2 Band5", IIR2, BAND5, 255, 0, 5,
+	tapan_get_iir_band_audio_mixer, tapan_put_iir_band_audio_mixer),
+
+};
+
+static const char * const rx_mix1_text[] = {
+	"ZERO", "SRC1", "SRC2", "IIR1", "IIR2", "RX1", "RX2", "RX3", "RX4",
+		"RX5", "RX6", "RX7"
+};
+
+static const char * const rx_mix2_text[] = {
+	"ZERO", "SRC1", "SRC2", "IIR1", "IIR2"
+};
+
+static const char * const rx_rdac5_text[] = {
+	"DEM4", "DEM3_INV"
+};
+
+static const char * const rx_rdac7_text[] = {
+	"DEM6", "DEM5_INV"
+};
+
+static const char * const sb_tx1_mux_text[] = {
+	"ZERO", "RMIX1", "RMIX2", "RMIX3", "RMIX4", "RMIX5", "RMIX6", "RMIX7",
+		"DEC1"
+};
+
+static const char * const sb_tx2_mux_text[] = {
+	"ZERO", "RMIX1", "RMIX2", "RMIX3", "RMIX4", "RMIX5", "RMIX6", "RMIX7",
+		"DEC2"
+};
+
+static const char * const sb_tx3_mux_text[] = {
+	"ZERO", "RMIX1", "RMIX2", "RMIX3", "RMIX4", "RMIX5", "RMIX6", "RMIX7",
+		"DEC3"
+};
+
+static const char * const sb_tx4_mux_text[] = {
+	"ZERO", "RMIX1", "RMIX2", "RMIX3", "RMIX4", "RMIX5", "RMIX6", "RMIX7",
+		"DEC4"
+};
+
+static const char * const dec1_mux_text[] = {
+	"ZERO", "DMIC1", "ADC6",
+};
+
+static const char * const dec2_mux_text[] = {
+	"ZERO", "DMIC2", "ADC5",
+};
+
+static const char * const dec3_mux_text[] = {
+	"ZERO", "DMIC3", "ADC4",
+};
+
+static const char * const dec4_mux_text[] = {
+	"ZERO", "DMIC4", "ADC3",
+};
+
+static const char * const anc_mux_text[] = {
+	"ZERO", "ADC1", "ADC2", "ADC3", "ADC4", "ADC5", "ADC6", "ADC_MB",
+		"RSVD_1", "DMIC1", "DMIC2", "DMIC3", "DMIC4", "DMIC5", "DMIC6"
+};
+
+static const char * const anc1_fb_mux_text[] = {
+	"ZERO", "EAR_HPH_L", "EAR_LINE_1",
+};
+
+static const char * const iir1_inp1_text[] = {
+	"ZERO", "DEC1", "DEC2", "DEC3", "DEC4", "DEC5", "DEC6", "DEC7", "DEC8",
+	"DEC9", "DEC10", "RX1", "RX2", "RX3", "RX4", "RX5", "RX6", "RX7"
+};
+
+static const struct soc_enum rx_mix1_inp1_chain_enum =
+	SOC_ENUM_SINGLE(TAPAN_A_CDC_CONN_RX1_B1_CTL, 0, 12, rx_mix1_text);
+
+static const struct soc_enum rx_mix1_inp2_chain_enum =
+	SOC_ENUM_SINGLE(TAPAN_A_CDC_CONN_RX1_B1_CTL, 4, 12, rx_mix1_text);
+
+static const struct soc_enum rx_mix1_inp3_chain_enum =
+	SOC_ENUM_SINGLE(TAPAN_A_CDC_CONN_RX1_B2_CTL, 0, 12, rx_mix1_text);
+
+static const struct soc_enum rx2_mix1_inp1_chain_enum =
+	SOC_ENUM_SINGLE(TAPAN_A_CDC_CONN_RX2_B1_CTL, 0, 12, rx_mix1_text);
+
+static const struct soc_enum rx2_mix1_inp2_chain_enum =
+	SOC_ENUM_SINGLE(TAPAN_A_CDC_CONN_RX2_B1_CTL, 4, 12, rx_mix1_text);
+
+static const struct soc_enum rx3_mix1_inp1_chain_enum =
+	SOC_ENUM_SINGLE(TAPAN_A_CDC_CONN_RX3_B1_CTL, 0, 12, rx_mix1_text);
+
+static const struct soc_enum rx3_mix1_inp2_chain_enum =
+	SOC_ENUM_SINGLE(TAPAN_A_CDC_CONN_RX3_B1_CTL, 4, 12, rx_mix1_text);
+
+static const struct soc_enum rx4_mix1_inp1_chain_enum =
+	SOC_ENUM_SINGLE(TAPAN_A_CDC_CONN_RX4_B1_CTL, 0, 12, rx_mix1_text);
+
+static const struct soc_enum rx4_mix1_inp2_chain_enum =
+	SOC_ENUM_SINGLE(TAPAN_A_CDC_CONN_RX4_B1_CTL, 4, 12, rx_mix1_text);
+
+static const struct soc_enum rx1_mix2_inp1_chain_enum =
+	SOC_ENUM_SINGLE(TAPAN_A_CDC_CONN_RX1_B3_CTL, 0, 5, rx_mix2_text);
+
+static const struct soc_enum rx1_mix2_inp2_chain_enum =
+	SOC_ENUM_SINGLE(TAPAN_A_CDC_CONN_RX1_B3_CTL, 3, 5, rx_mix2_text);
+
+static const struct soc_enum rx2_mix2_inp1_chain_enum =
+	SOC_ENUM_SINGLE(TAPAN_A_CDC_CONN_RX2_B3_CTL, 0, 5, rx_mix2_text);
+
+static const struct soc_enum rx2_mix2_inp2_chain_enum =
+	SOC_ENUM_SINGLE(TAPAN_A_CDC_CONN_RX2_B3_CTL, 3, 5, rx_mix2_text);
+
+static const struct soc_enum rx_rdac5_enum =
+	SOC_ENUM_SINGLE(TAPAN_A_CDC_CONN_MISC, 2, 2, rx_rdac5_text);
+
+static const struct soc_enum rx_rdac7_enum =
+	SOC_ENUM_SINGLE(TAPAN_A_CDC_CONN_MISC, 1, 2, rx_rdac7_text);
+
+static const struct soc_enum sb_tx1_mux_enum =
+	SOC_ENUM_SINGLE(TAPAN_A_CDC_CONN_TX_SB_B1_CTL, 0, 9, sb_tx1_mux_text);
+
+static const struct soc_enum sb_tx2_mux_enum =
+	SOC_ENUM_SINGLE(TAPAN_A_CDC_CONN_TX_SB_B2_CTL, 0, 9, sb_tx2_mux_text);
+
+static const struct soc_enum sb_tx3_mux_enum =
+	SOC_ENUM_SINGLE(TAPAN_A_CDC_CONN_TX_SB_B3_CTL, 0, 9, sb_tx3_mux_text);
+
+static const struct soc_enum sb_tx4_mux_enum =
+	SOC_ENUM_SINGLE(TAPAN_A_CDC_CONN_TX_SB_B4_CTL, 0, 9, sb_tx4_mux_text);
+
+static const struct soc_enum dec1_mux_enum =
+	SOC_ENUM_SINGLE(TAPAN_A_CDC_CONN_TX_B1_CTL, 0, 3, dec1_mux_text);
+
+static const struct soc_enum dec2_mux_enum =
+	SOC_ENUM_SINGLE(TAPAN_A_CDC_CONN_TX_B1_CTL, 2, 3, dec2_mux_text);
+
+static const struct soc_enum dec3_mux_enum =
+	SOC_ENUM_SINGLE(TAPAN_A_CDC_CONN_TX_B1_CTL, 4, 3, dec3_mux_text);
+
+static const struct soc_enum dec4_mux_enum =
+	SOC_ENUM_SINGLE(TAPAN_A_CDC_CONN_TX_B1_CTL, 6, 3, dec4_mux_text);
+
+static const struct soc_enum iir1_inp1_mux_enum =
+	SOC_ENUM_SINGLE(TAPAN_A_CDC_CONN_EQ1_B1_CTL, 0, 18, iir1_inp1_text);
+
+static const struct snd_kcontrol_new rx_mix1_inp1_mux =
+	SOC_DAPM_ENUM("RX1 MIX1 INP1 Mux", rx_mix1_inp1_chain_enum);
+
+static const struct snd_kcontrol_new rx_mix1_inp2_mux =
+	SOC_DAPM_ENUM("RX1 MIX1 INP2 Mux", rx_mix1_inp2_chain_enum);
+
+static const struct snd_kcontrol_new rx_mix1_inp3_mux =
+	SOC_DAPM_ENUM("RX1 MIX1 INP3 Mux", rx_mix1_inp3_chain_enum);
+
+static const struct snd_kcontrol_new rx2_mix1_inp1_mux =
+	SOC_DAPM_ENUM("RX2 MIX1 INP1 Mux", rx2_mix1_inp1_chain_enum);
+
+static const struct snd_kcontrol_new rx2_mix1_inp2_mux =
+	SOC_DAPM_ENUM("RX2 MIX1 INP2 Mux", rx2_mix1_inp2_chain_enum);
+
+static const struct snd_kcontrol_new rx3_mix1_inp1_mux =
+	SOC_DAPM_ENUM("RX3 MIX1 INP1 Mux", rx3_mix1_inp1_chain_enum);
+
+static const struct snd_kcontrol_new rx3_mix1_inp2_mux =
+	SOC_DAPM_ENUM("RX3 MIX1 INP2 Mux", rx3_mix1_inp2_chain_enum);
+
+static const struct snd_kcontrol_new rx4_mix1_inp1_mux =
+	SOC_DAPM_ENUM("RX4 MIX1 INP1 Mux", rx4_mix1_inp1_chain_enum);
+
+static const struct snd_kcontrol_new rx4_mix1_inp2_mux =
+	SOC_DAPM_ENUM("RX4 MIX1 INP2 Mux", rx4_mix1_inp2_chain_enum);
+
+static const struct snd_kcontrol_new rx1_mix2_inp1_mux =
+	SOC_DAPM_ENUM("RX1 MIX2 INP1 Mux", rx1_mix2_inp1_chain_enum);
+
+static const struct snd_kcontrol_new rx1_mix2_inp2_mux =
+	SOC_DAPM_ENUM("RX1 MIX2 INP2 Mux", rx1_mix2_inp2_chain_enum);
+
+static const struct snd_kcontrol_new rx2_mix2_inp1_mux =
+	SOC_DAPM_ENUM("RX2 MIX2 INP1 Mux", rx2_mix2_inp1_chain_enum);
+
+static const struct snd_kcontrol_new rx2_mix2_inp2_mux =
+	SOC_DAPM_ENUM("RX2 MIX2 INP2 Mux", rx2_mix2_inp2_chain_enum);
+
+static const struct snd_kcontrol_new rx_dac5_mux =
+	SOC_DAPM_ENUM("RDAC5 MUX Mux", rx_rdac5_enum);
+
+static const struct snd_kcontrol_new sb_tx1_mux =
+	SOC_DAPM_ENUM("SLIM TX1 MUX Mux", sb_tx1_mux_enum);
+
+static const struct snd_kcontrol_new sb_tx2_mux =
+	SOC_DAPM_ENUM("SLIM TX2 MUX Mux", sb_tx2_mux_enum);
+
+static const struct snd_kcontrol_new sb_tx3_mux =
+	SOC_DAPM_ENUM("SLIM TX3 MUX Mux", sb_tx3_mux_enum);
+
+static const struct snd_kcontrol_new sb_tx4_mux =
+	SOC_DAPM_ENUM("SLIM TX4 MUX Mux", sb_tx4_mux_enum);
+
+/*static const struct snd_kcontrol_new sb_tx5_mux =
+	SOC_DAPM_ENUM("SLIM TX5 MUX Mux", sb_tx5_mux_enum);
+*/
+
+static int wcd9306_put_dec_enum(struct snd_kcontrol *kcontrol,
+			      struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_dapm_widget_list *wlist = snd_kcontrol_chip(kcontrol);
+	struct snd_soc_dapm_widget *w = wlist->widgets[0];
+	struct snd_soc_codec *codec = w->codec;
+	struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
+	unsigned int dec_mux, decimator;
+	char *dec_name = NULL;
+	char *widget_name = NULL;
+	char *temp;
+	u16 tx_mux_ctl_reg;
+	u8 adc_dmic_sel = 0x0;
+	int ret = 0;
+
+	if (ucontrol->value.enumerated.item[0] > e->max - 1)
+		return -EINVAL;
+
+	dec_mux = ucontrol->value.enumerated.item[0];
+
+	widget_name = kstrndup(w->name, 15, GFP_KERNEL);
+	if (!widget_name)
+		return -ENOMEM;
+	temp = widget_name;
+
+	dec_name = strsep(&widget_name, " ");
+	widget_name = temp;
+	if (!dec_name) {
+		pr_err("%s: Invalid decimator = %s\n", __func__, w->name);
+		ret =  -EINVAL;
+		goto out;
+	}
+
+	ret = kstrtouint(strpbrk(dec_name, "1234"), 10, &decimator);
+	if (ret < 0) {
+		pr_err("%s: Invalid decimator = %s\n", __func__, dec_name);
+		ret =  -EINVAL;
+		goto out;
+	}
+
+	dev_dbg(w->dapm->dev, "%s(): widget = %s decimator = %u dec_mux = %u\n"
+		, __func__, w->name, decimator, dec_mux);
+
+	switch (decimator) {
+	case 1:
+	case 2:
+	case 3:
+	case 4:
+	case 5:
+	case 6:
+		if (dec_mux == 1)
+			adc_dmic_sel = 0x1;
+		else
+			adc_dmic_sel = 0x0;
+		break;
+	case 7:
+	case 8:
+	case 9:
+	case 10:
+		if ((dec_mux == 1) || (dec_mux == 2))
+			adc_dmic_sel = 0x1;
+		else
+			adc_dmic_sel = 0x0;
+		break;
+	default:
+		pr_err("%s: Invalid Decimator = %u\n", __func__, decimator);
+		ret = -EINVAL;
+		goto out;
+	}
+
+	tx_mux_ctl_reg = TAPAN_A_CDC_TX1_MUX_CTL + 8 * (decimator - 1);
+
+	snd_soc_update_bits(codec, tx_mux_ctl_reg, 0x1, adc_dmic_sel);
+
+	ret = snd_soc_dapm_put_enum_double(kcontrol, ucontrol);
+
+out:
+	kfree(widget_name);
+	return ret;
+}
+
+#define WCD9306_DEC_ENUM(xname, xenum) \
+{	.iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
+	.info = snd_soc_info_enum_double, \
+	.get = snd_soc_dapm_get_enum_double, \
+	.put = wcd9306_put_dec_enum, \
+	.private_value = (unsigned long)&xenum }
+
+static const struct snd_kcontrol_new dec1_mux =
+	WCD9306_DEC_ENUM("DEC1 MUX Mux", dec1_mux_enum);
+
+static const struct snd_kcontrol_new dec2_mux =
+	WCD9306_DEC_ENUM("DEC2 MUX Mux", dec2_mux_enum);
+
+static const struct snd_kcontrol_new dec3_mux =
+	WCD9306_DEC_ENUM("DEC3 MUX Mux", dec3_mux_enum);
+
+static const struct snd_kcontrol_new dec4_mux =
+	WCD9306_DEC_ENUM("DEC4 MUX Mux", dec4_mux_enum);
+
+static const struct snd_kcontrol_new iir1_inp1_mux =
+	SOC_DAPM_ENUM("IIR1 INP1 Mux", iir1_inp1_mux_enum);
+
+static const struct snd_kcontrol_new dac1_switch[] = {
+	SOC_DAPM_SINGLE("Switch", TAPAN_A_RX_EAR_EN, 5, 1, 0)
+};
+static const struct snd_kcontrol_new hphl_switch[] = {
+	SOC_DAPM_SINGLE("Switch", TAPAN_A_RX_HPH_L_DAC_CTL, 6, 1, 0)
+};
+
+static const struct snd_kcontrol_new hphl_pa_mix[] = {
+	SOC_DAPM_SINGLE("AUX_PGA_L Switch", TAPAN_A_RX_PA_AUX_IN_CONN,
+					7, 1, 0),
+};
+
+static const struct snd_kcontrol_new hphr_pa_mix[] = {
+	SOC_DAPM_SINGLE("AUX_PGA_R Switch", TAPAN_A_RX_PA_AUX_IN_CONN,
+					6, 1, 0),
+};
+
+static const struct snd_kcontrol_new ear_pa_mix[] = {
+	SOC_DAPM_SINGLE("AUX_PGA_L Switch", TAPAN_A_RX_PA_AUX_IN_CONN,
+					5, 1, 0),
+};
+static const struct snd_kcontrol_new lineout1_pa_mix[] = {
+	SOC_DAPM_SINGLE("AUX_PGA_L Switch", TAPAN_A_RX_PA_AUX_IN_CONN,
+					4, 1, 0),
+};
+
+static const struct snd_kcontrol_new lineout2_pa_mix[] = {
+	SOC_DAPM_SINGLE("AUX_PGA_R Switch", TAPAN_A_RX_PA_AUX_IN_CONN,
+					3, 1, 0),
+};
+
+static const struct snd_kcontrol_new lineout3_pa_mix[] = {
+	SOC_DAPM_SINGLE("AUX_PGA_L Switch", TAPAN_A_RX_PA_AUX_IN_CONN,
+					2, 1, 0),
+};
+
+static const struct snd_kcontrol_new lineout4_pa_mix[] = {
+	SOC_DAPM_SINGLE("AUX_PGA_R Switch", TAPAN_A_RX_PA_AUX_IN_CONN,
+					1, 1, 0),
+};
+
+/* virtual port entries */
+static int slim_tx_mixer_get(struct snd_kcontrol *kcontrol,
+			     struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_dapm_widget_list *wlist = snd_kcontrol_chip(kcontrol);
+	struct snd_soc_dapm_widget *widget = wlist->widgets[0];
+
+	ucontrol->value.integer.value[0] = widget->value;
+	return 0;
+}
+
+static int slim_tx_mixer_put(struct snd_kcontrol *kcontrol,
+			     struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_dapm_widget_list *wlist = snd_kcontrol_chip(kcontrol);
+	struct snd_soc_dapm_widget *widget = wlist->widgets[0];
+	struct snd_soc_codec *codec = widget->codec;
+	struct tapan_priv *tapan_p = snd_soc_codec_get_drvdata(codec);
+	struct wcd9xxx *core = dev_get_drvdata(codec->dev->parent);
+	struct soc_multi_mixer_control *mixer =
+		((struct soc_multi_mixer_control *)kcontrol->private_value);
+	u32 dai_id = widget->shift;
+	u32 port_id = mixer->shift;
+	u32 enable = ucontrol->value.integer.value[0];
+
+	dev_dbg(codec->dev, "%s: wname %s cname %s\n",
+		__func__, widget->name,	ucontrol->id.name);
+	dev_dbg(codec->dev, "%s: value %u shift %d item %ld\n",
+		__func__, widget->value, widget->shift,
+		ucontrol->value.integer.value[0]);
+
+	mutex_lock(&codec->mutex);
+
+	if (tapan_p->intf_type != WCD9XXX_INTERFACE_TYPE_SLIMBUS) {
+		if (dai_id != AIF1_CAP) {
+			dev_err(codec->dev, "%s: invalid AIF for I2C mode\n",
+				__func__);
+			mutex_unlock(&codec->mutex);
+			return -EINVAL;
+		}
+	}
+	switch (dai_id) {
+	case AIF1_CAP:
+	case AIF2_CAP:
+	case AIF3_CAP:
+		/* only add to the list if value not set
+		 */
+		if (enable && !(widget->value & 1 << port_id)) {
+			if (wcd9xxx_tx_vport_validation(
+						vport_check_table[dai_id],
+						port_id,
+						tapan_p->dai)) {
+				dev_dbg(codec->dev, "%s: TX%u is used by other virtual port\n",
+					__func__, port_id + 1);
+				mutex_unlock(&codec->mutex);
+				return -EINVAL;
+			}
+			widget->value |= 1 << port_id;
+			list_add_tail(&core->tx_chs[port_id].list,
+				      &tapan_p->dai[dai_id].wcd9xxx_ch_list
+				      );
+		} else if (!enable && (widget->value & 1 << port_id)) {
+			widget->value &= ~(1 << port_id);
+			list_del_init(&core->tx_chs[port_id].list);
+		} else {
+			if (enable)
+				dev_dbg(codec->dev, "%s: TX%u port is used by this virtual port\n",
+					__func__, port_id + 1);
+			else
+				dev_dbg(codec->dev, "%s: TX%u port is not used by this virtual port\n",
+					__func__, port_id + 1);
+			/* avoid update power function */
+			mutex_unlock(&codec->mutex);
+			return 0;
+		}
+		break;
+	default:
+		pr_err("Unknown AIF %d\n", dai_id);
+		mutex_unlock(&codec->mutex);
+		return -EINVAL;
+	}
+	dev_dbg(codec->dev, "%s: name %s sname %s updated value %u shift %d\n",
+		 __func__, widget->name, widget->sname,
+		 widget->value, widget->shift);
+
+	snd_soc_dapm_mixer_update_power(widget, kcontrol, enable);
+
+	mutex_unlock(&codec->mutex);
+	return 0;
+}
+
+static int slim_rx_mux_get(struct snd_kcontrol *kcontrol,
+			   struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_dapm_widget_list *wlist = snd_kcontrol_chip(kcontrol);
+	struct snd_soc_dapm_widget *widget = wlist->widgets[0];
+
+	ucontrol->value.enumerated.item[0] = widget->value;
+	return 0;
+}
+
+static const char *const slim_rx_mux_text[] = {
+	"ZERO", "AIF1_PB", "AIF2_PB", "AIF3_PB"
+};
+
+static int slim_rx_mux_put(struct snd_kcontrol *kcontrol,
+			   struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_dapm_widget_list *wlist = snd_kcontrol_chip(kcontrol);
+	struct snd_soc_dapm_widget *widget = wlist->widgets[0];
+	struct snd_soc_codec *codec = widget->codec;
+	struct tapan_priv *tapan_p = snd_soc_codec_get_drvdata(codec);
+	struct wcd9xxx *core = dev_get_drvdata(codec->dev->parent);
+	struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
+	u32 port_id = widget->shift;
+
+	dev_dbg(codec->dev, "%s: wname %s cname %s value %u shift %d item %ld\n",
+		 __func__, widget->name, ucontrol->id.name, widget->value,
+		 widget->shift, ucontrol->value.integer.value[0]);
+
+	widget->value = ucontrol->value.enumerated.item[0];
+
+	mutex_lock(&codec->mutex);
+
+	if (tapan_p->intf_type != WCD9XXX_INTERFACE_TYPE_SLIMBUS) {
+		if (widget->value > 1) {
+			dev_err(codec->dev, "%s: invalid AIF for I2C mode\n",
+				__func__);
+			goto err;
+		}
+	}
+	/* value need to match the Virtual port and AIF number
+	 */
+	switch (widget->value) {
+	case 0:
+		list_del_init(&core->rx_chs[port_id].list);
+	break;
+	case 1:
+		if (wcd9xxx_rx_vport_validation(port_id + core->num_tx_port,
+			&tapan_p->dai[AIF1_PB].wcd9xxx_ch_list))
+			goto pr_err;
+		list_add_tail(&core->rx_chs[port_id].list,
+			      &tapan_p->dai[AIF1_PB].wcd9xxx_ch_list);
+	break;
+	case 2:
+		if (wcd9xxx_rx_vport_validation(port_id + core->num_tx_port,
+			&tapan_p->dai[AIF1_PB].wcd9xxx_ch_list))
+			goto pr_err;
+		list_add_tail(&core->rx_chs[port_id].list,
+			      &tapan_p->dai[AIF2_PB].wcd9xxx_ch_list);
+	break;
+	case 3:
+		if (wcd9xxx_rx_vport_validation(port_id + core->num_tx_port,
+			&tapan_p->dai[AIF1_PB].wcd9xxx_ch_list))
+			goto pr_err;
+		list_add_tail(&core->rx_chs[port_id].list,
+			      &tapan_p->dai[AIF3_PB].wcd9xxx_ch_list);
+	break;
+	default:
+		pr_err("Unknown AIF %d\n", widget->value);
+		goto err;
+	}
+
+	snd_soc_dapm_mux_update_power(widget, kcontrol, 1, widget->value, e);
+
+	mutex_unlock(&codec->mutex);
+	return 0;
+pr_err:
+	pr_err("%s: RX%u is used by current requesting AIF_PB itself\n",
+		__func__, port_id + 1);
+err:
+	mutex_unlock(&codec->mutex);
+	return -EINVAL;
+}
+
+static const struct soc_enum slim_rx_mux_enum =
+	SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(slim_rx_mux_text), slim_rx_mux_text);
+
+static const struct snd_kcontrol_new slim_rx_mux[TAPAN_RX_MAX] = {
+	SOC_DAPM_ENUM_EXT("SLIM RX1 Mux", slim_rx_mux_enum,
+			  slim_rx_mux_get, slim_rx_mux_put),
+	SOC_DAPM_ENUM_EXT("SLIM RX2 Mux", slim_rx_mux_enum,
+			  slim_rx_mux_get, slim_rx_mux_put),
+	SOC_DAPM_ENUM_EXT("SLIM RX3 Mux", slim_rx_mux_enum,
+			  slim_rx_mux_get, slim_rx_mux_put),
+	SOC_DAPM_ENUM_EXT("SLIM RX4 Mux", slim_rx_mux_enum,
+			  slim_rx_mux_get, slim_rx_mux_put),
+	SOC_DAPM_ENUM_EXT("SLIM RX5 Mux", slim_rx_mux_enum,
+			  slim_rx_mux_get, slim_rx_mux_put),
+};
+
+static const struct snd_kcontrol_new aif_cap_mixer[] = {
+	SOC_SINGLE_EXT("SLIM TX1", SND_SOC_NOPM, TAPAN_TX1, 1, 0,
+			slim_tx_mixer_get, slim_tx_mixer_put),
+	SOC_SINGLE_EXT("SLIM TX2", SND_SOC_NOPM, TAPAN_TX2, 1, 0,
+			slim_tx_mixer_get, slim_tx_mixer_put),
+	SOC_SINGLE_EXT("SLIM TX3", SND_SOC_NOPM, TAPAN_TX3, 1, 0,
+			slim_tx_mixer_get, slim_tx_mixer_put),
+	SOC_SINGLE_EXT("SLIM TX4", SND_SOC_NOPM, TAPAN_TX4, 1, 0,
+			slim_tx_mixer_get, slim_tx_mixer_put),
+	SOC_SINGLE_EXT("SLIM TX5", SND_SOC_NOPM, TAPAN_TX5, 1, 0,
+			slim_tx_mixer_get, slim_tx_mixer_put),
+};
+
+static int tapan_codec_enable_aux_pga(struct snd_soc_dapm_widget *w,
+	struct snd_kcontrol *kcontrol, int event)
+{
+	struct snd_soc_codec *codec = w->codec;
+	struct tapan_priv *tapan = snd_soc_codec_get_drvdata(codec);
+
+	dev_dbg(codec->dev, "%s: %d\n", __func__, event);
+
+	switch (event) {
+	case SND_SOC_DAPM_PRE_PMU:
+		WCD9XXX_BCL_LOCK(&tapan->resmgr);
+		wcd9xxx_resmgr_get_bandgap(&tapan->resmgr,
+					   WCD9XXX_BANDGAP_AUDIO_MODE);
+		/* AUX PGA requires RCO or MCLK */
+		wcd9xxx_resmgr_get_clk_block(&tapan->resmgr, WCD9XXX_CLK_RCO);
+		wcd9xxx_resmgr_enable_rx_bias(&tapan->resmgr, 1);
+		WCD9XXX_BCL_UNLOCK(&tapan->resmgr);
+		break;
+
+	case SND_SOC_DAPM_POST_PMD:
+		WCD9XXX_BCL_LOCK(&tapan->resmgr);
+		wcd9xxx_resmgr_enable_rx_bias(&tapan->resmgr, 0);
+		wcd9xxx_resmgr_put_bandgap(&tapan->resmgr,
+					   WCD9XXX_BANDGAP_AUDIO_MODE);
+		wcd9xxx_resmgr_put_clk_block(&tapan->resmgr, WCD9XXX_CLK_RCO);
+		WCD9XXX_BCL_UNLOCK(&tapan->resmgr);
+		break;
+	}
+	return 0;
+}
+
+static int tapan_codec_enable_lineout(struct snd_soc_dapm_widget *w,
+		struct snd_kcontrol *kcontrol, int event)
+{
+	struct snd_soc_codec *codec = w->codec;
+	u16 lineout_gain_reg;
+
+	dev_dbg(codec->dev, "%s %d %s\n", __func__, event, w->name);
+
+	switch (w->shift) {
+	case 0:
+		lineout_gain_reg = TAPAN_A_RX_LINE_1_GAIN;
+		break;
+	case 1:
+		lineout_gain_reg = TAPAN_A_RX_LINE_2_GAIN;
+		break;
+	default:
+		pr_err("%s: Error, incorrect lineout register value\n",
+			__func__);
+		return -EINVAL;
+	}
+
+	switch (event) {
+	case SND_SOC_DAPM_PRE_PMU:
+		snd_soc_update_bits(codec, lineout_gain_reg, 0x40, 0x40);
+		break;
+	case SND_SOC_DAPM_POST_PMU:
+		dev_dbg(codec->dev, "%s: sleeping 16 ms after %s PA turn on\n",
+				__func__, w->name);
+		usleep_range(16000, 16000);
+		break;
+	case SND_SOC_DAPM_POST_PMD:
+		snd_soc_update_bits(codec, lineout_gain_reg, 0x40, 0x00);
+		break;
+	}
+	return 0;
+}
+
+static int tapan_codec_enable_spk_pa(struct snd_soc_dapm_widget *w,
+				     struct snd_kcontrol *kcontrol, int event)
+{
+	dev_dbg(w->codec->dev, "%s %d %s\n", __func__, event, w->name);
+	return 0;
+}
+
+static int tapan_codec_enable_dmic(struct snd_soc_dapm_widget *w,
+	struct snd_kcontrol *kcontrol, int event)
+{
+	struct snd_soc_codec *codec = w->codec;
+	struct tapan_priv *tapan = snd_soc_codec_get_drvdata(codec);
+	u8  dmic_clk_en;
+	u16 dmic_clk_reg;
+	s32 *dmic_clk_cnt;
+	unsigned int dmic;
+	int ret;
+
+	ret = kstrtouint(strpbrk(w->name, "123456"), 10, &dmic);
+	if (ret < 0) {
+		pr_err("%s: Invalid DMIC line on the codec\n", __func__);
+		return -EINVAL;
+	}
+
+	switch (dmic) {
+	case 1:
+	case 2:
+		dmic_clk_en = 0x01;
+		dmic_clk_cnt = &(tapan->dmic_1_2_clk_cnt);
+		dmic_clk_reg = TAPAN_A_CDC_CLK_DMIC_B1_CTL;
+		dev_dbg(codec->dev, "%s() event %d DMIC%d dmic_1_2_clk_cnt %d\n",
+			__func__, event,  dmic, *dmic_clk_cnt);
+
+		break;
+
+	case 3:
+	case 4:
+		dmic_clk_en = 0x10;
+		dmic_clk_cnt = &(tapan->dmic_3_4_clk_cnt);
+		dmic_clk_reg = TAPAN_A_CDC_CLK_DMIC_B1_CTL;
+
+		dev_dbg(codec->dev, "%s() event %d DMIC%d dmic_3_4_clk_cnt %d\n",
+			__func__, event,  dmic, *dmic_clk_cnt);
+		break;
+
+	case 5:
+	case 6:
+		dmic_clk_en = 0x01;
+		dmic_clk_cnt = &(tapan->dmic_5_6_clk_cnt);
+		dmic_clk_reg = TAPAN_A_CDC_CLK_DMIC_B2_CTL;
+
+		dev_dbg(codec->dev, "%s() event %d DMIC%d dmic_5_6_clk_cnt %d\n",
+			__func__, event,  dmic, *dmic_clk_cnt);
+
+		break;
+
+	default:
+		pr_err("%s: Invalid DMIC Selection\n", __func__);
+		return -EINVAL;
+	}
+
+	switch (event) {
+	case SND_SOC_DAPM_PRE_PMU:
+
+		(*dmic_clk_cnt)++;
+		if (*dmic_clk_cnt == 1)
+			snd_soc_update_bits(codec, dmic_clk_reg,
+					dmic_clk_en, dmic_clk_en);
+
+		break;
+	case SND_SOC_DAPM_POST_PMD:
+
+		(*dmic_clk_cnt)--;
+		if (*dmic_clk_cnt  == 0)
+			snd_soc_update_bits(codec, dmic_clk_reg,
+					dmic_clk_en, 0);
+		break;
+	}
+	return 0;
+}
+
+static int tapan_codec_enable_anc(struct snd_soc_dapm_widget *w,
+	struct snd_kcontrol *kcontrol, int event)
+{
+	struct snd_soc_codec *codec = w->codec;
+	const char *filename;
+	const struct firmware *fw;
+	int i;
+	int ret;
+	int num_anc_slots;
+	struct anc_header *anc_head;
+	struct tapan_priv *tapan = snd_soc_codec_get_drvdata(codec);
+	u32 anc_writes_size = 0;
+	int anc_size_remaining;
+	u32 *anc_ptr;
+	u16 reg;
+	u8 mask, val;
+
+	dev_dbg(codec->dev, "%s %d\n", __func__, event);
+	switch (event) {
+	case SND_SOC_DAPM_PRE_PMU:
+
+		filename = "wcd9306/wcd9306_anc.bin";
+
+		ret = request_firmware(&fw, filename, codec->dev);
+		if (ret != 0) {
+			dev_err(codec->dev, "Failed to acquire ANC data: %d\n",
+				ret);
+			return -ENODEV;
+		}
+
+		if (fw->size < sizeof(struct anc_header)) {
+			dev_err(codec->dev, "Not enough data\n");
+			release_firmware(fw);
+			return -ENOMEM;
+		}
+
+		/* First number is the number of register writes */
+		anc_head = (struct anc_header *)(fw->data);
+		anc_ptr = (u32 *)((u32)fw->data + sizeof(struct anc_header));
+		anc_size_remaining = fw->size - sizeof(struct anc_header);
+		num_anc_slots = anc_head->num_anc_slots;
+
+		if (tapan->anc_slot >= num_anc_slots) {
+			dev_err(codec->dev, "Invalid ANC slot selected\n");
+			release_firmware(fw);
+			return -EINVAL;
+		}
+
+		for (i = 0; i < num_anc_slots; i++) {
+
+			if (anc_size_remaining < TAPAN_PACKED_REG_SIZE) {
+				dev_err(codec->dev, "Invalid register format\n");
+				release_firmware(fw);
+				return -EINVAL;
+			}
+			anc_writes_size = (u32)(*anc_ptr);
+			anc_size_remaining -= sizeof(u32);
+			anc_ptr += 1;
+
+			if (anc_writes_size * TAPAN_PACKED_REG_SIZE
+				> anc_size_remaining) {
+				dev_err(codec->dev, "Invalid register format\n");
+				release_firmware(fw);
+				return -ENOMEM;
+			}
+
+			if (tapan->anc_slot == i)
+				break;
+
+			anc_size_remaining -= (anc_writes_size *
+				TAPAN_PACKED_REG_SIZE);
+			anc_ptr += anc_writes_size;
+		}
+		if (i == num_anc_slots) {
+			dev_err(codec->dev, "Selected ANC slot not present\n");
+			release_firmware(fw);
+			return -ENOMEM;
+		}
+
+		for (i = 0; i < anc_writes_size; i++) {
+			TAPAN_CODEC_UNPACK_ENTRY(anc_ptr[i], reg,
+				mask, val);
+			snd_soc_write(codec, reg, val);
+		}
+		release_firmware(fw);
+
+		break;
+	case SND_SOC_DAPM_POST_PMD:
+		snd_soc_write(codec, TAPAN_A_CDC_CLK_ANC_RESET_CTL, 0xFF);
+		snd_soc_write(codec, TAPAN_A_CDC_CLK_ANC_CLK_EN_CTL, 0);
+		break;
+	}
+	return 0;
+}
+
+static int tapan_codec_enable_micbias(struct snd_soc_dapm_widget *w,
+	struct snd_kcontrol *kcontrol, int event)
+{
+	struct snd_soc_codec *codec = w->codec;
+	struct tapan_priv *tapan = snd_soc_codec_get_drvdata(codec);
+	u16 micb_int_reg;
+	u8 cfilt_sel_val = 0;
+	char *internal1_text = "Internal1";
+	char *internal2_text = "Internal2";
+	char *internal3_text = "Internal3";
+	enum wcd9xxx_notify_event e_post_off, e_pre_on, e_post_on;
+
+	dev_dbg(codec->dev, "%s %d\n", __func__, event);
+	switch (w->reg) {
+	case TAPAN_A_MICB_1_CTL:
+		micb_int_reg = TAPAN_A_MICB_1_INT_RBIAS;
+		cfilt_sel_val = tapan->resmgr.pdata->micbias.bias1_cfilt_sel;
+		e_pre_on = WCD9XXX_EVENT_PRE_MICBIAS_1_ON;
+		e_post_on = WCD9XXX_EVENT_POST_MICBIAS_1_ON;
+		e_post_off = WCD9XXX_EVENT_POST_MICBIAS_1_OFF;
+		break;
+	case TAPAN_A_MICB_2_CTL:
+		micb_int_reg = TAPAN_A_MICB_2_INT_RBIAS;
+		cfilt_sel_val = tapan->resmgr.pdata->micbias.bias2_cfilt_sel;
+		e_pre_on = WCD9XXX_EVENT_PRE_MICBIAS_2_ON;
+		e_post_on = WCD9XXX_EVENT_POST_MICBIAS_2_ON;
+		e_post_off = WCD9XXX_EVENT_POST_MICBIAS_2_OFF;
+		break;
+	case TAPAN_A_MICB_3_CTL:
+		micb_int_reg = TAPAN_A_MICB_3_INT_RBIAS;
+		cfilt_sel_val = tapan->resmgr.pdata->micbias.bias3_cfilt_sel;
+		e_pre_on = WCD9XXX_EVENT_PRE_MICBIAS_3_ON;
+		e_post_on = WCD9XXX_EVENT_POST_MICBIAS_3_ON;
+		e_post_off = WCD9XXX_EVENT_POST_MICBIAS_3_OFF;
+		break;
+	default:
+		pr_err("%s: Error, invalid micbias register\n", __func__);
+		return -EINVAL;
+	}
+
+	switch (event) {
+	case SND_SOC_DAPM_PRE_PMU:
+		/* Let MBHC module know so micbias switch to be off */
+		wcd9xxx_resmgr_notifier_call(&tapan->resmgr, e_pre_on);
+
+		/* Get cfilt */
+		wcd9xxx_resmgr_cfilt_get(&tapan->resmgr, cfilt_sel_val);
+
+		if (strnstr(w->name, internal1_text, 30))
+			snd_soc_update_bits(codec, micb_int_reg, 0xE0, 0xE0);
+		else if (strnstr(w->name, internal2_text, 30))
+			snd_soc_update_bits(codec, micb_int_reg, 0x1C, 0x1C);
+		else if (strnstr(w->name, internal3_text, 30))
+			snd_soc_update_bits(codec, micb_int_reg, 0x3, 0x3);
+
+		break;
+	case SND_SOC_DAPM_POST_PMU:
+		usleep_range(20000, 20000);
+		/* Let MBHC module know so micbias is on */
+		wcd9xxx_resmgr_notifier_call(&tapan->resmgr, e_post_on);
+		break;
+	case SND_SOC_DAPM_POST_PMD:
+		/* Let MBHC module know so micbias switch to be off */
+		wcd9xxx_resmgr_notifier_call(&tapan->resmgr, e_post_off);
+
+		if (strnstr(w->name, internal1_text, 30))
+			snd_soc_update_bits(codec, micb_int_reg, 0x80, 0x00);
+		else if (strnstr(w->name, internal2_text, 30))
+			snd_soc_update_bits(codec, micb_int_reg, 0x10, 0x00);
+		else if (strnstr(w->name, internal3_text, 30))
+			snd_soc_update_bits(codec, micb_int_reg, 0x2, 0x0);
+
+		/* Put cfilt */
+		wcd9xxx_resmgr_cfilt_put(&tapan->resmgr, cfilt_sel_val);
+		break;
+	}
+
+	return 0;
+}
+
+static void tx_hpf_corner_freq_callback(struct work_struct *work)
+{
+	struct delayed_work *hpf_delayed_work;
+	struct hpf_work *hpf_work;
+	struct tapan_priv *tapan;
+	struct snd_soc_codec *codec;
+	u16 tx_mux_ctl_reg;
+	u8 hpf_cut_of_freq;
+
+	hpf_delayed_work = to_delayed_work(work);
+	hpf_work = container_of(hpf_delayed_work, struct hpf_work, dwork);
+	tapan = hpf_work->tapan;
+	codec = hpf_work->tapan->codec;
+	hpf_cut_of_freq = hpf_work->tx_hpf_cut_of_freq;
+
+	tx_mux_ctl_reg = TAPAN_A_CDC_TX1_MUX_CTL +
+			(hpf_work->decimator - 1) * 8;
+
+	dev_dbg(codec->dev, "%s(): decimator %u hpf_cut_of_freq 0x%x\n",
+		 __func__, hpf_work->decimator, (unsigned int)hpf_cut_of_freq);
+
+	snd_soc_update_bits(codec, tx_mux_ctl_reg, 0x30, hpf_cut_of_freq << 4);
+}
+
+#define  TX_MUX_CTL_CUT_OFF_FREQ_MASK	0x30
+#define  CF_MIN_3DB_4HZ			0x0
+#define  CF_MIN_3DB_75HZ		0x1
+#define  CF_MIN_3DB_150HZ		0x2
+
+static int tapan_codec_enable_dec(struct snd_soc_dapm_widget *w,
+	struct snd_kcontrol *kcontrol, int event)
+{
+	struct snd_soc_codec *codec = w->codec;
+	unsigned int decimator;
+	char *dec_name = NULL;
+	char *widget_name = NULL;
+	char *temp;
+	int ret = 0;
+	u16 dec_reset_reg, tx_vol_ctl_reg, tx_mux_ctl_reg;
+	u8 dec_hpf_cut_of_freq;
+	int offset;
+
+	dev_dbg(codec->dev, "%s %d\n", __func__, event);
+
+	widget_name = kstrndup(w->name, 15, GFP_KERNEL);
+	if (!widget_name)
+		return -ENOMEM;
+	temp = widget_name;
+
+	dec_name = strsep(&widget_name, " ");
+	widget_name = temp;
+	if (!dec_name) {
+		pr_err("%s: Invalid decimator = %s\n", __func__, w->name);
+		ret =  -EINVAL;
+		goto out;
+	}
+
+	ret = kstrtouint(strpbrk(dec_name, "123456789"), 10, &decimator);
+	if (ret < 0) {
+		pr_err("%s: Invalid decimator = %s\n", __func__, dec_name);
+		ret =  -EINVAL;
+		goto out;
+	}
+
+	dev_dbg(codec->dev, "%s(): widget = %s dec_name = %s decimator = %u\n",
+			__func__, w->name, dec_name, decimator);
+
+	if (w->reg == TAPAN_A_CDC_CLK_TX_CLK_EN_B1_CTL) {
+		dec_reset_reg = TAPAN_A_CDC_CLK_TX_RESET_B1_CTL;
+		offset = 0;
+	} else if (w->reg == TAPAN_A_CDC_CLK_TX_CLK_EN_B2_CTL) {
+		dec_reset_reg = TAPAN_A_CDC_CLK_TX_RESET_B2_CTL;
+		offset = 8;
+	} else {
+		pr_err("%s: Error, incorrect dec\n", __func__);
+		ret = -EINVAL;
+		goto out;
+	}
+
+	tx_vol_ctl_reg = TAPAN_A_CDC_TX1_VOL_CTL_CFG + 8 * (decimator - 1);
+	tx_mux_ctl_reg = TAPAN_A_CDC_TX1_MUX_CTL + 8 * (decimator - 1);
+
+	switch (event) {
+	case SND_SOC_DAPM_PRE_PMU:
+
+		/* Enableable TX digital mute */
+		snd_soc_update_bits(codec, tx_vol_ctl_reg, 0x01, 0x01);
+
+		snd_soc_update_bits(codec, dec_reset_reg, 1 << w->shift,
+			1 << w->shift);
+		snd_soc_update_bits(codec, dec_reset_reg, 1 << w->shift, 0x0);
+
+		dec_hpf_cut_of_freq = snd_soc_read(codec, tx_mux_ctl_reg);
+
+		dec_hpf_cut_of_freq = (dec_hpf_cut_of_freq & 0x30) >> 4;
+
+		tx_hpf_work[decimator - 1].tx_hpf_cut_of_freq =
+			dec_hpf_cut_of_freq;
+
+		if ((dec_hpf_cut_of_freq != CF_MIN_3DB_150HZ)) {
+
+			/* set cut of freq to CF_MIN_3DB_150HZ (0x1); */
+			snd_soc_update_bits(codec, tx_mux_ctl_reg, 0x30,
+					    CF_MIN_3DB_150HZ << 4);
+		}
+
+		/* enable HPF */
+		snd_soc_update_bits(codec, tx_mux_ctl_reg , 0x08, 0x00);
+
+		break;
+
+	case SND_SOC_DAPM_POST_PMU:
+
+		/* Disable TX digital mute */
+		snd_soc_update_bits(codec, tx_vol_ctl_reg, 0x01, 0x00);
+
+		if (tx_hpf_work[decimator - 1].tx_hpf_cut_of_freq !=
+				CF_MIN_3DB_150HZ) {
+
+			schedule_delayed_work(&tx_hpf_work[decimator - 1].dwork,
+					msecs_to_jiffies(300));
+		}
+		/* apply the digital gain after the decimator is enabled*/
+		if ((w->shift) < ARRAY_SIZE(tx_digital_gain_reg))
+			snd_soc_write(codec,
+				  tx_digital_gain_reg[w->shift + offset],
+				  snd_soc_read(codec,
+				  tx_digital_gain_reg[w->shift + offset])
+				  );
+
+		break;
+
+	case SND_SOC_DAPM_PRE_PMD:
+
+		snd_soc_update_bits(codec, tx_vol_ctl_reg, 0x01, 0x01);
+		cancel_delayed_work_sync(&tx_hpf_work[decimator - 1].dwork);
+		break;
+
+	case SND_SOC_DAPM_POST_PMD:
+
+		snd_soc_update_bits(codec, tx_mux_ctl_reg, 0x08, 0x08);
+		snd_soc_update_bits(codec, tx_mux_ctl_reg, 0x30,
+			(tx_hpf_work[decimator - 1].tx_hpf_cut_of_freq) << 4);
+
+		break;
+	}
+out:
+	kfree(widget_name);
+	return ret;
+}
+
+static int tapan_codec_enable_interpolator(struct snd_soc_dapm_widget *w,
+	struct snd_kcontrol *kcontrol, int event)
+{
+	struct snd_soc_codec *codec = w->codec;
+
+	dev_dbg(codec->dev, "%s %d %s\n", __func__, event, w->name);
+
+	switch (event) {
+	case SND_SOC_DAPM_PRE_PMU:
+		snd_soc_update_bits(codec, TAPAN_A_CDC_CLK_RX_RESET_CTL,
+			1 << w->shift, 1 << w->shift);
+		snd_soc_update_bits(codec, TAPAN_A_CDC_CLK_RX_RESET_CTL,
+			1 << w->shift, 0x0);
+		break;
+	case SND_SOC_DAPM_POST_PMU:
+		/* apply the digital gain after the interpolator is enabled*/
+		if ((w->shift) < ARRAY_SIZE(rx_digital_gain_reg))
+			snd_soc_write(codec,
+				  rx_digital_gain_reg[w->shift],
+				  snd_soc_read(codec,
+				  rx_digital_gain_reg[w->shift])
+				  );
+		break;
+	}
+	return 0;
+}
+
+static int tapan_codec_enable_ldo_h(struct snd_soc_dapm_widget *w,
+	struct snd_kcontrol *kcontrol, int event)
+{
+	switch (event) {
+	case SND_SOC_DAPM_POST_PMU:
+	case SND_SOC_DAPM_POST_PMD:
+		usleep_range(1000, 1000);
+		break;
+	}
+	return 0;
+}
+
+static int tapan_codec_enable_rx_bias(struct snd_soc_dapm_widget *w,
+	struct snd_kcontrol *kcontrol, int event)
+{
+	struct snd_soc_codec *codec = w->codec;
+	struct tapan_priv *tapan = snd_soc_codec_get_drvdata(codec);
+
+	dev_dbg(codec->dev, "%s %d\n", __func__, event);
+
+	switch (event) {
+	case SND_SOC_DAPM_PRE_PMU:
+		wcd9xxx_resmgr_enable_rx_bias(&tapan->resmgr, 1);
+		break;
+	case SND_SOC_DAPM_POST_PMD:
+		wcd9xxx_resmgr_enable_rx_bias(&tapan->resmgr, 0);
+		break;
+	}
+	return 0;
+}
+static int tapan_hphr_dac_event(struct snd_soc_dapm_widget *w,
+	struct snd_kcontrol *kcontrol, int event)
+{
+	struct snd_soc_codec *codec = w->codec;
+
+	dev_dbg(codec->dev, "%s %s %d\n", __func__, w->name, event);
+
+	switch (event) {
+	case SND_SOC_DAPM_PRE_PMU:
+		snd_soc_update_bits(codec, w->reg, 0x40, 0x40);
+		break;
+	case SND_SOC_DAPM_POST_PMD:
+		snd_soc_update_bits(codec, w->reg, 0x40, 0x00);
+		break;
+	}
+	return 0;
+}
+
+static int tapan_hph_pa_event(struct snd_soc_dapm_widget *w,
+			      struct snd_kcontrol *kcontrol, int event)
+{
+	struct snd_soc_codec *codec = w->codec;
+	struct tapan_priv *tapan = snd_soc_codec_get_drvdata(codec);
+	enum wcd9xxx_notify_event e_pre_on, e_post_off;
+
+	dev_dbg(codec->dev, "%s: %s event = %d\n", __func__, w->name, event);
+	if (w->shift == 5) {
+		e_pre_on = WCD9XXX_EVENT_PRE_HPHR_PA_ON;
+		e_post_off = WCD9XXX_EVENT_POST_HPHR_PA_OFF;
+	} else if (w->shift == 4) {
+		e_pre_on = WCD9XXX_EVENT_PRE_HPHL_PA_ON;
+		e_post_off = WCD9XXX_EVENT_POST_HPHL_PA_OFF;
+	} else {
+		pr_err("%s: Invalid w->shift %d\n", __func__, w->shift);
+		return -EINVAL;
+	}
+
+	switch (event) {
+	case SND_SOC_DAPM_PRE_PMU:
+		/* Let MBHC module know PA is turning on */
+		wcd9xxx_resmgr_notifier_call(&tapan->resmgr, e_pre_on);
+		break;
+
+	case SND_SOC_DAPM_POST_PMU:
+		usleep_range(10000, 10000);
+
+		snd_soc_update_bits(codec, TAPAN_A_BUCK_MODE_5, 0x02, 0x00);
+		snd_soc_update_bits(codec, TAPAN_A_NCP_STATIC, 0x20, 0x00);
+		snd_soc_update_bits(codec, TAPAN_A_BUCK_MODE_3, 0x04, 0x04);
+		snd_soc_update_bits(codec, TAPAN_A_BUCK_MODE_3, 0x08, 0x00);
+
+		usleep_range(10, 10);
+		break;
+
+	case SND_SOC_DAPM_POST_PMD:
+		/* Let MBHC module know PA turned off */
+		wcd9xxx_resmgr_notifier_call(&tapan->resmgr, e_post_off);
+
+		/*
+		 * schedule work is required because at the time HPH PA DAPM
+		 * event callback is called by DAPM framework, CODEC dapm mutex
+		 * would have been locked while snd_soc_jack_report also
+		 * attempts to acquire same lock.
+		 */
+		dev_dbg(codec->dev, "%s: sleep 10 ms after %s PA disable.\n",
+			 __func__, w->name);
+		usleep_range(5000, 5000);
+		break;
+	}
+	return 0;
+}
+
+static int tapan_lineout_dac_event(struct snd_soc_dapm_widget *w,
+	struct snd_kcontrol *kcontrol, int event)
+{
+	struct snd_soc_codec *codec = w->codec;
+
+	dev_dbg(codec->dev, "%s %s %d\n", __func__, w->name, event);
+
+	switch (event) {
+	case SND_SOC_DAPM_PRE_PMU:
+		snd_soc_update_bits(codec, w->reg, 0x40, 0x40);
+		break;
+
+	case SND_SOC_DAPM_POST_PMD:
+		snd_soc_update_bits(codec, w->reg, 0x40, 0x00);
+		break;
+	}
+	return 0;
+}
+
+static int tapan_spk_dac_event(struct snd_soc_dapm_widget *w,
+	struct snd_kcontrol *kcontrol, int event)
+{
+	struct snd_soc_codec *codec = w->codec;
+
+	dev_dbg(codec->dev, "%s %s %d\n", __func__, w->name, event);
+	return 0;
+}
+
+static const struct snd_soc_dapm_route audio_i2s_map[] = {
+	{"RX_I2S_CLK", NULL, "CDC_CONN"},
+	{"SLIM RX1", NULL, "RX_I2S_CLK"},
+	{"SLIM RX2", NULL, "RX_I2S_CLK"},
+
+	{"SLIM TX1 MUX", NULL, "TX_I2S_CLK"},
+	{"SLIM TX2 MUX", NULL, "TX_I2S_CLK"},
+};
+
+static const struct snd_soc_dapm_route audio_map[] = {
+	/* SLIMBUS Connections */
+	{"AIF1 CAP", NULL, "AIF1_CAP Mixer"},
+	{"AIF2 CAP", NULL, "AIF2_CAP Mixer"},
+	{"AIF3 CAP", NULL, "AIF3_CAP Mixer"},
+
+	/* SLIM_MIXER("AIF1_CAP Mixer"),*/
+	{"AIF1_CAP Mixer", "SLIM TX1", "SLIM TX1 MUX"},
+	{"AIF1_CAP Mixer", "SLIM TX2", "SLIM TX2 MUX"},
+	{"AIF1_CAP Mixer", "SLIM TX3", "SLIM TX3 MUX"},
+	{"AIF1_CAP Mixer", "SLIM TX4", "SLIM TX4 MUX"},
+	{"AIF1_CAP Mixer", "SLIM TX5", "SLIM TX5 MUX"},
+	{"AIF1_CAP Mixer", "SLIM TX6", "SLIM TX6 MUX"},
+	{"AIF1_CAP Mixer", "SLIM TX7", "SLIM TX7 MUX"},
+	{"AIF1_CAP Mixer", "SLIM TX8", "SLIM TX8 MUX"},
+	{"AIF1_CAP Mixer", "SLIM TX9", "SLIM TX9 MUX"},
+	{"AIF1_CAP Mixer", "SLIM TX10", "SLIM TX10 MUX"},
+	/* SLIM_MIXER("AIF2_CAP Mixer"),*/
+	{"AIF2_CAP Mixer", "SLIM TX1", "SLIM TX1 MUX"},
+	{"AIF2_CAP Mixer", "SLIM TX2", "SLIM TX2 MUX"},
+	{"AIF2_CAP Mixer", "SLIM TX3", "SLIM TX3 MUX"},
+	{"AIF2_CAP Mixer", "SLIM TX4", "SLIM TX4 MUX"},
+	{"AIF2_CAP Mixer", "SLIM TX5", "SLIM TX5 MUX"},
+	{"AIF2_CAP Mixer", "SLIM TX6", "SLIM TX6 MUX"},
+	{"AIF2_CAP Mixer", "SLIM TX7", "SLIM TX7 MUX"},
+	{"AIF2_CAP Mixer", "SLIM TX8", "SLIM TX8 MUX"},
+	{"AIF2_CAP Mixer", "SLIM TX9", "SLIM TX9 MUX"},
+	{"AIF2_CAP Mixer", "SLIM TX10", "SLIM TX10 MUX"},
+	/* SLIM_MIXER("AIF3_CAP Mixer"),*/
+	{"AIF3_CAP Mixer", "SLIM TX1", "SLIM TX1 MUX"},
+	{"AIF3_CAP Mixer", "SLIM TX2", "SLIM TX2 MUX"},
+	{"AIF3_CAP Mixer", "SLIM TX3", "SLIM TX3 MUX"},
+	{"AIF3_CAP Mixer", "SLIM TX4", "SLIM TX4 MUX"},
+	{"AIF3_CAP Mixer", "SLIM TX5", "SLIM TX5 MUX"},
+	{"AIF3_CAP Mixer", "SLIM TX6", "SLIM TX6 MUX"},
+	{"AIF3_CAP Mixer", "SLIM TX7", "SLIM TX7 MUX"},
+	{"AIF3_CAP Mixer", "SLIM TX8", "SLIM TX8 MUX"},
+	{"AIF3_CAP Mixer", "SLIM TX9", "SLIM TX9 MUX"},
+	{"AIF3_CAP Mixer", "SLIM TX10", "SLIM TX10 MUX"},
+
+	{"SLIM TX1 MUX", "DEC1", "DEC1 MUX"},
+
+	{"SLIM TX2 MUX", "DEC2", "DEC2 MUX"},
+
+	{"SLIM TX3 MUX", "DEC3", "DEC3 MUX"},
+	{"SLIM TX3 MUX", "RMIX1", "RX1 MIX1"},
+	{"SLIM TX3 MUX", "RMIX2", "RX2 MIX1"},
+	{"SLIM TX3 MUX", "RMIX3", "RX3 MIX1"},
+	{"SLIM TX3 MUX", "RMIX4", "RX4 MIX1"},
+	{"SLIM TX3 MUX", "RMIX5", "RX5 MIX1"},
+	{"SLIM TX3 MUX", "RMIX6", "RX6 MIX1"},
+	{"SLIM TX3 MUX", "RMIX7", "RX7 MIX1"},
+
+	{"SLIM TX4 MUX", "DEC4", "DEC4 MUX"},
+
+	{"SLIM TX5 MUX", "DEC5", "DEC5 MUX"},
+	{"SLIM TX5 MUX", "RMIX1", "RX1 MIX1"},
+	{"SLIM TX5 MUX", "RMIX2", "RX2 MIX1"},
+	{"SLIM TX5 MUX", "RMIX3", "RX3 MIX1"},
+	{"SLIM TX5 MUX", "RMIX4", "RX4 MIX1"},
+	{"SLIM TX5 MUX", "RMIX5", "RX5 MIX1"},
+	{"SLIM TX5 MUX", "RMIX6", "RX6 MIX1"},
+	{"SLIM TX5 MUX", "RMIX7", "RX7 MIX1"},
+
+	{"SLIM TX6 MUX", "DEC6", "DEC6 MUX"},
+
+	{"SLIM TX7 MUX", "DEC1", "DEC1 MUX"},
+	{"SLIM TX7 MUX", "DEC2", "DEC2 MUX"},
+	{"SLIM TX7 MUX", "DEC3", "DEC3 MUX"},
+	{"SLIM TX7 MUX", "DEC4", "DEC4 MUX"},
+	{"SLIM TX7 MUX", "DEC5", "DEC5 MUX"},
+	{"SLIM TX7 MUX", "DEC6", "DEC6 MUX"},
+	{"SLIM TX7 MUX", "DEC7", "DEC7 MUX"},
+	{"SLIM TX7 MUX", "DEC8", "DEC8 MUX"},
+	{"SLIM TX7 MUX", "DEC9", "DEC9 MUX"},
+	{"SLIM TX7 MUX", "DEC10", "DEC10 MUX"},
+	{"SLIM TX7 MUX", "RMIX1", "RX1 MIX1"},
+	{"SLIM TX7 MUX", "RMIX2", "RX2 MIX1"},
+	{"SLIM TX7 MUX", "RMIX3", "RX3 MIX1"},
+	{"SLIM TX7 MUX", "RMIX4", "RX4 MIX1"},
+	{"SLIM TX7 MUX", "RMIX5", "RX5 MIX1"},
+	{"SLIM TX7 MUX", "RMIX6", "RX6 MIX1"},
+	{"SLIM TX7 MUX", "RMIX7", "RX7 MIX1"},
+
+	{"SLIM TX8 MUX", "DEC1", "DEC1 MUX"},
+	{"SLIM TX8 MUX", "DEC2", "DEC2 MUX"},
+	{"SLIM TX8 MUX", "DEC3", "DEC3 MUX"},
+	{"SLIM TX8 MUX", "DEC4", "DEC4 MUX"},
+	{"SLIM TX8 MUX", "DEC5", "DEC5 MUX"},
+	{"SLIM TX8 MUX", "DEC6", "DEC6 MUX"},
+	{"SLIM TX8 MUX", "DEC7", "DEC7 MUX"},
+	{"SLIM TX8 MUX", "DEC8", "DEC8 MUX"},
+	{"SLIM TX8 MUX", "DEC9", "DEC9 MUX"},
+	{"SLIM TX8 MUX", "DEC10", "DEC10 MUX"},
+
+	{"SLIM TX9 MUX", "DEC1", "DEC1 MUX"},
+	{"SLIM TX9 MUX", "DEC2", "DEC2 MUX"},
+	{"SLIM TX9 MUX", "DEC3", "DEC3 MUX"},
+	{"SLIM TX9 MUX", "DEC4", "DEC4 MUX"},
+	{"SLIM TX9 MUX", "DEC5", "DEC5 MUX"},
+	{"SLIM TX9 MUX", "DEC6", "DEC6 MUX"},
+	{"SLIM TX9 MUX", "DEC7", "DEC7 MUX"},
+	{"SLIM TX9 MUX", "DEC8", "DEC8 MUX"},
+	{"SLIM TX9 MUX", "DEC9", "DEC9 MUX"},
+	{"SLIM TX9 MUX", "DEC10", "DEC10 MUX"},
+
+	{"SLIM TX10 MUX", "DEC1", "DEC1 MUX"},
+	{"SLIM TX10 MUX", "DEC2", "DEC2 MUX"},
+	{"SLIM TX10 MUX", "DEC3", "DEC3 MUX"},
+	{"SLIM TX10 MUX", "DEC4", "DEC4 MUX"},
+	{"SLIM TX10 MUX", "DEC5", "DEC5 MUX"},
+	{"SLIM TX10 MUX", "DEC6", "DEC6 MUX"},
+	{"SLIM TX10 MUX", "DEC7", "DEC7 MUX"},
+	{"SLIM TX10 MUX", "DEC8", "DEC8 MUX"},
+	{"SLIM TX10 MUX", "DEC9", "DEC9 MUX"},
+	{"SLIM TX10 MUX", "DEC10", "DEC10 MUX"},
+
+	/* Earpiece (RX MIX1) */
+	{"EAR", NULL, "EAR PA"},
+	{"EAR PA", NULL, "EAR_PA_MIXER"},
+	{"EAR_PA_MIXER", NULL, "DAC1"},
+	{"DAC1", NULL, "CP"},
+	{"CP", NULL, "CLASS_H_EAR"},
+	{"CLASS_H_EAR", NULL, "CLASS_H_CLK"},
+
+	{"ANC1 FB MUX", "EAR_HPH_L", "RX1 MIX2"},
+	{"ANC1 FB MUX", "EAR_LINE_1", "RX2 MIX2"},
+	{"ANC", NULL, "ANC1 FB MUX"},
+
+	/* Headset (RX MIX1 and RX MIX2) */
+	{"HEADPHONE", NULL, "HPHL"},
+	{"HEADPHONE", NULL, "HPHR"},
+
+	{"HPHL", NULL, "HPHL_PA_MIXER"},
+	{"HPHL_PA_MIXER", NULL, "HPHL DAC"},
+
+	{"HPHR", NULL, "HPHR_PA_MIXER"},
+	{"HPHR_PA_MIXER", NULL, "HPHR DAC"},
+
+	{"HPHL DAC", NULL, "CP"},
+	{"CP", NULL, "CLASS_H_HPH_L"},
+	{"CLASS_H_HPH_L", NULL, "CLASS_H_CLK"},
+
+	{"HPHR DAC", NULL, "CP"},
+	{"CP", NULL, "CLASS_H_HPH_R"},
+	{"CLASS_H_HPH_R", NULL, "CLASS_H_CLK"},
+
+	{"ANC", NULL, "ANC1 MUX"},
+	{"ANC", NULL, "ANC2 MUX"},
+	{"ANC1 MUX", "ADC1", "ADC1"},
+	{"ANC1 MUX", "ADC2", "ADC2"},
+	{"ANC1 MUX", "ADC3", "ADC3"},
+	{"ANC1 MUX", "ADC4", "ADC4"},
+	{"ANC2 MUX", "ADC1", "ADC1"},
+	{"ANC2 MUX", "ADC2", "ADC2"},
+	{"ANC2 MUX", "ADC3", "ADC3"},
+	{"ANC2 MUX", "ADC4", "ADC4"},
+
+	{"ANC", NULL, "CDC_CONN"},
+
+	{"DAC1", "Switch", "RX1 CHAIN"},
+	{"HPHL DAC", "Switch", "RX1 CHAIN"},
+	{"HPHR DAC", NULL, "RX2 CHAIN"},
+
+	{"LINEOUT1", NULL, "LINEOUT1 PA"},
+	{"LINEOUT2", NULL, "LINEOUT2 PA"},
+	{"LINEOUT3", NULL, "LINEOUT3 PA"},
+	{"LINEOUT4", NULL, "LINEOUT4 PA"},
+	{"SPK_OUT", NULL, "SPK PA"},
+
+	{"LINEOUT1 PA", NULL, "CP"},
+	{"LINEOUT1 PA", NULL, "LINEOUT1_PA_MIXER"},
+	{"LINEOUT1_PA_MIXER", NULL, "LINEOUT1 DAC"},
+
+	{"LINEOUT2 PA", NULL, "CP"},
+	{"LINEOUT2 PA", NULL, "LINEOUT2_PA_MIXER"},
+	{"LINEOUT2_PA_MIXER", NULL, "LINEOUT2 DAC"},
+
+	{"LINEOUT3 PA", NULL, "CP"},
+	{"LINEOUT3 PA", NULL, "LINEOUT3_PA_MIXER"},
+	{"LINEOUT3_PA_MIXER", NULL, "LINEOUT3 DAC"},
+
+	{"LINEOUT4 PA", NULL, "CP"},
+	{"LINEOUT4 PA", NULL, "LINEOUT4_PA_MIXER"},
+	{"LINEOUT4_PA_MIXER", NULL, "LINEOUT4 DAC"},
+
+	{"CP", NULL, "CLASS_H_LINEOUTS_PA"},
+	{"CLASS_H_LINEOUTS_PA", NULL, "CLASS_H_CLK"},
+
+	{"LINEOUT1 DAC", NULL, "RX3 MIX1"},
+
+	{"RDAC5 MUX", "DEM3_INV", "RX3 MIX1"},
+	{"RDAC5 MUX", "DEM4", "RX4 MIX1"},
+
+	{"LINEOUT3 DAC", NULL, "RDAC5 MUX"},
+
+	{"LINEOUT2 DAC", NULL, "RX5 MIX1"},
+
+	{"RDAC7 MUX", "DEM5_INV", "RX5 MIX1"},
+	{"RDAC7 MUX", "DEM6", "RX6 MIX1"},
+
+	{"LINEOUT4 DAC", NULL, "RDAC7 MUX"},
+
+	{"SPK PA", NULL, "SPK DAC"},
+	{"SPK DAC", NULL, "RX7 MIX2"},
+
+	{"RX1 CHAIN", NULL, "RX1 MIX2"},
+	{"RX2 CHAIN", NULL, "RX2 MIX2"},
+	{"RX1 CHAIN", NULL, "ANC"},
+	{"RX2 CHAIN", NULL, "ANC"},
+
+	{"CLASS_H_CLK", NULL, "RX_BIAS"},
+	{"LINEOUT1 DAC", NULL, "RX_BIAS"},
+	{"LINEOUT2 DAC", NULL, "RX_BIAS"},
+	{"LINEOUT3 DAC", NULL, "RX_BIAS"},
+	{"LINEOUT4 DAC", NULL, "RX_BIAS"},
+	{"SPK DAC", NULL, "RX_BIAS"},
+
+	{"RX1 MIX1", NULL, "COMP1_CLK"},
+	{"RX2 MIX1", NULL, "COMP1_CLK"},
+	{"RX3 MIX1", NULL, "COMP2_CLK"},
+	{"RX5 MIX1", NULL, "COMP2_CLK"},
+
+	{"RX1 MIX1", NULL, "RX1 MIX1 INP1"},
+	{"RX1 MIX1", NULL, "RX1 MIX1 INP2"},
+	{"RX1 MIX1", NULL, "RX1 MIX1 INP3"},
+	{"RX2 MIX1", NULL, "RX2 MIX1 INP1"},
+	{"RX2 MIX1", NULL, "RX2 MIX1 INP2"},
+	{"RX3 MIX1", NULL, "RX3 MIX1 INP1"},
+	{"RX3 MIX1", NULL, "RX3 MIX1 INP2"},
+	{"RX4 MIX1", NULL, "RX4 MIX1 INP1"},
+	{"RX4 MIX1", NULL, "RX4 MIX1 INP2"},
+	{"RX5 MIX1", NULL, "RX5 MIX1 INP1"},
+	{"RX5 MIX1", NULL, "RX5 MIX1 INP2"},
+	{"RX6 MIX1", NULL, "RX6 MIX1 INP1"},
+	{"RX6 MIX1", NULL, "RX6 MIX1 INP2"},
+	{"RX7 MIX1", NULL, "RX7 MIX1 INP1"},
+	{"RX7 MIX1", NULL, "RX7 MIX1 INP2"},
+	{"RX1 MIX2", NULL, "RX1 MIX1"},
+	{"RX1 MIX2", NULL, "RX1 MIX2 INP1"},
+	{"RX1 MIX2", NULL, "RX1 MIX2 INP2"},
+	{"RX2 MIX2", NULL, "RX2 MIX1"},
+	{"RX2 MIX2", NULL, "RX2 MIX2 INP1"},
+	{"RX2 MIX2", NULL, "RX2 MIX2 INP2"},
+	{"RX7 MIX2", NULL, "RX7 MIX1"},
+	{"RX7 MIX2", NULL, "RX7 MIX2 INP1"},
+	{"RX7 MIX2", NULL, "RX7 MIX2 INP2"},
+
+	/* SLIM_MUX("AIF1_PB", "AIF1 PB"),*/
+	{"SLIM RX1 MUX", "AIF1_PB", "AIF1 PB"},
+	{"SLIM RX2 MUX", "AIF1_PB", "AIF1 PB"},
+	{"SLIM RX3 MUX", "AIF1_PB", "AIF1 PB"},
+	{"SLIM RX4 MUX", "AIF1_PB", "AIF1 PB"},
+	{"SLIM RX5 MUX", "AIF1_PB", "AIF1 PB"},
+	{"SLIM RX6 MUX", "AIF1_PB", "AIF1 PB"},
+	{"SLIM RX7 MUX", "AIF1_PB", "AIF1 PB"},
+	/* SLIM_MUX("AIF2_PB", "AIF2 PB"),*/
+	{"SLIM RX1 MUX", "AIF2_PB", "AIF2 PB"},
+	{"SLIM RX2 MUX", "AIF2_PB", "AIF2 PB"},
+	{"SLIM RX3 MUX", "AIF2_PB", "AIF2 PB"},
+	{"SLIM RX4 MUX", "AIF2_PB", "AIF2 PB"},
+	{"SLIM RX5 MUX", "AIF2_PB", "AIF2 PB"},
+	{"SLIM RX6 MUX", "AIF2_PB", "AIF2 PB"},
+	{"SLIM RX7 MUX", "AIF2_PB", "AIF2 PB"},
+	/* SLIM_MUX("AIF3_PB", "AIF3 PB"),*/
+	{"SLIM RX1 MUX", "AIF3_PB", "AIF3 PB"},
+	{"SLIM RX2 MUX", "AIF3_PB", "AIF3 PB"},
+	{"SLIM RX3 MUX", "AIF3_PB", "AIF3 PB"},
+	{"SLIM RX4 MUX", "AIF3_PB", "AIF3 PB"},
+	{"SLIM RX5 MUX", "AIF3_PB", "AIF3 PB"},
+	{"SLIM RX6 MUX", "AIF3_PB", "AIF3 PB"},
+	{"SLIM RX7 MUX", "AIF3_PB", "AIF3 PB"},
+
+	{"SLIM RX1", NULL, "SLIM RX1 MUX"},
+	{"SLIM RX2", NULL, "SLIM RX2 MUX"},
+	{"SLIM RX3", NULL, "SLIM RX3 MUX"},
+	{"SLIM RX4", NULL, "SLIM RX4 MUX"},
+	{"SLIM RX5", NULL, "SLIM RX5 MUX"},
+	{"SLIM RX6", NULL, "SLIM RX6 MUX"},
+	{"SLIM RX7", NULL, "SLIM RX7 MUX"},
+
+	{"RX1 MIX1 INP1", "RX1", "SLIM RX1"},
+	{"RX1 MIX1 INP1", "RX2", "SLIM RX2"},
+	{"RX1 MIX1 INP1", "RX3", "SLIM RX3"},
+	{"RX1 MIX1 INP1", "RX4", "SLIM RX4"},
+	{"RX1 MIX1 INP1", "RX5", "SLIM RX5"},
+	{"RX1 MIX1 INP1", "RX6", "SLIM RX6"},
+	{"RX1 MIX1 INP1", "RX7", "SLIM RX7"},
+	{"RX1 MIX1 INP1", "IIR1", "IIR1"},
+	{"RX1 MIX1 INP2", "RX1", "SLIM RX1"},
+	{"RX1 MIX1 INP2", "RX2", "SLIM RX2"},
+	{"RX1 MIX1 INP2", "RX3", "SLIM RX3"},
+	{"RX1 MIX1 INP2", "RX4", "SLIM RX4"},
+	{"RX1 MIX1 INP2", "RX5", "SLIM RX5"},
+	{"RX1 MIX1 INP2", "RX6", "SLIM RX6"},
+	{"RX1 MIX1 INP2", "RX7", "SLIM RX7"},
+	{"RX1 MIX1 INP2", "IIR1", "IIR1"},
+	{"RX1 MIX1 INP3", "RX1", "SLIM RX1"},
+	{"RX1 MIX1 INP3", "RX2", "SLIM RX2"},
+	{"RX1 MIX1 INP3", "RX3", "SLIM RX3"},
+	{"RX1 MIX1 INP3", "RX4", "SLIM RX4"},
+	{"RX1 MIX1 INP3", "RX5", "SLIM RX5"},
+	{"RX1 MIX1 INP3", "RX6", "SLIM RX6"},
+	{"RX1 MIX1 INP3", "RX7", "SLIM RX7"},
+	{"RX2 MIX1 INP1", "RX1", "SLIM RX1"},
+	{"RX2 MIX1 INP1", "RX2", "SLIM RX2"},
+	{"RX2 MIX1 INP1", "RX3", "SLIM RX3"},
+	{"RX2 MIX1 INP1", "RX4", "SLIM RX4"},
+	{"RX2 MIX1 INP1", "RX5", "SLIM RX5"},
+	{"RX2 MIX1 INP1", "RX6", "SLIM RX6"},
+	{"RX2 MIX1 INP1", "RX7", "SLIM RX7"},
+	{"RX2 MIX1 INP1", "IIR1", "IIR1"},
+	{"RX2 MIX1 INP2", "RX1", "SLIM RX1"},
+	{"RX2 MIX1 INP2", "RX2", "SLIM RX2"},
+	{"RX2 MIX1 INP2", "RX3", "SLIM RX3"},
+	{"RX2 MIX1 INP2", "RX4", "SLIM RX4"},
+	{"RX2 MIX1 INP2", "RX5", "SLIM RX5"},
+	{"RX2 MIX1 INP2", "RX6", "SLIM RX6"},
+	{"RX2 MIX1 INP2", "RX7", "SLIM RX7"},
+	{"RX2 MIX1 INP2", "IIR1", "IIR1"},
+	{"RX3 MIX1 INP1", "RX1", "SLIM RX1"},
+	{"RX3 MIX1 INP1", "RX2", "SLIM RX2"},
+	{"RX3 MIX1 INP1", "RX3", "SLIM RX3"},
+	{"RX3 MIX1 INP1", "RX4", "SLIM RX4"},
+	{"RX3 MIX1 INP1", "RX5", "SLIM RX5"},
+	{"RX3 MIX1 INP1", "RX6", "SLIM RX6"},
+	{"RX3 MIX1 INP1", "RX7", "SLIM RX7"},
+	{"RX3 MIX1 INP1", "IIR1", "IIR1"},
+	{"RX3 MIX1 INP2", "RX1", "SLIM RX1"},
+	{"RX3 MIX1 INP2", "RX2", "SLIM RX2"},
+	{"RX3 MIX1 INP2", "RX3", "SLIM RX3"},
+	{"RX3 MIX1 INP2", "RX4", "SLIM RX4"},
+	{"RX3 MIX1 INP2", "RX5", "SLIM RX5"},
+	{"RX3 MIX1 INP2", "RX6", "SLIM RX6"},
+	{"RX3 MIX1 INP2", "RX7", "SLIM RX7"},
+	{"RX3 MIX1 INP2", "IIR1", "IIR1"},
+	{"RX4 MIX1 INP1", "RX1", "SLIM RX1"},
+	{"RX4 MIX1 INP1", "RX2", "SLIM RX2"},
+	{"RX4 MIX1 INP1", "RX3", "SLIM RX3"},
+	{"RX4 MIX1 INP1", "RX4", "SLIM RX4"},
+	{"RX4 MIX1 INP1", "RX5", "SLIM RX5"},
+	{"RX4 MIX1 INP1", "RX6", "SLIM RX6"},
+	{"RX4 MIX1 INP1", "RX7", "SLIM RX7"},
+	{"RX4 MIX1 INP1", "IIR1", "IIR1"},
+	{"RX4 MIX1 INP2", "RX1", "SLIM RX1"},
+	{"RX4 MIX1 INP2", "RX2", "SLIM RX2"},
+	{"RX4 MIX1 INP2", "RX3", "SLIM RX3"},
+	{"RX4 MIX1 INP2", "RX5", "SLIM RX5"},
+	{"RX4 MIX1 INP2", "RX4", "SLIM RX4"},
+	{"RX4 MIX1 INP2", "RX6", "SLIM RX6"},
+	{"RX4 MIX1 INP2", "RX7", "SLIM RX7"},
+	{"RX4 MIX1 INP2", "IIR1", "IIR1"},
+	{"RX5 MIX1 INP1", "RX1", "SLIM RX1"},
+	{"RX5 MIX1 INP1", "RX2", "SLIM RX2"},
+	{"RX5 MIX1 INP1", "RX3", "SLIM RX3"},
+	{"RX5 MIX1 INP1", "RX4", "SLIM RX4"},
+	{"RX5 MIX1 INP1", "RX5", "SLIM RX5"},
+	{"RX5 MIX1 INP1", "RX6", "SLIM RX6"},
+	{"RX5 MIX1 INP1", "RX7", "SLIM RX7"},
+	{"RX5 MIX1 INP1", "IIR1", "IIR1"},
+	{"RX5 MIX1 INP2", "RX1", "SLIM RX1"},
+	{"RX5 MIX1 INP2", "RX2", "SLIM RX2"},
+	{"RX5 MIX1 INP2", "RX3", "SLIM RX3"},
+	{"RX5 MIX1 INP2", "RX4", "SLIM RX4"},
+	{"RX5 MIX1 INP2", "RX5", "SLIM RX5"},
+	{"RX5 MIX1 INP2", "RX6", "SLIM RX6"},
+	{"RX5 MIX1 INP2", "RX7", "SLIM RX7"},
+	{"RX5 MIX1 INP2", "IIR1", "IIR1"},
+	{"RX6 MIX1 INP1", "RX1", "SLIM RX1"},
+	{"RX6 MIX1 INP1", "RX2", "SLIM RX2"},
+	{"RX6 MIX1 INP1", "RX3", "SLIM RX3"},
+	{"RX6 MIX1 INP1", "RX4", "SLIM RX4"},
+	{"RX6 MIX1 INP1", "RX5", "SLIM RX5"},
+	{"RX6 MIX1 INP1", "RX6", "SLIM RX6"},
+	{"RX6 MIX1 INP1", "RX7", "SLIM RX7"},
+	{"RX6 MIX1 INP1", "IIR1", "IIR1"},
+	{"RX6 MIX1 INP2", "RX1", "SLIM RX1"},
+	{"RX6 MIX1 INP2", "RX2", "SLIM RX2"},
+	{"RX6 MIX1 INP2", "RX3", "SLIM RX3"},
+	{"RX6 MIX1 INP2", "RX4", "SLIM RX4"},
+	{"RX6 MIX1 INP2", "RX5", "SLIM RX5"},
+	{"RX6 MIX1 INP2", "RX6", "SLIM RX6"},
+	{"RX6 MIX1 INP2", "RX7", "SLIM RX7"},
+	{"RX6 MIX1 INP2", "IIR1", "IIR1"},
+	{"RX7 MIX1 INP1", "RX1", "SLIM RX1"},
+	{"RX7 MIX1 INP1", "RX2", "SLIM RX2"},
+	{"RX7 MIX1 INP1", "RX3", "SLIM RX3"},
+	{"RX7 MIX1 INP1", "RX4", "SLIM RX4"},
+	{"RX7 MIX1 INP1", "RX5", "SLIM RX5"},
+	{"RX7 MIX1 INP1", "RX6", "SLIM RX6"},
+	{"RX7 MIX1 INP1", "RX7", "SLIM RX7"},
+	{"RX7 MIX1 INP1", "IIR1", "IIR1"},
+	{"RX7 MIX1 INP2", "RX1", "SLIM RX1"},
+	{"RX7 MIX1 INP2", "RX2", "SLIM RX2"},
+	{"RX7 MIX1 INP2", "RX3", "SLIM RX3"},
+	{"RX7 MIX1 INP2", "RX4", "SLIM RX4"},
+	{"RX7 MIX1 INP2", "RX5", "SLIM RX5"},
+	{"RX7 MIX1 INP2", "RX6", "SLIM RX6"},
+	{"RX7 MIX1 INP2", "RX7", "SLIM RX7"},
+	{"RX7 MIX1 INP2", "IIR1", "IIR1"},
+	{"RX1 MIX2 INP1", "IIR1", "IIR1"},
+	{"RX1 MIX2 INP2", "IIR1", "IIR1"},
+	{"RX2 MIX2 INP1", "IIR1", "IIR1"},
+	{"RX2 MIX2 INP2", "IIR1", "IIR1"},
+	{"RX7 MIX2 INP1", "IIR1", "IIR1"},
+	{"RX7 MIX2 INP2", "IIR1", "IIR1"},
+
+	/* Decimator Inputs */
+	{"DEC1 MUX", "DMIC1", "DMIC1"},
+	{"DEC1 MUX", "ADC6", "ADC6"},
+	{"DEC1 MUX", NULL, "CDC_CONN"},
+	{"DEC2 MUX", "DMIC2", "DMIC2"},
+	{"DEC2 MUX", "ADC5", "ADC5"},
+	{"DEC2 MUX", NULL, "CDC_CONN"},
+	{"DEC3 MUX", "DMIC3", "DMIC3"},
+	{"DEC3 MUX", "ADC4", "ADC4"},
+	{"DEC3 MUX", NULL, "CDC_CONN"},
+	{"DEC4 MUX", "DMIC4", "DMIC4"},
+	{"DEC4 MUX", "ADC3", "ADC3"},
+	{"DEC4 MUX", NULL, "CDC_CONN"},
+	{"DEC5 MUX", "DMIC5", "DMIC5"},
+	{"DEC5 MUX", "ADC2", "ADC2"},
+	{"DEC5 MUX", NULL, "CDC_CONN"},
+	{"DEC6 MUX", "DMIC6", "DMIC6"},
+	{"DEC6 MUX", "ADC1", "ADC1"},
+	{"DEC6 MUX", NULL, "CDC_CONN"},
+	{"DEC7 MUX", "DMIC1", "DMIC1"},
+	{"DEC7 MUX", "DMIC6", "DMIC6"},
+	{"DEC7 MUX", "ADC1", "ADC1"},
+	{"DEC7 MUX", "ADC6", "ADC6"},
+	{"DEC7 MUX", NULL, "CDC_CONN"},
+	{"DEC8 MUX", "DMIC2", "DMIC2"},
+	{"DEC8 MUX", "DMIC5", "DMIC5"},
+	{"DEC8 MUX", "ADC2", "ADC2"},
+	{"DEC8 MUX", "ADC5", "ADC5"},
+	{"DEC8 MUX", NULL, "CDC_CONN"},
+	{"DEC9 MUX", "DMIC4", "DMIC4"},
+	{"DEC9 MUX", "DMIC5", "DMIC5"},
+	{"DEC9 MUX", "ADC2", "ADC2"},
+	{"DEC9 MUX", "ADC3", "ADC3"},
+	{"DEC9 MUX", NULL, "CDC_CONN"},
+	{"DEC10 MUX", "DMIC3", "DMIC3"},
+	{"DEC10 MUX", "DMIC6", "DMIC6"},
+	{"DEC10 MUX", "ADC1", "ADC1"},
+	{"DEC10 MUX", "ADC4", "ADC4"},
+	{"DEC10 MUX", NULL, "CDC_CONN"},
+
+	/* ADC Connections */
+	{"ADC1", NULL, "AMIC1"},
+	{"ADC2", NULL, "AMIC2"},
+	{"ADC3", NULL, "AMIC3"},
+	{"ADC4", NULL, "AMIC4"},
+	{"ADC5", NULL, "AMIC5"},
+	{"ADC6", NULL, "AMIC6"},
+
+	/* AUX PGA Connections */
+	{"EAR_PA_MIXER", "AUX_PGA_L Switch", "AUX_PGA_Left"},
+	{"HPHL_PA_MIXER", "AUX_PGA_L Switch", "AUX_PGA_Left"},
+	{"HPHR_PA_MIXER", "AUX_PGA_R Switch", "AUX_PGA_Right"},
+	{"LINEOUT1_PA_MIXER", "AUX_PGA_L Switch", "AUX_PGA_Left"},
+	{"LINEOUT2_PA_MIXER", "AUX_PGA_R Switch", "AUX_PGA_Right"},
+	{"LINEOUT3_PA_MIXER", "AUX_PGA_L Switch", "AUX_PGA_Left"},
+	{"LINEOUT4_PA_MIXER", "AUX_PGA_R Switch", "AUX_PGA_Right"},
+	{"AUX_PGA_Left", NULL, "AMIC5"},
+	{"AUX_PGA_Right", NULL, "AMIC6"},
+
+	{"IIR1", NULL, "IIR1 INP1 MUX"},
+	{"IIR1 INP1 MUX", "DEC1", "DEC1 MUX"},
+	{"IIR1 INP1 MUX", "DEC2", "DEC2 MUX"},
+	{"IIR1 INP1 MUX", "DEC3", "DEC3 MUX"},
+	{"IIR1 INP1 MUX", "DEC4", "DEC4 MUX"},
+	{"IIR1 INP1 MUX", "DEC5", "DEC5 MUX"},
+	{"IIR1 INP1 MUX", "DEC6", "DEC6 MUX"},
+	{"IIR1 INP1 MUX", "DEC7", "DEC7 MUX"},
+	{"IIR1 INP1 MUX", "DEC8", "DEC8 MUX"},
+	{"IIR1 INP1 MUX", "DEC9", "DEC9 MUX"},
+	{"IIR1 INP1 MUX", "DEC10", "DEC10 MUX"},
+
+	{"MIC BIAS1 Internal1", NULL, "LDO_H"},
+	{"MIC BIAS1 Internal2", NULL, "LDO_H"},
+	{"MIC BIAS1 External", NULL, "LDO_H"},
+	{"MIC BIAS2 Internal1", NULL, "LDO_H"},
+	{"MIC BIAS2 Internal2", NULL, "LDO_H"},
+	{"MIC BIAS2 Internal3", NULL, "LDO_H"},
+	{"MIC BIAS2 External", NULL, "LDO_H"},
+	{"MIC BIAS3 Internal1", NULL, "LDO_H"},
+	{"MIC BIAS3 Internal2", NULL, "LDO_H"},
+	{"MIC BIAS3 External", NULL, "LDO_H"},
+	{"MIC BIAS4 External", NULL, "LDO_H"},
+};
+
+static int tapan_readable(struct snd_soc_codec *ssc, unsigned int reg)
+{
+	return tapan_reg_readable[reg];
+}
+
+static bool tapan_is_digital_gain_register(unsigned int reg)
+{
+	bool rtn = false;
+	switch (reg) {
+	case TAPAN_A_CDC_RX1_VOL_CTL_B2_CTL:
+	case TAPAN_A_CDC_RX2_VOL_CTL_B2_CTL:
+	case TAPAN_A_CDC_RX3_VOL_CTL_B2_CTL:
+	case TAPAN_A_CDC_RX4_VOL_CTL_B2_CTL:
+	case TAPAN_A_CDC_TX1_VOL_CTL_GAIN:
+	case TAPAN_A_CDC_TX2_VOL_CTL_GAIN:
+	case TAPAN_A_CDC_TX3_VOL_CTL_GAIN:
+	case TAPAN_A_CDC_TX4_VOL_CTL_GAIN:
+		rtn = true;
+		break;
+	default:
+		break;
+	}
+	return rtn;
+}
+
+static int tapan_volatile(struct snd_soc_codec *ssc, unsigned int reg)
+{
+	/* Registers lower than 0x100 are top level registers which can be
+	 * written by the Taiko core driver.
+	 */
+
+	if ((reg >= TAPAN_A_CDC_MBHC_EN_CTL) || (reg < 0x100))
+		return 1;
+
+	/* IIR Coeff registers are not cacheable */
+	if ((reg >= TAPAN_A_CDC_IIR1_COEF_B1_CTL) &&
+		(reg <= TAPAN_A_CDC_IIR2_COEF_B2_CTL))
+		return 1;
+
+	/* Digital gain register is not cacheable so we have to write
+	 * the setting even it is the same
+	 */
+	if (tapan_is_digital_gain_register(reg))
+		return 1;
+
+	/* HPH status registers */
+	if (reg == TAPAN_A_RX_HPH_L_STATUS || reg == TAPAN_A_RX_HPH_R_STATUS)
+		return 1;
+
+	if (reg == TAPAN_A_MBHC_INSERT_DET_STATUS)
+		return 1;
+
+	return 0;
+}
+
+#define TAPAN_FORMATS (SNDRV_PCM_FMTBIT_S16_LE)
+static int tapan_write(struct snd_soc_codec *codec, unsigned int reg,
+	unsigned int value)
+{
+	int ret;
+
+	if (reg == SND_SOC_NOPM)
+		return 0;
+
+	BUG_ON(reg > TAPAN_MAX_REGISTER);
+
+	if (!tapan_volatile(codec, reg)) {
+		ret = snd_soc_cache_write(codec, reg, value);
+		if (ret != 0)
+			dev_err(codec->dev, "Cache write to %x failed: %d\n",
+				reg, ret);
+	}
+
+	return wcd9xxx_reg_write(codec->control_data, reg, value);
+}
+static unsigned int tapan_read(struct snd_soc_codec *codec,
+				unsigned int reg)
+{
+	unsigned int val;
+	int ret;
+
+	if (reg == SND_SOC_NOPM)
+		return 0;
+
+	BUG_ON(reg > TAPAN_MAX_REGISTER);
+
+	if (!tapan_volatile(codec, reg) && tapan_readable(codec, reg) &&
+		reg < codec->driver->reg_cache_size) {
+		ret = snd_soc_cache_read(codec, reg, &val);
+		if (ret >= 0) {
+			return val;
+		} else
+			dev_err(codec->dev, "Cache read from %x failed: %d\n",
+				reg, ret);
+	}
+
+	val = wcd9xxx_reg_read(codec->control_data, reg);
+	return val;
+}
+
+static int tapan_startup(struct snd_pcm_substream *substream,
+		struct snd_soc_dai *dai)
+{
+	struct wcd9xxx *tapan_core = dev_get_drvdata(dai->codec->dev->parent);
+	dev_dbg(dai->codec->dev, "%s(): substream = %s  stream = %d\n",
+		 __func__, substream->name, substream->stream);
+	if ((tapan_core != NULL) &&
+	    (tapan_core->dev != NULL) &&
+	    (tapan_core->dev->parent != NULL))
+		pm_runtime_get_sync(tapan_core->dev->parent);
+
+	return 0;
+}
+
+static void tapan_shutdown(struct snd_pcm_substream *substream,
+		struct snd_soc_dai *dai)
+{
+	struct wcd9xxx *tapan_core = dev_get_drvdata(dai->codec->dev->parent);
+	dev_dbg(dai->codec->dev, "%s(): substream = %s  stream = %d\n",
+		 __func__, substream->name, substream->stream);
+	if ((tapan_core != NULL) &&
+	    (tapan_core->dev != NULL) &&
+	    (tapan_core->dev->parent != NULL)) {
+		pm_runtime_mark_last_busy(tapan_core->dev->parent);
+		pm_runtime_put(tapan_core->dev->parent);
+	}
+}
+
+int tapan_mclk_enable(struct snd_soc_codec *codec, int mclk_enable, bool dapm)
+{
+	struct tapan_priv *tapan = snd_soc_codec_get_drvdata(codec);
+
+	dev_dbg(codec->dev, "%s: mclk_enable = %u, dapm = %d\n", __func__,
+		 mclk_enable, dapm);
+
+	WCD9XXX_BCL_LOCK(&tapan->resmgr);
+	if (mclk_enable) {
+		wcd9xxx_resmgr_get_bandgap(&tapan->resmgr,
+					   WCD9XXX_BANDGAP_AUDIO_MODE);
+		wcd9xxx_resmgr_get_clk_block(&tapan->resmgr, WCD9XXX_CLK_MCLK);
+	} else {
+		/* Put clock and BG */
+		wcd9xxx_resmgr_put_clk_block(&tapan->resmgr, WCD9XXX_CLK_MCLK);
+		wcd9xxx_resmgr_put_bandgap(&tapan->resmgr,
+					   WCD9XXX_BANDGAP_AUDIO_MODE);
+	}
+	WCD9XXX_BCL_UNLOCK(&tapan->resmgr);
+
+	return 0;
+}
+
+static int tapan_set_dai_sysclk(struct snd_soc_dai *dai,
+		int clk_id, unsigned int freq, int dir)
+{
+	dev_dbg(dai->codec->dev, "%s\n", __func__);
+	return 0;
+}
+
+static int tapan_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt)
+{
+	return 0;
+}
+
+static int tapan_set_channel_map(struct snd_soc_dai *dai,
+				unsigned int tx_num, unsigned int *tx_slot,
+				unsigned int rx_num, unsigned int *rx_slot)
+
+{
+	struct tapan_priv *tapan = snd_soc_codec_get_drvdata(dai->codec);
+	struct wcd9xxx *core = dev_get_drvdata(dai->codec->dev->parent);
+	if (!tx_slot && !rx_slot) {
+		pr_err("%s: Invalid\n", __func__);
+		return -EINVAL;
+	}
+	dev_dbg(dai->codec->dev, "%s(): dai_name = %s DAI-ID %x\n",
+		 __func__, dai->name, dai->id);
+	dev_dbg(dai->codec->dev, "%s(): tx_ch %d rx_ch %d\n intf_type %d\n",
+		 __func__, tx_num, rx_num, tapan->intf_type);
+
+	if (tapan->intf_type == WCD9XXX_INTERFACE_TYPE_SLIMBUS)
+		wcd9xxx_init_slimslave(core, core->slim->laddr,
+				       tx_num, tx_slot, rx_num, rx_slot);
+	return 0;
+}
+
+static int tapan_get_channel_map(struct snd_soc_dai *dai,
+				 unsigned int *tx_num, unsigned int *tx_slot,
+				 unsigned int *rx_num, unsigned int *rx_slot)
+
+{
+	struct tapan_priv *tapan_p = snd_soc_codec_get_drvdata(dai->codec);
+	u32 i = 0;
+	struct wcd9xxx_ch *ch;
+
+	switch (dai->id) {
+	case AIF1_PB:
+	case AIF2_PB:
+	case AIF3_PB:
+		if (!rx_slot || !rx_num) {
+			pr_err("%s: Invalid rx_slot %d or rx_num %d\n",
+				 __func__, (u32) rx_slot, (u32) rx_num);
+			return -EINVAL;
+		}
+		list_for_each_entry(ch, &tapan_p->dai[dai->id].wcd9xxx_ch_list,
+				    list) {
+			dev_dbg(dai->codec->dev, "%s: rx_slot[%d] %d ch->ch_num %d\n",
+				 __func__, i, rx_slot[i], ch->ch_num);
+			rx_slot[i++] = ch->ch_num;
+		}
+		dev_dbg(dai->codec->dev, "%s: rx_num %d\n", __func__, i);
+		*rx_num = i;
+		break;
+	case AIF1_CAP:
+	case AIF2_CAP:
+	case AIF3_CAP:
+		if (!tx_slot || !tx_num) {
+			pr_err("%s: Invalid tx_slot %d or tx_num %d\n",
+				 __func__, (u32) tx_slot, (u32) tx_num);
+			return -EINVAL;
+		}
+		list_for_each_entry(ch, &tapan_p->dai[dai->id].wcd9xxx_ch_list,
+				    list) {
+			dev_dbg(dai->codec->dev, "%s: tx_slot[%d] %d, ch->ch_num %d\n",
+				 __func__, i, tx_slot[i], ch->ch_num);
+			tx_slot[i++] = ch->ch_num;
+		}
+		dev_dbg(dai->codec->dev, "%s: tx_num %d\n", __func__, i);
+		*tx_num = i;
+		break;
+
+	default:
+		pr_err("%s: Invalid DAI ID %x\n", __func__, dai->id);
+		break;
+	}
+
+	return 0;
+}
+
+static int tapan_set_interpolator_rate(struct snd_soc_dai *dai,
+	u8 rx_fs_rate_reg_val, u32 sample_rate)
+{
+	u32 j;
+	u8 rx_mix1_inp;
+	u16 rx_mix_1_reg_1, rx_mix_1_reg_2;
+	u16 rx_fs_reg;
+	u8 rx_mix_1_reg_1_val, rx_mix_1_reg_2_val;
+	struct snd_soc_codec *codec = dai->codec;
+	struct wcd9xxx_ch *ch;
+	struct tapan_priv *tapan = snd_soc_codec_get_drvdata(codec);
+
+	list_for_each_entry(ch, &tapan->dai[dai->id].wcd9xxx_ch_list, list) {
+		/* for RX port starting from 16 instead of 10 like tabla */
+		rx_mix1_inp = ch->port + RX_MIX1_INP_SEL_RX1 -
+			      TAPAN_TX_PORT_NUMBER;
+		if ((rx_mix1_inp < RX_MIX1_INP_SEL_RX1) ||
+			(rx_mix1_inp > RX_MIX1_INP_SEL_RX7)) {
+			pr_err("%s: Invalid TAPAN_RX%u port. Dai ID is %d\n",
+				__func__,  rx_mix1_inp - 5 , dai->id);
+			return -EINVAL;
+		}
+
+		rx_mix_1_reg_1 = TAPAN_A_CDC_CONN_RX1_B1_CTL;
+
+		for (j = 0; j < NUM_INTERPOLATORS; j++) {
+			rx_mix_1_reg_2 = rx_mix_1_reg_1 + 1;
+
+			rx_mix_1_reg_1_val = snd_soc_read(codec,
+							  rx_mix_1_reg_1);
+			rx_mix_1_reg_2_val = snd_soc_read(codec,
+							  rx_mix_1_reg_2);
+
+			if (((rx_mix_1_reg_1_val & 0x0F) == rx_mix1_inp) ||
+			    (((rx_mix_1_reg_1_val >> 4) & 0x0F)
+				== rx_mix1_inp) ||
+			    ((rx_mix_1_reg_2_val & 0x0F) == rx_mix1_inp)) {
+
+				rx_fs_reg = TAPAN_A_CDC_RX1_B5_CTL + 8 * j;
+
+				dev_dbg(codec->dev, "%s: AIF_PB DAI(%d) connected to RX%u\n",
+					__func__, dai->id, j + 1);
+
+				dev_dbg(codec->dev, "%s: set RX%u sample rate to %u\n",
+					__func__, j + 1, sample_rate);
+
+				snd_soc_update_bits(codec, rx_fs_reg,
+						0xE0, rx_fs_rate_reg_val);
+
+			}
+			if (j <= 2)
+				rx_mix_1_reg_1 += 3;
+			else
+				rx_mix_1_reg_1 += 2;
+		}
+	}
+	return 0;
+}
+
+static int tapan_set_decimator_rate(struct snd_soc_dai *dai,
+	u8 tx_fs_rate_reg_val, u32 sample_rate)
+{
+	struct snd_soc_codec *codec = dai->codec;
+	struct wcd9xxx_ch *ch;
+	struct tapan_priv *tapan = snd_soc_codec_get_drvdata(codec);
+	u32 tx_port;
+	u16 tx_port_reg, tx_fs_reg;
+	u8 tx_port_reg_val;
+	s8 decimator;
+
+	list_for_each_entry(ch, &tapan->dai[dai->id].wcd9xxx_ch_list, list) {
+
+		tx_port = ch->port + 1;
+		dev_dbg(codec->dev, "%s: dai->id = %d, tx_port = %d",
+			__func__, dai->id, tx_port);
+
+		if ((tx_port < 1) || (tx_port > NUM_DECIMATORS)) {
+			pr_err("%s: Invalid SLIM TX%u port. DAI ID is %d\n",
+				__func__, tx_port, dai->id);
+			return -EINVAL;
+		}
+
+		tx_port_reg = TAPAN_A_CDC_CONN_TX_SB_B1_CTL + (tx_port - 1);
+		tx_port_reg_val =  snd_soc_read(codec, tx_port_reg);
+
+		decimator = 0;
+
+		if ((tx_port >= 1) && (tx_port <= 6)) {
+
+			tx_port_reg_val =  tx_port_reg_val & 0x0F;
+			if (tx_port_reg_val == 0x8)
+				decimator = tx_port;
+
+		} else if ((tx_port >= 7) && (tx_port <= NUM_DECIMATORS)) {
+
+			tx_port_reg_val =  tx_port_reg_val & 0x1F;
+
+			if ((tx_port_reg_val >= 0x8) &&
+			    (tx_port_reg_val <= 0x11)) {
+
+				decimator = (tx_port_reg_val - 0x8) + 1;
+			}
+		}
+
+		if (decimator) { /* SLIM_TX port has a DEC as input */
+
+			tx_fs_reg = TAPAN_A_CDC_TX1_CLK_FS_CTL +
+				    8 * (decimator - 1);
+
+			dev_dbg(codec->dev, "%s: set DEC%u (-> SLIM_TX%u) rate to %u\n",
+				__func__, decimator, tx_port, sample_rate);
+
+			snd_soc_update_bits(codec, tx_fs_reg, 0x07,
+					    tx_fs_rate_reg_val);
+
+		} else {
+			if ((tx_port_reg_val >= 0x1) &&
+			    (tx_port_reg_val <= 0x7)) {
+
+				dev_dbg(codec->dev, "%s: RMIX%u going to SLIM TX%u\n",
+					__func__, tx_port_reg_val, tx_port);
+
+			} else if  ((tx_port_reg_val >= 0x8) &&
+				    (tx_port_reg_val <= 0x11)) {
+
+				pr_err("%s: ERROR: Should not be here\n",
+				       __func__);
+				pr_err("%s: ERROR: DEC connected to SLIM TX%u\n",
+					__func__, tx_port);
+				return -EINVAL;
+
+			} else if (tx_port_reg_val == 0) {
+				dev_dbg(codec->dev, "%s: no signal to SLIM TX%u\n",
+					__func__, tx_port);
+			} else {
+				pr_err("%s: ERROR: wrong signal to SLIM TX%u\n",
+					__func__, tx_port);
+				pr_err("%s: ERROR: wrong signal = %u\n",
+					__func__, tx_port_reg_val);
+				return -EINVAL;
+			}
+		}
+	}
+	return 0;
+}
+
+static int tapan_hw_params(struct snd_pcm_substream *substream,
+			    struct snd_pcm_hw_params *params,
+			    struct snd_soc_dai *dai)
+{
+	struct tapan_priv *tapan = snd_soc_codec_get_drvdata(dai->codec);
+	u8 tx_fs_rate, rx_fs_rate;
+	int ret;
+
+	dev_dbg(dai->codec->dev, "%s: dai_name = %s DAI-ID %x rate %d num_ch %d\n",
+		 __func__, dai->name, dai->id,
+		 params_rate(params), params_channels(params));
+
+	switch (params_rate(params)) {
+	case 8000:
+		tx_fs_rate = 0x00;
+		rx_fs_rate = 0x00;
+		break;
+	case 16000:
+		tx_fs_rate = 0x01;
+		rx_fs_rate = 0x20;
+		break;
+	case 32000:
+		tx_fs_rate = 0x02;
+		rx_fs_rate = 0x40;
+		break;
+	case 48000:
+		tx_fs_rate = 0x03;
+		rx_fs_rate = 0x60;
+		break;
+	case 96000:
+		tx_fs_rate = 0x04;
+		rx_fs_rate = 0x80;
+		break;
+	case 192000:
+		tx_fs_rate = 0x05;
+		rx_fs_rate = 0xA0;
+		break;
+	default:
+		pr_err("%s: Invalid sampling rate %d\n", __func__,
+			params_rate(params));
+		return -EINVAL;
+	}
+
+	switch (substream->stream) {
+	case SNDRV_PCM_STREAM_CAPTURE:
+		ret = tapan_set_decimator_rate(dai, tx_fs_rate,
+					       params_rate(params));
+		if (ret < 0) {
+			pr_err("%s: set decimator rate failed %d\n", __func__,
+				ret);
+			return ret;
+		}
+
+		if (tapan->intf_type == WCD9XXX_INTERFACE_TYPE_I2C)
+			pr_err("%s: I2C interface not yet supported\n",
+				   __func__);
+		else
+			tapan->dai[dai->id].rate = params_rate(params);
+
+		break;
+
+	case SNDRV_PCM_STREAM_PLAYBACK:
+		ret = tapan_set_interpolator_rate(dai, rx_fs_rate,
+						  params_rate(params));
+		if (ret < 0) {
+			pr_err("%s: set decimator rate failed %d\n", __func__,
+				ret);
+			return ret;
+		}
+		if (tapan->intf_type == WCD9XXX_INTERFACE_TYPE_I2C)
+			pr_err("%s: I2C interface not yet supported\n",
+				   __func__);
+		else
+			tapan->dai[dai->id].rate   = params_rate(params);
+
+		break;
+	default:
+		pr_err("%s: Invalid stream type %d\n", __func__,
+			substream->stream);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static struct snd_soc_dai_ops tapan_dai_ops = {
+	.startup = tapan_startup,
+	.shutdown = tapan_shutdown,
+	.hw_params = tapan_hw_params,
+	.set_sysclk = tapan_set_dai_sysclk,
+	.set_fmt = tapan_set_dai_fmt,
+	.set_channel_map = tapan_set_channel_map,
+	.get_channel_map = tapan_get_channel_map,
+};
+
+static struct snd_soc_dai_driver tapan_dai[] = {
+	{
+		.name = "tapan_rx1",
+		.id = AIF1_PB,
+		.playback = {
+			.stream_name = "AIF1 Playback",
+			.rates = WCD9306_RATES,
+			.formats = TAPAN_FORMATS,
+			.rate_max = 192000,
+			.rate_min = 8000,
+			.channels_min = 1,
+			.channels_max = 2,
+		},
+		.ops = &tapan_dai_ops,
+	},
+	{
+		.name = "tapan_tx1",
+		.id = AIF1_CAP,
+		.capture = {
+			.stream_name = "AIF1 Capture",
+			.rates = WCD9306_RATES,
+			.formats = TAPAN_FORMATS,
+			.rate_max = 192000,
+			.rate_min = 8000,
+			.channels_min = 1,
+			.channels_max = 4,
+		},
+		.ops = &tapan_dai_ops,
+	},
+	{
+		.name = "tapan_rx2",
+		.id = AIF2_PB,
+		.playback = {
+			.stream_name = "AIF2 Playback",
+			.rates = WCD9306_RATES,
+			.formats = TAPAN_FORMATS,
+			.rate_min = 8000,
+			.rate_max = 192000,
+			.channels_min = 1,
+			.channels_max = 2,
+		},
+		.ops = &tapan_dai_ops,
+	},
+	{
+		.name = "tapan_tx2",
+		.id = AIF2_CAP,
+		.capture = {
+			.stream_name = "AIF2 Capture",
+			.rates = WCD9306_RATES,
+			.formats = TAPAN_FORMATS,
+			.rate_max = 192000,
+			.rate_min = 8000,
+			.channels_min = 1,
+			.channels_max = 4,
+		},
+		.ops = &tapan_dai_ops,
+	},
+	{
+		.name = "tapan_tx3",
+		.id = AIF3_CAP,
+		.capture = {
+			.stream_name = "AIF3 Capture",
+			.rates = WCD9306_RATES,
+			.formats = TAPAN_FORMATS,
+			.rate_max = 48000,
+			.rate_min = 8000,
+			.channels_min = 1,
+			.channels_max = 2,
+		},
+		.ops = &tapan_dai_ops,
+	},
+	{
+		.name = "tapan_rx3",
+		.id = AIF3_PB,
+		.playback = {
+			.stream_name = "AIF3 Playback",
+			.rates = WCD9306_RATES,
+			.formats = TAPAN_FORMATS,
+			.rate_min = 8000,
+			.rate_max = 192000,
+			.channels_min = 1,
+			.channels_max = 2,
+		},
+		.ops = &tapan_dai_ops,
+	},
+};
+
+static struct snd_soc_dai_driver tapan_i2s_dai[] = {
+	{
+		.name = "tapan_i2s_rx1",
+		.id = AIF1_PB,
+		.playback = {
+			.stream_name = "AIF1 Playback",
+			.rates = WCD9306_RATES,
+			.formats = TAPAN_FORMATS,
+			.rate_max = 192000,
+			.rate_min = 8000,
+			.channels_min = 1,
+			.channels_max = 4,
+		},
+		.ops = &tapan_dai_ops,
+	},
+	{
+		.name = "tapan_i2s_tx1",
+		.id = AIF1_CAP,
+		.capture = {
+			.stream_name = "AIF1 Capture",
+			.rates = WCD9306_RATES,
+			.formats = TAPAN_FORMATS,
+			.rate_max = 192000,
+			.rate_min = 8000,
+			.channels_min = 1,
+			.channels_max = 4,
+		},
+		.ops = &tapan_dai_ops,
+	},
+};
+
+static int tapan_codec_enable_slimrx(struct snd_soc_dapm_widget *w,
+				     struct snd_kcontrol *kcontrol,
+				     int event)
+{
+	struct wcd9xxx *core;
+	struct snd_soc_codec *codec = w->codec;
+	struct tapan_priv *tapan_p = snd_soc_codec_get_drvdata(codec);
+	u32  ret = 0;
+	struct wcd9xxx_codec_dai_data *dai;
+
+	core = dev_get_drvdata(codec->dev->parent);
+
+	dev_dbg(codec->dev, "%s: event called! codec name %s\n",
+		__func__, w->codec->name);
+	dev_dbg(codec->dev, "%s: num_dai %d stream name %s event %d\n",
+		__func__, w->codec->num_dai, w->sname, event);
+
+	/* Execute the callback only if interface type is slimbus */
+	if (tapan_p->intf_type != WCD9XXX_INTERFACE_TYPE_SLIMBUS)
+		return 0;
+
+	dai = &tapan_p->dai[w->shift];
+	dev_dbg(codec->dev, "%s: w->name %s w->shift %d event %d\n",
+		 __func__, w->name, w->shift, event);
+
+	switch (event) {
+	case SND_SOC_DAPM_POST_PMU:
+		ret = wcd9xxx_cfg_slim_sch_rx(core, &dai->wcd9xxx_ch_list,
+					      dai->rate, dai->bit_width,
+					      &dai->grph);
+		break;
+	case SND_SOC_DAPM_POST_PMD:
+		ret = wcd9xxx_close_slim_sch_rx(core, &dai->wcd9xxx_ch_list,
+						dai->grph);
+		usleep_range(15000, 15000);
+		break;
+	}
+	return ret;
+}
+
+static int tapan_codec_enable_slimtx(struct snd_soc_dapm_widget *w,
+				     struct snd_kcontrol *kcontrol,
+				     int event)
+{
+	struct wcd9xxx *core;
+	struct snd_soc_codec *codec = w->codec;
+	struct tapan_priv *tapan_p = snd_soc_codec_get_drvdata(codec);
+	u32  ret = 0;
+	struct wcd9xxx_codec_dai_data *dai;
+
+	core = dev_get_drvdata(codec->dev->parent);
+
+	dev_dbg(codec->dev, "%s: event called! codec name %s\n",
+		__func__, w->codec->name);
+	dev_dbg(codec->dev, "%s: num_dai %d stream name %s\n",
+		__func__, w->codec->num_dai, w->sname);
+
+	/* Execute the callback only if interface type is slimbus */
+	if (tapan_p->intf_type != WCD9XXX_INTERFACE_TYPE_SLIMBUS)
+		return 0;
+
+	dev_dbg(codec->dev, "%s(): w->name %s event %d w->shift %d\n",
+		__func__, w->name, event, w->shift);
+
+	dai = &tapan_p->dai[w->shift];
+	switch (event) {
+	case SND_SOC_DAPM_POST_PMU:
+		ret = wcd9xxx_cfg_slim_sch_tx(core, &dai->wcd9xxx_ch_list,
+					      dai->rate, dai->bit_width,
+					      &dai->grph);
+		break;
+	case SND_SOC_DAPM_POST_PMD:
+		ret = wcd9xxx_close_slim_sch_tx(core, &dai->wcd9xxx_ch_list,
+						dai->grph);
+		break;
+	}
+	return ret;
+}
+
+static int tapan_codec_enable_ear_pa(struct snd_soc_dapm_widget *w,
+	struct snd_kcontrol *kcontrol, int event)
+{
+	struct snd_soc_codec *codec = w->codec;
+
+	dev_dbg(codec->dev, "%s %s %d\n", __func__, w->name, event);
+
+	switch (event) {
+
+	case SND_SOC_DAPM_POST_PMU:
+
+		snd_soc_update_bits(codec, TAPAN_A_BUCK_MODE_5, 0x02, 0x00);
+		snd_soc_update_bits(codec, TAPAN_A_NCP_STATIC, 0x20, 0x00);
+		snd_soc_update_bits(codec, TAPAN_A_BUCK_MODE_3, 0x04, 0x04);
+		snd_soc_update_bits(codec, TAPAN_A_BUCK_MODE_3, 0x08, 0x00);
+
+		usleep_range(5000, 5000);
+		break;
+	}
+	return 0;
+}
+
+/* Todo: Have seperate dapm widgets for I2S and Slimbus.
+ * Might Need to have callbacks registered only for slimbus
+ */
+static const struct snd_soc_dapm_widget tapan_dapm_widgets[] = {
+	/*RX stuff */
+	SND_SOC_DAPM_OUTPUT("EAR"),
+
+	SND_SOC_DAPM_PGA_E("EAR PA", TAPAN_A_RX_EAR_EN, 4, 0, NULL, 0,
+			tapan_codec_enable_ear_pa, SND_SOC_DAPM_POST_PMU),
+
+	SND_SOC_DAPM_MIXER("DAC1", TAPAN_A_RX_EAR_EN, 6, 0, dac1_switch,
+		ARRAY_SIZE(dac1_switch)),
+
+	SND_SOC_DAPM_AIF_IN_E("AIF1 PB", "AIF1 Playback", 0, SND_SOC_NOPM,
+				AIF1_PB, 0, tapan_codec_enable_slimrx,
+				SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+	SND_SOC_DAPM_AIF_IN_E("AIF2 PB", "AIF2 Playback", 0, SND_SOC_NOPM,
+				AIF2_PB, 0, tapan_codec_enable_slimrx,
+				SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+	SND_SOC_DAPM_AIF_IN_E("AIF3 PB", "AIF3 Playback", 0, SND_SOC_NOPM,
+				AIF3_PB, 0, tapan_codec_enable_slimrx,
+				SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_MUX("SLIM RX1 MUX", SND_SOC_NOPM, TAPAN_RX1, 0,
+				&slim_rx_mux[TAPAN_RX1]),
+	SND_SOC_DAPM_MUX("SLIM RX2 MUX", SND_SOC_NOPM, TAPAN_RX2, 0,
+				&slim_rx_mux[TAPAN_RX2]),
+	SND_SOC_DAPM_MUX("SLIM RX3 MUX", SND_SOC_NOPM, TAPAN_RX3, 0,
+				&slim_rx_mux[TAPAN_RX3]),
+	SND_SOC_DAPM_MUX("SLIM RX4 MUX", SND_SOC_NOPM, TAPAN_RX4, 0,
+				&slim_rx_mux[TAPAN_RX4]),
+	SND_SOC_DAPM_MUX("SLIM RX5 MUX", SND_SOC_NOPM, TAPAN_RX5, 0,
+				&slim_rx_mux[TAPAN_RX5]),
+
+	SND_SOC_DAPM_MIXER("SLIM RX1", SND_SOC_NOPM, 0, 0, NULL, 0),
+	SND_SOC_DAPM_MIXER("SLIM RX2", SND_SOC_NOPM, 0, 0, NULL, 0),
+	SND_SOC_DAPM_MIXER("SLIM RX3", SND_SOC_NOPM, 0, 0, NULL, 0),
+	SND_SOC_DAPM_MIXER("SLIM RX4", SND_SOC_NOPM, 0, 0, NULL, 0),
+	SND_SOC_DAPM_MIXER("SLIM RX5", SND_SOC_NOPM, 0, 0, NULL, 0),
+
+	/* Headphone */
+	SND_SOC_DAPM_OUTPUT("HEADPHONE"),
+	SND_SOC_DAPM_PGA_E("HPHL", TAPAN_A_RX_HPH_CNP_EN, 5, 0, NULL, 0,
+		tapan_hph_pa_event, SND_SOC_DAPM_PRE_PMU |
+		SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+	SND_SOC_DAPM_MIXER("HPHL DAC", TAPAN_A_RX_HPH_L_DAC_CTL, 7, 0,
+		hphl_switch, ARRAY_SIZE(hphl_switch)),
+
+	SND_SOC_DAPM_PGA_E("HPHR", TAPAN_A_RX_HPH_CNP_EN, 4, 0, NULL, 0,
+		tapan_hph_pa_event, SND_SOC_DAPM_PRE_PMU |
+		SND_SOC_DAPM_POST_PMU |	SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_DAC_E("HPHR DAC", NULL, TAPAN_A_RX_HPH_R_DAC_CTL, 7, 0,
+		tapan_hphr_dac_event,
+		SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+
+	/* Speaker */
+	SND_SOC_DAPM_OUTPUT("LINEOUT1"),
+	SND_SOC_DAPM_OUTPUT("LINEOUT2"),
+	SND_SOC_DAPM_OUTPUT("SPK_OUT"),
+
+	SND_SOC_DAPM_PGA_E("LINEOUT1 PA", TAPAN_A_RX_LINE_CNP_EN, 0, 0, NULL,
+			0, tapan_codec_enable_lineout, SND_SOC_DAPM_PRE_PMU |
+			SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+	SND_SOC_DAPM_PGA_E("LINEOUT2 PA", TAPAN_A_RX_LINE_CNP_EN, 1, 0, NULL,
+			0, tapan_codec_enable_lineout, SND_SOC_DAPM_PRE_PMU |
+			SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_PGA_E("SPK PA", TAPAN_A_SPKR_DRV_EN, 7, 0 , NULL,
+			   0, tapan_codec_enable_spk_pa, SND_SOC_DAPM_PRE_PMU |
+			   SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_DAC_E("LINEOUT1 DAC", NULL, TAPAN_A_RX_LINE_1_DAC_CTL, 7, 0
+		, tapan_lineout_dac_event,
+		SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+	SND_SOC_DAPM_DAC_E("LINEOUT2 DAC", NULL, TAPAN_A_RX_LINE_2_DAC_CTL, 7, 0
+		, tapan_lineout_dac_event,
+		SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_DAC_E("SPK DAC", NULL, SND_SOC_NOPM, 0, 0,
+			   tapan_spk_dac_event,
+			   SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_MIXER("RX1 MIX1", SND_SOC_NOPM, 0, 0, NULL, 0),
+	SND_SOC_DAPM_MIXER("RX2 MIX1", SND_SOC_NOPM, 0, 0, NULL, 0),
+
+	SND_SOC_DAPM_MIXER_E("RX1 MIX2", TAPAN_A_CDC_CLK_RX_B1_CTL, 0, 0, NULL,
+		0, tapan_codec_enable_interpolator, SND_SOC_DAPM_PRE_PMU |
+		SND_SOC_DAPM_POST_PMU),
+	SND_SOC_DAPM_MIXER_E("RX2 MIX2", TAPAN_A_CDC_CLK_RX_B1_CTL, 1, 0, NULL,
+		0, tapan_codec_enable_interpolator, SND_SOC_DAPM_PRE_PMU |
+		SND_SOC_DAPM_POST_PMU),
+	SND_SOC_DAPM_MIXER_E("RX3 MIX1", TAPAN_A_CDC_CLK_RX_B1_CTL, 2, 0, NULL,
+		0, tapan_codec_enable_interpolator, SND_SOC_DAPM_PRE_PMU |
+		SND_SOC_DAPM_POST_PMU),
+	SND_SOC_DAPM_MIXER_E("RX4 MIX1", TAPAN_A_CDC_CLK_RX_B1_CTL, 3, 0, NULL,
+		0, tapan_codec_enable_interpolator, SND_SOC_DAPM_PRE_PMU |
+		SND_SOC_DAPM_POST_PMU),
+	SND_SOC_DAPM_MIXER_E("RX5 MIX1", TAPAN_A_CDC_CLK_RX_B1_CTL, 4, 0, NULL,
+		0, tapan_codec_enable_interpolator, SND_SOC_DAPM_PRE_PMU |
+		SND_SOC_DAPM_POST_PMU),
+
+	SND_SOC_DAPM_MIXER("RX1 CHAIN", TAPAN_A_CDC_RX1_B6_CTL, 5, 0, NULL, 0),
+	SND_SOC_DAPM_MIXER("RX2 CHAIN", TAPAN_A_CDC_RX2_B6_CTL, 5, 0, NULL, 0),
+
+	SND_SOC_DAPM_MUX("RX1 MIX1 INP1", SND_SOC_NOPM, 0, 0,
+		&rx_mix1_inp1_mux),
+	SND_SOC_DAPM_MUX("RX1 MIX1 INP2", SND_SOC_NOPM, 0, 0,
+		&rx_mix1_inp2_mux),
+	SND_SOC_DAPM_MUX("RX1 MIX1 INP3", SND_SOC_NOPM, 0, 0,
+		&rx_mix1_inp3_mux),
+	SND_SOC_DAPM_MUX("RX2 MIX1 INP1", SND_SOC_NOPM, 0, 0,
+		&rx2_mix1_inp1_mux),
+	SND_SOC_DAPM_MUX("RX2 MIX1 INP2", SND_SOC_NOPM, 0, 0,
+		&rx2_mix1_inp2_mux),
+	SND_SOC_DAPM_MUX("RX3 MIX1 INP1", SND_SOC_NOPM, 0, 0,
+		&rx3_mix1_inp1_mux),
+	SND_SOC_DAPM_MUX("RX3 MIX1 INP2", SND_SOC_NOPM, 0, 0,
+		&rx3_mix1_inp2_mux),
+	SND_SOC_DAPM_MUX("RX4 MIX1 INP1", SND_SOC_NOPM, 0, 0,
+		&rx4_mix1_inp1_mux),
+	SND_SOC_DAPM_MUX("RX4 MIX1 INP2", SND_SOC_NOPM, 0, 0,
+		&rx4_mix1_inp2_mux),
+	SND_SOC_DAPM_MUX("RX1 MIX2 INP1", SND_SOC_NOPM, 0, 0,
+		&rx1_mix2_inp1_mux),
+	SND_SOC_DAPM_MUX("RX1 MIX2 INP2", SND_SOC_NOPM, 0, 0,
+		&rx1_mix2_inp2_mux),
+	SND_SOC_DAPM_MUX("RX2 MIX2 INP1", SND_SOC_NOPM, 0, 0,
+		&rx2_mix2_inp1_mux),
+	SND_SOC_DAPM_MUX("RX2 MIX2 INP2", SND_SOC_NOPM, 0, 0,
+		&rx2_mix2_inp2_mux),
+
+	SND_SOC_DAPM_MUX("RDAC5 MUX", SND_SOC_NOPM, 0, 0,
+		&rx_dac5_mux),
+
+	SND_SOC_DAPM_SUPPLY("CLASS_H_CLK", TAPAN_A_CDC_CLK_OTHR_CTL, 0, 0,
+		tapan_codec_enable_class_h_clk, SND_SOC_DAPM_PRE_PMU |
+		SND_SOC_DAPM_PRE_PMD),
+
+	SND_SOC_DAPM_SUPPLY("CLASS_H_EAR", TAPAN_A_CDC_CLSH_B1_CTL, 4, 0,
+		tapan_codec_enable_class_h, SND_SOC_DAPM_POST_PMU),
+
+	SND_SOC_DAPM_SUPPLY("CLASS_H_HPH_L", TAPAN_A_CDC_CLSH_B1_CTL, 3, 0,
+		tapan_codec_enable_class_h, SND_SOC_DAPM_POST_PMU),
+
+	SND_SOC_DAPM_SUPPLY("CLASS_H_HPH_R", TAPAN_A_CDC_CLSH_B1_CTL, 2, 0,
+		tapan_codec_enable_class_h, SND_SOC_DAPM_POST_PMU),
+
+	SND_SOC_DAPM_SUPPLY("CLASS_H_LINEOUTS_PA", SND_SOC_NOPM, 0, 0,
+		tapan_codec_enable_class_h, SND_SOC_DAPM_POST_PMU),
+
+	SND_SOC_DAPM_SUPPLY("CP", TAPAN_A_NCP_EN, 0, 0,
+		tapan_codec_enable_charge_pump, SND_SOC_DAPM_PRE_PMU |
+		SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
+
+	SND_SOC_DAPM_SUPPLY("RX_BIAS", SND_SOC_NOPM, 0, 0,
+		tapan_codec_enable_rx_bias, SND_SOC_DAPM_PRE_PMU |
+		SND_SOC_DAPM_POST_PMD),
+
+	/* TX */
+
+	SND_SOC_DAPM_SUPPLY("CDC_CONN", TAPAN_A_CDC_CLK_OTHR_CTL, 2, 0, NULL,
+		0),
+
+	SND_SOC_DAPM_SUPPLY("LDO_H", TAPAN_A_LDO_H_MODE_1, 7, 0,
+		tapan_codec_enable_ldo_h, SND_SOC_DAPM_POST_PMU),
+
+	SND_SOC_DAPM_INPUT("AMIC1"),
+	SND_SOC_DAPM_MICBIAS_E("MIC BIAS1 External", TAPAN_A_MICB_1_CTL, 7, 0,
+		tapan_codec_enable_micbias, SND_SOC_DAPM_PRE_PMU |
+		SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+	SND_SOC_DAPM_MICBIAS_E("MIC BIAS1 Internal1", TAPAN_A_MICB_1_CTL, 7, 0,
+		tapan_codec_enable_micbias, SND_SOC_DAPM_PRE_PMU |
+		SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+	SND_SOC_DAPM_MICBIAS_E("MIC BIAS1 Internal2", TAPAN_A_MICB_1_CTL, 7, 0,
+		tapan_codec_enable_micbias, SND_SOC_DAPM_PRE_PMU |
+		SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+	SND_SOC_DAPM_INPUT("AMIC3"),
+
+	SND_SOC_DAPM_INPUT("AMIC4"),
+
+	SND_SOC_DAPM_INPUT("AMIC5"),
+
+	SND_SOC_DAPM_MUX_E("DEC1 MUX", TAPAN_A_CDC_CLK_TX_CLK_EN_B1_CTL, 0, 0,
+		&dec1_mux, tapan_codec_enable_dec,
+		SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+		SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_MUX_E("DEC2 MUX", TAPAN_A_CDC_CLK_TX_CLK_EN_B1_CTL, 1, 0,
+		&dec2_mux, tapan_codec_enable_dec,
+		SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+		SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_MUX_E("DEC3 MUX", TAPAN_A_CDC_CLK_TX_CLK_EN_B1_CTL, 2, 0,
+		&dec3_mux, tapan_codec_enable_dec,
+		SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+		SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_MUX_E("DEC4 MUX", TAPAN_A_CDC_CLK_TX_CLK_EN_B1_CTL, 3, 0,
+		&dec4_mux, tapan_codec_enable_dec,
+		SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+		SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_MIXER_E("ANC", SND_SOC_NOPM, 0, 0, NULL, 0,
+		tapan_codec_enable_anc, SND_SOC_DAPM_PRE_PMU |
+		SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_INPUT("AMIC2"),
+	SND_SOC_DAPM_MICBIAS_E("MIC BIAS2 External", TAPAN_A_MICB_2_CTL, 7, 0,
+		tapan_codec_enable_micbias, SND_SOC_DAPM_PRE_PMU |
+		SND_SOC_DAPM_POST_PMU |	SND_SOC_DAPM_POST_PMD),
+	SND_SOC_DAPM_MICBIAS_E("MIC BIAS2 Internal1", TAPAN_A_MICB_2_CTL, 7, 0,
+		tapan_codec_enable_micbias, SND_SOC_DAPM_PRE_PMU |
+		SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+	SND_SOC_DAPM_MICBIAS_E("MIC BIAS2 Internal2", TAPAN_A_MICB_2_CTL, 7, 0,
+		tapan_codec_enable_micbias, SND_SOC_DAPM_PRE_PMU |
+		SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+	SND_SOC_DAPM_MICBIAS_E("MIC BIAS2 Internal3", TAPAN_A_MICB_2_CTL, 7, 0,
+		tapan_codec_enable_micbias, SND_SOC_DAPM_PRE_PMU |
+		SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+	SND_SOC_DAPM_MICBIAS_E("MIC BIAS3 External", TAPAN_A_MICB_3_CTL, 7, 0,
+		tapan_codec_enable_micbias, SND_SOC_DAPM_PRE_PMU |
+		SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+	SND_SOC_DAPM_MICBIAS_E("MIC BIAS3 Internal1", TAPAN_A_MICB_3_CTL, 7, 0,
+		tapan_codec_enable_micbias, SND_SOC_DAPM_PRE_PMU |
+		SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+	SND_SOC_DAPM_MICBIAS_E("MIC BIAS3 Internal2", TAPAN_A_MICB_3_CTL, 7, 0,
+		tapan_codec_enable_micbias, SND_SOC_DAPM_PRE_PMU |
+		SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_AIF_OUT_E("AIF1 CAP", "AIF1 Capture", 0, SND_SOC_NOPM,
+		AIF1_CAP, 0, tapan_codec_enable_slimtx,
+		SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_AIF_OUT_E("AIF2 CAP", "AIF2 Capture", 0, SND_SOC_NOPM,
+		AIF2_CAP, 0, tapan_codec_enable_slimtx,
+		SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_AIF_OUT_E("AIF3 CAP", "AIF3 Capture", 0, SND_SOC_NOPM,
+		AIF3_CAP, 0, tapan_codec_enable_slimtx,
+		SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_MIXER("AIF1_CAP Mixer", SND_SOC_NOPM, AIF1_CAP, 0,
+		aif_cap_mixer, ARRAY_SIZE(aif_cap_mixer)),
+
+	SND_SOC_DAPM_MIXER("AIF2_CAP Mixer", SND_SOC_NOPM, AIF2_CAP, 0,
+		aif_cap_mixer, ARRAY_SIZE(aif_cap_mixer)),
+
+	SND_SOC_DAPM_MIXER("AIF3_CAP Mixer", SND_SOC_NOPM, AIF3_CAP, 0,
+		aif_cap_mixer, ARRAY_SIZE(aif_cap_mixer)),
+
+	SND_SOC_DAPM_MUX("SLIM TX1 MUX", SND_SOC_NOPM, TAPAN_TX1, 0,
+		&sb_tx1_mux),
+	SND_SOC_DAPM_MUX("SLIM TX2 MUX", SND_SOC_NOPM, TAPAN_TX2, 0,
+		&sb_tx2_mux),
+	SND_SOC_DAPM_MUX("SLIM TX3 MUX", SND_SOC_NOPM, TAPAN_TX3, 0,
+		&sb_tx3_mux),
+	SND_SOC_DAPM_MUX("SLIM TX4 MUX", SND_SOC_NOPM, TAPAN_TX4, 0,
+		&sb_tx4_mux),
+
+	/* Digital Mic Inputs */
+	SND_SOC_DAPM_ADC_E("DMIC1", NULL, SND_SOC_NOPM, 0, 0,
+		tapan_codec_enable_dmic, SND_SOC_DAPM_PRE_PMU |
+		SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_ADC_E("DMIC2", NULL, SND_SOC_NOPM, 0, 0,
+		tapan_codec_enable_dmic, SND_SOC_DAPM_PRE_PMU |
+		SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_ADC_E("DMIC3", NULL, SND_SOC_NOPM, 0, 0,
+		tapan_codec_enable_dmic, SND_SOC_DAPM_PRE_PMU |
+		SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_ADC_E("DMIC4", NULL, SND_SOC_NOPM, 0, 0,
+		tapan_codec_enable_dmic, SND_SOC_DAPM_PRE_PMU |
+		SND_SOC_DAPM_POST_PMD),
+
+	/* Sidetone */
+	SND_SOC_DAPM_MUX("IIR1 INP1 MUX", SND_SOC_NOPM, 0, 0, &iir1_inp1_mux),
+	SND_SOC_DAPM_PGA("IIR1", TAPAN_A_CDC_CLK_SD_CTL, 0, 0, NULL, 0),
+
+	/* AUX PGA */
+	SND_SOC_DAPM_ADC_E("AUX_PGA_Left", NULL, TAPAN_A_RX_AUX_SW_CTL, 7, 0,
+		tapan_codec_enable_aux_pga, SND_SOC_DAPM_PRE_PMU |
+		SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_ADC_E("AUX_PGA_Right", NULL, TAPAN_A_RX_AUX_SW_CTL, 6, 0,
+		tapan_codec_enable_aux_pga, SND_SOC_DAPM_PRE_PMU |
+		SND_SOC_DAPM_POST_PMD),
+
+	/* Lineout, ear and HPH PA Mixers */
+
+	SND_SOC_DAPM_MIXER("EAR_PA_MIXER", SND_SOC_NOPM, 0, 0,
+		ear_pa_mix, ARRAY_SIZE(ear_pa_mix)),
+
+	SND_SOC_DAPM_MIXER("HPHL_PA_MIXER", SND_SOC_NOPM, 0, 0,
+		hphl_pa_mix, ARRAY_SIZE(hphl_pa_mix)),
+
+	SND_SOC_DAPM_MIXER("HPHR_PA_MIXER", SND_SOC_NOPM, 0, 0,
+		hphr_pa_mix, ARRAY_SIZE(hphr_pa_mix)),
+
+	SND_SOC_DAPM_MIXER("LINEOUT1_PA_MIXER", SND_SOC_NOPM, 0, 0,
+		lineout1_pa_mix, ARRAY_SIZE(lineout1_pa_mix)),
+
+	SND_SOC_DAPM_MIXER("LINEOUT2_PA_MIXER", SND_SOC_NOPM, 0, 0,
+		lineout2_pa_mix, ARRAY_SIZE(lineout2_pa_mix)),
+
+};
+
+static unsigned long slimbus_value;
+
+static irqreturn_t tapan_slimbus_irq(int irq, void *data)
+{
+	struct tapan_priv *priv = data;
+	struct snd_soc_codec *codec = priv->codec;
+	int i, j;
+	u8 val;
+
+	for (i = 0; i < WCD9XXX_SLIM_NUM_PORT_REG; i++) {
+		slimbus_value = wcd9xxx_interface_reg_read(codec->control_data,
+			TAPAN_SLIM_PGD_PORT_INT_STATUS0 + i);
+		for_each_set_bit(j, &slimbus_value, BITS_PER_BYTE) {
+			val = wcd9xxx_interface_reg_read(codec->control_data,
+				TAPAN_SLIM_PGD_PORT_INT_SOURCE0 + i*8 + j);
+			if (val & 0x1)
+				pr_err_ratelimited(
+				"overflow error on port %x, value %x\n",
+				i*8 + j, val);
+			if (val & 0x2)
+				pr_err_ratelimited(
+				"underflow error on port %x, value %x\n",
+				i*8 + j, val);
+		}
+		wcd9xxx_interface_reg_write(codec->control_data,
+			TAPAN_SLIM_PGD_PORT_INT_CLR0 + i, 0xFF);
+
+	}
+	return IRQ_HANDLED;
+}
+
+static const struct tapan_reg_mask_val tapan_1_0_class_h_ear[] = {
+
+	/* CLASS-H EAR  IDLE_THRESHOLD Table */
+	TAPAN_REG_VAL(TAPAN_A_CDC_CLSH_IDLE_EAR_THSD, 0x26),
+	TAPAN_REG_VAL(TAPAN_A_CDC_CLSH_FCLKONLY_EAR_THSD, 0x2C),
+
+	/* CLASS-H EAR I_PA_FACT Table. */
+	TAPAN_REG_VAL(TAPAN_A_CDC_CLSH_I_PA_FACT_EAR_L,	0xA9),
+	TAPAN_REG_VAL(TAPAN_A_CDC_CLSH_I_PA_FACT_EAR_U, 0x07),
+
+	/* CLASS-H EAR Voltage Headroom , Voltage Min. */
+	TAPAN_REG_VAL(TAPAN_A_CDC_CLSH_V_PA_HD_EAR, 0x0D),
+	TAPAN_REG_VAL(TAPAN_A_CDC_CLSH_V_PA_MIN_EAR, 0x3A),
+
+	/* CLASS-H EAR K values --chnages from load. */
+	TAPAN_REG_VAL(TAPAN_A_CDC_CLSH_K_ADDR, 0x08),
+	TAPAN_REG_VAL(TAPAN_A_CDC_CLSH_K_DATA, 0x1B),
+	TAPAN_REG_VAL(TAPAN_A_CDC_CLSH_K_DATA, 0x00),
+	TAPAN_REG_VAL(TAPAN_A_CDC_CLSH_K_DATA, 0x2D),
+	TAPAN_REG_VAL(TAPAN_A_CDC_CLSH_K_DATA, 0x00),
+	TAPAN_REG_VAL(TAPAN_A_CDC_CLSH_K_DATA, 0x36),
+	TAPAN_REG_VAL(TAPAN_A_CDC_CLSH_K_DATA, 0x00),
+	TAPAN_REG_VAL(TAPAN_A_CDC_CLSH_K_DATA, 0x37),
+	TAPAN_REG_VAL(TAPAN_A_CDC_CLSH_K_DATA, 0x00),
+	/** end of Ear PA load 32 */
+};
+
+static const struct tapan_reg_mask_val tapan_1_0_class_h_hph[] = {
+
+	/* CLASS-H HPH  IDLE_THRESHOLD Table */
+	TAPAN_REG_VAL(TAPAN_A_CDC_CLSH_IDLE_HPH_THSD, 0x13),
+	TAPAN_REG_VAL(TAPAN_A_CDC_CLSH_FCLKONLY_HPH_THSD, 0x19),
+
+	/* CLASS-H HPH I_PA_FACT Table */
+	TAPAN_REG_VAL(TAPAN_A_CDC_CLSH_I_PA_FACT_HPH_L, 0x9A),
+	TAPAN_REG_VAL(TAPAN_A_CDC_CLSH_I_PA_FACT_HPH_U, 0x06),
+
+	/* CLASS-H HPH Voltage Headroom , Voltage Min */
+	TAPAN_REG_VAL(TAPAN_A_CDC_CLSH_V_PA_HD_HPH, 0x0D),
+	TAPAN_REG_VAL(TAPAN_A_CDC_CLSH_V_PA_MIN_HPH, 0x1D),
+
+	/* CLASS-H HPH K values --chnages from load .*/
+	TAPAN_REG_VAL(TAPAN_A_CDC_CLSH_K_ADDR, 0x00),
+	TAPAN_REG_VAL(TAPAN_A_CDC_CLSH_K_DATA, 0xAE),
+	TAPAN_REG_VAL(TAPAN_A_CDC_CLSH_K_DATA, 0x01),
+	TAPAN_REG_VAL(TAPAN_A_CDC_CLSH_K_DATA, 0x1C),
+	TAPAN_REG_VAL(TAPAN_A_CDC_CLSH_K_DATA, 0x00),
+	TAPAN_REG_VAL(TAPAN_A_CDC_CLSH_K_DATA, 0x25),
+	TAPAN_REG_VAL(TAPAN_A_CDC_CLSH_K_DATA, 0x00),
+	TAPAN_REG_VAL(TAPAN_A_CDC_CLSH_K_DATA, 0x27),
+	TAPAN_REG_VAL(TAPAN_A_CDC_CLSH_K_DATA, 0x00),
+};
+
+static int tapan_config_ear_class_h(struct snd_soc_codec *codec, u32 ear_load)
+{
+	u32 i;
+
+	if (ear_load  != 32)
+		return -EINVAL;
+
+	for (i = 0; i < ARRAY_SIZE(tapan_1_0_class_h_ear); i++)
+		snd_soc_write(codec, tapan_1_0_class_h_ear[i].reg,
+				tapan_1_0_class_h_ear[i].val);
+	return 0;
+}
+
+static int tapan_config_hph_class_h(struct snd_soc_codec *codec, u32 hph_load)
+{
+	u32 i;
+	if (hph_load  != 16)
+		return -EINVAL;
+
+	for (i = 0; i < ARRAY_SIZE(tapan_1_0_class_h_hph); i++)
+		snd_soc_write(codec, tapan_1_0_class_h_hph[i].reg,
+				tapan_1_0_class_h_hph[i].val);
+	return 0;
+}
+
+static int tapan_handle_pdata(struct tapan_priv *tapan)
+{
+	struct snd_soc_codec *codec = tapan->codec;
+	struct wcd9xxx_pdata *pdata = tapan->resmgr.pdata;
+	int k1, k2, k3, rc = 0;
+	u8 leg_mode, txfe_bypass, txfe_buff, flag;
+	u8 value = 0;
+
+	if (!pdata) {
+		pr_err("%s: NULL pdata\n", __func__);
+		rc = -ENODEV;
+		goto done;
+	}
+
+	leg_mode = pdata->amic_settings.legacy_mode;
+	txfe_bypass = pdata->amic_settings.txfe_enable;
+	txfe_buff = pdata->amic_settings.txfe_buff;
+	flag = pdata->amic_settings.use_pdata;
+
+	/* Make sure settings are correct */
+	if ((pdata->micbias.ldoh_v > WCD9XXX_LDOH_3P0_V) ||
+	    (pdata->micbias.bias1_cfilt_sel > WCD9XXX_CFILT3_SEL) ||
+	    (pdata->micbias.bias2_cfilt_sel > WCD9XXX_CFILT3_SEL) ||
+	    (pdata->micbias.bias3_cfilt_sel > WCD9XXX_CFILT3_SEL)) {
+		rc = -EINVAL;
+		goto done;
+	}
+	/* figure out k value */
+	k1 = wcd9xxx_resmgr_get_k_val(&tapan->resmgr, pdata->micbias.cfilt1_mv);
+	k2 = wcd9xxx_resmgr_get_k_val(&tapan->resmgr, pdata->micbias.cfilt2_mv);
+	k3 = wcd9xxx_resmgr_get_k_val(&tapan->resmgr, pdata->micbias.cfilt3_mv);
+
+	if (IS_ERR_VALUE(k1) || IS_ERR_VALUE(k2) || IS_ERR_VALUE(k3)) {
+		rc = -EINVAL;
+		goto done;
+	}
+	/* Set voltage level and always use LDO */
+	snd_soc_update_bits(codec, TAPAN_A_LDO_H_MODE_1, 0x0C,
+			    (pdata->micbias.ldoh_v << 2));
+
+	snd_soc_update_bits(codec, TAPAN_A_MICB_CFILT_1_VAL, 0xFC, (k1 << 2));
+	snd_soc_update_bits(codec, TAPAN_A_MICB_CFILT_2_VAL, 0xFC, (k2 << 2));
+	snd_soc_update_bits(codec, TAPAN_A_MICB_CFILT_3_VAL, 0xFC, (k3 << 2));
+
+	snd_soc_update_bits(codec, TAPAN_A_MICB_1_CTL, 0x60,
+			    (pdata->micbias.bias1_cfilt_sel << 5));
+	snd_soc_update_bits(codec, TAPAN_A_MICB_2_CTL, 0x60,
+			    (pdata->micbias.bias2_cfilt_sel << 5));
+	snd_soc_update_bits(codec, TAPAN_A_MICB_3_CTL, 0x60,
+			    (pdata->micbias.bias3_cfilt_sel << 5));
+
+	if (flag & 0x40) {
+		value = (leg_mode & 0x40) ? 0x10 : 0x00;
+		value = value | ((txfe_bypass & 0x40) ? 0x02 : 0x00);
+		value = value | ((txfe_buff & 0x40) ? 0x01 : 0x00);
+		snd_soc_update_bits(codec, TAPAN_A_TX_7_MBHC_EN,
+			0x13, value);
+	}
+
+	if (pdata->ocp.use_pdata) {
+		/* not defined in CODEC specification */
+		if (pdata->ocp.hph_ocp_limit == 1 ||
+			pdata->ocp.hph_ocp_limit == 5) {
+			rc = -EINVAL;
+			goto done;
+		}
+		snd_soc_update_bits(codec, TAPAN_A_RX_COM_OCP_CTL,
+			0x0F, pdata->ocp.num_attempts);
+		snd_soc_write(codec, TAPAN_A_RX_COM_OCP_COUNT,
+			((pdata->ocp.run_time << 4) | pdata->ocp.wait_time));
+		snd_soc_update_bits(codec, TAPAN_A_RX_HPH_OCP_CTL,
+			0xE0, (pdata->ocp.hph_ocp_limit << 5));
+	}
+
+	tapan_config_ear_class_h(codec, 32);
+	tapan_config_hph_class_h(codec, 16);
+
+done:
+	return rc;
+}
+
+static const struct tapan_reg_mask_val tapan_reg_defaults[] = {
+
+	/* set MCLk to 9.6 */
+	TAPAN_REG_VAL(TAPAN_A_CHIP_CTL, 0x0A),
+	TAPAN_REG_VAL(TAPAN_A_CDC_CLK_POWER_CTL, 0x03),
+
+	/* EAR PA deafults  */
+	TAPAN_REG_VAL(TAPAN_A_RX_EAR_CMBUFF, 0x05),
+
+	/** BUCK and NCP defaults for EAR and HS */
+	TAPAN_REG_VAL(TAPAN_A_BUCK_CTRL_CCL_4, 0x50),
+	TAPAN_REG_VAL(TAPAN_A_BUCK_CTRL_CCL_1, 0x5B),
+
+	/* CLASS-H defaults for EAR and HS */
+	TAPAN_REG_VAL(TAPAN_A_CDC_CLSH_BUCK_NCP_VARS, 0x00),
+	TAPAN_REG_VAL(TAPAN_A_CDC_CLSH_BUCK_NCP_VARS, 0x04),
+	TAPAN_REG_VAL(TAPAN_A_CDC_CLSH_B2_CTL, 0x01),
+	TAPAN_REG_VAL(TAPAN_A_CDC_CLSH_B2_CTL, 0x05),
+	TAPAN_REG_VAL(TAPAN_A_CDC_CLSH_B2_CTL, 0x35),
+	TAPAN_REG_VAL(TAPAN_A_CDC_CLSH_B3_CTL, 0x30),
+	TAPAN_REG_VAL(TAPAN_A_CDC_CLSH_B3_CTL, 0x3B),
+
+	/*
+	 * For CLASS-H, Enable ANC delay buffer,
+	 * set HPHL and EAR PA ref gain to 0 DB.
+	 */
+	TAPAN_REG_VAL(TAPAN_A_CDC_CLSH_B1_CTL, 0x26),
+
+	/* RX deafults */
+	TAPAN_REG_VAL(TAPAN_A_CDC_RX1_B5_CTL, 0x78),
+	TAPAN_REG_VAL(TAPAN_A_CDC_RX2_B5_CTL, 0x78),
+	TAPAN_REG_VAL(TAPAN_A_CDC_RX3_B5_CTL, 0x78),
+	TAPAN_REG_VAL(TAPAN_A_CDC_RX4_B5_CTL, 0x78),
+
+	/* RX1 and RX2 defaults */
+	TAPAN_REG_VAL(TAPAN_A_CDC_RX1_B6_CTL, 0xA0),
+	TAPAN_REG_VAL(TAPAN_A_CDC_RX2_B6_CTL, 0xA0),
+
+	/* RX3 to RX7 defaults */
+	TAPAN_REG_VAL(TAPAN_A_CDC_RX3_B6_CTL, 0x80),
+	TAPAN_REG_VAL(TAPAN_A_CDC_RX4_B6_CTL, 0x80),
+
+	/*
+	 * The following only need to be written for Taiko 1.0 parts.
+	 * Taiko 2.0 will have appropriate defaults for these registers.
+	 */
+	/* Choose max non-overlap time for NCP */
+	TAPAN_REG_VAL(TAPAN_A_NCP_CLK, 0xFC),
+	/* Use 25mV/50mV for deltap/m to reduce ripple */
+	TAPAN_REG_VAL(TAPAN_A_BUCK_CTRL_VCL_1, 0x08),
+	/*
+	 * Set DISABLE_MODE_SEL<1:0> to 0b10 (disable PWM in auto mode).
+	 * Note that the other bits of this register will be changed during
+	 * Rx PA bring up.
+	 */
+	TAPAN_REG_VAL(TAPAN_A_BUCK_MODE_3, 0xCE),
+	/* Reduce HPH DAC bias to 70% */
+	TAPAN_REG_VAL(TAPAN_A_RX_HPH_BIAS_PA, 0x7A),
+	/*Reduce EAR DAC bias to 70% */
+	TAPAN_REG_VAL(TAPAN_A_RX_EAR_BIAS_PA, 0x76),
+	/* Reduce LINE DAC bias to 70% */
+	TAPAN_REG_VAL(TAPAN_A_RX_LINE_BIAS_PA, 0x78),
+
+	/*
+	 * There is a diode to pull down the micbias while doing
+	 * insertion detection.  This diode can cause leakage.
+	 * Set bit 0 to 1 to prevent leakage.
+	 * Setting this bit of micbias 2 prevents leakage for all other micbias.
+	 */
+	TAPAN_REG_VAL(TAPAN_A_MICB_2_MBHC, 0x41),
+
+	/* Disable TX7 internal biasing path which can cause leakage */
+	TAPAN_REG_VAL(TAPAN_A_TX_SUP_SWITCH_CTRL_1, 0xBF),
+};
+
+static void tapan_update_reg_defaults(struct snd_soc_codec *codec)
+{
+	u32 i;
+
+	for (i = 0; i < ARRAY_SIZE(tapan_reg_defaults); i++)
+		snd_soc_write(codec, tapan_reg_defaults[i].reg,
+				tapan_reg_defaults[i].val);
+}
+
+static const struct tapan_reg_mask_val tapan_codec_reg_init_val[] = {
+	/* Initialize current threshold to 350MA
+	 * number of wait and run cycles to 4096
+	 */
+	{TAPAN_A_RX_HPH_OCP_CTL, 0xE1, 0x61},
+	{TAPAN_A_RX_COM_OCP_COUNT, 0xFF, 0xFF},
+
+	/* Initialize gain registers to use register gain */
+	{TAPAN_A_RX_HPH_L_GAIN, 0x20, 0x20},
+	{TAPAN_A_RX_HPH_R_GAIN, 0x20, 0x20},
+	{TAPAN_A_RX_LINE_1_GAIN, 0x20, 0x20},
+	{TAPAN_A_RX_LINE_2_GAIN, 0x20, 0x20},
+
+	/* CLASS H config */
+	{TAPAN_A_CDC_CONN_CLSH_CTL, 0x3C, 0x14},
+
+	/* Use 16 bit sample size for TX1 to TX6 */
+	{TAPAN_A_CDC_CONN_TX_SB_B1_CTL, 0x30, 0x20},
+	{TAPAN_A_CDC_CONN_TX_SB_B2_CTL, 0x30, 0x20},
+	{TAPAN_A_CDC_CONN_TX_SB_B3_CTL, 0x30, 0x20},
+	{TAPAN_A_CDC_CONN_TX_SB_B4_CTL, 0x30, 0x20},
+	{TAPAN_A_CDC_CONN_TX_SB_B5_CTL, 0x30, 0x20},
+
+	/* Use 16 bit sample size for RX */
+	{TAPAN_A_CDC_CONN_RX_SB_B1_CTL, 0xFF, 0xAA},
+	{TAPAN_A_CDC_CONN_RX_SB_B2_CTL, 0xFF, 0x2A},
+
+	/*enable HPF filter for TX paths */
+	{TAPAN_A_CDC_TX1_MUX_CTL, 0x8, 0x0},
+	{TAPAN_A_CDC_TX2_MUX_CTL, 0x8, 0x0},
+	{TAPAN_A_CDC_TX3_MUX_CTL, 0x8, 0x0},
+	{TAPAN_A_CDC_TX4_MUX_CTL, 0x8, 0x0},
+
+	/* config Decimator for DMIC CLK_MODE_1(3.2Mhz@9.6Mhz mclk) */
+	{TAPAN_A_CDC_TX1_DMIC_CTL, 0x7, 0x1},
+	{TAPAN_A_CDC_TX2_DMIC_CTL, 0x7, 0x1},
+	{TAPAN_A_CDC_TX3_DMIC_CTL, 0x7, 0x1},
+	{TAPAN_A_CDC_TX4_DMIC_CTL, 0x7, 0x1},
+
+	/* config DMIC clk to CLK_MODE_1 (3.2Mhz@9.6Mhz mclk) */
+	{TAPAN_A_CDC_CLK_DMIC_B1_CTL, 0xEE, 0x22},
+	{TAPAN_A_CDC_CLK_DMIC_B2_CTL, 0x0E, 0x02},
+
+};
+
+static void tapan_codec_init_reg(struct snd_soc_codec *codec)
+{
+	u32 i;
+
+	for (i = 0; i < ARRAY_SIZE(tapan_codec_reg_init_val); i++)
+		snd_soc_update_bits(codec, tapan_codec_reg_init_val[i].reg,
+				tapan_codec_reg_init_val[i].mask,
+				tapan_codec_reg_init_val[i].val);
+}
+
+static int tapan_setup_irqs(struct tapan_priv *tapan)
+{
+	int i;
+	int ret = 0;
+	struct snd_soc_codec *codec = tapan->codec;
+
+	ret = wcd9xxx_request_irq(codec->control_data, WCD9XXX_IRQ_SLIMBUS,
+				  tapan_slimbus_irq, "SLIMBUS Slave", tapan);
+	if (ret) {
+		pr_err("%s: Failed to request irq %d\n", __func__,
+		       WCD9XXX_IRQ_SLIMBUS);
+		goto exit;
+	}
+
+	for (i = 0; i < WCD9XXX_SLIM_NUM_PORT_REG; i++)
+		wcd9xxx_interface_reg_write(codec->control_data,
+					    TAPAN_SLIM_PGD_PORT_INT_EN0 + i,
+					    0xFF);
+exit:
+	return ret;
+}
+
+int tapan_hs_detect(struct snd_soc_codec *codec,
+		    struct wcd9xxx_mbhc_config *mbhc_cfg)
+{
+	struct tapan_priv *tapan = snd_soc_codec_get_drvdata(codec);
+	return wcd9xxx_mbhc_start(&tapan->mbhc, mbhc_cfg);
+}
+EXPORT_SYMBOL_GPL(tapan_hs_detect);
+
+static struct wcd9xxx_reg_address tapan_reg_address = {
+};
+
+static int tapan_codec_probe(struct snd_soc_codec *codec)
+{
+	struct wcd9xxx *control;
+	struct tapan_priv *tapan;
+	struct wcd9xxx_pdata *pdata;
+	struct wcd9xxx *wcd9xxx;
+	struct snd_soc_dapm_context *dapm = &codec->dapm;
+	int ret = 0;
+	int i;
+	void *ptr = NULL;
+
+	codec->control_data = dev_get_drvdata(codec->dev->parent);
+	control = codec->control_data;
+
+	dev_info(codec->dev, "%s()\n", __func__);
+
+	tapan = kzalloc(sizeof(struct tapan_priv), GFP_KERNEL);
+	if (!tapan) {
+		dev_err(codec->dev, "Failed to allocate private data\n");
+		return -ENOMEM;
+	}
+	for (i = 0 ; i < NUM_DECIMATORS; i++) {
+		tx_hpf_work[i].tapan = tapan;
+		tx_hpf_work[i].decimator = i + 1;
+		INIT_DELAYED_WORK(&tx_hpf_work[i].dwork,
+			tx_hpf_corner_freq_callback);
+	}
+
+	snd_soc_codec_set_drvdata(codec, tapan);
+
+	/* codec resmgr module init */
+	wcd9xxx = codec->control_data;
+	pdata = dev_get_platdata(codec->dev->parent);
+	ret = wcd9xxx_resmgr_init(&tapan->resmgr, codec, wcd9xxx, pdata,
+				  &tapan_reg_address);
+	if (ret) {
+		pr_err("%s: wcd9xxx init failed %d\n", __func__, ret);
+		goto err_codec;
+	}
+
+	/* init and start mbhc */
+	ret = wcd9xxx_mbhc_init(&tapan->mbhc, &tapan->resmgr, codec);
+	if (ret) {
+		pr_err("%s: mbhc init failed %d\n", __func__, ret);
+		goto err_codec;
+	}
+
+	tapan->codec = codec;
+
+	tapan->intf_type = wcd9xxx_get_intf_type();
+	tapan->aux_pga_cnt = 0;
+	tapan->aux_l_gain = 0x1F;
+	tapan->aux_r_gain = 0x1F;
+	tapan_update_reg_defaults(codec);
+	tapan_codec_init_reg(codec);
+	ret = tapan_handle_pdata(tapan);
+	if (IS_ERR_VALUE(ret)) {
+		pr_err("%s: bad pdata\n", __func__);
+		goto err_codec;
+	}
+
+	ptr = kmalloc((sizeof(tapan_rx_chs) +
+		       sizeof(tapan_tx_chs)), GFP_KERNEL);
+	if (!ptr) {
+		pr_err("%s: no mem for slim chan ctl data\n", __func__);
+		ret = -ENOMEM;
+		goto err_nomem_slimch;
+	}
+
+	if (tapan->intf_type == WCD9XXX_INTERFACE_TYPE_I2C) {
+		pr_err("%s: I2C interface not supported yet\n",
+			   __func__);
+	} else if (tapan->intf_type == WCD9XXX_INTERFACE_TYPE_SLIMBUS) {
+		for (i = 0; i < NUM_CODEC_DAIS; i++) {
+			INIT_LIST_HEAD(&tapan->dai[i].wcd9xxx_ch_list);
+			init_waitqueue_head(&tapan->dai[i].dai_wait);
+		}
+	}
+
+	control->num_rx_port = TAPAN_RX_MAX;
+	control->rx_chs = ptr;
+	memcpy(control->rx_chs, tapan_rx_chs, sizeof(tapan_rx_chs));
+	control->num_tx_port = TAPAN_TX_MAX;
+	control->tx_chs = ptr + sizeof(tapan_rx_chs);
+	memcpy(control->tx_chs, tapan_tx_chs, sizeof(tapan_tx_chs));
+
+	snd_soc_dapm_sync(dapm);
+
+	(void) tapan_setup_irqs(tapan);
+
+	codec->ignore_pmdown_time = 1;
+	return ret;
+
+err_nomem_slimch:
+	kfree(ptr);
+err_codec:
+	kfree(tapan);
+	return ret;
+}
+
+static int tapan_codec_remove(struct snd_soc_codec *codec)
+{
+	struct tapan_priv *tapan = snd_soc_codec_get_drvdata(codec);
+
+	/* cleanup MBHC */
+	wcd9xxx_mbhc_deinit(&tapan->mbhc);
+	/* cleanup resmgr */
+	wcd9xxx_resmgr_deinit(&tapan->resmgr);
+
+	kfree(tapan);
+	return 0;
+}
+
+static struct snd_soc_codec_driver soc_codec_dev_tapan = {
+	.probe	= tapan_codec_probe,
+	.remove	= tapan_codec_remove,
+
+	.read = tapan_read,
+	.write = tapan_write,
+
+	.readable_register = tapan_readable,
+	.volatile_register = tapan_volatile,
+
+	.reg_cache_size = TAPAN_CACHE_SIZE,
+	.reg_cache_default = tapan_reset_reg_defaults,
+	.reg_word_size = 1,
+
+	.controls = tapan_snd_controls,
+	.num_controls = ARRAY_SIZE(tapan_snd_controls),
+	.dapm_widgets = tapan_dapm_widgets,
+	.num_dapm_widgets = ARRAY_SIZE(tapan_dapm_widgets),
+	.dapm_routes = audio_map,
+	.num_dapm_routes = ARRAY_SIZE(audio_map),
+};
+
+#ifdef CONFIG_PM
+static int tapan_suspend(struct device *dev)
+{
+	dev_dbg(dev, "%s: system suspend\n", __func__);
+	return 0;
+}
+
+static int tapan_resume(struct device *dev)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct tapan_priv *tapan = platform_get_drvdata(pdev);
+	dev_dbg(dev, "%s: system resume\n", __func__);
+	wcd9xxx_resmgr_notifier_call(&tapan->resmgr, WCD9XXX_EVENT_POST_RESUME);
+	return 0;
+}
+
+static const struct dev_pm_ops tapan_pm_ops = {
+	.suspend	= tapan_suspend,
+	.resume		= tapan_resume,
+};
+#endif
+
+static int __devinit tapan_probe(struct platform_device *pdev)
+{
+	int ret = 0;
+	if (wcd9xxx_get_intf_type() == WCD9XXX_INTERFACE_TYPE_SLIMBUS)
+		ret = snd_soc_register_codec(&pdev->dev, &soc_codec_dev_tapan,
+			tapan_dai, ARRAY_SIZE(tapan_dai));
+	else if (wcd9xxx_get_intf_type() == WCD9XXX_INTERFACE_TYPE_I2C)
+		ret = snd_soc_register_codec(&pdev->dev, &soc_codec_dev_tapan,
+			tapan_i2s_dai, ARRAY_SIZE(tapan_i2s_dai));
+	return ret;
+}
+static int __devexit tapan_remove(struct platform_device *pdev)
+{
+	snd_soc_unregister_codec(&pdev->dev);
+	return 0;
+}
+static struct platform_driver tapan_codec_driver = {
+	.probe = tapan_probe,
+	.remove = tapan_remove,
+	.driver = {
+		.name = "tapan_codec",
+		.owner = THIS_MODULE,
+#ifdef CONFIG_PM
+		.pm = &tapan_pm_ops,
+#endif
+	},
+};
+
+static int __init tapan_codec_init(void)
+{
+	return platform_driver_register(&tapan_codec_driver);
+}
+
+static void __exit tapan_codec_exit(void)
+{
+	platform_driver_unregister(&tapan_codec_driver);
+}
+
+module_init(tapan_codec_init);
+module_exit(tapan_codec_exit);
+
+MODULE_DESCRIPTION("Tapan codec driver");
+MODULE_LICENSE("GPL v2");
diff --git a/sound/soc/codecs/wcd9306.h b/sound/soc/codecs/wcd9306.h
new file mode 100644
index 0000000..61d47b5
--- /dev/null
+++ b/sound/soc/codecs/wcd9306.h
@@ -0,0 +1,84 @@
+/* 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 WCD9306_H
+#define WCD9306_H
+
+#include <sound/soc.h>
+#include <sound/jack.h>
+#include <linux/mfd/wcd9xxx/wcd9xxx-slimslave.h>
+#include "wcd9xxx-mbhc.h"
+#include "wcd9xxx-resmgr.h"
+
+#define TAPAN_NUM_REGISTERS 0x400
+#define TAPAN_MAX_REGISTER (TAPAN_NUM_REGISTERS-1)
+#define TAPAN_CACHE_SIZE TAPAN_NUM_REGISTERS
+
+#define TAPAN_REG_VAL(reg, val)		{reg, 0, val}
+
+extern const u8 tapan_reg_readable[TAPAN_CACHE_SIZE];
+extern const u8 tapan_reset_reg_defaults[TAPAN_CACHE_SIZE];
+struct tapan_codec_dai_data {
+	u32 rate;
+	u32 *ch_num;
+	u32 ch_act;
+	u32 ch_tot;
+};
+
+enum tapan_pid_current {
+	TAPAN_PID_MIC_2P5_UA,
+	TAPAN_PID_MIC_5_UA,
+	TAPAN_PID_MIC_10_UA,
+	TAPAN_PID_MIC_20_UA,
+};
+
+struct tapan_reg_mask_val {
+	u16	reg;
+	u8	mask;
+	u8	val;
+};
+
+enum tapan_mbhc_analog_pwr_cfg {
+	TAPAN_ANALOG_PWR_COLLAPSED = 0,
+	TAPAN_ANALOG_PWR_ON,
+	TAPAN_NUM_ANALOG_PWR_CONFIGS,
+};
+
+/* Number of input and output Slimbus port */
+enum {
+	TAPAN_RX1 = 0,
+	TAPAN_RX2,
+	TAPAN_RX3,
+	TAPAN_RX4,
+	TAPAN_RX5,
+	TAPAN_RX_MAX,
+};
+
+enum {
+	TAPAN_TX1 = 0,
+	TAPAN_TX2,
+	TAPAN_TX3,
+	TAPAN_TX4,
+	TAPAN_TX5,
+	TAPAN_TX_MAX,
+};
+
+struct anc_header {
+	u32 reserved[3];
+	u32 num_anc_slots;
+};
+
+extern int tapan_mclk_enable(struct snd_soc_codec *codec, int mclk_enable,
+			     bool dapm);
+extern int tapan_hs_detect(struct snd_soc_codec *codec,
+			   struct wcd9xxx_mbhc_config *mbhc_cfg);
+
+#endif
diff --git a/sound/soc/codecs/wcd9320.c b/sound/soc/codecs/wcd9320.c
index 76623b1..1546b9e 100644
--- a/sound/soc/codecs/wcd9320.c
+++ b/sound/soc/codecs/wcd9320.c
@@ -37,6 +37,19 @@
 #include "wcd9320.h"
 #include "wcd9xxx-resmgr.h"
 
+static atomic_t kp_taiko_priv;
+static int spkr_drv_wrnd_param_set(const char *val,
+				   const struct kernel_param *kp);
+static int spkr_drv_wrnd = 1;
+
+static struct kernel_param_ops spkr_drv_wrnd_param_ops = {
+	.set = spkr_drv_wrnd_param_set,
+	.get = param_get_int,
+};
+module_param_cb(spkr_drv_wrnd, &spkr_drv_wrnd_param_ops, &spkr_drv_wrnd, 0644);
+MODULE_PARM_DESC(spkr_drv_wrnd,
+	       "Run software workaround to avoid leakage on the speaker drive");
+
 #define WCD9320_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 |\
 			SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_48000 |\
 			SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_192000)
@@ -185,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 {
@@ -212,6 +227,8 @@
 	u8 aux_l_gain;
 	u8 aux_r_gain;
 
+	bool spkr_pa_widget_on;
+
 	/* resmgr module */
 	struct wcd9xxx_resmgr resmgr;
 	/* mbhc module */
@@ -298,6 +315,45 @@
 	TAIKO_A_CDC_TX10_VOL_CTL_GAIN,
 };
 
+static int spkr_drv_wrnd_param_set(const char *val,
+				   const struct kernel_param *kp)
+{
+	struct snd_soc_codec *codec;
+	int ret, old;
+	struct taiko_priv *priv;
+
+	priv = (struct taiko_priv *)atomic_read(&kp_taiko_priv);
+	if (!priv) {
+		pr_debug("%s: codec isn't yet registered\n", __func__);
+		return 0;
+	}
+
+	WCD9XXX_BCL_LOCK(&priv->resmgr);
+	old = spkr_drv_wrnd;
+	ret = param_set_int(val, kp);
+	if (ret) {
+		WCD9XXX_BCL_UNLOCK(&priv->resmgr);
+		return ret;
+	}
+
+	pr_debug("%s: spkr_drv_wrnd %d -> %d\n", __func__, old, spkr_drv_wrnd);
+	codec = priv->codec;
+	if (old == 0 && spkr_drv_wrnd == 1) {
+		wcd9xxx_resmgr_get_bandgap(&priv->resmgr,
+					   WCD9XXX_BANDGAP_AUDIO_MODE);
+		snd_soc_update_bits(codec, TAIKO_A_SPKR_DRV_EN, 0x80, 0x80);
+	} else if (old == 1 && spkr_drv_wrnd == 0) {
+		wcd9xxx_resmgr_put_bandgap(&priv->resmgr,
+					   WCD9XXX_BANDGAP_AUDIO_MODE);
+		if (!priv->spkr_pa_widget_on)
+			snd_soc_update_bits(codec, TAIKO_A_SPKR_DRV_EN, 0x80,
+					    0x00);
+	}
+
+	WCD9XXX_BCL_UNLOCK(&priv->resmgr);
+	return 0;
+}
+
 static int taiko_codec_enable_class_h_clk(struct snd_soc_dapm_widget *w,
 		struct snd_kcontrol *kcontrol, int event)
 {
@@ -1640,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;
@@ -1876,7 +1932,22 @@
 static int taiko_codec_enable_spk_pa(struct snd_soc_dapm_widget *w,
 				     struct snd_kcontrol *kcontrol, int event)
 {
-	pr_debug("%s %d %s\n", __func__, event, w->name);
+	struct snd_soc_codec *codec = w->codec;
+	struct taiko_priv *taiko = snd_soc_codec_get_drvdata(codec);
+
+	pr_debug("%s: %d %s\n", __func__, event, w->name);
+	WCD9XXX_BCL_LOCK(&taiko->resmgr);
+	switch (event) {
+	case SND_SOC_DAPM_PRE_PMU:
+		taiko->spkr_pa_widget_on = true;
+		snd_soc_update_bits(codec, TAIKO_A_SPKR_DRV_EN, 0x80, 0x80);
+		break;
+	case SND_SOC_DAPM_POST_PMD:
+		taiko->spkr_pa_widget_on = false;
+		snd_soc_update_bits(codec, TAIKO_A_SPKR_DRV_EN, 0x80, 0x00);
+		break;
+	}
+	WCD9XXX_BCL_UNLOCK(&taiko->resmgr);
 	return 0;
 }
 
@@ -2288,6 +2359,42 @@
 	return ret;
 }
 
+static int taiko_codec_enable_vdd_spkr(struct snd_soc_dapm_widget *w,
+				       struct snd_kcontrol *kcontrol, int event)
+{
+	int ret = 0;
+	struct snd_soc_codec *codec = w->codec;
+	struct wcd9xxx *core = dev_get_drvdata(codec->dev->parent);
+
+	pr_debug("%s: %d %s\n", __func__, event, w->name);
+	switch (event) {
+	case SND_SOC_DAPM_PRE_PMU:
+		if (spkr_drv_wrnd > 0) {
+			WARN_ON(!(snd_soc_read(codec, TAIKO_A_SPKR_DRV_EN) &
+				  0x80));
+			snd_soc_update_bits(codec, TAIKO_A_SPKR_DRV_EN, 0x80,
+					    0x00);
+		}
+		if (TAIKO_IS_1_0(core->version))
+			snd_soc_update_bits(codec, TAIKO_A_SPKR_DRV_DBG_PWRSTG,
+					    0x24, 0x00);
+		break;
+	case SND_SOC_DAPM_POST_PMD:
+		if (TAIKO_IS_1_0(core->version))
+			snd_soc_update_bits(codec, TAIKO_A_SPKR_DRV_DBG_PWRSTG,
+					    0x24, 0x24);
+		if (spkr_drv_wrnd > 0) {
+			WARN_ON(!!(snd_soc_read(codec, TAIKO_A_SPKR_DRV_EN) &
+				   0x80));
+			snd_soc_update_bits(codec, TAIKO_A_SPKR_DRV_EN, 0x80,
+					    0x80);
+		}
+		break;
+	}
+
+	return ret;
+}
+
 static int taiko_codec_enable_interpolator(struct snd_soc_dapm_widget *w,
 	struct snd_kcontrol *kcontrol, int event)
 {
@@ -2671,6 +2778,7 @@
 
 	{"SPK PA", NULL, "SPK DAC"},
 	{"SPK DAC", NULL, "RX7 MIX2"},
+	{"SPK DAC", NULL, "VDD_SPKDRV"},
 
 	{"RX1 CHAIN", NULL, "RX1 MIX2"},
 	{"RX2 CHAIN", NULL, "RX2 MIX2"},
@@ -3637,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,
@@ -3866,9 +4002,9 @@
 	SND_SOC_DAPM_PGA_E("LINEOUT4 PA", TAIKO_A_RX_LINE_CNP_EN, 3, 0, NULL,
 			0, taiko_codec_enable_lineout, SND_SOC_DAPM_PRE_PMU |
 			SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
-	SND_SOC_DAPM_PGA_E("SPK PA", TAIKO_A_SPKR_DRV_EN, 7, 0 , NULL,
-			   0, taiko_codec_enable_spk_pa, SND_SOC_DAPM_PRE_PMU |
-			   SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+	SND_SOC_DAPM_PGA_E("SPK PA", SND_SOC_NOPM, 0, 0 , NULL,
+			   0, taiko_codec_enable_spk_pa,
+			   SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
 
 	SND_SOC_DAPM_DAC_E("LINEOUT1 DAC", NULL, TAIKO_A_RX_LINE_1_DAC_CTL, 7, 0
 		, taiko_lineout_dac_event,
@@ -3891,6 +4027,10 @@
 			   taiko_spk_dac_event,
 			   SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
 
+	SND_SOC_DAPM_SUPPLY("VDD_SPKDRV", SND_SOC_NOPM, 0, 0,
+			    taiko_codec_enable_vdd_spkr,
+			    SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+
 	SND_SOC_DAPM_MIXER("RX1 MIX1", SND_SOC_NOPM, 0, 0, NULL, 0),
 	SND_SOC_DAPM_MIXER("RX2 MIX1", SND_SOC_NOPM, 0, 0, NULL, 0),
 	SND_SOC_DAPM_MIXER("RX7 MIX1", SND_SOC_NOPM, 0, 0, NULL, 0),
@@ -4610,6 +4750,9 @@
 	TAIKO_REG_VAL(TAIKO_A_TX_SUP_SWITCH_CTRL_1, 0xBF),
 	/* Enable MICB 4 VDDIO switch to prevent leakage */
 	TAIKO_REG_VAL(TAIKO_A_MICB_4_MBHC, 0x81),
+
+	/* Close leakage on the spkdrv */
+	TAIKO_REG_VAL(TAIKO_A_SPKR_DRV_DBG_PWRSTG, 0x24),
 };
 
 static void taiko_update_reg_defaults(struct snd_soc_codec *codec)
@@ -4626,6 +4769,11 @@
 			snd_soc_write(codec, taiko_1_0_reg_defaults[i].reg,
 				taiko_1_0_reg_defaults[i].val);
 	}
+
+	if (!TAIKO_IS_1_0(taiko_core->version))
+		spkr_drv_wrnd = -1;
+	else if (spkr_drv_wrnd == 1)
+		snd_soc_write(codec, TAIKO_A_SPKR_DRV_EN, 0xEF);
 }
 
 static const struct taiko_reg_mask_val taiko_codec_reg_init_val[] = {
@@ -4819,6 +4967,13 @@
 		goto err_pdata;
 	}
 
+	if (spkr_drv_wrnd > 0) {
+		WCD9XXX_BCL_LOCK(&taiko->resmgr);
+		wcd9xxx_resmgr_get_bandgap(&taiko->resmgr,
+					   WCD9XXX_BANDGAP_AUDIO_MODE);
+		WCD9XXX_BCL_UNLOCK(&taiko->resmgr);
+	}
+
 	ptr = kmalloc((sizeof(taiko_rx_chs) +
 		       sizeof(taiko_tx_chs)), GFP_KERNEL);
 	if (!ptr) {
@@ -4852,6 +5007,8 @@
 
 	(void) taiko_setup_irqs(taiko);
 
+	atomic_set(&kp_taiko_priv, (unsigned long)taiko);
+
 	codec->ignore_pmdown_time = 1;
 	return ret;
 
@@ -4865,6 +5022,14 @@
 {
 	struct taiko_priv *taiko = snd_soc_codec_get_drvdata(codec);
 
+	WCD9XXX_BCL_LOCK(&taiko->resmgr);
+	atomic_set(&kp_taiko_priv, 0);
+
+	if (spkr_drv_wrnd > 0)
+		wcd9xxx_resmgr_put_bandgap(&taiko->resmgr,
+					   WCD9XXX_BANDGAP_AUDIO_MODE);
+	WCD9XXX_BCL_UNLOCK(&taiko->resmgr);
+
 	/* cleanup MBHC */
 	wcd9xxx_mbhc_deinit(&taiko->mbhc);
 	/* cleanup resmgr */
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/Kconfig b/sound/soc/msm/Kconfig
index c957526..20b9d2d 100644
--- a/sound/soc/msm/Kconfig
+++ b/sound/soc/msm/Kconfig
@@ -107,7 +107,7 @@
 
 config SND_SOC_MSM_QDSP6V2_INTF
 	bool "SoC Q6 audio driver for MSM8974"
-	depends on MSM_QDSP6_APRV2
+	depends on MSM_QDSP6_APR
 	help
 	 To add support for SoC audio on MSM8974.
 	 This will enable all the platform specific
@@ -180,6 +180,21 @@
 	 the machine drivers and the corresponding
 	 DAI-links.
 
+config SND_SOC_MSM8226
+	tristate "SoC Machine driver for MSM8226 boards"
+	depends on ARCH_MSM8226
+	select SND_SOC_QDSP6V2
+	select SND_SOC_MSM_STUB
+	select SND_SOC_MSM_HOSTLESS_PCM
+	select SND_SOC_WCD9306
+	select SND_DYNAMIC_MINORS
+	help
+	 To add support for SoC audio on MSM8226.
+	 This will enable sound soc drivers which
+	 interfaces with DSP, also it will enable
+	 the machine drivers and the corresponding
+	 DAI-links.
+
 config SND_SOC_MDM9615
 	tristate "SoC Machine driver for MDM9615 boards"
 	depends on ARCH_MSM9615
diff --git a/sound/soc/msm/Makefile b/sound/soc/msm/Makefile
index a4c365a..4c8d2e3 100644
--- a/sound/soc/msm/Makefile
+++ b/sound/soc/msm/Makefile
@@ -87,3 +87,7 @@
 #for MDM9625 sound card driver
 snd-soc-mdm9625-objs := mdm9625.o
 obj-$(CONFIG_SND_SOC_MDM9625) += snd-soc-mdm9625.o
+
+#for MSM 8226 sound card driver
+snd-soc-msm8226-objs := msm8226.o
+obj-$(CONFIG_SND_SOC_MSM8226) += snd-soc-msm8226.o
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-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-routing.c b/sound/soc/msm/msm-pcm-routing.c
index 841d313..8237d81 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
@@ -71,6 +71,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 +82,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 */
@@ -982,6 +990,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 +1041,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)
 {
@@ -2124,6 +2165,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 +2183,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",
@@ -3188,13 +3241,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/msm8226.c b/sound/soc/msm/msm8226.c
new file mode 100644
index 0000000..328c380
--- /dev/null
+++ b/sound/soc/msm/msm8226.c
@@ -0,0 +1,1065 @@
+/* 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/clk.h>
+#include <linux/delay.h>
+#include <linux/gpio.h>
+#include <linux/of_gpio.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/mfd/pm8xxx/pm8921.h>
+#include <sound/core.h>
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+#include <sound/pcm.h>
+#include <sound/jack.h>
+#include <asm/mach-types.h>
+#include <mach/socinfo.h>
+#include <qdsp6v2/msm-pcm-routing-v2.h>
+#include "../codecs/wcd9306.h"
+
+#define DRV_NAME "msm8226-asoc-tapan"
+
+#define MSM_SLIM_0_RX_MAX_CHANNELS		2
+#define MSM_SLIM_0_TX_MAX_CHANNELS		4
+
+#define BTSCO_RATE_8KHZ 8000
+#define BTSCO_RATE_16KHZ 16000
+
+#define GPIO_AUX_PCM_DOUT 43
+#define GPIO_AUX_PCM_DIN 44
+#define GPIO_AUX_PCM_SYNC 45
+#define GPIO_AUX_PCM_CLK 46
+
+#define WCD9XXX_MBHC_DEF_BUTTONS 8
+#define WCD9XXX_MBHC_DEF_RLOADS 5
+#define TAPAN_EXT_CLK_RATE 9600000
+
+void *def_tapan_mbhc_cal(void);
+static int msm_snd_enable_codec_ext_clk(struct snd_soc_codec *codec, int enable,
+					bool dapm);
+
+static struct wcd9xxx_mbhc_config mbhc_cfg = {
+	.read_fw_bin = false,
+	.calibration = NULL,
+	.micbias = MBHC_MICBIAS2,
+	.mclk_cb_fn = msm_snd_enable_codec_ext_clk,
+	.mclk_rate = TAPAN_EXT_CLK_RATE,
+	.gpio = 0,
+	.gpio_irq = 0,
+	.gpio_level_insert = 1,
+	.detect_extn_cable = true,
+	.insert_detect = true,
+	.swap_gnd_mic = NULL,
+};
+
+struct msm8226_asoc_mach_data {
+	int mclk_gpio;
+	u32 mclk_freq;
+};
+
+/* Shared channel numbers for Slimbus ports that connect APQ to MDM. */
+enum {
+	SLIM_1_RX_1 = 145, /* BT-SCO and USB TX */
+	SLIM_1_TX_1 = 146, /* BT-SCO and USB RX */
+	SLIM_2_RX_1 = 147, /* HDMI RX */
+	SLIM_3_RX_1 = 148, /* In-call recording RX */
+	SLIM_3_RX_2 = 149, /* In-call recording RX */
+	SLIM_4_TX_1 = 150, /* In-call musid delivery TX */
+};
+
+static int msm_slim_0_rx_ch = 1;
+static int msm_slim_0_tx_ch = 1;
+
+static int msm_btsco_rate = BTSCO_RATE_8KHZ;
+static int msm_btsco_ch = 1;
+
+static struct mutex cdc_mclk_mutex;
+static struct q_clkdiv *codec_clk;
+static int clk_users;
+
+static int msm_snd_enable_codec_ext_clk(struct snd_soc_codec *codec, int enable,
+					bool dapm)
+{
+	int ret = 0;
+	pr_debug("%s: enable = %d clk_users = %d\n",
+		__func__, enable, clk_users);
+
+	mutex_lock(&cdc_mclk_mutex);
+	if (enable) {
+		if (!codec_clk) {
+			dev_err(codec->dev, "%s: did not get Taiko MCLK\n",
+				__func__);
+			ret = -EINVAL;
+			goto exit;
+		}
+
+		clk_users++;
+		if (clk_users != 1)
+			goto exit;
+		/* TODO: qpnp_clkdiv_enable */
+		tapan_mclk_enable(codec, 1, dapm);
+	} else {
+		if (clk_users > 0) {
+			clk_users--;
+			if (clk_users == 0) {
+				tapan_mclk_enable(codec, 0, dapm);
+				/* TODO: qpnp_clkdiv_disable */
+			}
+		} else {
+			pr_err("%s: Error releasing Tabla MCLK\n", __func__);
+			ret = -EINVAL;
+			goto exit;
+		}
+	}
+exit:
+	mutex_unlock(&cdc_mclk_mutex);
+	return ret;
+}
+
+static int msm8226_mclk_event(struct snd_soc_dapm_widget *w,
+		struct snd_kcontrol *kcontrol, int event)
+{
+	pr_debug("%s: event = %d\n", __func__, event);
+
+	switch (event) {
+	case SND_SOC_DAPM_PRE_PMU:
+		return msm_snd_enable_codec_ext_clk(w->codec, 1, true);
+	case SND_SOC_DAPM_POST_PMD:
+		return msm_snd_enable_codec_ext_clk(w->codec, 0, true);
+	}
+
+	return 0;
+}
+
+static const struct snd_soc_dapm_widget msm8226_dapm_widgets[] = {
+
+	SND_SOC_DAPM_SUPPLY("MCLK",  SND_SOC_NOPM, 0, 0,
+	msm8226_mclk_event, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_MIC("Handset Mic", NULL),
+	SND_SOC_DAPM_MIC("Headset Mic", NULL),
+	SND_SOC_DAPM_MIC("ANCRight Headset Mic", NULL),
+	SND_SOC_DAPM_MIC("ANCLeft Headset Mic", NULL),
+
+	SND_SOC_DAPM_MIC("Digital Mic1", NULL),
+	SND_SOC_DAPM_MIC("Digital Mic2", NULL),
+	SND_SOC_DAPM_MIC("Digital Mic3", NULL),
+	SND_SOC_DAPM_MIC("Digital Mic4", NULL),
+	SND_SOC_DAPM_MIC("Digital Mic5", NULL),
+	SND_SOC_DAPM_MIC("Digital Mic6", NULL),
+};
+
+static const char *const slim0_rx_ch_text[] = {"One", "Two"};
+static const char *const slim0_tx_ch_text[] = {"One", "Two", "Three", "Four"};
+
+static const struct soc_enum msm_enum[] = {
+	SOC_ENUM_SINGLE_EXT(2, slim0_rx_ch_text),
+	SOC_ENUM_SINGLE_EXT(4, slim0_tx_ch_text),
+};
+
+static const char *const btsco_rate_text[] = {"8000", "16000"};
+static const struct soc_enum msm_btsco_enum[] = {
+	SOC_ENUM_SINGLE_EXT(2, btsco_rate_text),
+};
+
+static int msm_slim_0_rx_ch_get(struct snd_kcontrol *kcontrol,
+	struct snd_ctl_elem_value *ucontrol)
+{
+	pr_debug("%s: msm_slim_0_rx_ch  = %d\n", __func__,
+		 msm_slim_0_rx_ch);
+	ucontrol->value.integer.value[0] = msm_slim_0_rx_ch - 1;
+	return 0;
+}
+
+static int msm_slim_0_rx_ch_put(struct snd_kcontrol *kcontrol,
+	struct snd_ctl_elem_value *ucontrol)
+{
+	msm_slim_0_rx_ch = ucontrol->value.integer.value[0] + 1;
+
+	pr_debug("%s: msm_slim_0_rx_ch = %d\n", __func__,
+		 msm_slim_0_rx_ch);
+	return 1;
+}
+
+static int msm_slim_0_tx_ch_get(struct snd_kcontrol *kcontrol,
+	struct snd_ctl_elem_value *ucontrol)
+{
+	pr_debug("%s: msm_slim_0_tx_ch  = %d\n", __func__,
+		 msm_slim_0_tx_ch);
+	ucontrol->value.integer.value[0] = msm_slim_0_tx_ch - 1;
+	return 0;
+}
+
+static int msm_slim_0_tx_ch_put(struct snd_kcontrol *kcontrol,
+	struct snd_ctl_elem_value *ucontrol)
+{
+	msm_slim_0_tx_ch = ucontrol->value.integer.value[0] + 1;
+
+	pr_debug("%s: msm_slim_0_tx_ch = %d\n", __func__, msm_slim_0_tx_ch);
+	return 1;
+}
+
+static int msm_btsco_rate_get(struct snd_kcontrol *kcontrol,
+				struct snd_ctl_elem_value *ucontrol)
+{
+	pr_debug("%s: msm_btsco_rate  = %d", __func__, msm_btsco_rate);
+	ucontrol->value.integer.value[0] = msm_btsco_rate;
+	return 0;
+}
+
+static int msm_btsco_rate_put(struct snd_kcontrol *kcontrol,
+				struct snd_ctl_elem_value *ucontrol)
+{
+	switch (ucontrol->value.integer.value[0]) {
+	case 0:
+		msm_btsco_rate = BTSCO_RATE_8KHZ;
+		break;
+	case 1:
+		msm_btsco_rate = BTSCO_RATE_16KHZ;
+		break;
+	default:
+		msm_btsco_rate = BTSCO_RATE_8KHZ;
+		break;
+	}
+
+	pr_debug("%s: msm_btsco_rate = %d\n", __func__, msm_btsco_rate);
+	return 0;
+}
+
+static const struct snd_kcontrol_new int_btsco_rate_mixer_controls[] = {
+	SOC_ENUM_EXT("Internal BTSCO SampleRate", msm_btsco_enum[0],
+		     msm_btsco_rate_get, msm_btsco_rate_put),
+};
+
+static int msm_btsco_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
+					struct snd_pcm_hw_params *params)
+{
+	struct snd_interval *rate = hw_param_interval(params,
+					SNDRV_PCM_HW_PARAM_RATE);
+
+	struct snd_interval *channels = hw_param_interval(params,
+					SNDRV_PCM_HW_PARAM_CHANNELS);
+
+	rate->min = rate->max = msm_btsco_rate;
+	channels->min = channels->max = msm_btsco_ch;
+
+	return 0;
+}
+
+static int msm_proxy_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
+			struct snd_pcm_hw_params *params)
+{
+	struct snd_interval *rate = hw_param_interval(params,
+	SNDRV_PCM_HW_PARAM_RATE);
+
+	pr_debug("%s()\n", __func__);
+	rate->min = rate->max = 48000;
+
+	return 0;
+}
+
+static int msm8226_hdmi_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
+					struct snd_pcm_hw_params *params)
+{
+	struct snd_interval *rate = hw_param_interval(params,
+					SNDRV_PCM_HW_PARAM_RATE);
+
+	struct snd_interval *channels = hw_param_interval(params,
+					SNDRV_PCM_HW_PARAM_CHANNELS);
+
+	pr_debug("%s channels->min %u channels->max %u ()\n", __func__,
+			channels->min, channels->max);
+
+	rate->min = rate->max = 48000;
+
+	return 0;
+}
+
+static int msm_slim_0_rx_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
+					    struct snd_pcm_hw_params *params)
+{
+	struct snd_interval *rate = hw_param_interval(params,
+		SNDRV_PCM_HW_PARAM_RATE);
+
+	struct snd_interval *channels =
+		hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
+
+	pr_debug("%s()\n", __func__);
+	rate->min = rate->max = 48000;
+	channels->min = channels->max = msm_slim_0_rx_ch;
+
+	return 0;
+}
+
+static int msm_slim_0_tx_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
+					    struct snd_pcm_hw_params *params)
+{
+	struct snd_interval *rate = hw_param_interval(params,
+	SNDRV_PCM_HW_PARAM_RATE);
+
+	struct snd_interval *channels = hw_param_interval(params,
+			SNDRV_PCM_HW_PARAM_CHANNELS);
+
+	pr_debug("%s()\n", __func__);
+	rate->min = rate->max = 48000;
+	channels->min = channels->max = msm_slim_0_tx_ch;
+
+	return 0;
+}
+
+static int msm_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
+				struct snd_pcm_hw_params *params)
+{
+	struct snd_interval *rate = hw_param_interval(params,
+					SNDRV_PCM_HW_PARAM_RATE);
+
+	pr_debug("%s()\n", __func__);
+	rate->min = rate->max = 48000;
+
+	return 0;
+}
+
+static const struct soc_enum msm_snd_enum[] = {
+	SOC_ENUM_SINGLE_EXT(2, slim0_rx_ch_text),
+	SOC_ENUM_SINGLE_EXT(4, slim0_tx_ch_text),
+};
+
+static const struct snd_kcontrol_new msm_snd_controls[] = {
+	SOC_ENUM_EXT("SLIM_0_RX Channels", msm_snd_enum[1],
+		     msm_slim_0_rx_ch_get, msm_slim_0_rx_ch_put),
+	SOC_ENUM_EXT("SLIM_0_TX Channels", msm_snd_enum[2],
+		     msm_slim_0_tx_ch_get, msm_slim_0_tx_ch_put),
+};
+
+static int msm_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;
+	struct snd_soc_dai *codec_dai = rtd->codec_dai;
+
+	/*
+	 * Tapan SLIMBUS configuration
+	 * RX1, RX2, RX3, RX4, RX5, RX6, RX7, RX8, RX9, RX10, RX11, RX12, RX13
+	 * TX1, TX2, TX3, TX4, TX5, TX6, TX7, TX8, TX9, TX10, TX11, TX12, TX13
+	 * TX14, TX15, TX16
+	 */
+	unsigned int rx_ch[TAPAN_RX_MAX] = {144, 145, 146, 147, 148};
+	unsigned int tx_ch[TAPAN_TX_MAX]  = {128, 129, 130, 131, 132};
+
+
+	pr_debug("%s(), dev_name%s\n", __func__, dev_name(cpu_dai->dev));
+
+	rtd->pmdown_time = 0;
+
+	err = snd_soc_add_codec_controls(codec, msm_snd_controls,
+					 ARRAY_SIZE(msm_snd_controls));
+	if (err < 0)
+		return err;
+
+	snd_soc_dapm_new_controls(dapm, msm8226_dapm_widgets,
+				ARRAY_SIZE(msm8226_dapm_widgets));
+
+	snd_soc_dapm_sync(dapm);
+
+	snd_soc_dai_set_channel_map(codec_dai, ARRAY_SIZE(tx_ch),
+				    tx_ch, ARRAY_SIZE(rx_ch), rx_ch);
+
+	/* start mbhc */
+	mbhc_cfg.calibration = def_tapan_mbhc_cal();
+	if (mbhc_cfg.calibration)
+		err = tapan_hs_detect(codec, &mbhc_cfg);
+	else
+		err = -ENOMEM;
+
+	return err;
+}
+
+static int msm_snd_startup(struct snd_pcm_substream *substream)
+{
+	pr_debug("%s(): substream = %s  stream = %d\n", __func__,
+		 substream->name, substream->stream);
+	return 0;
+}
+
+void *def_tapan_mbhc_cal(void)
+{
+	void *tapan_cal;
+	struct wcd9xxx_mbhc_btn_detect_cfg *btn_cfg;
+	u16 *btn_low, *btn_high;
+	u8 *n_ready, *n_cic, *gain;
+
+	tapan_cal = kzalloc(WCD9XXX_MBHC_CAL_SIZE(WCD9XXX_MBHC_DEF_BUTTONS,
+						WCD9XXX_MBHC_DEF_RLOADS),
+			    GFP_KERNEL);
+	if (!tapan_cal) {
+		pr_err("%s: out of memory\n", __func__);
+		return NULL;
+	}
+
+#define S(X, Y) ((WCD9XXX_MBHC_CAL_GENERAL_PTR(tapan_cal)->X) = (Y))
+	S(t_ldoh, 100);
+	S(t_bg_fast_settle, 100);
+	S(t_shutdown_plug_rem, 255);
+	S(mbhc_nsa, 4);
+	S(mbhc_navg, 4);
+#undef S
+#define S(X, Y) ((WCD9XXX_MBHC_CAL_PLUG_DET_PTR(tapan_cal)->X) = (Y))
+	S(mic_current, TAPAN_PID_MIC_5_UA);
+	S(hph_current, TAPAN_PID_MIC_5_UA);
+	S(t_mic_pid, 100);
+	S(t_ins_complete, 250);
+	S(t_ins_retry, 200);
+#undef S
+#define S(X, Y) ((WCD9XXX_MBHC_CAL_PLUG_TYPE_PTR(tapan_cal)->X) = (Y))
+	S(v_no_mic, 30);
+	S(v_hs_max, 2400);
+#undef S
+#define S(X, Y) ((WCD9XXX_MBHC_CAL_BTN_DET_PTR(tapan_cal)->X) = (Y))
+	S(c[0], 62);
+	S(c[1], 124);
+	S(nc, 1);
+	S(n_meas, 3);
+	S(mbhc_nsc, 11);
+	S(n_btn_meas, 1);
+	S(n_btn_con, 2);
+	S(num_btn, WCD9XXX_MBHC_DEF_BUTTONS);
+	S(v_btn_press_delta_sta, 100);
+	S(v_btn_press_delta_cic, 50);
+#undef S
+	btn_cfg = WCD9XXX_MBHC_CAL_BTN_DET_PTR(tapan_cal);
+	btn_low = wcd9xxx_mbhc_cal_btn_det_mp(btn_cfg, MBHC_BTN_DET_V_BTN_LOW);
+	btn_high = wcd9xxx_mbhc_cal_btn_det_mp(btn_cfg,
+					       MBHC_BTN_DET_V_BTN_HIGH);
+	btn_low[0] = -50;
+	btn_high[0] = 10;
+	btn_low[1] = 11;
+	btn_high[1] = 52;
+	btn_low[2] = 53;
+	btn_high[2] = 94;
+	btn_low[3] = 95;
+	btn_high[3] = 133;
+	btn_low[4] = 134;
+	btn_high[4] = 171;
+	btn_low[5] = 172;
+	btn_high[5] = 208;
+	btn_low[6] = 209;
+	btn_high[6] = 244;
+	btn_low[7] = 245;
+	btn_high[7] = 330;
+	n_ready = wcd9xxx_mbhc_cal_btn_det_mp(btn_cfg, MBHC_BTN_DET_N_READY);
+	n_ready[0] = 80;
+	n_ready[1] = 68;
+	n_cic = wcd9xxx_mbhc_cal_btn_det_mp(btn_cfg, MBHC_BTN_DET_N_CIC);
+	n_cic[0] = 60;
+	n_cic[1] = 47;
+	gain = wcd9xxx_mbhc_cal_btn_det_mp(btn_cfg, MBHC_BTN_DET_GAIN);
+	gain[0] = 11;
+	gain[1] = 9;
+
+	return tapan_cal;
+}
+
+static int msm_snd_hw_params(struct snd_pcm_substream *substream,
+			     struct snd_pcm_hw_params *params)
+{
+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
+	struct snd_soc_dai *codec_dai = rtd->codec_dai;
+	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
+	int ret = 0;
+	unsigned int rx_ch[SLIM_MAX_RX_PORTS], tx_ch[SLIM_MAX_TX_PORTS];
+	unsigned int rx_ch_cnt = 0, tx_ch_cnt = 0;
+	unsigned int user_set_tx_ch = 0;
+
+	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+		pr_debug("%s: rx_0_ch=%d\n", __func__, msm_slim_0_rx_ch);
+		ret = snd_soc_dai_get_channel_map(codec_dai,
+					&tx_ch_cnt, tx_ch, &rx_ch_cnt , rx_ch);
+		if (ret < 0) {
+			pr_err("%s: failed to get codec chan map\n", __func__);
+			goto end;
+		}
+
+		ret = snd_soc_dai_set_channel_map(cpu_dai, 0, 0,
+						  msm_slim_0_rx_ch, rx_ch);
+		if (ret < 0) {
+			pr_err("%s: failed to set cpu chan map\n", __func__);
+			goto end;
+		}
+	} else {
+
+		pr_debug("%s: %s_tx_dai_id_%d_ch=%d\n", __func__,
+			 codec_dai->name, codec_dai->id, user_set_tx_ch);
+
+		ret = snd_soc_dai_get_channel_map(codec_dai,
+					 &tx_ch_cnt, tx_ch, &rx_ch_cnt , rx_ch);
+		if (ret < 0) {
+			pr_err("%s: failed to get codec chan map\n", __func__);
+			goto end;
+		}
+		/* For tabla_tx1 case */
+		if (codec_dai->id == 1)
+			user_set_tx_ch = msm_slim_0_tx_ch;
+		/* For tabla_tx2 case */
+		else if (codec_dai->id == 3)
+			user_set_tx_ch = params_channels(params);
+		else
+			user_set_tx_ch = tx_ch_cnt;
+
+		pr_debug("%s: msm_slim_0_tx_ch(%d)user_set_tx_ch(%d)tx_ch_cnt(%d)\n",
+			 __func__, msm_slim_0_tx_ch, user_set_tx_ch, tx_ch_cnt);
+
+		ret = snd_soc_dai_set_channel_map(cpu_dai,
+						  user_set_tx_ch, tx_ch, 0 , 0);
+		if (ret < 0) {
+			pr_err("%s: failed to set cpu chan map\n", __func__);
+			goto end;
+		}
+	}
+end:
+	return ret;
+}
+
+static void msm_snd_shutdown(struct snd_pcm_substream *substream)
+{
+	pr_debug("%s(): substream = %s stream = %d\n", __func__,
+		 substream->name, substream->stream);
+}
+
+static struct snd_soc_ops msm8226_be_ops = {
+	.startup = msm_snd_startup,
+	.hw_params = msm_snd_hw_params,
+	.shutdown = msm_snd_shutdown,
+};
+
+/* Digital audio interface glue - connects codec <---> CPU */
+static struct snd_soc_dai_link msm8226_dai[] = {
+	/* FrontEnd DAI Links */
+	{
+		.name = "MSM8226 Media1",
+		.stream_name = "MultiMedia1",
+		.cpu_dai_name	= "MultiMedia1",
+		.platform_name  = "msm-pcm-dsp",
+		.dynamic = 1,
+		.trigger = {SND_SOC_DPCM_TRIGGER_POST,
+			SND_SOC_DPCM_TRIGGER_POST},
+		.codec_dai_name = "snd-soc-dummy-dai",
+		.codec_name = "snd-soc-dummy",
+		.ignore_suspend = 1,
+		/* This dainlink has playback support */
+		.ignore_pmdown_time = 1,
+		.be_id = MSM_FRONTEND_DAI_MULTIMEDIA1
+	},
+	{
+		.name = "MSM8226 Media2",
+		.stream_name = "MultiMedia2",
+		.cpu_dai_name   = "MultiMedia2",
+		.platform_name  = "msm-pcm-dsp",
+		.dynamic = 1,
+		.codec_dai_name = "snd-soc-dummy-dai",
+		.codec_name = "snd-soc-dummy",
+		.trigger = {SND_SOC_DPCM_TRIGGER_POST,
+			SND_SOC_DPCM_TRIGGER_POST},
+		.ignore_suspend = 1,
+		/* This dainlink has playback support */
+		.ignore_pmdown_time = 1,
+		.be_id = MSM_FRONTEND_DAI_MULTIMEDIA2,
+	},
+	{
+		.name = "Circuit-Switch Voice",
+		.stream_name = "CS-Voice",
+		.cpu_dai_name   = "CS-VOICE",
+		.platform_name  = "msm-pcm-voice",
+		.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},
+		.no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
+		.ignore_suspend = 1,
+		/* this dainlink has playback support */
+		.ignore_pmdown_time = 1,
+		.be_id = MSM_FRONTEND_DAI_CS_VOICE,
+	},
+	{
+		.name = "MSM VoIP",
+		.stream_name = "VoIP",
+		.cpu_dai_name	= "VoIP",
+		.platform_name  = "msm-voip-dsp",
+		.dynamic = 1,
+		.trigger = {SND_SOC_DPCM_TRIGGER_POST,
+			SND_SOC_DPCM_TRIGGER_POST},
+		.codec_dai_name = "snd-soc-dummy-dai",
+		.codec_name = "snd-soc-dummy",
+		.ignore_suspend = 1,
+		/* this dainlink has playback support */
+		.ignore_pmdown_time = 1,
+		.be_id = MSM_FRONTEND_DAI_VOIP,
+	},
+	{
+		.name = "MSM8226 LPA",
+		.stream_name = "LPA",
+		.cpu_dai_name	= "MultiMedia3",
+		.platform_name  = "msm-pcm-lpa",
+		.dynamic = 1,
+		.trigger = {SND_SOC_DPCM_TRIGGER_POST,
+			SND_SOC_DPCM_TRIGGER_POST},
+		.codec_dai_name = "snd-soc-dummy-dai",
+		.codec_name = "snd-soc-dummy",
+		.ignore_suspend = 1,
+		/* this dainlink has playback support */
+		.ignore_pmdown_time = 1,
+		.be_id = MSM_FRONTEND_DAI_MULTIMEDIA3,
+	},
+	/* Hostless PCM purpose */
+	{
+		.name = "SLIMBUS_0 Hostless",
+		.stream_name = "SLIMBUS_0 Hostless",
+		.cpu_dai_name = "SLIMBUS0_HOSTLESS",
+		.platform_name = "msm-pcm-hostless",
+		.dynamic = 1,
+		.trigger = {SND_SOC_DPCM_TRIGGER_POST,
+			    SND_SOC_DPCM_TRIGGER_POST},
+		.no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
+		.ignore_suspend = 1,
+		.ignore_pmdown_time = 1, /* dai link has playback support */
+		.codec_dai_name = "snd-soc-dummy-dai",
+		.codec_name = "snd-soc-dummy",
+	},
+	{
+		.name = "INT_FM Hostless",
+		.stream_name = "INT_FM Hostless",
+		.cpu_dai_name	= "INT_FM_HOSTLESS",
+		.platform_name  = "msm-pcm-hostless",
+		.dynamic = 1,
+		.trigger = {SND_SOC_DPCM_TRIGGER_POST,
+			SND_SOC_DPCM_TRIGGER_POST},
+		.no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
+		.ignore_suspend = 1,
+		/* this dainlink has playback support */
+		.ignore_pmdown_time = 1,
+		.codec_dai_name = "snd-soc-dummy-dai",
+		.codec_name = "snd-soc-dummy",
+	},
+	{
+		.name = "MSM AFE-PCM RX",
+		.stream_name = "AFE-PROXY RX",
+		.cpu_dai_name = "msm-dai-q6-dev.241",
+		.codec_name = "msm-stub-codec.1",
+		.codec_dai_name = "msm-stub-rx",
+		.platform_name  = "msm-pcm-afe",
+		.ignore_suspend = 1,
+		/* this dainlink has playback support */
+		.ignore_pmdown_time = 1,
+	},
+	{
+		.name = "MSM AFE-PCM TX",
+		.stream_name = "AFE-PROXY TX",
+		.cpu_dai_name = "msm-dai-q6-dev.240",
+		.codec_name = "msm-stub-codec.1",
+		.codec_dai_name = "msm-stub-tx",
+		.platform_name  = "msm-pcm-afe",
+		.ignore_suspend = 1,
+	},
+	{
+		.name = "MSM8226 Compr",
+		.stream_name = "COMPR",
+		.cpu_dai_name	= "MultiMedia4",
+		.platform_name  = "msm-compr-dsp",
+		.dynamic = 1,
+		.trigger = {SND_SOC_DPCM_TRIGGER_POST,
+			 SND_SOC_DPCM_TRIGGER_POST},
+		.codec_dai_name = "snd-soc-dummy-dai",
+		.codec_name = "snd-soc-dummy",
+		.ignore_suspend = 1,
+		.ignore_pmdown_time = 1,
+		 /* this dainlink has playback support */
+		.be_id = MSM_FRONTEND_DAI_MULTIMEDIA4,
+	},
+	{
+		.name = "AUXPCM Hostless",
+		.stream_name = "AUXPCM Hostless",
+		.cpu_dai_name   = "AUXPCM_HOSTLESS",
+		.platform_name  = "msm-pcm-hostless",
+		.dynamic = 1,
+		.trigger = {SND_SOC_DPCM_TRIGGER_POST,
+			SND_SOC_DPCM_TRIGGER_POST},
+		.no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
+		.ignore_suspend = 1,
+		/* this dainlink has playback support */
+		.ignore_pmdown_time = 1,
+		.codec_dai_name = "snd-soc-dummy-dai",
+		.codec_name = "snd-soc-dummy",
+	},
+	{
+		.name = "SLIMBUS_1 Hostless",
+		.stream_name = "SLIMBUS_1 Hostless",
+		.cpu_dai_name = "SLIMBUS1_HOSTLESS",
+		.platform_name = "msm-pcm-hostless",
+		.dynamic = 1,
+		.trigger = {SND_SOC_DPCM_TRIGGER_POST,
+			    SND_SOC_DPCM_TRIGGER_POST},
+		.no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
+		.ignore_suspend = 1,
+		.ignore_pmdown_time = 1, /* dai link has playback support */
+		.codec_dai_name = "snd-soc-dummy-dai",
+		.codec_name = "snd-soc-dummy",
+	},
+	{
+		.name = "SLIMBUS_3 Hostless",
+		.stream_name = "SLIMBUS_3 Hostless",
+		.cpu_dai_name = "SLIMBUS3_HOSTLESS",
+		.platform_name = "msm-pcm-hostless",
+		.dynamic = 1,
+		.trigger = {SND_SOC_DPCM_TRIGGER_POST,
+			    SND_SOC_DPCM_TRIGGER_POST},
+		.no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
+		.ignore_suspend = 1,
+		.ignore_pmdown_time = 1, /* dai link has playback support */
+		.codec_dai_name = "snd-soc-dummy-dai",
+		.codec_name = "snd-soc-dummy",
+	},
+	{
+		.name = "SLIMBUS_4 Hostless",
+		.stream_name = "SLIMBUS_4 Hostless",
+		.cpu_dai_name = "SLIMBUS4_HOSTLESS",
+		.platform_name = "msm-pcm-hostless",
+		.dynamic = 1,
+		.trigger = {SND_SOC_DPCM_TRIGGER_POST,
+			    SND_SOC_DPCM_TRIGGER_POST},
+		.no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
+		.ignore_suspend = 1,
+		.ignore_pmdown_time = 1, /* dai link has playback support */
+		.codec_dai_name = "snd-soc-dummy-dai",
+		.codec_name = "snd-soc-dummy",
+	},
+	/* Backend BT/FM DAI Links */
+	{
+		.name = LPASS_BE_INT_BT_SCO_RX,
+		.stream_name = "Internal BT-SCO Playback",
+		.cpu_dai_name = "msm-dai-q6-dev.12288",
+		.platform_name = "msm-pcm-routing",
+		.codec_name = "msm-stub-codec.1",
+		.codec_dai_name	= "msm-stub-rx",
+		.no_pcm = 1,
+		.be_id = MSM_BACKEND_DAI_INT_BT_SCO_RX,
+		.be_hw_params_fixup = msm_btsco_be_hw_params_fixup,
+		/* this dainlink has playback support */
+		.ignore_pmdown_time = 1,
+	},
+	{
+		.name = LPASS_BE_INT_BT_SCO_TX,
+		.stream_name = "Internal BT-SCO Capture",
+		.cpu_dai_name = "msm-dai-q6-dev.12289",
+		.platform_name = "msm-pcm-routing",
+		.codec_name = "msm-stub-codec.1",
+		.codec_dai_name	= "msm-stub-tx",
+		.no_pcm = 1,
+		.be_id = MSM_BACKEND_DAI_INT_BT_SCO_TX,
+		.be_hw_params_fixup = msm_btsco_be_hw_params_fixup,
+	},
+	{
+		.name = LPASS_BE_INT_FM_RX,
+		.stream_name = "Internal FM Playback",
+		.cpu_dai_name = "msm-dai-q6-dev.12292",
+		.platform_name = "msm-pcm-routing",
+		.codec_name = "msm-stub-codec.1",
+		.codec_dai_name = "msm-stub-rx",
+		.no_pcm = 1,
+		.be_id = MSM_BACKEND_DAI_INT_FM_RX,
+		.be_hw_params_fixup = msm_be_hw_params_fixup,
+		/* this dainlink has playback support */
+		.ignore_pmdown_time = 1,
+	},
+	{
+		.name = LPASS_BE_INT_FM_TX,
+		.stream_name = "Internal FM Capture",
+		.cpu_dai_name = "msm-dai-q6-dev.12293",
+		.platform_name = "msm-pcm-routing",
+		.codec_name = "msm-stub-codec.1",
+		.codec_dai_name = "msm-stub-tx",
+		.no_pcm = 1,
+		.be_id = MSM_BACKEND_DAI_INT_FM_TX,
+		.be_hw_params_fixup = msm_be_hw_params_fixup,
+	},
+	/* Backend AFE DAI Links */
+	{
+		.name = LPASS_BE_AFE_PCM_RX,
+		.stream_name = "AFE Playback",
+		.cpu_dai_name = "msm-dai-q6-dev.224",
+		.platform_name = "msm-pcm-routing",
+		.codec_name = "msm-stub-codec.1",
+		.codec_dai_name = "msm-stub-rx",
+		.no_pcm = 1,
+		.be_id = MSM_BACKEND_DAI_AFE_PCM_RX,
+		.be_hw_params_fixup = msm_proxy_be_hw_params_fixup,
+		/* this dainlink has playback support */
+		.ignore_pmdown_time = 1,
+	},
+	{
+		.name = LPASS_BE_AFE_PCM_TX,
+		.stream_name = "AFE Capture",
+		.cpu_dai_name = "msm-dai-q6-dev.225",
+		.platform_name = "msm-pcm-routing",
+		.codec_name = "msm-stub-codec.1",
+		.codec_dai_name = "msm-stub-tx",
+		.no_pcm = 1,
+		.be_id = MSM_BACKEND_DAI_AFE_PCM_TX,
+		.be_hw_params_fixup = msm_proxy_be_hw_params_fixup,
+	},
+	/* HDMI Hostless */
+	{
+		.name = "HDMI_RX_HOSTLESS",
+		.stream_name = "HDMI_RX_HOSTLESS",
+		.cpu_dai_name = "HDMI_HOSTLESS",
+		.platform_name = "msm-pcm-hostless",
+		.dynamic = 1,
+		.trigger = {SND_SOC_DPCM_TRIGGER_POST,
+			SND_SOC_DPCM_TRIGGER_POST},
+		.no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
+		.ignore_suspend = 1,
+		.ignore_pmdown_time = 1,
+		.codec_dai_name = "snd-soc-dummy-dai",
+		.codec_name = "snd-soc-dummy",
+	},
+	/* HDMI BACK END DAI Link */
+	{
+		.name = LPASS_BE_HDMI,
+		.stream_name = "HDMI Playback",
+		.cpu_dai_name = "msm-dai-q6-hdmi.8",
+		.platform_name = "msm-pcm-routing",
+		.codec_name     = "msm-stub-codec.1",
+		.codec_dai_name = "msm-stub-rx",
+		.no_pcm = 1,
+		.be_id = MSM_BACKEND_DAI_HDMI_RX,
+		.be_hw_params_fixup = msm8226_hdmi_be_hw_params_fixup,
+		.ignore_pmdown_time = 1,
+	},
+	/* Backend DAI Links */
+	{
+		.name = LPASS_BE_SLIMBUS_0_RX,
+		.stream_name = "Slimbus Playback",
+		.cpu_dai_name = "msm-dai-q6-dev.16384",
+		.platform_name = "msm-pcm-routing",
+		.codec_name = "tapan_codec",
+		.codec_dai_name	= "tapan_rx1",
+		.no_pcm = 1,
+		.be_id = MSM_BACKEND_DAI_SLIMBUS_0_RX,
+		.init = &msm_audrx_init,
+		.be_hw_params_fixup = msm_slim_0_rx_be_hw_params_fixup,
+		.ops = &msm8226_be_ops,
+		.ignore_pmdown_time = 1, /* dai link has playback support */
+	},
+	{
+		.name = LPASS_BE_SLIMBUS_0_TX,
+		.stream_name = "Slimbus Capture",
+		.cpu_dai_name = "msm-dai-q6-dev.16385",
+		.platform_name = "msm-pcm-routing",
+		.codec_name = "tapan_codec",
+		.codec_dai_name	= "tapan_tx1",
+		.no_pcm = 1,
+		.be_id = MSM_BACKEND_DAI_SLIMBUS_0_TX,
+		.be_hw_params_fixup = msm_slim_0_tx_be_hw_params_fixup,
+		.ops = &msm8226_be_ops,
+	},
+	{
+		.name = LPASS_BE_SLIMBUS_1_RX,
+		.stream_name = "Slimbus1 Playback",
+		.cpu_dai_name = "msm-dai-q6-dev.16386",
+		.platform_name = "msm-pcm-routing",
+		.codec_name = "tapan_codec",
+		.codec_dai_name	= "tapan_rx1",
+		.no_pcm = 1,
+		.be_id = MSM_BACKEND_DAI_SLIMBUS_1_RX,
+		.be_hw_params_fixup = msm_slim_0_rx_be_hw_params_fixup,
+		.ops = &msm8226_be_ops,
+		/* dai link has playback support */
+		.ignore_pmdown_time = 1,
+	},
+	{
+		.name = LPASS_BE_SLIMBUS_1_TX,
+		.stream_name = "Slimbus1 Capture",
+		.cpu_dai_name = "msm-dai-q6-dev.16387",
+		.platform_name = "msm-pcm-routing",
+		.codec_name = "tapan_codec",
+		.codec_dai_name	= "tapan_tx1",
+		.no_pcm = 1,
+		.be_id = MSM_BACKEND_DAI_SLIMBUS_1_TX,
+		.be_hw_params_fixup = msm_slim_0_tx_be_hw_params_fixup,
+		.ops = &msm8226_be_ops,
+	},
+	{
+		.name = LPASS_BE_SLIMBUS_3_RX,
+		.stream_name = "Slimbus3 Playback",
+		.cpu_dai_name = "msm-dai-q6-dev.16390",
+		.platform_name = "msm-pcm-routing",
+		.codec_name = "tapan_codec",
+		.codec_dai_name	= "tapan_rx1",
+		.no_pcm = 1,
+		.be_id = MSM_BACKEND_DAI_SLIMBUS_3_RX,
+		.be_hw_params_fixup = msm_slim_0_rx_be_hw_params_fixup,
+		.ops = &msm8226_be_ops,
+		/* dai link has playback support */
+		.ignore_pmdown_time = 1,
+	},
+	{
+		.name = LPASS_BE_SLIMBUS_3_TX,
+		.stream_name = "Slimbus3 Capture",
+		.cpu_dai_name = "msm-dai-q6-dev.16391",
+		.platform_name = "msm-pcm-routing",
+		.codec_name = "tapan_codec",
+		.codec_dai_name	= "tapan_tx1",
+		.no_pcm = 1,
+		.be_id = MSM_BACKEND_DAI_SLIMBUS_3_TX,
+		.be_hw_params_fixup = msm_slim_0_tx_be_hw_params_fixup,
+		.ops = &msm8226_be_ops,
+	},
+	{
+		.name = LPASS_BE_SLIMBUS_4_RX,
+		.stream_name = "Slimbus4 Playback",
+		.cpu_dai_name = "msm-dai-q6-dev.16392",
+		.platform_name = "msm-pcm-routing",
+		.codec_name = "tapan_codec",
+		.codec_dai_name	= "tapan_rx1",
+		.no_pcm = 1,
+		.be_id = MSM_BACKEND_DAI_SLIMBUS_4_RX,
+		.be_hw_params_fixup = msm_slim_0_rx_be_hw_params_fixup,
+		.ops = &msm8226_be_ops,
+		/* dai link has playback support */
+		.ignore_pmdown_time = 1,
+	},
+	{
+		.name = LPASS_BE_SLIMBUS_4_TX,
+		.stream_name = "Slimbus4 Capture",
+		.cpu_dai_name = "msm-dai-q6-dev.16393",
+		.platform_name = "msm-pcm-routing",
+		.codec_name = "tapan_codec",
+		.codec_dai_name	= "tapan_tx1",
+		.no_pcm = 1,
+		.be_id = MSM_BACKEND_DAI_SLIMBUS_4_TX,
+		.be_hw_params_fixup = msm_slim_0_tx_be_hw_params_fixup,
+		.ops = &msm8226_be_ops,
+	},
+};
+
+struct snd_soc_card snd_soc_card_msm8226 = {
+	.name		= "msm8226-tapan-snd-card",
+	.dai_link	= msm8226_dai,
+	.num_links	= ARRAY_SIZE(msm8226_dai),
+};
+
+static int msm8226_prepare_codec_mclk(struct snd_soc_card *card)
+{
+	return 0;
+}
+
+static __devinit int msm8226_asoc_machine_probe(struct platform_device *pdev)
+{
+	struct snd_soc_card *card = &snd_soc_card_msm8226;
+	struct msm8226_asoc_mach_data *pdata;
+	int ret;
+
+	if (!pdev->dev.of_node) {
+		dev_err(&pdev->dev, "No platform supplied from device tree\n");
+		return -EINVAL;
+	}
+
+	pdata = devm_kzalloc(&pdev->dev,
+			sizeof(struct msm8226_asoc_mach_data), GFP_KERNEL);
+	if (!pdata) {
+		dev_err(&pdev->dev, "Can't allocate msm8226_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)
+		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,tapan-mclk-clk-freq", &pdata->mclk_freq);
+	if (ret) {
+		dev_err(&pdev->dev, "Looking up %s property in node %s failed",
+			"qcom,tapan-mclk-clk-freq",
+			pdev->dev.of_node->full_name);
+		goto err;
+	}
+
+	if (pdata->mclk_freq != 9600000) {
+		dev_err(&pdev->dev, "unsupported tapan mclk freq %u\n",
+			pdata->mclk_freq);
+		ret = -EINVAL;
+		goto err;
+	}
+
+	/* TODO: MCLK GPIO */
+
+	ret = msm8226_prepare_codec_mclk(card);
+	if (ret)
+		goto err;
+
+	ret = snd_soc_register_card(card);
+	if (ret) {
+		dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n",
+			ret);
+		goto err;
+	}
+	mutex_init(&cdc_mclk_mutex);
+
+	return 0;
+err:
+	devm_kfree(&pdev->dev, pdata);
+	return ret;
+}
+
+static int __devexit msm8226_asoc_machine_remove(struct platform_device *pdev)
+{
+	struct snd_soc_card *card = platform_get_drvdata(pdev);
+
+	/* TODO: GPIO MCLK */
+	snd_soc_unregister_card(card);
+
+	return 0;
+}
+
+static const struct of_device_id msm8226_asoc_machine_of_match[]  = {
+	{ .compatible = "qcom,msm8226-audio-tapan", },
+	{},
+};
+
+static struct platform_driver msm8226_asoc_machine_driver = {
+	.driver = {
+		.name = DRV_NAME,
+		.owner = THIS_MODULE,
+		.pm = &snd_soc_pm_ops,
+		.of_match_table = msm8226_asoc_machine_of_match,
+	},
+	.probe = msm8226_asoc_machine_probe,
+	.remove = __devexit_p(msm8226_asoc_machine_remove),
+};
+module_platform_driver(msm8226_asoc_machine_driver);
+
+MODULE_DESCRIPTION("ALSA SoC msm");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:" DRV_NAME);
+MODULE_DEVICE_TABLE(of, msm8226_asoc_machine_of_match);
diff --git a/sound/soc/msm/msm8930.c b/sound/soc/msm/msm8930.c
index bb9f2be..d674b8b 100644
--- a/sound/soc/msm/msm8930.c
+++ b/sound/soc/msm/msm8930.c
@@ -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);
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/msm-pcm-voice-v2.c b/sound/soc/msm/qdsp6v2/msm-pcm-voice-v2.c
index a1e461d..28806c0 100644
--- a/sound/soc/msm/qdsp6v2/msm-pcm-voice-v2.c
+++ b/sound/soc/msm/qdsp6v2/msm-pcm-voice-v2.c
@@ -44,10 +44,10 @@
 	.channels_max =         1,
 
 	.buffer_bytes_max =     4096 * 2,
-	.period_bytes_min =     4096,
+	.period_bytes_min =     2048,
 	.period_bytes_max =     4096,
 	.periods_min =          2,
-	.periods_max =          2,
+	.periods_max =          4,
 
 	.fifo_size =            0,
 };
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;