Merge "msm: vidc: wfd: Add switch node mechanism"
diff --git a/Documentation/devicetree/bindings/arm/msm/jtag-mm.txt b/Documentation/devicetree/bindings/arm/msm/jtag-mm.txt
new file mode 100644
index 0000000..21dead3
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/msm/jtag-mm.txt
@@ -0,0 +1,21 @@
+* JTAG-MM
+
+The jtag-mm entry specifies the memory mapped addresses for the debug and ETM
+registers. The jtag-mm driver uses these to save and restore the registers
+using memory mapped access during power collapse so as to retain their state
+accross power collapse. This is necessary in case cp14 access to the registers
+is not permitted.
+
+Required Properties:
+compatible: component name used for driver matching, should be "qcom,jtag-mm"
+reg: physical base address and length of the register set
+reg-names: should be "etm-base" for etm register set and "debug-base" for debug
+	register set.
+
+Example:
+jtag_mm: jtagmm@fc332000 {
+	compatible = "qcom,jtag-mm";
+	reg = <0xfc332000 0x1000>,
+		<0xfc333000 0x1000>;
+	reg-names = "etm-base","debug-base";
+	};
diff --git a/Documentation/devicetree/bindings/arm/msm/msm_bus.txt b/Documentation/devicetree/bindings/arm/msm/msm_bus.txt
index fb72525..5f534a2 100644
--- a/Documentation/devicetree/bindings/arm/msm/msm_bus.txt
+++ b/Documentation/devicetree/bindings/arm/msm/msm_bus.txt
@@ -1,6 +1,11 @@
 MSM Bus Scaling Driver
 
-The msm bus scaling driver provides the ability to configure
+The bus scaling driver builds the topology of chipsets by adding
+bus devices (fabrics/NoCs) to the kernel tree. The device-tree
+data for bus devices contains the register addresses for QoS
+related registers on each NoC/Fabric.
+
+The bus scaling driver also provides the ability to configure
 bus performance parameters across the entire chip-set.
 Various clients use MSM scaling APIs to request bandwidth
 between multiple master-slave pairs. The bus driver then finds
diff --git a/Documentation/devicetree/bindings/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/mmc/mmc-dev-attrs.txt b/Documentation/mmc/mmc-dev-attrs.txt
index 43453d0..d96b431 100644
--- a/Documentation/mmc/mmc-dev-attrs.txt
+++ b/Documentation/mmc/mmc-dev-attrs.txt
@@ -25,14 +25,14 @@
 	running parallel lmdd write and lmdd read operations and calculating
 	the max number of packed writes requests.
 
-	min_sectors_to_check_bkops_status	This attribute is used to
-	determine whether the status bit that indicates the need for BKOPS
-	should be checked. The value is stored in this attribute represents
-	the minimum number of sectors that needs to be changed in the device
-	(written or discarded) in order to require the status-bit of BKOPS
-	to be checked. The value can modified via sysfs by writing the
-	required value to:
-	/sys/block/<block_dev_name>/min_sectors_to_check_bkops_status
+	bkops_check_threshold	This attribute is used to determine whether
+	the status bit that indicates the need for BKOPS should be checked.
+	The value should be given in percentages of the card size.
+	This value is used to calculate the minimum number of sectors that
+	needs to be changed in the device (written or discarded) in order to
+	require the status-bit of BKOPS to be checked.
+	The value can modified via sysfs by writing the required value to:
+	/sys/block/<block_dev_name>/bkops_check_threshold
 
 SD and MMC Device Attributes
 ============================
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 23181d9..5a9cecf 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -782,6 +782,7 @@
 	select HAVE_CLK_PREPARE
 	select NEED_MACH_MEMORY_H
 	select NEED_MACH_IO_H
+	select SOC_BUS
 	help
 	  Support for Qualcomm MSM/QSD based systems.  This runs on the
 	  apps processor of the MSM/QSD and depends on a shared memory
diff --git a/arch/arm/boot/dts/msm-iommu.dtsi b/arch/arm/boot/dts/msm-iommu.dtsi
index 8343c7a..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 36bcdd7..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";
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 9be99af..e43ff69 100644
--- a/arch/arm/boot/dts/msm8974.dtsi
+++ b/arch/arm/boot/dts/msm8974.dtsi
@@ -70,6 +70,7 @@
 			<783360 410000000>,
 			<489600 266670000>,
 			<244800 133330000>;
+		hfi = "venus";
 	};
 
 	qcom,wfd {
diff --git a/arch/arm/boot/dts/msm9625-coresight.dtsi b/arch/arm/boot/dts/msm9625-coresight.dtsi
index f01fe63..9a49c32 100644
--- a/arch/arm/boot/dts/msm9625-coresight.dtsi
+++ b/arch/arm/boot/dts/msm9625-coresight.dtsi
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -107,11 +107,23 @@
 		coresight-child-ports = <7>;
 	};
 
+	etm: etm@fc332000 {
+		compatible = "arm,coresight-etm";
+		reg = <0xfc332000 0x1000>;
+
+		coresight-id = <8>;
+		coresight-name = "coresight-etm";
+		coresight-nr-inports = <0>;
+		coresight-outports = <0>;
+		coresight-child-list = <&funnel_in0>;
+		coresight-child-ports = <4>;
+	};
+
 	csr: csr@fc302000 {
 		compatible = "qcom,coresight-csr";
 		reg = <0xfc302000 0x1000>;
 
-		coresight-id = <8>;
+		coresight-id = <9>;
 		coresight-name = "coresight-csr";
 		coresight-nr-inports = <0>;
 	};
diff --git a/arch/arm/boot/dts/msm9625.dtsi b/arch/arm/boot/dts/msm9625.dtsi
index 09f43a4..d374b59 100644
--- a/arch/arm/boot/dts/msm9625.dtsi
+++ b/arch/arm/boot/dts/msm9625.dtsi
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -81,7 +81,7 @@
 		vbus_otg-supply = <&usb_vbus>;
 
 		qcom,hsusb-otg-phy-type = <2>;
-		qcom,hsusb-otg-mode = <1>;
+		qcom,hsusb-otg-mode = <3>;
 		qcom,hsusb-otg-otg-control = <1>;
 		qcom,hsusb-otg-disable-reset;
 	};
@@ -602,6 +602,12 @@
 		qcom,bam-pipe-pair = <2>;
 	};
 
+	jtag_mm: jtagmm@fc332000 {
+		compatible = "qcom,jtag-mm";
+		reg = <0xfc332000 0x1000>,
+			<0xfc330000 0x1000>;
+		reg-names = "etm-base","debug-base";
+	};
 };
 
 /include/ "msm-pm8019-rpm-regulator.dtsi"
diff --git a/arch/arm/configs/msm8974-perf_defconfig b/arch/arm/configs/msm8974-perf_defconfig
index 2668566..079177e 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
@@ -330,6 +329,7 @@
 CONFIG_FB_MSM_MDSS=y
 CONFIG_FB_MSM_MDSS_WRITEBACK=y
 CONFIG_FB_MSM_MDSS_HDMI_PANEL=y
+CONFIG_FB_MSM_MDSS_HDMI_MHL_SII8334=y
 CONFIG_BACKLIGHT_LCD_SUPPORT=y
 # CONFIG_LCD_CLASS_DEVICE is not set
 CONFIG_BACKLIGHT_CLASS_DEVICE=y
diff --git a/arch/arm/configs/msm8974_defconfig b/arch/arm/configs/msm8974_defconfig
index 3d2a587..0738f2d 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
@@ -331,6 +330,7 @@
 CONFIG_FB_MSM_MDSS=y
 CONFIG_FB_MSM_MDSS_WRITEBACK=y
 CONFIG_FB_MSM_MDSS_HDMI_PANEL=y
+CONFIG_FB_MSM_MDSS_HDMI_MHL_SII8334=y
 CONFIG_BACKLIGHT_LCD_SUPPORT=y
 # CONFIG_LCD_CLASS_DEVICE is not set
 CONFIG_BACKLIGHT_CLASS_DEVICE=y
diff --git a/arch/arm/configs/msm9625_defconfig b/arch/arm/configs/msm9625_defconfig
index 0b003fd..decd8f2 100644
--- a/arch/arm/configs/msm9625_defconfig
+++ b/arch/arm/configs/msm9625_defconfig
@@ -238,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
diff --git a/arch/arm/mach-msm/Kconfig b/arch/arm/mach-msm/Kconfig
index 5b0ac52..83a5fb0 100644
--- a/arch/arm/mach-msm/Kconfig
+++ b/arch/arm/mach-msm/Kconfig
@@ -184,6 +184,7 @@
 	select ARM_USE_USER_ACCESSIBLE_TIMERS
 	select MSM_USE_USER_ACCESSIBLE_TIMERS
 	select MSM_CPU_PWRCTL
+	select MSM_LPM_TEST
 
 config ARCH_MSM8930
 	bool "MSM8930"
@@ -374,6 +375,7 @@
 	select MSM_QDSP6V2_CODECS
 	select MSM_AUDIO_QDSP6V2 if SND_SOC
 	select CPU_HAS_L2_PMU
+	select MSM_JTAG_MM if MSM_QDSS
 
 config ARCH_MSM8910
 	bool "MSM8910"
@@ -522,6 +524,17 @@
 	  enables the MPM driver that supports initialization from a device
 	  tree
 
+config MSM_LPM_TEST
+	bool "Low Power Mode test framework"
+	depends on MSM_RPM
+	depends on MSM_PM8X60
+	help
+	  LPM_TEST is a test framework that assists in exercising the low
+	  power mode algorithm on MSM targets. This test framework tracks
+	  notifications sent during entry/exit of the low power modes and
+	  processes them to measure various stats including latency
+	  measurement.
+
 config MSM_XO
 	bool
 
@@ -1568,6 +1581,16 @@
 	  to perform QMI message marshaling and transport them over IPC
 	  Router.
 
+config MSM_TEST_QMI_CLIENT
+	depends on MSM_QMI_INTERFACE
+	bool "MSM TEST QMI CLIENT"
+	help
+	  The sample QMI client provides a test code for QMI usage. The
+	  test_service client driver uses QMI interface library to send
+	  and receive QMI messages over IPC Router. The test code sends
+	  a synchronous QMI request to the test_service and handles the
+	  QMI responses.
+
 config MSM_ONCRPCROUTER_DEBUG
 	depends on MSM_ONCRPCROUTER
 	default y
@@ -2250,6 +2273,19 @@
 	  For production builds, you should probably say 'N' here to avoid
 	  potential power, performance and memory penalty.
 
+config MSM_JTAG_MM
+	bool "ETM trace and debug support across power collapse using memory mapped access"
+	help
+	   Enables support for kernel debugging (specifically breakpoints) and
+	   processor tracing using ETM across power collapse both for JTag and
+	   OS hosted software running on the target. Enabling this will ensure
+	   debug and ETM registers are saved and restored across power collapse.
+	   Needed on targets on which cp14 access to debug and ETM registers is
+	   not permitted and so memory mapped access is necessary.
+
+	   For production builds, you should probably say 'N' here to avoid
+	   potential power, performance and memory penalty.
+
 config MSM_ETM
 	tristate "Enable MSM ETM and ETB"
 	depends on ARCH_MSM8X60
@@ -2742,4 +2778,9 @@
 	  stand alone power collapse operation. Selecting this option
 	  ensures that they are always off.
 
+config MSM_UARTDM_Core_v14
+	bool "Use MSM BLSP based HSUART Core v1.4"
+	depends on SERIAL_MSM_HS
+	help
+		Select if BLSP based UART Core v.14 or higher is present.
 endif
diff --git a/arch/arm/mach-msm/Makefile b/arch/arm/mach-msm/Makefile
index 594bb5f..e92e4de 100644
--- a/arch/arm/mach-msm/Makefile
+++ b/arch/arm/mach-msm/Makefile
@@ -60,6 +60,7 @@
 obj-$(CONFIG_CPU_V6) += idle-v6.o
 obj-$(CONFIG_CPU_V7) += idle-v7.o
 obj-$(CONFIG_MSM_JTAG) += jtag.o
+obj-$(CONFIG_MSM_JTAG_MM) +=  jtag-mm.o
 
 msm-etm-objs := etm.o
 obj-$(CONFIG_MSM_ETM) += msm-etm.o
@@ -138,6 +139,7 @@
 obj-$(CONFIG_MSM_IPC_ROUTER)+= ipc_socket.o
 obj-$(CONFIG_MSM_IPC_ROUTER_SECURITY)+= msm_ipc_router_security.o
 obj-$(CONFIG_MSM_QMI_INTERFACE) += msm_qmi_interface.o
+obj-$(CONFIG_MSM_TEST_QMI_CLIENT) += kernel_test_service_v01.o test_qmi_client.o
 obj-$(CONFIG_DEBUG_FS) += smd_rpc_sym.o
 obj-$(CONFIG_MSM_ONCRPCROUTER) += smd_rpcrouter_servers.o
 obj-$(CONFIG_MSM_ONCRPCROUTER) += smd_rpcrouter_clients.o
@@ -327,6 +329,7 @@
 	obj-$(CONFIG_ARCH_MSM8960) += rpm_resources.o
 	obj-$(CONFIG_ARCH_MSM8X60) += rpm_resources.o
 	obj-$(CONFIG_ARCH_MSM9615) += rpm_resources.o
+	obj-$(CONFIG_MSM_LPM_TEST) += test-lpm.o
 endif
 ifdef CONFIG_MSM_RPM_SMD
 	obj-$(CONFIG_ARCH_MSM8974) += lpm_levels.o lpm_resources.o
diff --git a/arch/arm/mach-msm/acpuclock-8064.c b/arch/arm/mach-msm/acpuclock-8064.c
index e8c7680..359a156 100644
--- a/arch/arm/mach-msm/acpuclock-8064.c
+++ b/arch/arm/mach-msm/acpuclock-8064.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2011-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -239,6 +239,118 @@
 	{ 0, { 0 } }
 };
 
+static struct acpu_level tbl_PVS0_1512MHz[] __initdata = {
+	{ 1, {   384000, PLL_8, 0, 0x00 }, L2(0),   950000 },
+	{ 1, {   486000, HFPLL, 2, 0x24 }, L2(5),   950000 },
+	{ 1, {   594000, HFPLL, 1, 0x16 }, L2(5),   950000 },
+	{ 1, {   702000, HFPLL, 1, 0x1A }, L2(5),   962500 },
+	{ 1, {   810000, HFPLL, 1, 0x1E }, L2(5),  1000000 },
+	{ 1, {   918000, HFPLL, 1, 0x22 }, L2(5),  1025000 },
+	{ 1, {  1026000, HFPLL, 1, 0x26 }, L2(5),  1037500 },
+	{ 1, {  1134000, HFPLL, 1, 0x2A }, L2(15), 1075000 },
+	{ 1, {  1242000, HFPLL, 1, 0x2E }, L2(15), 1087500 },
+	{ 1, {  1350000, HFPLL, 1, 0x32 }, L2(15), 1125000 },
+	{ 1, {  1458000, HFPLL, 1, 0x36 }, L2(15), 1150000 },
+	{ 1, {  1512000, HFPLL, 1, 0x38 }, L2(15), 1162500 },
+	{ 0, { 0 } }
+};
+
+static struct acpu_level tbl_PVS1_1512MHz[] __initdata = {
+	{ 1, {   384000, PLL_8, 0, 0x00 }, L2(0),   950000 },
+	{ 1, {   486000, HFPLL, 2, 0x24 }, L2(5),   950000 },
+	{ 1, {   594000, HFPLL, 1, 0x16 }, L2(5),   950000 },
+	{ 1, {   702000, HFPLL, 1, 0x1A }, L2(5),   962500 },
+	{ 1, {   810000, HFPLL, 1, 0x1E }, L2(5),   975000 },
+	{ 1, {   918000, HFPLL, 1, 0x22 }, L2(5),  1000000 },
+	{ 1, {  1026000, HFPLL, 1, 0x26 }, L2(5),  1012500 },
+	{ 1, {  1134000, HFPLL, 1, 0x2A }, L2(15), 1037500 },
+	{ 1, {  1242000, HFPLL, 1, 0x2E }, L2(15), 1050000 },
+	{ 1, {  1350000, HFPLL, 1, 0x32 }, L2(15), 1087500 },
+	{ 1, {  1458000, HFPLL, 1, 0x36 }, L2(15), 1112500 },
+	{ 1, {  1512000, HFPLL, 1, 0x38 }, L2(15), 1125000 },
+	{ 0, { 0 } }
+};
+
+static struct acpu_level tbl_PVS2_1512MHz[] __initdata = {
+	{ 1, {   384000, PLL_8, 0, 0x00 }, L2(0),   925000 },
+	{ 1, {   486000, HFPLL, 2, 0x24 }, L2(5),   925000 },
+	{ 1, {   594000, HFPLL, 1, 0x16 }, L2(5),   925000 },
+	{ 1, {   702000, HFPLL, 1, 0x1A }, L2(5),   925000 },
+	{ 1, {   810000, HFPLL, 1, 0x1E }, L2(5),   937500 },
+	{ 1, {   918000, HFPLL, 1, 0x22 }, L2(5),   950000 },
+	{ 1, {  1026000, HFPLL, 1, 0x26 }, L2(5),   975000 },
+	{ 1, {  1134000, HFPLL, 1, 0x2A }, L2(15), 1000000 },
+	{ 1, {  1242000, HFPLL, 1, 0x2E }, L2(15), 1012500 },
+	{ 1, {  1350000, HFPLL, 1, 0x32 }, L2(15), 1037500 },
+	{ 1, {  1458000, HFPLL, 1, 0x36 }, L2(15), 1075000 },
+	{ 1, {  1512000, HFPLL, 1, 0x38 }, L2(15), 1087500 },
+	{ 0, { 0 } }
+};
+
+static struct acpu_level tbl_PVS3_1512MHz[] __initdata = {
+	{ 1, {   384000, PLL_8, 0, 0x00 }, L2(0),   900000 },
+	{ 1, {   486000, HFPLL, 2, 0x24 }, L2(5),   900000 },
+	{ 1, {   594000, HFPLL, 1, 0x16 }, L2(5),   900000 },
+	{ 1, {   702000, HFPLL, 1, 0x1A }, L2(5),   900000 },
+	{ 1, {   810000, HFPLL, 1, 0x1E }, L2(5),   900000 },
+	{ 1, {   918000, HFPLL, 1, 0x22 }, L2(5),   925000 },
+	{ 1, {  1026000, HFPLL, 1, 0x26 }, L2(5),   950000 },
+	{ 1, {  1134000, HFPLL, 1, 0x2A }, L2(15),  975000 },
+	{ 1, {  1242000, HFPLL, 1, 0x2E }, L2(15),  987500 },
+	{ 1, {  1350000, HFPLL, 1, 0x32 }, L2(15), 1000000 },
+	{ 1, {  1458000, HFPLL, 1, 0x36 }, L2(15), 1037500 },
+	{ 1, {  1512000, HFPLL, 1, 0x38 }, L2(15), 1050000 },
+	{ 0, { 0 } }
+};
+
+static struct acpu_level tbl_PVS4_1512MHz[] __initdata = {
+	{ 1, {   384000, PLL_8, 0, 0x00 }, L2(0),   875000 },
+	{ 1, {   486000, HFPLL, 2, 0x24 }, L2(5),   875000 },
+	{ 1, {   594000, HFPLL, 1, 0x16 }, L2(5),   875000 },
+	{ 1, {   702000, HFPLL, 1, 0x1A }, L2(5),   875000 },
+	{ 1, {   810000, HFPLL, 1, 0x1E }, L2(5),   887500 },
+	{ 1, {   918000, HFPLL, 1, 0x22 }, L2(5),   900000 },
+	{ 1, {  1026000, HFPLL, 1, 0x26 }, L2(5),   925000 },
+	{ 1, {  1134000, HFPLL, 1, 0x2A }, L2(15),  950000 },
+	{ 1, {  1242000, HFPLL, 1, 0x2E }, L2(15),  962500 },
+	{ 1, {  1350000, HFPLL, 1, 0x32 }, L2(15),  975000 },
+	{ 1, {  1458000, HFPLL, 1, 0x36 }, L2(15), 1000000 },
+	{ 1, {  1512000, HFPLL, 1, 0x38 }, L2(15), 1012500 },
+	{ 0, { 0 } }
+};
+
+static struct acpu_level tbl_PVS5_1512MHz[] __initdata = {
+	{ 1, {   384000, PLL_8, 0, 0x00 }, L2(0),   875000 },
+	{ 1, {   486000, HFPLL, 2, 0x24 }, L2(5),   875000 },
+	{ 1, {   594000, HFPLL, 1, 0x16 }, L2(5),   875000 },
+	{ 1, {   702000, HFPLL, 1, 0x1A }, L2(5),   875000 },
+	{ 1, {   810000, HFPLL, 1, 0x1E }, L2(5),   887500 },
+	{ 1, {   918000, HFPLL, 1, 0x22 }, L2(5),   900000 },
+	{ 1, {  1026000, HFPLL, 1, 0x26 }, L2(5),   925000 },
+	{ 1, {  1134000, HFPLL, 1, 0x2A }, L2(15),  937500 },
+	{ 1, {  1242000, HFPLL, 1, 0x2E }, L2(15),  950000 },
+	{ 1, {  1350000, HFPLL, 1, 0x32 }, L2(15),  962500 },
+	{ 1, {  1458000, HFPLL, 1, 0x36 }, L2(15),  987500 },
+	{ 1, {  1512000, HFPLL, 1, 0x38 }, L2(15), 1000000 },
+	{ 0, { 0 } }
+};
+
+static struct acpu_level tbl_PVS6_1512MHz[] __initdata = {
+	{ 1, {   384000, PLL_8, 0, 0x00 }, L2(0),   875000 },
+	{ 1, {   486000, HFPLL, 2, 0x24 }, L2(5),   875000 },
+	{ 1, {   594000, HFPLL, 1, 0x16 }, L2(5),   875000 },
+	{ 1, {   702000, HFPLL, 1, 0x1A }, L2(5),   875000 },
+	{ 1, {   810000, HFPLL, 1, 0x1E }, L2(5),   887500 },
+	{ 1, {   918000, HFPLL, 1, 0x22 }, L2(5),   900000 },
+	{ 1, {  1026000, HFPLL, 1, 0x26 }, L2(5),   925000 },
+	{ 1, {  1134000, HFPLL, 1, 0x2A }, L2(15),  937500 },
+	{ 1, {  1242000, HFPLL, 1, 0x2E }, L2(15),  950000 },
+	{ 1, {  1350000, HFPLL, 1, 0x32 }, L2(15),  962500 },
+	{ 1, {  1458000, HFPLL, 1, 0x36 }, L2(15),  975000 },
+	{ 1, {  1512000, HFPLL, 1, 0x38 }, L2(15),  987500 },
+	{ 0, { 0 } }
+};
+
 static struct acpu_level tbl_PVS0_1700MHz[] __initdata = {
 	{ 1, {   384000, PLL_8, 0, 0x00 }, L2(0),   950000 },
 	{ 1, {   486000, HFPLL, 2, 0x24 }, L2(5),   950000 },
@@ -519,6 +631,14 @@
 	[2][4] = { tbl_PVS4_2000MHz, sizeof(tbl_PVS4_2000MHz),     25000 },
 	[2][5] = { tbl_PVS5_2000MHz, sizeof(tbl_PVS5_2000MHz),     25000 },
 	[2][6] = { tbl_PVS6_2000MHz, sizeof(tbl_PVS6_2000MHz),     25000 },
+
+	[14][0] = { tbl_PVS0_1512MHz, sizeof(tbl_PVS0_1512MHz),     0 },
+	[14][1] = { tbl_PVS1_1512MHz, sizeof(tbl_PVS1_1512MHz),     25000 },
+	[14][2] = { tbl_PVS2_1512MHz, sizeof(tbl_PVS2_1512MHz),     25000 },
+	[14][3] = { tbl_PVS3_1512MHz, sizeof(tbl_PVS3_1512MHz),     25000 },
+	[14][4] = { tbl_PVS4_1512MHz, sizeof(tbl_PVS4_1512MHz),     25000 },
+	[14][5] = { tbl_PVS5_1512MHz, sizeof(tbl_PVS5_1512MHz),     25000 },
+	[14][6] = { tbl_PVS6_1512MHz, sizeof(tbl_PVS6_1512MHz),     25000 },
 };
 
 static struct acpuclk_krait_params acpuclk_8064_params __initdata = {
diff --git a/arch/arm/mach-msm/board-8064-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 f782dfe..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>
@@ -2072,7 +2073,8 @@
 {
 	msm_shared_ram_phys = MSM_SHARED_RAM_PHYS;
 	msm_map_apq8064_io();
-	if (socinfo_init() < 0)
+
+	if (IS_ERR_OR_NULL(socinfo_init()))
 		pr_err("socinfo_init() failed!\n");
 }
 
@@ -3538,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);
@@ -3582,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));
@@ -3656,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.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.c b/arch/arm/mach-msm/board-8226.c
index 2f2eb2c..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>
@@ -75,6 +76,18 @@
 	CLK_DUMMY("bus_clk",	NULL,		"msm_sdcc.2", OFF),
 	CLK_DUMMY("core_clk",	NULL,		"f9928000.spi", OFF),
 	CLK_DUMMY("iface_clk",	NULL,		"f9928000.spi", OFF),
+	CLK_DUMMY("iface_clk",		NULL, "fda64000.qcom,iommu", OFF),
+	CLK_DUMMY("core_clk",		NULL, "fda64000.qcom,iommu", OFF),
+	CLK_DUMMY("iface_clk",		NULL, "fda44000.qcom,iommu", OFF),
+	CLK_DUMMY("core_clk",		NULL, "fda44000.qcom,iommu", OFF),
+	CLK_DUMMY("iface_clk",		NULL, "fd928000.qcom,iommu", OFF),
+	CLK_DUMMY("core_clk",		NULL, "fd928000.qcom,iommu", OFF),
+	CLK_DUMMY("core_clk",		NULL, "fdb10000.qcom,iommu", OFF),
+	CLK_DUMMY("iface_clk",		NULL, "fdb10000.qcom,iommu", OFF),
+	CLK_DUMMY("alt_core_clk",	NULL, "fdb10000.qcom,iommu", OFF),
+	CLK_DUMMY("iface_clk",		NULL, "fdc84000.qcom,iommu", OFF),
+	CLK_DUMMY("alt_core_clk",	NULL, "fdc84000.qcom,iommu", OFF),
+	CLK_DUMMY("core_clk",		NULL, "fdc84000.qcom,iommu", OFF),
 };
 
 static struct clock_init_data msm_dummy_clock_init_data __initdata = {
@@ -109,14 +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.c b/arch/arm/mach-msm/board-8910.c
index 2ff4567..f779c1f 100644
--- a/arch/arm/mach-msm/board-8910.c
+++ b/arch/arm/mach-msm/board-8910.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -10,6 +10,7 @@
  * GNU General Public License for more details.
  */
 
+#include <linux/err.h>
 #include <linux/kernel.h>
 #include <linux/errno.h>
 #include <linux/platform_device.h>
@@ -86,6 +87,11 @@
 void __init msm8910_init(void)
 {
 	struct of_dev_auxdata *adata = msm8910_auxdata_lookup;
+	struct device *parent;
+
+	parent = socinfo_init();
+	if (IS_ERR_OR_NULL(parent))
+		pr_err("%s: socinfo_init() failed\n", __func__);
 
 	msm8910_init_gpiomux();
 
@@ -93,10 +99,6 @@
 		msm_clock_init(&msm8910_rumi_clock_init_data);
 	else
 		msm_clock_init(&msm8910_clock_init_data);
-
-	if (socinfo_init() < 0)
-		pr_err("%s: socinfo_init() failed\n", __func__);
-
 	of_platform_populate(NULL, of_default_bus_match_table, adata, NULL);
 }
 
diff --git a/arch/arm/mach-msm/board-8930.c b/arch/arm/mach-msm/board-8930.c
index 3785fb2..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>
@@ -1464,8 +1465,9 @@
 	msm_shared_ram_phys = MSM_SHARED_RAM_PHYS;
 	msm_map_msm8930_io();
 
-	if (socinfo_init() < 0)
+	if (IS_ERR_OR_NULL(socinfo_init()))
 		pr_err("socinfo_init() failed!\n");
+
 }
 
 static void __init msm8930_init_irq(void)
diff --git a/arch/arm/mach-msm/board-8960.c b/arch/arm/mach-msm/board-8960.c
index f64bf18..f4e7880 100644
--- a/arch/arm/mach-msm/board-8960.c
+++ b/arch/arm/mach-msm/board-8960.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011-2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2011-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -10,6 +10,7 @@
  * GNU General Public License for more details.
  *
  */
+#include <linux/err.h>
 #include <linux/kernel.h>
 #include <linux/platform_device.h>
 #include <linux/io.h>
@@ -1486,9 +1487,9 @@
 {
 	msm_shared_ram_phys = MSM_SHARED_RAM_PHYS;
 	msm_map_msm8960_io();
-
-	if (socinfo_init() < 0)
+	if (IS_ERR_OR_NULL(socinfo_init()))
 		pr_err("socinfo_init() failed!\n");
+
 }
 
 static void __init msm8960_init_irq(void)
diff --git a/arch/arm/mach-msm/board-8974.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-9625-gpiomux.c b/arch/arm/mach-msm/board-9625-gpiomux.c
index 2f75470..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
@@ -142,34 +142,6 @@
 		},
 	},
 	{
-		.gpio	= 16,		/* Sec mi2s ws */
-		.settings = {
-			[GPIOMUX_SUSPENDED] = &mi2s_suspend_cfg,
-			[GPIOMUX_ACTIVE] = &mi2s_active_cfg,
-		},
-	},
-	{
-		.gpio	= 17,		/* Sec mi2s din */
-		.settings = {
-			[GPIOMUX_SUSPENDED] = &mi2s_suspend_cfg,
-			[GPIOMUX_ACTIVE] = &mi2s_active_cfg,
-		},
-	},
-	{
-		.gpio	= 18,		/* Sec mi2s dout */
-		.settings = {
-			[GPIOMUX_SUSPENDED] = &mi2s_suspend_cfg,
-			[GPIOMUX_ACTIVE] = &mi2s_active_cfg,
-		},
-	},
-	{
-		.gpio	= 19,		/* Sec mi2s clk */
-		.settings = {
-			[GPIOMUX_SUSPENDED] = &mi2s_suspend_cfg,
-			[GPIOMUX_ACTIVE] = &mi2s_active_cfg,
-		},
-	},
-	{
 		.gpio	= 71,		/* mi2s mclk */
 		.settings = {
 			[GPIOMUX_SUSPENDED] = &mi2s_suspend_cfg,
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 43a03a0..435cc7d 100644
--- a/arch/arm/mach-msm/clock-8974.c
+++ b/arch/arm/mach-msm/clock-8974.c
@@ -662,9 +662,9 @@
 
 #define D0_ID		 1
 #define D1_ID		 2
-#define A0_ID		 3
-#define A1_ID		 4
-#define A2_ID		 5
+#define A0_ID		 4
+#define A1_ID		 5
+#define A2_ID		 6
 #define DIFF_CLK_ID	 7
 #define DIV_CLK1_ID	11
 #define DIV_CLK2_ID	12
@@ -2550,6 +2550,7 @@
 	F_MM(133330000, mmpll0,   6,   0,   0),
 	F_MM(160000000, mmpll0,   5,   0,   0),
 	F_MM(200000000, mmpll0,   4,   0,   0),
+	F_MM(240000000,  gpll0, 2.5,   0,   0),
 	F_MM(266670000, mmpll0,   3,   0,   0),
 	F_MM(320000000, mmpll0, 2.5,   0,   0),
 	F_END
@@ -5139,6 +5140,7 @@
 	/* Multimedia clocks */
 	CLK_LOOKUP("bus_clk_src", axi_clk_src.c, ""),
 	CLK_LOOKUP("bus_clk", mmss_mmssnoc_axi_clk.c, ""),
+	CLK_LOOKUP("bus_clk", mmssnoc_ahb_clk.c, ""),
 	CLK_LOOKUP("core_clk", mdss_edpaux_clk.c, "fd923400.qcom,mdss_edp"),
 	CLK_LOOKUP("pixel_clk", mdss_edppixel_clk.c, "fd923400.qcom,mdss_edp"),
 	CLK_LOOKUP("link_clk", mdss_edplink_clk.c, "fd923400.qcom,mdss_edp"),
diff --git a/arch/arm/mach-msm/clock-9625.c b/arch/arm/mach-msm/clock-9625.c
index 151f192..9f8c79b 100644
--- a/arch/arm/mach-msm/clock-9625.c
+++ b/arch/arm/mach-msm/clock-9625.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -2175,6 +2175,7 @@
 	CLK_LOOKUP("core_clk", qdss_clk.c, "fc31a000.funnel"),
 	CLK_LOOKUP("core_clk", qdss_clk.c, "fc321000.stm"),
 	CLK_LOOKUP("core_clk", qdss_clk.c, "fc332000.etm"),
+	CLK_LOOKUP("core_clk", qdss_clk.c, "fc332000.jtagmm"),
 
 	CLK_LOOKUP("core_a_clk", qdss_clk.c, "fc322000.tmc"),
 	CLK_LOOKUP("core_a_clk", qdss_clk.c, "fc318000.tpiu"),
@@ -2185,6 +2186,7 @@
 	CLK_LOOKUP("core_a_clk", qdss_clk.c, "fc31a000.funnel"),
 	CLK_LOOKUP("core_a_clk", qdss_clk.c, "fc321000.stm"),
 	CLK_LOOKUP("core_a_clk", qdss_clk.c, "fc332000.etm"),
+	CLK_LOOKUP("core_a_clk", qdss_clk.c, "fc332000.jtagmm"),
 
 };
 
diff --git a/arch/arm/mach-msm/cpuidle.c b/arch/arm/mach-msm/cpuidle.c
index dd2dc1d..2932b7e 100644
--- a/arch/arm/mach-msm/cpuidle.c
+++ b/arch/arm/mach-msm/cpuidle.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
@@ -80,8 +80,7 @@
 	cpu_pm_enter();
 #endif
 
-	pm_mode = msm_pm_idle_prepare(dev, drv, index);
-	dev->last_residency = msm_pm_idle_enter(pm_mode);
+	pm_mode = msm_pm_idle_enter(dev, drv, index);
 	for (i = 0; i < dev->state_count; i++) {
 		st_usage = &dev->states_usage[i];
 		if ((enum msm_pm_sleep_mode) cpuidle_get_statedata(st_usage)
diff --git a/arch/arm/mach-msm/devices-9615.c b/arch/arm/mach-msm/devices-9615.c
index cec57fd..15994565 100644
--- a/arch/arm/mach-msm/devices-9615.c
+++ b/arch/arm/mach-msm/devices-9615.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011-2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2011-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -11,6 +11,7 @@
  *
  */
 
+#include <linux/err.h>
 #include <linux/kernel.h>
 #include <linux/platform_device.h>
 #include <linux/irq.h>
@@ -1545,7 +1546,7 @@
 	msm_shared_ram_phys = MSM_SHARED_RAM_PHYS;
 	msm_map_msm9615_io();
 	l2x0_cache_init();
-	if (socinfo_init() < 0)
+	if (IS_ERR_OR_NULL(socinfo_init()))
 		pr_err("socinfo_init() failed!\n");
 }
 
diff --git a/arch/arm/mach-msm/devices-msm7x27a.c b/arch/arm/mach-msm/devices-msm7x27a.c
index 3c60fa6..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
@@ -2147,8 +2147,8 @@
 void __init msm_common_io_init(void)
 {
 	msm_map_common_io();
-	if (socinfo_init() < 0)
-		pr_err("%s: socinfo_init() failed!\n", __func__);
+	if (IS_ERR_OR_NULL(socinfo_init()))
+		pr_err("socinfo_init() failed!\n");
 	msm7x27x_cache_init();
 }
 
@@ -2163,8 +2163,8 @@
 {
 	msm_map_msm8625_io();
 
-	if (socinfo_init() < 0)
-		pr_err("%s: socinfo_init() failed!\n", __func__);
+	if (IS_ERR_OR_NULL(socinfo_init()))
+		pr_err("socinfo_init() failed!\n");
 	msm7x27x_cache_init();
 }
 
diff --git a/arch/arm/mach-msm/idle-v7.S b/arch/arm/mach-msm/idle-v7.S
index 9a22996..6840f1c 100644
--- a/arch/arm/mach-msm/idle-v7.S
+++ b/arch/arm/mach-msm/idle-v7.S
@@ -2,7 +2,7 @@
  * Idle processing for ARMv7-based Qualcomm SoCs.
  *
  * Copyright (C) 2007 Google, Inc.
- * Copyright (c) 2007-2009, 2011-2012 Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2007-2009, 2011-2013 The Linux Foundation. All rights reserved.
  *
  * This software is licensed under the terms of the GNU General Public
  * License version 2, as published by the Free Software Foundation, and
@@ -97,7 +97,7 @@
 	mrc     p15, 0, ip, c13, c0, 1 /* context ID */
 	stmia   r0!, {r1-r9, ip}
 
-#ifdef CONFIG_MSM_JTAG
+#if defined(CONFIG_MSM_JTAG) || defined(CONFIG_MSM_JTAG_MM)
 	bl      msm_jtag_save_state
 #endif
 
@@ -185,7 +185,7 @@
 	blxne	r1
 	dmb
 
-#ifdef CONFIG_MSM_JTAG
+#if defined(CONFIG_MSM_JTAG) || defined(CONFIG_MSM_JTAG_MM)
 	bl	msm_jtag_restore_state
 #endif
 	ldr     r0, =msm_saved_state	/* address of msm_saved_state ptr */
@@ -286,7 +286,7 @@
 	stmfd   sp!, {lr}
 	blxne	r1
 	dmb
-#ifdef CONFIG_MSM_JTAG
+#if defined(CONFIG_MSM_JTAG) || defined(CONFIG_MSM_JTAG_MM)
 	bl      msm_jtag_restore_state
 #endif
 	ldmfd   sp!, {lr}
diff --git a/arch/arm/mach-msm/include/mach/jtag.h b/arch/arm/mach-msm/include/mach/jtag.h
index 3850eff..2131be6 100644
--- a/arch/arm/mach-msm/include/mach/jtag.h
+++ b/arch/arm/mach-msm/include/mach/jtag.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -13,7 +13,7 @@
 #ifndef __MACH_JTAG_H
 #define __MACH_JTAG_H
 
-#ifdef CONFIG_MSM_JTAG
+#if defined(CONFIG_MSM_JTAG) || defined(CONFIG_MSM_JTAG_MM)
 extern void msm_jtag_save_state(void);
 extern void msm_jtag_restore_state(void);
 #else
diff --git a/arch/arm/mach-msm/include/mach/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/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/jtag-mm.c b/arch/arm/mach-msm/jtag-mm.c
new file mode 100644
index 0000000..af05995
--- /dev/null
+++ b/arch/arm/mach-msm/jtag-mm.c
@@ -0,0 +1,747 @@
+/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/err.h>
+#include <linux/slab.h>
+#include <linux/smp.h>
+#include <linux/export.h>
+#include <linux/printk.h>
+#include <linux/ratelimit.h>
+#include <linux/coresight.h>
+#include <linux/io.h>
+#include <linux/platform_device.h>
+#include <linux/bitops.h>
+#include <mach/scm.h>
+#include <mach/jtag.h>
+
+/* Coresight management registers */
+#define CORESIGHT_ITCTRL	(0xF00)
+#define CORESIGHT_CLAIMSET	(0xFA0)
+#define CORESIGHT_CLAIMCLR	(0xFA4)
+#define CORESIGHT_LAR		(0xFB0)
+#define CORESIGHT_LSR		(0xFB4)
+#define CORESIGHT_AUTHSTATUS	(0xFB8)
+#define CORESIGHT_DEVID		(0xFC8)
+#define CORESIGHT_DEVTYPE	(0xFCC)
+
+#define CORESIGHT_UNLOCK	(0xC5ACCE55)
+
+#define TIMEOUT_US		(100)
+
+#define BM(lsb, msb)		((BIT(msb) - BIT(lsb)) + BIT(msb))
+#define BMVAL(val, lsb, msb)	((val & BM(lsb, msb)) >> lsb)
+#define BVAL(val, n)		((val & BIT(n)) >> n)
+
+/* Trace registers */
+#define ETMCR			(0x000)
+#define ETMCCR			(0x004)
+#define ETMTRIGGER		(0x008)
+#define ETMASICCTLR		(0x00C)
+#define ETMSR			(0x010)
+#define ETMSCR			(0x014)
+#define ETMTSSCR		(0x018)
+#define ETMTECR2		(0x01C)
+#define ETMTEEVR		(0x020)
+#define ETMTECR1		(0x024)
+#define ETMFFLR			(0x02C)
+#define ETMVDEVR		(0x030)
+#define ETMVDCR1		(0x034)
+#define ETMVDCR3		(0x03C)
+#define ETMACVRn(n)		(0x040 + (n * 4))
+#define ETMACTRn(n)		(0x080 + (n * 4))
+#define ETMDCVRn(n)		(0x0C0 + (n * 8))
+#define ETMDCMRn(n)		(0x100 + (n * 8))
+#define ETMCNTRLDVRn(n)		(0x140 + (n * 4))
+#define ETMCNTENRn(n)		(0x150 + (n * 4))
+#define ETMCNTRLDEVRn(n)	(0x160 + (n * 4))
+#define ETMCNTVRn(n)		(0x170 + (n * 4))
+#define ETMSQ12EVR		(0x180)
+#define ETMSQ21EVR		(0x184)
+#define ETMSQ23EVR		(0x188)
+#define ETMSQ31EVR		(0x18C)
+#define ETMSQ32EVR		(0x190)
+#define ETMSQ13EVR		(0x194)
+#define ETMSQR			(0x19C)
+#define ETMEXTOUTEVRn(n)	(0x1A0 + (n * 4))
+#define ETMCIDCVRn(n)		(0x1B0 + (n * 4))
+#define ETMCIDCMR		(0x1BC)
+#define ETMIMPSPEC0		(0x1C0)
+#define ETMIMPSPEC1		(0x1C4)
+#define ETMIMPSPEC2		(0x1C8)
+#define ETMIMPSPEC3		(0x1CC)
+#define ETMIMPSPEC4		(0x1D0)
+#define ETMIMPSPEC5		(0x1D4)
+#define ETMIMPSPEC6		(0x1D8)
+#define ETMIMPSPEC7		(0x1DC)
+#define ETMSYNCFR		(0x1E0)
+#define ETMIDR			(0x1E4)
+#define ETMCCER			(0x1E8)
+#define ETMEXTINSELR		(0x1EC)
+#define ETMTESSEICR		(0x1F0)
+#define ETMEIBCR		(0x1F4)
+#define ETMTSEVR		(0x1F8)
+#define ETMAUXCR		(0x1FC)
+#define ETMTRACEIDR		(0x200)
+#define ETMIDR2			(0x208)
+#define ETMVMIDCVR		(0x240)
+#define ETMCLAIMSET		(0xFA0)
+#define ETMCLAIMCLR		(0xFA4)
+/* ETM Management registers */
+#define ETMOSLAR		(0x300)
+#define ETMOSLSR		(0x304)
+#define ETMOSSRR		(0x308)
+#define ETMPDCR			(0x310)
+#define ETMPDSR			(0x314)
+
+#define ETM_MAX_ADDR_CMP	(16)
+#define ETM_MAX_CNTR		(4)
+#define ETM_MAX_CTXID_CMP	(3)
+
+/* DBG Registers */
+#define DBGDIDR			(0x0)
+#define DBGWFAR			(0x18)
+#define DBGVCR			(0x1C)
+#define DBGDTRRXext		(0x80)
+#define DBGDSCRext		(0x88)
+#define DBGDTRTXext		(0x8C)
+#define DBGDRCR			(0x90)
+#define DBGBVRn(n)		(0x100 + (n * 4))
+#define DBGBCRn(n)		(0x140 + (n * 4))
+#define DBGWVRn(n)		(0x180 + (n * 4))
+#define DBGWCRn(n)		(0x1C0 + (n * 4))
+#define DBGPRCR			(0x310)
+#define DBGITMISCOUT		(0xEF8)
+#define DBGITMISCIN		(0xEFC)
+#define DBGCLAIMSET		(0xFA0)
+#define DBGCLAIMCLR		(0xFA4)
+
+#define DBGDSCR_MASK		(0x6C30FC3C)
+
+#define MAX_DBG_STATE_SIZE	(90)
+#define MAX_ETM_STATE_SIZE	(78)
+
+#define TZ_DBG_ETM_FEAT_ID	(0x8)
+#define TZ_DBG_ETM_VER		(0x400000)
+
+#define ARCH_V3_5		(0x25)
+#define ARM_DEBUG_ARCH_V7B	(0x3)
+
+#define etm_write(etm, val, off)	\
+			__raw_writel(val, etm->base + off)
+#define etm_read(etm, off)	\
+			__raw_readl(etm->base + off)
+
+#define dbg_write(dbg, val, off)	\
+			__raw_writel(val, dbg->base + off)
+#define dbg_read(dbg, off)	\
+			__raw_readl(dbg->base + off)
+
+#define ETM_LOCK(base)						\
+do {									\
+	/* recommended by spec to ensure ETM writes are committed prior
+	 * to resuming execution
+	 */								\
+	mb();								\
+	etm_write(base, 0x0, CORESIGHT_LAR);			\
+} while (0)
+
+#define ETM_UNLOCK(base)						\
+do {									\
+	etm_write(base, CORESIGHT_UNLOCK, CORESIGHT_LAR);	\
+	/* ensure unlock and any pending writes are committed prior to
+	 * programming ETM registers
+	 */								\
+	mb();								\
+} while (0)
+
+#define DBG_LOCK(base)						\
+do {									\
+	/* recommended by spec to ensure ETM writes are committed prior
+	 * to resuming execution
+	 */								\
+	mb();								\
+	dbg_write(base, 0x0, CORESIGHT_LAR);			\
+} while (0)
+
+#define DBG_UNLOCK(base)						\
+do {									\
+	dbg_write(base, CORESIGHT_UNLOCK, CORESIGHT_LAR);	\
+	/* ensure unlock and any pending writes are committed prior to
+	 * programming ETM registers
+	 */								\
+	mb();								\
+} while (0)
+
+uint32_t msm_jtag_save_cntr[NR_CPUS];
+uint32_t msm_jtag_restore_cntr[NR_CPUS];
+
+struct dbg_cpu_ctx {
+	void __iomem		*base;
+	uint32_t		*state;
+};
+
+struct dbg_ctx {
+	uint8_t			arch;
+	uint8_t			nr_wp;
+	uint8_t			nr_bp;
+	uint8_t			nr_ctx_cmp;
+	struct dbg_cpu_ctx	*cpu_ctx[NR_CPUS];
+	bool			save_restore_enabled[NR_CPUS];
+};
+static struct dbg_ctx dbg;
+
+struct etm_cpu_ctx {
+	void __iomem		*base;
+	struct device		*dev;
+	uint32_t		*state;
+};
+
+struct etm_ctx {
+	uint8_t			arch;
+	uint8_t			nr_addr_cmp;
+	uint8_t			nr_data_cmp;
+	uint8_t			nr_cntr;
+	uint8_t			nr_ext_inp;
+	uint8_t			nr_ext_out;
+	uint8_t			nr_ctxid_cmp;
+	struct etm_cpu_ctx	*cpu_ctx[NR_CPUS];
+	bool			save_restore_enabled[NR_CPUS];
+};
+
+static struct etm_ctx etm;
+
+static struct clk *clock[NR_CPUS];
+
+static void etm_set_pwrdwn(struct etm_cpu_ctx *etmdata)
+{
+	uint32_t etmcr;
+
+	/* ensure all writes are complete before setting pwrdwn */
+	mb();
+	etmcr = etm_read(etmdata, ETMCR);
+	etmcr |= BIT(0);
+	etm_write(etmdata, etmcr, ETMCR);
+}
+
+static void etm_clr_pwrdwn(struct etm_cpu_ctx *etmdata)
+{
+	uint32_t etmcr;
+
+	etmcr = etm_read(etmdata, ETMCR);
+	etmcr &= ~BIT(0);
+	etm_write(etmdata, etmcr, ETMCR);
+	/* ensure pwrup completes before subsequent register accesses */
+	mb();
+}
+
+static void etm_set_prog(struct etm_cpu_ctx *etmdata)
+{
+	uint32_t etmcr;
+	int count;
+
+	etmcr = etm_read(etmdata, ETMCR);
+	etmcr |= BIT(10);
+	etm_write(etmdata, etmcr, ETMCR);
+	for (count = TIMEOUT_US; BVAL(etm_read(etmdata, ETMSR), 1) != 1
+				&& count > 0; count--)
+		udelay(1);
+	WARN(count == 0, "timeout while setting prog bit, ETMSR: %#x\n",
+	     etm_read(etmdata, ETMSR));
+}
+
+static inline void etm_save_state(struct etm_cpu_ctx *etmdata)
+{
+	int i, j;
+
+	i = 0;
+	ETM_UNLOCK(etmdata);
+
+	switch (etm.arch) {
+	case ETM_ARCH_V3_5:
+		etmdata->state[i++] = etm_read(etmdata, ETMTRIGGER);
+		etmdata->state[i++] = etm_read(etmdata, ETMASICCTLR);
+		etmdata->state[i++] = etm_read(etmdata, ETMSR);
+		etmdata->state[i++] = etm_read(etmdata, ETMTSSCR);
+		etmdata->state[i++] = etm_read(etmdata, ETMTECR2);
+		etmdata->state[i++] = etm_read(etmdata, ETMTEEVR);
+		etmdata->state[i++] = etm_read(etmdata, ETMTECR1);
+		etmdata->state[i++] = etm_read(etmdata, ETMFFLR);
+		etmdata->state[i++] = etm_read(etmdata, ETMVDEVR);
+		etmdata->state[i++] = etm_read(etmdata, ETMVDCR1);
+		etmdata->state[i++] = etm_read(etmdata, ETMVDCR3);
+		for (j = 0; j < etm.nr_addr_cmp; j++) {
+			etmdata->state[i++] = etm_read(etmdata,
+								ETMACVRn(j));
+			etmdata->state[i++] = etm_read(etmdata,
+								ETMACTRn(j));
+		}
+		for (j = 0; j < etm.nr_data_cmp; j++) {
+			etmdata->state[i++] = etm_read(etmdata,
+								ETMDCVRn(j));
+			etmdata->state[i++] = etm_read(etmdata,
+								ETMDCMRn(j));
+		}
+		for (j = 0; j < etm.nr_cntr; j++) {
+			etmdata->state[i++] = etm_read(etmdata,
+							ETMCNTRLDVRn(j));
+			etmdata->state[i++] = etm_read(etmdata,
+							ETMCNTENRn(j));
+			etmdata->state[i++] = etm_read(etmdata,
+							ETMCNTRLDEVRn(j));
+			etmdata->state[i++] = etm_read(etmdata,
+							ETMCNTVRn(j));
+		}
+		etmdata->state[i++] = etm_read(etmdata, ETMSQ12EVR);
+		etmdata->state[i++] = etm_read(etmdata, ETMSQ21EVR);
+		etmdata->state[i++] = etm_read(etmdata, ETMSQ23EVR);
+		etmdata->state[i++] = etm_read(etmdata, ETMSQ31EVR);
+		etmdata->state[i++] = etm_read(etmdata, ETMSQ32EVR);
+		etmdata->state[i++] = etm_read(etmdata, ETMSQ13EVR);
+		etmdata->state[i++] = etm_read(etmdata, ETMSQR);
+		for (j = 0; j < etm.nr_ext_out; j++)
+			etmdata->state[i++] = etm_read(etmdata,
+							ETMEXTOUTEVRn(j));
+		for (j = 0; j < etm.nr_ctxid_cmp; j++)
+			etmdata->state[i++] = etm_read(etmdata,
+							ETMCIDCVRn(j));
+		etmdata->state[i++] = etm_read(etmdata, ETMCIDCMR);
+		etmdata->state[i++] = etm_read(etmdata, ETMSYNCFR);
+		etmdata->state[i++] = etm_read(etmdata, ETMEXTINSELR);
+		etmdata->state[i++] = etm_read(etmdata, ETMTSEVR);
+		etmdata->state[i++] = etm_read(etmdata, ETMAUXCR);
+		etmdata->state[i++] = etm_read(etmdata, ETMTRACEIDR);
+		etmdata->state[i++] = etm_read(etmdata, ETMVMIDCVR);
+		etmdata->state[i++] = etm_read(etmdata, ETMCLAIMCLR);
+		etmdata->state[i++] = etm_read(etmdata, ETMCR);
+		break;
+	default:
+		pr_err_ratelimited("unsupported etm arch %d in %s\n", etm.arch,
+								__func__);
+	}
+
+	ETM_LOCK(etmdata);
+}
+
+static inline void etm_restore_state(struct etm_cpu_ctx *etmdata)
+{
+	int i, j;
+
+	i = 0;
+	ETM_UNLOCK(etmdata);
+
+	switch (etm.arch) {
+	case ETM_ARCH_V3_5:
+		etm_clr_pwrdwn(etmdata);
+		etm_write(etmdata, etmdata->state[i++], ETMTRIGGER);
+		etm_write(etmdata, etmdata->state[i++], ETMASICCTLR);
+		etm_write(etmdata, etmdata->state[i++], ETMSR);
+		etm_write(etmdata, etmdata->state[i++], ETMTSSCR);
+		etm_write(etmdata, etmdata->state[i++], ETMTECR2);
+		etm_write(etmdata, etmdata->state[i++], ETMTEEVR);
+		etm_write(etmdata, etmdata->state[i++], ETMTECR1);
+		etm_write(etmdata, etmdata->state[i++], ETMFFLR);
+		etm_write(etmdata, etmdata->state[i++], ETMVDEVR);
+		etm_write(etmdata, etmdata->state[i++], ETMVDCR1);
+		etm_write(etmdata, etmdata->state[i++], ETMVDCR3);
+		for (j = 0; j < etm.nr_addr_cmp; j++) {
+			etm_write(etmdata, etmdata->state[i++],
+								ETMACVRn(j));
+			etm_write(etmdata, etmdata->state[i++],
+								ETMACTRn(j));
+		}
+		for (j = 0; j < etm.nr_data_cmp; j++) {
+			etm_write(etmdata, etmdata->state[i++],
+								ETMDCVRn(j));
+			etm_write(etmdata, etmdata->state[i++],
+								ETMDCMRn(j));
+		}
+		for (j = 0; j < etm.nr_cntr; j++) {
+			etm_write(etmdata, etmdata->state[i++],
+							ETMCNTRLDVRn(j));
+			etm_write(etmdata, etmdata->state[i++],
+							ETMCNTENRn(j));
+			etm_write(etmdata, etmdata->state[i++],
+							ETMCNTRLDEVRn(j));
+			etm_write(etmdata, etmdata->state[i++],
+							ETMCNTVRn(j));
+		}
+		etm_write(etmdata, etmdata->state[i++], ETMSQ12EVR);
+		etm_write(etmdata, etmdata->state[i++], ETMSQ21EVR);
+		etm_write(etmdata, etmdata->state[i++], ETMSQ23EVR);
+		etm_write(etmdata, etmdata->state[i++], ETMSQ31EVR);
+		etm_write(etmdata, etmdata->state[i++], ETMSQ32EVR);
+		etm_write(etmdata, etmdata->state[i++], ETMSQ13EVR);
+		etm_write(etmdata, etmdata->state[i++], ETMSQR);
+		for (j = 0; j < etm.nr_ext_out; j++)
+			etm_write(etmdata, etmdata->state[i++],
+							ETMEXTOUTEVRn(j));
+		for (j = 0; j < etm.nr_ctxid_cmp; j++)
+			etm_write(etmdata, etmdata->state[i++],
+							ETMCIDCVRn(j));
+		etm_write(etmdata, etmdata->state[i++], ETMCIDCMR);
+		etm_write(etmdata, etmdata->state[i++], ETMSYNCFR);
+		etm_write(etmdata, etmdata->state[i++], ETMEXTINSELR);
+		etm_write(etmdata, etmdata->state[i++], ETMTSEVR);
+		etm_write(etmdata, etmdata->state[i++], ETMAUXCR);
+		etm_write(etmdata, etmdata->state[i++], ETMTRACEIDR);
+		etm_write(etmdata, etmdata->state[i++], ETMVMIDCVR);
+		etm_write(etmdata, etmdata->state[i++], ETMCLAIMSET);
+		/*
+		 * Set ETMCR at last as we dont know the saved status of pwrdwn
+		 * bit
+		 */
+		etm_write(etmdata, etmdata->state[i++], ETMCR);
+		break;
+	default:
+		pr_err_ratelimited("unsupported etm arch %d in %s\n", etm.arch,
+								__func__);
+	}
+
+	ETM_LOCK(etmdata);
+}
+
+static inline void dbg_save_state(struct dbg_cpu_ctx *dbgdata)
+{
+	int i, j;
+
+	i = 0;
+	DBG_UNLOCK(dbgdata);
+
+	dbgdata->state[i++] =  dbg_read(dbgdata, DBGWFAR);
+	dbgdata->state[i++] =  dbg_read(dbgdata, DBGVCR);
+	for (j = 0; j < dbg.nr_bp; j++) {
+		dbgdata->state[i++] =  dbg_read(dbgdata, DBGBVRn(j));
+		dbgdata->state[i++] =  dbg_read(dbgdata, DBGBCRn(j));
+	}
+	for (j = 0; j < dbg.nr_wp; j++) {
+		dbgdata->state[i++] =  dbg_read(dbgdata, DBGWVRn(j));
+		dbgdata->state[i++] =  dbg_read(dbgdata, DBGWCRn(j));
+	}
+	dbgdata->state[i++] =  dbg_read(dbgdata, DBGPRCR);
+	dbgdata->state[i++] =  dbg_read(dbgdata, DBGCLAIMSET);
+	dbgdata->state[i++] =  dbg_read(dbgdata, DBGCLAIMCLR);
+	dbgdata->state[i++] =  dbg_read(dbgdata, DBGDTRTXext);
+	dbgdata->state[i++] =  dbg_read(dbgdata, DBGDTRRXext);
+	dbgdata->state[i++] =  dbg_read(dbgdata, DBGDSCRext);
+
+	DBG_LOCK(dbgdata);
+}
+
+static inline void dbg_restore_state(struct dbg_cpu_ctx *dbgdata)
+{
+	int i, j;
+
+	i = 0;
+	DBG_UNLOCK(dbgdata);
+
+	dbg_write(dbgdata, dbgdata->state[i++], DBGWFAR);
+	dbg_write(dbgdata, dbgdata->state[i++], DBGVCR);
+	for (j = 0; j < dbg.nr_bp; j++) {
+		dbg_write(dbgdata, dbgdata->state[i++], DBGBVRn(j));
+		dbg_write(dbgdata, dbgdata->state[i++], DBGBCRn(j));
+	}
+	for (j = 0; j < dbg.nr_wp; j++) {
+		dbg_write(dbgdata, dbgdata->state[i++], DBGWVRn(j));
+		dbg_write(dbgdata, dbgdata->state[i++], DBGWCRn(j));
+	}
+	dbg_write(dbgdata, dbgdata->state[i++], DBGPRCR);
+	dbg_write(dbgdata, dbgdata->state[i++], DBGCLAIMSET);
+	dbg_write(dbgdata, dbgdata->state[i++], DBGCLAIMCLR);
+	dbg_write(dbgdata, dbgdata->state[i++], DBGDTRTXext);
+	dbg_write(dbgdata, dbgdata->state[i++], DBGDTRRXext);
+	dbg_write(dbgdata, dbgdata->state[i++] & DBGDSCR_MASK,
+								DBGDSCRext);
+
+	DBG_LOCK(dbgdata);
+}
+
+void msm_jtag_save_state(void)
+{
+	int cpu;
+
+	cpu = raw_smp_processor_id();
+
+	msm_jtag_save_cntr[cpu]++;
+	/* ensure counter is updated before moving forward */
+	mb();
+
+	if (dbg.save_restore_enabled[cpu])
+		dbg_save_state(dbg.cpu_ctx[cpu]);
+	if (etm.save_restore_enabled[cpu])
+		etm_save_state(etm.cpu_ctx[cpu]);
+}
+EXPORT_SYMBOL(msm_jtag_save_state);
+
+void msm_jtag_restore_state(void)
+{
+	int cpu;
+
+	cpu = raw_smp_processor_id();
+
+	/* Attempt restore only if save has been done. If power collapse
+	 * is disabled, hotplug off of non-boot core will result in WFI
+	 * and hence msm_jtag_save_state will not occur. Subsequently,
+	 * during hotplug on of non-boot core when msm_jtag_restore_state
+	 * is called via msm_platform_secondary_init, this check will help
+	 * bail us out without restoring.
+	 */
+	if (msm_jtag_save_cntr[cpu] == msm_jtag_restore_cntr[cpu])
+		return;
+	else if (msm_jtag_save_cntr[cpu] != msm_jtag_restore_cntr[cpu] + 1)
+		pr_err_ratelimited("jtag imbalance, save:%lu, restore:%lu\n",
+				   (unsigned long)msm_jtag_save_cntr[cpu],
+				   (unsigned long)msm_jtag_restore_cntr[cpu]);
+
+	msm_jtag_restore_cntr[cpu]++;
+	/* ensure counter is updated before moving forward */
+	mb();
+
+	if (dbg.save_restore_enabled[cpu])
+		dbg_restore_state(dbg.cpu_ctx[cpu]);
+	if (etm.save_restore_enabled[cpu])
+		etm_restore_state(etm.cpu_ctx[cpu]);
+}
+EXPORT_SYMBOL(msm_jtag_restore_state);
+
+static inline bool etm_arch_supported(uint8_t arch)
+{
+	switch (arch) {
+	case ETM_ARCH_V3_5:
+		break;
+	default:
+		return false;
+	}
+	return true;
+}
+
+static void __devinit etm_init_arch_data(void *info)
+{
+	uint32_t etmidr;
+	uint32_t etmccr;
+	struct etm_cpu_ctx  *etmdata = info;
+
+	/*
+	 * Clear power down bit since when this bit is set writes to
+	 * certain registers might be ignored.
+	 */
+	ETM_UNLOCK(etmdata);
+
+	etm_clr_pwrdwn(etmdata);
+	/* Set prog bit. It will be set from reset but this is included to
+	 * ensure it is set
+	 */
+	etm_set_prog(etmdata);
+
+	/* find all capabilities */
+	etmidr = etm_read(etmdata, ETMIDR);
+	etm.arch = BMVAL(etmidr, 4, 11);
+
+	etmccr = etm_read(etmdata, ETMCCR);
+	etm.nr_addr_cmp = BMVAL(etmccr, 0, 3) * 2;
+	etm.nr_data_cmp = BMVAL(etmccr, 4, 7);
+	etm.nr_cntr = BMVAL(etmccr, 13, 15);
+	etm.nr_ext_inp = BMVAL(etmccr, 17, 19);
+	etm.nr_ext_out = BMVAL(etmccr, 20, 22);
+	etm.nr_ctxid_cmp = BMVAL(etmccr, 24, 25);
+
+	etm_set_pwrdwn(etmdata);
+
+	ETM_LOCK(etmdata);
+}
+
+static int __devinit jtag_mm_etm_probe(struct platform_device *pdev,
+								uint32_t cpu)
+{
+	struct etm_cpu_ctx *etmdata;
+	struct resource *res;
+	struct device *dev = &pdev->dev;
+
+	/* Allocate memory per cpu */
+	etmdata = devm_kzalloc(dev, sizeof(struct etm_cpu_ctx), GFP_KERNEL);
+	if (!etmdata)
+		return -ENOMEM;
+
+	etm.cpu_ctx[cpu] = etmdata;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+
+	etmdata->base = devm_ioremap(dev, res->start, resource_size(res));
+	if (!etmdata->base)
+		return -EINVAL;
+
+	/* Allocate etm state save space per core */
+	etmdata->state = devm_kzalloc(dev,
+			(MAX_ETM_STATE_SIZE * sizeof(uint32_t)), GFP_KERNEL);
+	if (!etmdata->state)
+		return -ENOMEM;
+
+	smp_call_function_single(0, etm_init_arch_data, etmdata, 1);
+
+	if (etm_arch_supported(etm.arch)) {
+		if (scm_get_feat_version(TZ_DBG_ETM_FEAT_ID) < TZ_DBG_ETM_VER)
+			etm.save_restore_enabled[cpu] = true;
+		else
+			pr_info("etm save-restore supported by TZ\n");
+	} else
+		pr_info("etm arch %u not supported\n", etm.arch);
+	return 0;
+}
+
+static inline bool dbg_arch_supported(uint8_t arch)
+{
+	switch (arch) {
+	case ARM_DEBUG_ARCH_V7B:
+		break;
+	default:
+		return false;
+	}
+	return true;
+}
+
+static void __devinit dbg_init_arch_data(void *info)
+{
+	uint32_t dbgdidr;
+	struct dbg_cpu_ctx *dbgdata = info;
+
+	/* This will run on core0 so use it to populate parameters */
+	dbgdidr = dbg_read(dbgdata, DBGDIDR);
+	dbg.arch = BMVAL(dbgdidr, 16, 19);
+	dbg.nr_ctx_cmp = BMVAL(dbgdidr, 20, 23) + 1;
+	dbg.nr_bp = BMVAL(dbgdidr, 24, 27) + 1;
+	dbg.nr_wp = BMVAL(dbgdidr, 28, 31) + 1;
+}
+
+
+
+static int __devinit jtag_mm_dbg_probe(struct platform_device *pdev,
+								uint32_t cpu)
+{
+	struct dbg_cpu_ctx *dbgdata;
+	struct resource *res;
+	struct device *dev = &pdev->dev;
+
+	/* Allocate memory per cpu */
+	dbgdata = devm_kzalloc(dev, sizeof(struct dbg_cpu_ctx), GFP_KERNEL);
+	if (!dbgdata)
+		return -ENOMEM;
+
+	dbg.cpu_ctx[cpu] = dbgdata;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+
+	dbgdata->base = devm_ioremap(dev, res->start, resource_size(res));
+	if (!dbgdata->base)
+		return -EINVAL;
+
+	/* Allocate etm state save space per core */
+	dbgdata->state = devm_kzalloc(dev,
+			(MAX_DBG_STATE_SIZE * sizeof(uint32_t)), GFP_KERNEL);
+	if (!dbgdata->state)
+		return -ENOMEM;
+
+	smp_call_function_single(0, dbg_init_arch_data, dbgdata, 1);
+
+	if (dbg_arch_supported(dbg.arch)) {
+		if (scm_get_feat_version(TZ_DBG_ETM_FEAT_ID) < TZ_DBG_ETM_VER)
+			dbg.save_restore_enabled[cpu] = true;
+		else
+			pr_info("dbg save-restore supported by TZ\n");
+	} else
+		pr_info("dbg arch %u not supported\n", dbg.arch);
+	return 0;
+}
+
+static int __devinit jtag_mm_probe(struct platform_device *pdev)
+{
+	int etm_ret, dbg_ret, ret;
+	static uint32_t cpu;
+	static uint32_t count;
+	struct device *dev = &pdev->dev;
+
+	cpu = count;
+	count++;
+
+	clock[cpu] = devm_clk_get(dev, "core_clk");
+	if (IS_ERR(clock[cpu])) {
+		ret = PTR_ERR(clock[cpu]);
+		return ret;
+	}
+
+	ret = clk_set_rate(clock[cpu], CORESIGHT_CLK_RATE_TRACE);
+	if (ret)
+		return ret;
+
+	ret = clk_prepare_enable(clock[cpu]);
+	if (ret)
+		return ret;
+
+	platform_set_drvdata(pdev, clock[cpu]);
+
+	etm_ret  = jtag_mm_etm_probe(pdev, cpu);
+
+	dbg_ret = jtag_mm_dbg_probe(pdev, cpu);
+
+	/* The probe succeeds even when only one of the etm and dbg probes
+	 * succeeds. This allows us to save-restore etm and dbg registers
+	 * independently.
+	 */
+	if (etm_ret && dbg_ret) {
+		clk_disable_unprepare(clock[cpu]);
+		ret = etm_ret;
+	} else
+		ret = 0;
+	return ret;
+}
+
+static int __devexit jtag_mm_remove(struct platform_device *pdev)
+{
+	struct clk *clock = platform_get_drvdata(pdev);
+
+	clk_disable_unprepare(clock);
+	return 0;
+}
+
+static struct of_device_id msm_qdss_mm_match[] = {
+	{ .compatible = "qcom,jtag-mm"},
+	{}
+};
+
+static struct platform_driver jtag_mm_driver = {
+	.probe          = jtag_mm_probe,
+	.remove         = __devexit_p(jtag_mm_remove),
+	.driver         = {
+		.name   = "msm-jtag-mm",
+		.owner	= THIS_MODULE,
+		.of_match_table	= msm_qdss_mm_match,
+		},
+};
+
+static int __init jtag_mm_init(void)
+{
+	return platform_driver_register(&jtag_mm_driver);
+}
+module_init(jtag_mm_init);
+
+static void __exit jtag_mm_exit(void)
+{
+	platform_driver_unregister(&jtag_mm_driver);
+}
+module_exit(jtag_mm_exit);
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("Coresight debug and ETM save-restore driver");
diff --git a/arch/arm/mach-msm/kernel_test_service_v01.c b/arch/arm/mach-msm/kernel_test_service_v01.c
new file mode 100644
index 0000000..498e046
--- /dev/null
+++ b/arch/arm/mach-msm/kernel_test_service_v01.c
@@ -0,0 +1,254 @@
+/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/qmi_encdec.h>
+
+#include <mach/msm_qmi_interface.h>
+
+#include "kernel_test_service_v01.h"
+
+#define PING_REQ1_TLV_TYPE 0x1
+#define PING_RESP1_TLV_TYPE 0x2
+#define PING_OPT1_TLV_TYPE 0x10
+#define PING_OPT2_TLV_TYPE 0x11
+
+#define DATA_REQ1_TLV_TYPE 0x1
+#define DATA_RESP1_TLV_TYPE 0x2
+#define DATA_OPT1_TLV_TYPE 0x10
+#define DATA_OPT2_TLV_TYPE 0x11
+
+static struct elem_info test_name_type_v01_ei[] = {
+	{
+		.data_type      = QMI_DATA_LEN,
+		.elem_len	= 1,
+		.elem_size      = sizeof(uint8_t),
+		.is_array	= NO_ARRAY,
+		.tlv_type	= QMI_COMMON_TLV_TYPE,
+		.offset		= offsetof(struct test_name_type_v01,
+					   name_len),
+	},
+	{
+		.data_type      = QMI_UNSIGNED_1_BYTE,
+		.elem_len       = TEST_MAX_NAME_SIZE_V01,
+		.elem_size      = sizeof(char),
+		.is_array       = VAR_LEN_ARRAY,
+		.tlv_type       = QMI_COMMON_TLV_TYPE,
+		.offset         = offsetof(struct test_name_type_v01,
+					   name),
+	},
+	{
+		.data_type      = QMI_EOTI,
+		.is_array       = NO_ARRAY,
+		.tlv_type       = QMI_COMMON_TLV_TYPE,
+	},
+};
+
+struct elem_info test_ping_req_msg_v01_ei[] = {
+	{
+		.data_type      = QMI_UNSIGNED_1_BYTE,
+		.elem_len       = 4,
+		.elem_size      = sizeof(char),
+		.is_array       = STATIC_ARRAY,
+		.tlv_type       = PING_REQ1_TLV_TYPE,
+		.offset         = offsetof(struct test_ping_req_msg_v01,
+					   ping),
+	},
+	{
+		.data_type      = QMI_OPT_FLAG,
+		.elem_len       = 1,
+		.elem_size      = sizeof(uint8_t),
+		.is_array       = NO_ARRAY,
+		.tlv_type       = PING_OPT1_TLV_TYPE,
+		.offset         = offsetof(struct test_ping_req_msg_v01,
+					   client_name_valid),
+	},
+	{
+		.data_type      = QMI_STRUCT,
+		.elem_len       = 1,
+		.elem_size      = sizeof(struct test_name_type_v01),
+		.is_array       = NO_ARRAY,
+		.tlv_type       = PING_OPT1_TLV_TYPE,
+		.offset         = offsetof(struct test_ping_req_msg_v01,
+					   client_name),
+		.ei_array       = test_name_type_v01_ei,
+	},
+	{
+		.data_type      = QMI_EOTI,
+		.is_array       = NO_ARRAY,
+		.tlv_type       = QMI_COMMON_TLV_TYPE,
+	},
+};
+
+struct elem_info test_ping_resp_msg_v01_ei[] = {
+	{
+		.data_type      = QMI_STRUCT,
+		.elem_len       = 1,
+		.elem_size      = sizeof(struct qmi_response_type_v01),
+		.is_array       = NO_ARRAY,
+		.tlv_type       = PING_RESP1_TLV_TYPE,
+		.offset         = offsetof(struct test_ping_resp_msg_v01,
+					   resp),
+		.ei_array       = get_qmi_response_type_v01_ei(),
+	},
+	{
+		.data_type      = QMI_OPT_FLAG,
+		.elem_len       = 1,
+		.elem_size      = sizeof(uint8_t),
+		.is_array       = NO_ARRAY,
+		.tlv_type       = PING_OPT1_TLV_TYPE,
+		.offset         = offsetof(struct test_ping_resp_msg_v01,
+					   pong_valid),
+	},
+	{
+		.data_type      = QMI_UNSIGNED_1_BYTE,
+		.elem_len       = 4,
+		.elem_size      = sizeof(char),
+		.is_array       = STATIC_ARRAY,
+		.tlv_type       = PING_OPT1_TLV_TYPE,
+		.offset         = offsetof(struct test_ping_resp_msg_v01,
+					   pong),
+	},
+	{
+		.data_type      = QMI_OPT_FLAG,
+		.elem_len       = 1,
+		.elem_size      = sizeof(uint8_t),
+		.is_array       = NO_ARRAY,
+		.tlv_type       = PING_OPT2_TLV_TYPE,
+		.offset         = offsetof(struct test_ping_resp_msg_v01,
+					   service_name_valid),
+	},
+	{
+		.data_type      = QMI_STRUCT,
+		.elem_len       = 1,
+		.elem_size      = sizeof(struct test_name_type_v01),
+		.is_array       = NO_ARRAY,
+		.tlv_type       = PING_OPT2_TLV_TYPE,
+		.offset         = offsetof(struct test_ping_resp_msg_v01,
+					   service_name),
+		.ei_array       = test_name_type_v01_ei,
+	},
+	{
+		.data_type      = QMI_EOTI,
+		.is_array       = NO_ARRAY,
+		.tlv_type       = QMI_COMMON_TLV_TYPE,
+	},
+};
+
+struct elem_info test_data_req_msg_v01_ei[] = {
+	{
+		.data_type      = QMI_DATA_LEN,
+		.elem_len       = 1,
+		.elem_size      = sizeof(uint32_t),
+		.is_array       = NO_ARRAY,
+		.tlv_type       = DATA_REQ1_TLV_TYPE,
+		.offset         = offsetof(struct test_data_req_msg_v01,
+					   data_len),
+	},
+	{
+		.data_type      = QMI_UNSIGNED_1_BYTE,
+		.elem_len       = TEST_MED_DATA_SIZE_V01,
+		.elem_size      = sizeof(uint8_t),
+		.is_array       = VAR_LEN_ARRAY,
+		.tlv_type       = DATA_REQ1_TLV_TYPE,
+		.offset         = offsetof(struct test_data_req_msg_v01,
+					   data),
+	},
+	{
+		.data_type      = QMI_OPT_FLAG,
+		.elem_len       = 1,
+		.elem_size      = sizeof(uint8_t),
+		.is_array       = NO_ARRAY,
+		.tlv_type       = DATA_OPT1_TLV_TYPE,
+		.offset         = offsetof(struct test_data_req_msg_v01,
+					   client_name_valid),
+	},
+	{
+		.data_type      = QMI_STRUCT,
+		.elem_len       = 1,
+		.elem_size      = sizeof(struct test_name_type_v01),
+		.is_array       = NO_ARRAY,
+		.tlv_type       = DATA_OPT1_TLV_TYPE,
+		.offset         = offsetof(struct test_data_req_msg_v01,
+					   client_name),
+		.ei_array       = test_name_type_v01_ei,
+	},
+	{
+		.data_type      = QMI_EOTI,
+		.is_array       = NO_ARRAY,
+		.tlv_type       = QMI_COMMON_TLV_TYPE,
+	},
+};
+
+struct elem_info test_data_resp_msg_v01_ei[] = {
+	{
+		.data_type      = QMI_STRUCT,
+		.elem_len       = 1,
+		.elem_size      = sizeof(struct qmi_response_type_v01),
+		.is_array       = NO_ARRAY,
+		.tlv_type       = DATA_RESP1_TLV_TYPE,
+		.offset         = offsetof(struct test_data_resp_msg_v01,
+					   resp),
+		.ei_array       = get_qmi_response_type_v01_ei(),
+	},
+	{
+		.data_type      = QMI_OPT_FLAG,
+		.elem_len       = 1,
+		.elem_size      = sizeof(uint8_t),
+		.is_array       = NO_ARRAY,
+		.tlv_type       = DATA_OPT1_TLV_TYPE,
+		.offset         = offsetof(struct test_data_resp_msg_v01,
+					   data_valid),
+	},
+	{
+		.data_type      = QMI_DATA_LEN,
+		.elem_len       = 1,
+		.elem_size      = sizeof(uint32_t),
+		.is_array       = NO_ARRAY,
+		.tlv_type       = DATA_OPT1_TLV_TYPE,
+		.offset         = offsetof(struct test_data_resp_msg_v01,
+					   data_len),
+	},
+	{
+		.data_type      = QMI_UNSIGNED_1_BYTE,
+		.elem_len       = TEST_MED_DATA_SIZE_V01,
+		.elem_size      = sizeof(uint8_t),
+		.is_array       = VAR_LEN_ARRAY,
+		.tlv_type       = DATA_OPT1_TLV_TYPE,
+		.offset         = offsetof(struct test_data_resp_msg_v01,
+					   data),
+	},
+	{
+		.data_type      = QMI_OPT_FLAG,
+		.elem_len       = 1,
+		.elem_size      = sizeof(uint8_t),
+		.is_array       = NO_ARRAY,
+		.tlv_type       = DATA_OPT2_TLV_TYPE,
+		.offset         = offsetof(struct test_data_resp_msg_v01,
+					   service_name_valid),
+	},
+	{
+		.data_type      = QMI_STRUCT,
+		.elem_len       = 1,
+		.elem_size      = sizeof(struct test_name_type_v01),
+		.is_array       = NO_ARRAY,
+		.tlv_type       = DATA_OPT2_TLV_TYPE,
+		.offset         = offsetof(struct test_data_resp_msg_v01,
+					   service_name),
+		.ei_array       = test_name_type_v01_ei,
+	},
+	{
+		.data_type      = QMI_EOTI,
+		.is_array       = NO_ARRAY,
+		.tlv_type       = QMI_COMMON_TLV_TYPE,
+	},
+};
diff --git a/arch/arm/mach-msm/kernel_test_service_v01.h b/arch/arm/mach-msm/kernel_test_service_v01.h
new file mode 100644
index 0000000..79c1845
--- /dev/null
+++ b/arch/arm/mach-msm/kernel_test_service_v01.h
@@ -0,0 +1,73 @@
+/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+#ifndef MSM_QMI_TEST_SERVICE_V01_H
+#define MSM_QMI_TEST_SERVICE_V01_H
+
+#include <mach/msm_qmi_interface.h>
+
+#define TEST_MED_DATA_SIZE_V01 8192
+#define TEST_MAX_NAME_SIZE_V01 255
+
+#define TEST_PING_REQ_MSG_ID_V01 0x20
+#define TEST_DATA_REQ_MSG_ID_V01 0x21
+
+#define TEST_PING_REQ_MAX_MSG_LEN_V01 266
+#define TEST_DATA_REQ_MAX_MSG_LEN_V01 8456
+
+struct test_name_type_v01 {
+	uint32_t name_len;
+	char name[TEST_MAX_NAME_SIZE_V01];
+};
+
+struct test_ping_req_msg_v01 {
+	char ping[4];
+
+	uint8_t client_name_valid;
+	struct test_name_type_v01 client_name;
+};
+
+struct test_ping_resp_msg_v01 {
+	struct qmi_response_type_v01 resp;
+
+	uint8_t pong_valid;
+	char pong[4];
+
+	uint8_t service_name_valid;
+	struct test_name_type_v01 service_name;
+};
+
+struct test_data_req_msg_v01 {
+	uint32_t data_len;
+	uint8_t data[TEST_MED_DATA_SIZE_V01];
+
+	uint8_t client_name_valid;
+	struct test_name_type_v01 client_name;
+};
+
+struct test_data_resp_msg_v01 {
+	struct qmi_response_type_v01 resp;
+
+	uint8_t data_valid;
+	uint32_t data_len;
+	uint8_t data[TEST_MED_DATA_SIZE_V01];
+
+	uint8_t service_name_valid;
+	struct test_name_type_v01 service_name;
+};
+
+extern struct elem_info test_ping_req_msg_v01_ei[];
+extern struct elem_info test_data_req_msg_v01_ei[];
+extern struct elem_info test_ping_resp_msg_v01_ei[];
+extern struct elem_info test_data_resp_msg_v01_ei[];
+
+#endif
diff --git a/arch/arm/mach-msm/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/no-pm.c b/arch/arm/mach-msm/no-pm.c
index d460c70..7602981 100644
--- a/arch/arm/mach-msm/no-pm.c
+++ b/arch/arm/mach-msm/no-pm.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010-2011, The Linux Foundation. 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
@@ -37,14 +37,9 @@
 
 void msm_pm_set_irq_extns(struct msm_pm_irq_calls *irq_calls) {}
 
-int msm_pm_idle_prepare(struct cpuidle_device *dev,
+enum msm_pm_sleep_mode msm_pm_idle_enter(struct cpuidle_device *dev,
 			struct cpuidle_driver *drv, int index)
 {
 	return -ENOSYS;
 }
 
-int msm_pm_idle_enter(enum msm_pm_sleep_mode sleep_mode)
-{
-	return -ENOSYS;
-}
-
diff --git a/arch/arm/mach-msm/peripheral-loader.c b/arch/arm/mach-msm/peripheral-loader.c
index c903b72..affb451 100644
--- a/arch/arm/mach-msm/peripheral-loader.c
+++ b/arch/arm/mach-msm/peripheral-loader.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2010-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -680,7 +680,7 @@
 	struct pil_priv *priv;
 	int id;
 	void __iomem *addr;
-	size_t len;
+	char buf[sizeof(priv->info->name)];
 
 	/* Ignore users who don't make any sense */
 	WARN(desc->ops->proxy_unvote && !desc->proxy_timeout,
@@ -703,9 +703,8 @@
 	addr = PIL_IMAGE_INFO_BASE + sizeof(struct pil_image_info) * id;
 	priv->info = (struct pil_image_info __iomem *)addr;
 
-	len = min(strlen(desc->name), sizeof(priv->info->name));
-	memset_io(priv->info->name, 0, sizeof(priv->info->name));
-	memcpy_toio(priv->info->name, desc->name, len);
+	strncpy(buf, desc->name, sizeof(buf));
+	__iowrite32_copy(priv->info->name, buf, sizeof(buf) / 4);
 
 	snprintf(priv->wname, sizeof(priv->wname), "pil-%s", desc->name);
 	wake_lock_init(&priv->wlock, WAKE_LOCK_SUSPEND, priv->wname);
diff --git a/arch/arm/mach-msm/pil-pronto.c b/arch/arm/mach-msm/pil-pronto.c
index cfcf5dc..9c89f2d 100644
--- a/arch/arm/mach-msm/pil-pronto.c
+++ b/arch/arm/mach-msm/pil-pronto.c
@@ -235,6 +235,12 @@
 	return pas_init_image(PAS_WCNSS, metadata, size);
 }
 
+static int pil_pronto_mem_setup_trusted(struct pil_desc *pil, phys_addr_t addr,
+			       size_t size)
+{
+	return pas_mem_setup(PAS_WCNSS, addr, size);
+}
+
 static int pil_pronto_reset_trusted(struct pil_desc *pil)
 {
 	return pas_auth_and_reset(PAS_WCNSS);
@@ -247,6 +253,7 @@
 
 static struct pil_reset_ops pil_pronto_ops_trusted = {
 	.init_image = pil_pronto_init_image_trusted,
+	.mem_setup = pil_pronto_mem_setup_trusted,
 	.auth_and_reset = pil_pronto_reset_trusted,
 	.shutdown = pil_pronto_shutdown_trusted,
 	.proxy_vote = pil_pronto_make_proxy_vote,
diff --git a/arch/arm/mach-msm/pil-q6v5-lpass.c b/arch/arm/mach-msm/pil-q6v5-lpass.c
index 5e03aa8..5c498ec 100644
--- a/arch/arm/mach-msm/pil-q6v5-lpass.c
+++ b/arch/arm/mach-msm/pil-q6v5-lpass.c
@@ -153,6 +153,12 @@
 	return pas_init_image(PAS_Q6, metadata, size);
 }
 
+static int pil_lpass_mem_setup_trusted(struct pil_desc *pil, phys_addr_t addr,
+			       size_t size)
+{
+	return pas_mem_setup(PAS_Q6, addr, size);
+}
+
 static int pil_lpass_reset_trusted(struct pil_desc *pil)
 {
 	return pas_auth_and_reset(PAS_Q6);
@@ -165,6 +171,7 @@
 
 static struct pil_reset_ops pil_lpass_ops_trusted = {
 	.init_image = pil_lpass_init_image_trusted,
+	.mem_setup = pil_lpass_mem_setup_trusted,
 	.proxy_vote = pil_q6v5_make_proxy_votes,
 	.proxy_unvote = pil_q6v5_remove_proxy_votes,
 	.auth_and_reset = pil_lpass_reset_trusted,
diff --git a/arch/arm/mach-msm/pil-venus.c b/arch/arm/mach-msm/pil-venus.c
index eb222e3..1fcd3ba 100644
--- a/arch/arm/mach-msm/pil-venus.c
+++ b/arch/arm/mach-msm/pil-venus.c
@@ -401,6 +401,12 @@
 	return pas_init_image(PAS_VIDC, metadata, size);
 }
 
+static int pil_venus_mem_setup_trusted(struct pil_desc *pil, phys_addr_t addr,
+			       size_t size)
+{
+	return pas_mem_setup(PAS_VIDC, addr, size);
+}
+
 static int pil_venus_reset_trusted(struct pil_desc *pil)
 {
 	int rc;
@@ -442,6 +448,7 @@
 
 static struct pil_reset_ops pil_venus_ops_trusted = {
 	.init_image = pil_venus_init_image_trusted,
+	.mem_setup =  pil_venus_mem_setup_trusted,
 	.auth_and_reset = pil_venus_reset_trusted,
 	.shutdown = pil_venus_shutdown_trusted,
 	.proxy_vote = pil_venus_make_proxy_vote,
diff --git a/arch/arm/mach-msm/pm-8x60.c b/arch/arm/mach-msm/pm-8x60.c
index b42ad94..7817533 100644
--- a/arch/arm/mach-msm/pm-8x60.c
+++ b/arch/arm/mach-msm/pm-8x60.c
@@ -474,8 +474,6 @@
 	}
 }
 
-static void *msm_pm_idle_rs_limits;
-
 static void msm_pm_swfi(void)
 {
 	msm_pm_config_hw_before_swfi();
@@ -774,12 +772,13 @@
 	}
 }
 
-int msm_pm_idle_prepare(struct cpuidle_device *dev,
-		struct cpuidle_driver *drv, int index)
+static int msm_pm_idle_prepare(struct cpuidle_device *dev,
+		struct cpuidle_driver *drv, int index,
+		void **msm_pm_idle_rs_limits)
 {
 	int i;
 	unsigned int power_usage = -1;
-	int ret = 0;
+	int ret = MSM_PM_SLEEP_MODE_NOT_SELECTED;
 	uint32_t modified_time_us = 0;
 	struct msm_pm_time_params time_param;
 
@@ -802,7 +801,6 @@
 		struct cpuidle_state_usage *st_usage = &dev->states_usage[i];
 		enum msm_pm_sleep_mode mode;
 		bool allow;
-		void *rs_limits = NULL;
 		uint32_t power;
 		int idx;
 
@@ -841,17 +839,20 @@
 			/* fall through */
 
 			if (pm_sleep_ops.lowest_limits)
-				rs_limits = pm_sleep_ops.lowest_limits(true,
-						mode, &time_param, &power);
+				*msm_pm_idle_rs_limits =
+					pm_sleep_ops.lowest_limits(
+						true, mode,
+						&time_param, &power);
 
 			if (MSM_PM_DEBUG_IDLE & msm_pm_debug_mask)
 				pr_info("CPU%u: %s: %s, latency %uus, "
 					"sleep %uus, limit %p\n",
 					dev->cpu, __func__, state->desc,
 					time_param.latency_us,
-					time_param.sleep_us, rs_limits);
+					time_param.sleep_us,
+					*msm_pm_idle_rs_limits);
 
-			if (!rs_limits)
+			if (!*msm_pm_idle_rs_limits)
 				allow = false;
 			break;
 
@@ -871,8 +872,6 @@
 				ret = mode;
 			}
 
-			if (MSM_PM_SLEEP_MODE_POWER_COLLAPSE == mode)
-				msm_pm_idle_rs_limits = rs_limits;
 		}
 	}
 
@@ -886,11 +885,27 @@
 	return ret;
 }
 
-int msm_pm_idle_enter(enum msm_pm_sleep_mode sleep_mode)
+enum msm_pm_sleep_mode msm_pm_idle_enter(struct cpuidle_device *dev,
+	struct cpuidle_driver *drv, int index)
 {
 	int64_t time;
-	int exit_stat;
 	bool collapsed = 1;
+	int exit_stat = -1;
+	enum msm_pm_sleep_mode sleep_mode;
+	void *msm_pm_idle_rs_limits = NULL;
+	int sleep_delay = 1;
+	int ret = -ENODEV;
+	int64_t timer_expiration = 0;
+	int notify_rpm = false;
+	bool timer_halted = false;
+
+	sleep_mode = msm_pm_idle_prepare(dev, drv, index,
+		&msm_pm_idle_rs_limits);
+
+	if (!msm_pm_idle_rs_limits) {
+		sleep_mode = MSM_PM_SLEEP_MODE_NOT_SELECTED;
+		goto cpuidle_enter_bail;
+	}
 
 	if (MSM_PM_DEBUG_IDLE & msm_pm_debug_mask)
 		pr_info("CPU%u: %s: mode %d\n",
@@ -898,71 +913,80 @@
 
 	time = ktime_to_ns(ktime_get());
 
-	switch (sleep_mode) {
-	case MSM_PM_SLEEP_MODE_WAIT_FOR_INTERRUPT:
-		msm_pm_swfi();
-		exit_stat = MSM_PM_STAT_IDLE_WFI;
-		break;
-
-	case MSM_PM_SLEEP_MODE_RETENTION:
-		msm_pm_retention();
-		exit_stat = MSM_PM_STAT_RETENTION;
-		break;
-
-	case MSM_PM_SLEEP_MODE_POWER_COLLAPSE_STANDALONE:
-		collapsed = msm_pm_power_collapse_standalone(true);
-		exit_stat = MSM_PM_STAT_IDLE_STANDALONE_POWER_COLLAPSE;
-		break;
-
-	case MSM_PM_SLEEP_MODE_POWER_COLLAPSE: {
-		int64_t timer_expiration = 0;
-		bool timer_halted = false;
-		uint32_t sleep_delay;
-		int ret = -ENODEV;
-		int notify_rpm =
-			(sleep_mode == MSM_PM_SLEEP_MODE_POWER_COLLAPSE);
+	if (sleep_mode == MSM_PM_SLEEP_MODE_POWER_COLLAPSE) {
+		notify_rpm = true;
 		timer_expiration = msm_pm_timer_enter_idle();
 
 		sleep_delay = (uint32_t) msm_pm_convert_and_cap_time(
 			timer_expiration, MSM_PM_SLEEP_TICK_LIMIT);
 		if (sleep_delay == 0) /* 0 would mean infinite time */
 			sleep_delay = 1;
+	}
 
-		if (MSM_PM_DEBUG_IDLE_CLK & msm_pm_debug_mask)
-			clock_debug_print_enabled();
+	if (pm_sleep_ops.enter_sleep)
+		ret = pm_sleep_ops.enter_sleep(sleep_delay,
+			msm_pm_idle_rs_limits,
+			true, notify_rpm);
+	if (!ret) {
 
-		if (pm_sleep_ops.enter_sleep)
-			ret = pm_sleep_ops.enter_sleep(sleep_delay,
-					msm_pm_idle_rs_limits,
-					true, notify_rpm);
-		if (!ret) {
+		switch (sleep_mode) {
+		case MSM_PM_SLEEP_MODE_WAIT_FOR_INTERRUPT:
+			msm_pm_swfi();
+			exit_stat = MSM_PM_STAT_IDLE_WFI;
+			break;
+
+		case MSM_PM_SLEEP_MODE_RETENTION:
+			msm_pm_retention();
+			exit_stat = MSM_PM_STAT_RETENTION;
+			break;
+
+		case MSM_PM_SLEEP_MODE_POWER_COLLAPSE_STANDALONE:
+			collapsed = msm_pm_power_collapse_standalone(true);
+			exit_stat = MSM_PM_STAT_IDLE_STANDALONE_POWER_COLLAPSE;
+			break;
+
+		case MSM_PM_SLEEP_MODE_POWER_COLLAPSE:
+			if (MSM_PM_DEBUG_IDLE_CLK & msm_pm_debug_mask)
+				clock_debug_print_enabled();
+
 			collapsed = msm_pm_power_collapse(true);
 			timer_halted = true;
 
-			if (pm_sleep_ops.exit_sleep)
-				pm_sleep_ops.exit_sleep(msm_pm_idle_rs_limits,
-						true, notify_rpm, collapsed);
+			exit_stat = MSM_PM_STAT_IDLE_POWER_COLLAPSE;
+			msm_pm_timer_exit_idle(timer_halted);
+			break;
+
+		case MSM_PM_SLEEP_MODE_NOT_SELECTED:
+			goto cpuidle_enter_bail;
+			break;
+
+		default:
+			__WARN();
+			goto cpuidle_enter_bail;
+			break;
 		}
+		if (pm_sleep_ops.exit_sleep)
+			pm_sleep_ops.exit_sleep(msm_pm_idle_rs_limits,
+					true, notify_rpm, collapsed);
+
+		time = ktime_to_ns(ktime_get()) - time;
+		msm_pm_ftrace_lpm_exit(smp_processor_id(), sleep_mode,
+					collapsed);
+		if (exit_stat >= 0)
+			msm_pm_add_stat(exit_stat, time);
+		do_div(time, 1000);
+		dev->last_residency = (int) time;
+		return sleep_mode;
+
+	} else if (sleep_mode == MSM_PM_SLEEP_MODE_POWER_COLLAPSE) {
 		msm_pm_timer_exit_idle(timer_halted);
-		exit_stat = MSM_PM_STAT_IDLE_POWER_COLLAPSE;
-		break;
-	}
-
-	default:
-		__WARN();
-		goto cpuidle_enter_bail;
-	}
-
-	time = ktime_to_ns(ktime_get()) - time;
-	msm_pm_add_stat(exit_stat, time);
-	msm_pm_ftrace_lpm_exit(smp_processor_id(), sleep_mode,
-				collapsed);
-
-	do_div(time, 1000);
-	return (int) time;
+		sleep_mode = MSM_PM_SLEEP_MODE_NOT_SELECTED;
+	} else
+		sleep_mode = MSM_PM_SLEEP_MODE_NOT_SELECTED;
 
 cpuidle_enter_bail:
-	return 0;
+	dev->last_residency = 0;
+	return sleep_mode;
 }
 
 void msm_pm_cpu_enter_lowpower(unsigned int cpu)
diff --git a/arch/arm/mach-msm/pm.h b/arch/arm/mach-msm/pm.h
index bd61feb..61ee441 100644
--- a/arch/arm/mach-msm/pm.h
+++ b/arch/arm/mach-msm/pm.h
@@ -52,7 +52,8 @@
 	MSM_PM_SLEEP_MODE_RETENTION = MSM_PM_SLEEP_MODE_APPS_SLEEP,
 	MSM_PM_SLEEP_MODE_POWER_COLLAPSE_SUSPEND = 5,
 	MSM_PM_SLEEP_MODE_POWER_COLLAPSE_NO_XO_SHUTDOWN = 6,
-	MSM_PM_SLEEP_MODE_NR
+	MSM_PM_SLEEP_MODE_NR = 7,
+	MSM_PM_SLEEP_MODE_NOT_SELECTED,
 };
 
 #define MSM_PM_MODE(cpu, mode_nr)  ((cpu) * MSM_PM_SLEEP_MODE_NR + (mode_nr))
@@ -107,10 +108,9 @@
 };
 
 void msm_pm_set_platform_data(struct msm_pm_platform_data *data, int count);
-int msm_pm_idle_prepare(struct cpuidle_device *dev,
+enum msm_pm_sleep_mode msm_pm_idle_enter(struct cpuidle_device *dev,
 			struct cpuidle_driver *drv, int index);
 void msm_pm_set_irq_extns(struct msm_pm_irq_calls *irq_calls);
-int msm_pm_idle_enter(enum msm_pm_sleep_mode sleep_mode);
 void msm_pm_cpu_enter_lowpower(unsigned int cpu);
 void __init msm_pm_set_tz_retention_flag(unsigned int flag);
 
diff --git a/arch/arm/mach-msm/pmu.c b/arch/arm/mach-msm/pmu.c
index cb191fc..21f65f8 100644
--- a/arch/arm/mach-msm/pmu.c
+++ b/arch/arm/mach-msm/pmu.c
@@ -181,7 +181,7 @@
 	 * and point to the appropriate 'struct resource'.
 	 */
 #ifdef CONFIG_ARCH_MSM8625
-	if (cpu_is_msm8625()) {
+	if (cpu_is_msm8625() || cpu_is_msm8625q()) {
 		pmu_devices[0] = &msm8625_cpu_pmu_device;
 		pmu_devices[1] = &msm8625_l2_pmu_device;
 		msm8625_cpu_pmu_device.dev.platform_data = &multicore_data;
diff --git a/arch/arm/mach-msm/qdsp5/audio_acdb.c b/arch/arm/mach-msm/qdsp5/audio_acdb.c
index d7a4607..681b41c 100644
--- a/arch/arm/mach-msm/qdsp5/audio_acdb.c
+++ b/arch/arm/mach-msm/qdsp5/audio_acdb.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -1301,6 +1301,15 @@
 }
 EXPORT_SYMBOL(acdb_get_calibration_data);
 
+int is_acdb_enabled()
+{
+	if (acdb_data.handle != NULL)
+		return 1;
+	else
+		return 0;
+}
+EXPORT_SYMBOL(is_acdb_enabled);
+
 static u8 check_device_info_already_present(
 		struct dev_evt_msg device_info,
 			struct acdb_cache_node *acdb_cache_free_node)
@@ -1522,7 +1531,7 @@
 			result = -EINVAL;
 			goto done;
 		} else
-			MM_DBG("AUDPP is calibrated with IIR parameters");
+			MM_DBG("AUDPP is calibrated with IIR parameters\n");
 	}
 	result = acdb_fill_audpp_mbadrc();
 	if (!IS_ERR_VALUE(result)) {
@@ -2270,13 +2279,9 @@
 		if (ret == 1) {
 			MM_DBG("got device ready call back for another "\
 					"audplay task sessions on same COPP\n");
-			/*stream_id is used to keep track of number of active*/
-			/*sessions active on this device*/
-			acdb_cache_free_node->stream_id++;
 			mutex_unlock(&acdb_data.acdb_mutex);
 			goto done;
 		}
-		acdb_cache_free_node->stream_id++;
 	}
 	update_acdb_data_struct(acdb_cache_free_node);
 	acdb_data.device_cb_compl = 1;
@@ -2317,6 +2322,9 @@
 		}
 		goto done;
 	}
+	/*stream_id is used to keep track of number of active*/
+	/*sessions active on this device*/
+	acdb_cache_rx.stream_id++;
 
 	acdb_data.acdb_state |= AUDPP_READY;
 	acdb_data.audpp_cb_compl = 1;
diff --git a/arch/arm/mach-msm/qdsp5/audio_out.c b/arch/arm/mach-msm/qdsp5/audio_out.c
index 6f3bf91..fee7404 100644
--- a/arch/arm/mach-msm/qdsp5/audio_out.c
+++ b/arch/arm/mach-msm/qdsp5/audio_out.c
@@ -4,7 +4,7 @@
  *
  * Copyright (C) 2008 Google, Inc.
  * Copyright (C) 2008 HTC Corporation
- * Copyright (c) 2012 Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
  *
  * This software is licensed under the terms of the GNU General Public
  * License version 2, as published by the Free Software Foundation, and
@@ -39,6 +39,7 @@
 
 #include "audmgr.h"
 
+#include <mach/qdsp5/audio_acdb_def.h>
 #include <mach/qdsp5/qdsp5audppcmdi.h>
 #include <mach/qdsp5/qdsp5audppmsg.h>
 #include <mach/qdsp5/qdsp5audpp.h>
@@ -298,19 +299,20 @@
 	if (!audio_copp->status)
 		return;
 
-	audpp_dsp_set_mbadrc(COMMON_OBJ_ID, audio_copp->mbadrc_enable,
+	if (!is_acdb_enabled()) {
+		audpp_dsp_set_mbadrc(COMMON_OBJ_ID, audio_copp->mbadrc_enable,
 						&audio_copp->mbadrc);
 
-	audpp_dsp_set_eq(COMMON_OBJ_ID, audio_copp->eq_enable,
+		audpp_dsp_set_eq(COMMON_OBJ_ID, audio_copp->eq_enable,
 						&audio_copp->eq);
-
-	audpp_dsp_set_rx_iir(COMMON_OBJ_ID, audio_copp->rx_iir_enable,
+		audpp_dsp_set_rx_iir(COMMON_OBJ_ID, audio_copp->rx_iir_enable,
 							&audio_copp->iir);
-	audpp_dsp_set_vol_pan(COMMON_OBJ_ID, &audio_copp->vol_pan);
+		audpp_dsp_set_vol_pan(COMMON_OBJ_ID, &audio_copp->vol_pan);
 
-	audpp_dsp_set_qconcert_plus(COMMON_OBJ_ID,
+		audpp_dsp_set_qconcert_plus(COMMON_OBJ_ID,
 				audio_copp->qconcert_plus_enable,
 				&audio_copp->qconcert_plus);
+	}
 	audio_enable_srs_trumedia(audio_copp, true);
 }
 EXPORT_SYMBOL(audio_commit_pending_pp_params);
diff --git a/arch/arm/mach-msm/qdsp5/audio_pcm_in.c b/arch/arm/mach-msm/qdsp5/audio_pcm_in.c
index 7b2090d..c5787fd 100644
--- a/arch/arm/mach-msm/qdsp5/audio_pcm_in.c
+++ b/arch/arm/mach-msm/qdsp5/audio_pcm_in.c
@@ -2,7 +2,7 @@
  *
  * pcm audio input device
  *
- * Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2011-2013, The Linux Foundation. All rights reserved.
  *
  * This code is based in part on arch/arm/mach-msm/qdsp5v2/audio_pcm_in.c,
  * Copyright (C) 2008 Google, Inc.
@@ -42,6 +42,7 @@
 
 #include "audmgr.h"
 
+#include <mach/qdsp5/audio_acdb_def.h>
 #include <mach/qdsp5/qdsp5audpreproc.h>
 #include <mach/qdsp5/qdsp5audpreproccmdi.h>
 #include <mach/qdsp5/qdsp5audpreprocmsg.h>
@@ -346,6 +347,8 @@
 	case AUDREC_MSG_CMD_AREC_PARAM_CFG_DONE_MSG: {
 		MM_INFO("PARAM CFG DONE\n");
 		audio->running = 1;
+		if (is_acdb_enabled())
+			break;
 		audio_dsp_set_tx_agc(audio);
 		audio_dsp_set_ns(audio);
 		audio_dsp_set_iir(audio);
@@ -914,6 +917,12 @@
 	mutex_lock(&audio->lock);
 	switch (cmd) {
 	case AUDIO_ENABLE_AUDPRE:
+
+		if (is_acdb_enabled()) {
+			MM_INFO("Audpp is supported via acdb\n");
+			rc = -EFAULT;
+			break;
+		}
 		if (copy_from_user(&enable_mask, (void *) arg,
 						sizeof(enable_mask))) {
 			rc = -EFAULT;
diff --git a/arch/arm/mach-msm/rpm_resources.c b/arch/arm/mach-msm/rpm_resources.c
index 43073d3..78c5ae0 100644
--- a/arch/arm/mach-msm/rpm_resources.c
+++ b/arch/arm/mach-msm/rpm_resources.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2010-2012, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -21,6 +21,7 @@
 #include <linux/spinlock.h>
 #include <linux/cpu.h>
 #include <linux/hrtimer.h>
+#include <linux/platform_device.h>
 #include <mach/rpm.h>
 #include <mach/msm_iomap.h>
 #include <asm/mach-types.h>
@@ -71,6 +72,10 @@
 static int vdd_mem_vlevels[MSM_RPMRS_VDD_MEM_LAST];
 static int vdd_mask;
 
+static DEFINE_PER_CPU(uint32_t , msm_lpm_sleep_time);
+static DEFINE_PER_CPU(int , lpm_permitted_level);
+static DEFINE_PER_CPU(struct atomic_notifier_head, lpm_notify_head);
+
 #define MSM_RPMRS_MAX_RS_REGISTER_COUNT 2
 
 #define RPMRS_ATTR(_name) \
@@ -869,6 +874,13 @@
 	spin_unlock_irqrestore(&msm_rpmrs_lock, flags);
 }
 
+static bool lpm_level_permitted(int cur_level_count)
+{
+	if (__get_cpu_var(lpm_permitted_level) == msm_rpmrs_level_count + 1)
+		return true;
+	return (__get_cpu_var(lpm_permitted_level) == cur_level_count);
+}
+
 s32 msm_cpuidle_get_deep_idle_latency(void)
 {
 	int i;
@@ -904,6 +916,7 @@
 	uint32_t pwr;
 	uint32_t next_wakeup_us = time_param->sleep_us;
 	bool modify_event_timer;
+	int best_level_iter = msm_rpmrs_level_count + 1;
 
 	if (sleep_mode == MSM_PM_SLEEP_MODE_POWER_COLLAPSE) {
 		irqs_detectable = msm_mpm_irqs_detectable(from_idle);
@@ -968,6 +981,7 @@
 			level->rs_limits.latency_us[cpu] = level->latency_us;
 			level->rs_limits.power[cpu] = pwr;
 			best_level = level;
+			best_level_iter = i;
 			if (power)
 				*power = pwr;
 			if (modify_event_timer && best_level->latency_us > 1)
@@ -978,6 +992,12 @@
 				time_param->modified_time_us = 0;
 		}
 	}
+	if (best_level && !lpm_level_permitted(best_level_iter))
+		best_level = NULL;
+	else
+		per_cpu(msm_lpm_sleep_time, cpu) =
+			time_param->modified_time_us ?
+			time_param->modified_time_us : time_param->sleep_us;
 
 	return best_level ? &best_level->rs_limits : NULL;
 }
@@ -986,6 +1006,12 @@
 		bool from_idle, bool notify_rpm)
 {
 	int rc = 0;
+	struct msm_lpm_sleep_data sleep_data;
+
+	sleep_data.limits = limits;
+	sleep_data.kernel_sleep = __get_cpu_var(msm_lpm_sleep_time);
+	atomic_notifier_call_chain(&__get_cpu_var(lpm_notify_head),
+		MSM_LPM_STATE_ENTER, &sleep_data);
 
 	if (notify_rpm) {
 		rc = msm_rpmrs_flush_buffer(sclk_count, limits, from_idle);
@@ -1009,6 +1035,9 @@
 
 	if (msm_rpmrs_use_mpm(limits))
 		msm_mpm_exit_sleep(from_idle);
+
+	atomic_notifier_call_chain(&__get_cpu_var(lpm_notify_head),
+			MSM_LPM_STATE_EXIT, NULL);
 }
 
 static int rpmrs_cpu_callback(struct notifier_block *nfb,
@@ -1033,6 +1062,16 @@
 	return NOTIFY_OK;
 }
 
+static struct lpm_test_platform_data lpm_test_pdata;
+
+static struct platform_device msm_lpm_test_device = {
+	.name		= "lpm_test",
+	.id		= -1,
+	.dev		= {
+		.platform_data = &lpm_test_pdata,
+	},
+};
+
 static struct notifier_block __refdata rpmrs_cpu_notifier = {
 	.notifier_call = rpmrs_cpu_callback,
 };
@@ -1041,6 +1080,7 @@
 {
 	int i, k;
 	struct msm_rpmrs_level *levels = data->levels;
+	unsigned int m_cpu = 0;
 
 	msm_rpmrs_level_count = data->num_levels;
 
@@ -1052,6 +1092,16 @@
 	memcpy(msm_rpmrs_levels, levels,
 			msm_rpmrs_level_count * sizeof(struct msm_rpmrs_level));
 
+	lpm_test_pdata.use_qtimer = 0;
+	lpm_test_pdata.msm_lpm_test_levels = msm_rpmrs_levels,
+	lpm_test_pdata.msm_lpm_test_level_count = msm_rpmrs_level_count;
+
+	for_each_possible_cpu(m_cpu)
+		per_cpu(lpm_permitted_level, m_cpu) =
+				msm_rpmrs_level_count + 1;
+
+	platform_device_register(&msm_lpm_test_device);
+
 	memcpy(vdd_dig_vlevels, data->vdd_dig_levels,
 		(MSM_RPMRS_VDD_DIG_MAX + 1) * sizeof(vdd_dig_vlevels[0]));
 
@@ -1087,6 +1137,41 @@
 	return 0;
 }
 
+uint32_t msm_pm_get_pxo(struct msm_rpmrs_limits *limits)
+{
+	return limits->pxo;
+}
+
+uint32_t msm_pm_get_l2_cache(struct msm_rpmrs_limits *limits)
+{
+	return limits->l2_cache;
+}
+
+uint32_t msm_pm_get_vdd_mem(struct msm_rpmrs_limits *limits)
+{
+	return limits->vdd_mem;
+}
+
+uint32_t msm_pm_get_vdd_dig(struct msm_rpmrs_limits *limits)
+{
+	return limits->vdd_dig;
+}
+
+int msm_lpm_register_notifier(int cpu, int level_iter,
+			struct notifier_block *nb, bool is_latency_measure)
+{
+	per_cpu(lpm_permitted_level, cpu) = level_iter;
+	return atomic_notifier_chain_register(&per_cpu(lpm_notify_head,
+			cpu), nb);
+}
+
+int msm_lpm_unregister_notifier(int cpu, struct notifier_block *nb)
+{
+	per_cpu(lpm_permitted_level, cpu) = msm_rpmrs_level_count + 1;
+	return atomic_notifier_chain_unregister(&per_cpu(lpm_notify_head, cpu),
+				nb);
+}
+
 static int __init msm_rpmrs_init(void)
 {
 	struct msm_rpm_iv_pair req;
diff --git a/arch/arm/mach-msm/rpm_resources.h b/arch/arm/mach-msm/rpm_resources.h
index 46d6d94..0a180fb 100644
--- a/arch/arm/mach-msm/rpm_resources.h
+++ b/arch/arm/mach-msm/rpm_resources.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2010-2012, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -15,7 +15,9 @@
 #define __ARCH_ARM_MACH_MSM_RPM_RESOURCES_H
 
 #include <mach/rpm.h>
+#include <linux/notifier.h>
 #include "pm.h"
+#include "test-lpm.h"
 
 enum {
 	MSM_RPMRS_ID_PXO_CLK = 0,
@@ -102,6 +104,94 @@
 	unsigned int rpmrs_target_id[MSM_RPMRS_ID_LAST];
 };
 
+enum {
+	MSM_LPM_STATE_ENTER = 0,
+	MSM_LPM_STATE_EXIT = 1,
+};
+
+/**
+ * struct msm_lpm_sleep_data - abstraction to get sleep data
+ * @limits:	pointer to the msm_rpmrs_limits structure
+ * @kernel_sleep:	kernel sleep time as decided by the power calculation
+ *			algorithm
+ *
+ * This structure is an abstraction to get the limits and kernel sleep time
+ * during enter sleep.
+ */
+
+struct msm_lpm_sleep_data {
+	struct msm_rpmrs_limits *limits;
+	uint32_t kernel_sleep;
+};
+
+#define MSM_PM(field) MSM_RPMRS_##field
+
+/**
+ * msm_pm_get_pxo() -  get the limits for pxo
+ * @limits:            pointer to the msm_rpmrs_limits structure
+ *
+ * This function gets the limits to the resource pxo on
+ * 8960
+ */
+
+uint32_t msm_pm_get_pxo(struct msm_rpmrs_limits *limits);
+
+/**
+ * msm_pm_get_l2_cache() -  get the limits for l2 cache
+ * @limits:            pointer to the msm_rpmrs_limits structure
+ *
+ * This function gets the limits to the resource l2 cache
+ * on 8960
+ */
+
+uint32_t msm_pm_get_l2_cache(struct msm_rpmrs_limits *limits);
+
+/**
+ * msm_pm_get_vdd_mem() -  get the limits for pxo
+ * @limits:            pointer to the msm_rpmrs_limits structure
+ *
+ * This function gets the limits to the resource vdd mem
+ * on 8960
+ */
+
+uint32_t msm_pm_get_vdd_mem(struct msm_rpmrs_limits *limits);
+
+/**
+ * msm_pm_get_vdd_dig() -  get the limits for vdd dig
+ * @limits:            pointer to the msm_rpmrs_limits structure
+ *
+ * This function gets the limits to the resource vdd dig
+ * on 8960
+ */
+
+uint32_t msm_pm_get_vdd_dig(struct msm_rpmrs_limits *limits);
+
+/**
+ * msm_lpm_register_notifier() - register for notifications
+ * @cpu:               cpu to debug
+ * @level_iter:        low power level index to debug
+ * @nb:       notifier block to callback on notifications
+ * @is_latency_measure: is it latency measure
+ *
+ * This function sets the permitted level to the index of the
+ * level under test and registers notifier for callback.
+ */
+
+int msm_lpm_register_notifier(int cpu, int level_iter,
+		struct notifier_block *nb, bool is_latency_measure);
+
+/**
+ * msm_lpm_unregister_notifier() - unregister from notifications
+ * @cpu:               cpu to debug
+ * @nb:       notifier block to callback on notifications
+ *
+ * This function sets the permitted level to a value one more than
+ * available levels count which indicates that all levels are
+ * permitted and it also unregisters notifier for callback.
+ */
+
+int msm_lpm_unregister_notifier(int cpu, struct notifier_block *nb);
+
 #if defined(CONFIG_MSM_RPM)
 
 int msm_rpmrs_set(int ctx, struct msm_rpm_iv_pair *req, int count);
diff --git a/arch/arm/mach-msm/socinfo.c b/arch/arm/mach-msm/socinfo.c
index 2743547..1ab1f71 100644
--- a/arch/arm/mach-msm/socinfo.c
+++ b/arch/arm/mach-msm/socinfo.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2009-2012, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2009-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -15,9 +15,17 @@
  *
  */
 
-#include <linux/types.h>
+#include <linux/err.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/sys_soc.h>
+#include <linux/slab.h>
+#include <linux/stat.h>
 #include <linux/sysdev.h>
+#include <linux/types.h>
+
 #include <asm/mach-types.h>
+
 #include <mach/socinfo.h>
 
 #include "smd_private.h"
@@ -399,6 +407,11 @@
 		: 0;
 }
 
+static uint32_t socinfo_get_format(void)
+{
+	return socinfo ? socinfo->v1.format : 0;
+}
+
 enum msm_cpu socinfo_get_msm_cpu(void)
 {
 	return cur_cpu;
@@ -607,6 +620,100 @@
 		socinfo_get_pmic_die_revision());
 }
 
+static ssize_t
+msm_get_vendor(struct device *dev,
+		struct device_attribute *attr,
+		char *buf)
+{
+	return snprintf(buf, PAGE_SIZE, "Qualcomm\n");
+}
+
+static ssize_t
+msm_get_raw_id(struct device *dev,
+		struct device_attribute *attr,
+		char *buf)
+{
+	return snprintf(buf, PAGE_SIZE, "%u\n",
+		socinfo_get_raw_id());
+}
+
+static ssize_t
+msm_get_raw_version(struct device *dev,
+		     struct device_attribute *attr,
+		     char *buf)
+{
+	return snprintf(buf, PAGE_SIZE, "%u\n",
+		socinfo_get_raw_version());
+}
+
+static ssize_t
+msm_get_build_id(struct device *dev,
+		   struct device_attribute *attr,
+		   char *buf)
+{
+	return snprintf(buf, PAGE_SIZE, "%-.32s\n",
+			socinfo_get_build_id());
+}
+
+static ssize_t
+msm_get_hw_platform(struct device *dev,
+			struct device_attribute *attr,
+			char *buf)
+{
+	uint32_t hw_type;
+	hw_type = socinfo_get_platform_type();
+
+	return snprintf(buf, PAGE_SIZE, "%-.32s\n",
+			hw_platform[hw_type]);
+}
+
+static ssize_t
+msm_get_platform_version(struct device *dev,
+				struct device_attribute *attr,
+				char *buf)
+{
+	return snprintf(buf, PAGE_SIZE, "%u\n",
+		socinfo_get_platform_version());
+}
+
+static ssize_t
+msm_get_accessory_chip(struct device *dev,
+				struct device_attribute *attr,
+				char *buf)
+{
+	return snprintf(buf, PAGE_SIZE, "%u\n",
+		socinfo_get_accessory_chip());
+}
+
+static ssize_t
+msm_get_platform_subtype(struct device *dev,
+			struct device_attribute *attr,
+			char *buf)
+{
+	uint32_t hw_subtype;
+	hw_subtype = socinfo_get_platform_subtype();
+	return snprintf(buf, PAGE_SIZE, "%-.32s\n",
+		hw_platform_subtype[hw_subtype]);
+}
+
+static ssize_t
+msm_get_pmic_model(struct device *dev,
+			struct device_attribute *attr,
+			char *buf)
+{
+	return snprintf(buf, PAGE_SIZE, "%u\n",
+		socinfo_get_pmic_model());
+}
+
+static ssize_t
+msm_get_pmic_die_revision(struct device *dev,
+			       struct device_attribute *attr,
+			       char *buf)
+{
+	return snprintf(buf, PAGE_SIZE, "%u\n",
+			 socinfo_get_pmic_die_revision());
+}
+
 static struct sysdev_attribute socinfo_v1_files[] = {
 	_SYSDEV_ATTR(id, 0444, socinfo_show_id, NULL),
 	_SYSDEV_ATTR(version, 0444, socinfo_show_version, NULL),
@@ -644,6 +751,42 @@
 			socinfo_show_pmic_die_revision, NULL),
 };
 
+static struct device_attribute msm_soc_attr_raw_version =
+	__ATTR(raw_version, S_IRUGO, msm_get_raw_version,  NULL);
+
+static struct device_attribute msm_soc_attr_raw_id =
+	__ATTR(raw_id, S_IRUGO, msm_get_raw_id,  NULL);
+
+static struct device_attribute msm_soc_attr_vendor =
+	__ATTR(vendor, S_IRUGO, msm_get_vendor,  NULL);
+
+static struct device_attribute msm_soc_attr_build_id =
+	__ATTR(build_id, S_IRUGO, msm_get_build_id, NULL);
+
+static struct device_attribute msm_soc_attr_hw_platform =
+	__ATTR(hw_platform, S_IRUGO, msm_get_hw_platform, NULL);
+
+
+static struct device_attribute msm_soc_attr_platform_version =
+	__ATTR(platform_version, S_IRUGO,
+			msm_get_platform_version, NULL);
+
+static struct device_attribute msm_soc_attr_accessory_chip =
+	__ATTR(accessory_chip, S_IRUGO,
+			msm_get_accessory_chip, NULL);
+
+static struct device_attribute msm_soc_attr_platform_subtype =
+	__ATTR(platform_subtype, S_IRUGO,
+			msm_get_platform_subtype, NULL);
+
+static struct device_attribute msm_soc_attr_pmic_model =
+	__ATTR(pmic_model, S_IRUGO,
+			msm_get_pmic_model, NULL);
+
+static struct device_attribute msm_soc_attr_pmic_die_revision =
+	__ATTR(pmic_die_revision, S_IRUGO,
+			msm_get_pmic_die_revision, NULL);
+
 static struct sysdev_class soc_sysdev_class = {
 	.name = "soc",
 };
@@ -764,47 +907,63 @@
 	return (void *) &dummy_socinfo;
 }
 
-int __init socinfo_init(void)
+static void __init populate_soc_sysfs_files(struct device *msm_soc_device)
 {
-	socinfo = smem_alloc(SMEM_HW_SW_BUILD_ID, sizeof(struct socinfo_v7));
+	uint32_t legacy_format = socinfo_get_format();
 
-	if (!socinfo)
-		socinfo = smem_alloc(SMEM_HW_SW_BUILD_ID,
-				sizeof(struct socinfo_v6));
+	device_create_file(msm_soc_device, &msm_soc_attr_vendor);
 
-	if (!socinfo)
-		socinfo = smem_alloc(SMEM_HW_SW_BUILD_ID,
-				sizeof(struct socinfo_v5));
-
-	if (!socinfo)
-		socinfo = smem_alloc(SMEM_HW_SW_BUILD_ID,
-				sizeof(struct socinfo_v4));
-
-	if (!socinfo)
-		socinfo = smem_alloc(SMEM_HW_SW_BUILD_ID,
-				sizeof(struct socinfo_v3));
-
-	if (!socinfo)
-		socinfo = smem_alloc(SMEM_HW_SW_BUILD_ID,
-				sizeof(struct socinfo_v2));
-
-	if (!socinfo)
-		socinfo = smem_alloc(SMEM_HW_SW_BUILD_ID,
-				sizeof(struct socinfo_v1));
-
-	if (!socinfo) {
-		pr_warn("%s: Can't find SMEM_HW_SW_BUILD_ID; falling back on "
-			"dummy values.\n", __func__);
-		socinfo = setup_dummy_socinfo();
+	switch (legacy_format) {
+	case 7:
+		device_create_file(msm_soc_device,
+					&msm_soc_attr_pmic_model);
+		device_create_file(msm_soc_device,
+					&msm_soc_attr_pmic_die_revision);
+	case 6:
+		device_create_file(msm_soc_device,
+					&msm_soc_attr_platform_subtype);
+	case 5:
+		device_create_file(msm_soc_device,
+					&msm_soc_attr_accessory_chip);
+	case 4:
+		device_create_file(msm_soc_device,
+					&msm_soc_attr_platform_version);
+	case 3:
+		device_create_file(msm_soc_device,
+					&msm_soc_attr_hw_platform);
+	case 2:
+		device_create_file(msm_soc_device,
+					&msm_soc_attr_raw_id);
+		device_create_file(msm_soc_device,
+					&msm_soc_attr_raw_version);
+	case 1:
+		device_create_file(msm_soc_device,
+					&msm_soc_attr_build_id);
+		break;
+	default:
+		pr_err("%s:Unknown socinfo format:%u\n", __func__,
+				legacy_format);
+		break;
 	}
 
-	WARN(!socinfo_get_id(), "Unknown SOC ID!\n");
-	WARN(socinfo_get_id() >= ARRAY_SIZE(cpu_of_id),
-		"New IDs added! ID => CPU mapping might need an update.\n");
+	return;
+}
 
-	if (socinfo->v1.id < ARRAY_SIZE(cpu_of_id))
-		cur_cpu = cpu_of_id[socinfo->v1.id];
+static void  __init soc_info_populate(struct soc_device_attribute *soc_dev_attr)
+{
+	uint32_t soc_version = socinfo_get_version();
 
+	soc_dev_attr->soc_id   = kasprintf(GFP_KERNEL, "%d", socinfo_get_id());
+	soc_dev_attr->machine  = "Snapdragon";
+	soc_dev_attr->revision = kasprintf(GFP_KERNEL, "%u.%u",
+			SOCINFO_VERSION_MAJOR(soc_version),
+			SOCINFO_VERSION_MINOR(soc_version));
+	return;
+
+}
+
+static void socinfo_print(void)
+{
 	switch (socinfo->v1.format) {
 	case 1:
 		pr_info("%s: v%u, id=%u, ver=%u.%u\n",
@@ -880,8 +1039,69 @@
 		pr_err("%s: Unknown format found\n", __func__);
 		break;
 	}
+}
 
-	return 0;
+struct device *  __init socinfo_init(void)
+{
+	struct device *msm_soc_device;
+	struct soc_device *soc_dev;
+	struct soc_device_attribute *soc_dev_attr;
+
+	socinfo = smem_alloc(SMEM_HW_SW_BUILD_ID, sizeof(struct socinfo_v7));
+
+	if (!socinfo)
+		socinfo = smem_alloc(SMEM_HW_SW_BUILD_ID,
+				sizeof(struct socinfo_v6));
+
+	if (!socinfo)
+		socinfo = smem_alloc(SMEM_HW_SW_BUILD_ID,
+				sizeof(struct socinfo_v5));
+
+	if (!socinfo)
+		socinfo = smem_alloc(SMEM_HW_SW_BUILD_ID,
+				sizeof(struct socinfo_v4));
+
+	if (!socinfo)
+		socinfo = smem_alloc(SMEM_HW_SW_BUILD_ID,
+				sizeof(struct socinfo_v3));
+
+	if (!socinfo)
+		socinfo = smem_alloc(SMEM_HW_SW_BUILD_ID,
+				sizeof(struct socinfo_v2));
+
+	if (!socinfo)
+		socinfo = smem_alloc(SMEM_HW_SW_BUILD_ID,
+				sizeof(struct socinfo_v1));
+
+	if (!socinfo) {
+		pr_warn("%s: Can't find SMEM_HW_SW_BUILD_ID; falling back on dummy values.\n",
+				__func__);
+		socinfo = setup_dummy_socinfo();
+	}
+
+	WARN(!socinfo_get_id(), "Unknown SOC ID!\n");
+	WARN(socinfo_get_id() >= ARRAY_SIZE(cpu_of_id),
+		"New IDs added! ID => CPU mapping might need an update.\n");
+
+	if (socinfo->v1.id < ARRAY_SIZE(cpu_of_id))
+		cur_cpu = cpu_of_id[socinfo->v1.id];
+
+	socinfo_print();
+	soc_dev_attr = kzalloc(sizeof(*soc_dev_attr), GFP_KERNEL);
+	if (!soc_dev_attr)
+		return ERR_PTR(-ENOMEM);
+
+	soc_info_populate(soc_dev_attr);
+	soc_dev = soc_device_register(soc_dev_attr);
+	if (IS_ERR_OR_NULL(soc_dev)) {
+		kfree(soc_dev_attr);
+		return ERR_PTR(-EIO);
+	}
+
+	msm_soc_device = soc_device_to_device(soc_dev);
+	populate_soc_sysfs_files(msm_soc_device);
+
+	return msm_soc_device;
 }
 
 const int get_core_count(void)
@@ -921,6 +1141,7 @@
 		return MSM_CPU_8064;
 
 	case 0x511F06F1:
+	case 0x511F06F2:
 	case 0x512F06F0:
 		return MSM_CPU_8974;
 
@@ -972,6 +1193,7 @@
 	case 0x512F04D0:
 	case 0x511F06F0:
 	case 0x511F06F1:
+	case 0x511F06F2:
 	case 0x510F05D0:
 		return 1;
 
diff --git a/arch/arm/mach-msm/test-lpm.c b/arch/arm/mach-msm/test-lpm.c
new file mode 100644
index 0000000..dbc8100
--- /dev/null
+++ b/arch/arm/mach-msm/test-lpm.c
@@ -0,0 +1,696 @@
+/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/pm.h>
+#include <linux/mutex.h>
+#include <linux/uaccess.h>
+#include <linux/debugfs.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/ctype.h>
+#include <linux/moduleparam.h>
+#include <linux/platform_device.h>
+#include <mach/socinfo.h>
+#if defined(CONFIG_MSM_RPM)
+#include "rpm_resources.h"
+#endif
+#include "timer.h"
+#include "test-lpm.h"
+
+#define LPM_STATS_RESET "reset"
+#define LPM_TEST_ALL_LEVELS "lpm"
+#define LPM_TEST_LATENCIES "latency"
+#define LPM_TEST_CLEAR "clear"
+#define BUF_SIZE 200
+#define STAT_BUF_EXTRA_SIZE 500
+#define WAIT_FOR_XO 1
+#define COMM_BUF_SIZE 15
+#define INPUT_COUNT_BUF 10
+#define LPM_DEFAULT_CPU 0
+
+#define SNPRINTF(buf, size, format, ...) \
+{ \
+	if (size > 0) { \
+		int ret; \
+		ret = snprintf(buf, size, format, ## __VA_ARGS__); \
+		if (ret > size) { \
+			buf += size; \
+			size = 0; \
+		} else { \
+			buf += ret; \
+			size -= ret; \
+		} \
+	} \
+} \
+
+static DEFINE_MUTEX(lpm_stats_mutex);
+
+struct lpm_level_stat {
+	char level_name[BUF_SIZE];
+	int64_t min_time;
+	int64_t max_time;
+	int64_t avg_time;
+	int64_t exit_early;
+	int64_t count;
+	unsigned long min_threshold;
+	uint32_t kernel_sleep_time;
+	bool entered;
+};
+
+static DEFINE_PER_CPU(struct lpm_level_stat *, lpm_levels);
+
+static struct dentry *lpm_stat;
+static struct dentry *lpm_ext_comm;
+static struct msm_rpmrs_level *lpm_supp_level;
+static int lpm_level_count;
+static int lpm_level_iter;
+static bool msm_lpm_use_qtimer;
+static unsigned long lpm_sleep_time;
+static bool lpm_latency_test;
+
+static unsigned int timer_interval = 5000;
+module_param_named(lpm_timer_interval_msec, timer_interval, uint,
+	S_IRUGO | S_IWUSR | S_IWGRP);
+
+static unsigned int latency_test_interval = 50;
+module_param_named(lpm_latency_timer_interval_usec, latency_test_interval, uint,
+	S_IRUGO | S_IWUSR | S_IWGRP);
+
+static unsigned int cpu_to_debug = LPM_DEFAULT_CPU;
+static int lpm_cpu_update(const char *val, const struct kernel_param *kp)
+{
+	int ret = 0;
+	unsigned int debug_val;
+
+	ret = kstrtouint(val, 10, &debug_val);
+	if ((ret < 0) || (debug_val >= num_possible_cpus()))
+		return -EINVAL;
+	cpu_to_debug = debug_val;
+	return ret;
+}
+
+static struct kernel_param_ops cpu_debug_events = {
+	.set = lpm_cpu_update,
+};
+
+module_param_cb(cpu_to_debug, &cpu_debug_events, &cpu_to_debug,
+			S_IRUGO | S_IWUSR | S_IWGRP);
+
+static void lpm_populate_name(struct lpm_level_stat *stat,
+		struct msm_rpmrs_level *supp)
+{
+	char nm[BUF_SIZE] = {0};
+	char default_buf[20];
+
+	switch (supp->sleep_mode) {
+	case MSM_PM_SLEEP_MODE_WAIT_FOR_INTERRUPT:
+		strlcat(nm, "WFI ", BUF_SIZE);
+		break;
+	case MSM_PM_SLEEP_MODE_RAMP_DOWN_AND_WAIT_FOR_INTERRUPT:
+		strlcat(nm, "WFI voltage Rampdown ", BUF_SIZE);
+		break;
+	case MSM_PM_SLEEP_MODE_RETENTION:
+		strlcat(nm, "Retention ", BUF_SIZE);
+		break;
+	case MSM_PM_SLEEP_MODE_POWER_COLLAPSE_STANDALONE:
+		strlcat(nm, "Standalone Power collapse ", BUF_SIZE);
+		break;
+	case MSM_PM_SLEEP_MODE_POWER_COLLAPSE:
+		strlcat(nm, "Idle Power collapse ", BUF_SIZE);
+		break;
+	case MSM_PM_SLEEP_MODE_POWER_COLLAPSE_SUSPEND:
+		strlcat(nm, "Suspend Power collapse ", BUF_SIZE);
+		break;
+	default:
+		strlcat(nm, "Invalid Mode ", BUF_SIZE);
+		break;
+	}
+
+	switch (msm_pm_get_pxo(&(supp->rs_limits))) {
+	case MSM_PM(PXO_OFF):
+		strlcat(nm, "XO: OFF ", BUF_SIZE);
+		break;
+	case MSM_PM(PXO_ON):
+		strlcat(nm, "XO: ON ", BUF_SIZE);
+		break;
+	default:
+		snprintf(default_buf, sizeof(default_buf),
+			"XO : %d ", msm_pm_get_pxo(&(supp->rs_limits)));
+		strlcat(nm, default_buf , BUF_SIZE);
+		break;
+	}
+
+	switch (msm_pm_get_l2_cache(&(supp->rs_limits))) {
+	case MSM_PM(L2_CACHE_HSFS_OPEN):
+		strlcat(nm, "L2: HSFS ", BUF_SIZE);
+		break;
+	case MSM_PM(L2_CACHE_GDHS):
+		strlcat(nm, "L2: GDHS ", BUF_SIZE);
+		break;
+	case MSM_PM(L2_CACHE_RETENTION):
+		strlcat(nm, "L2: Retention ", BUF_SIZE);
+		break;
+	case MSM_PM(L2_CACHE_ACTIVE):
+		strlcat(nm, "L2: Active ", BUF_SIZE);
+		break;
+	default:
+		snprintf(default_buf, sizeof(default_buf),
+			"L2 : %d ", msm_pm_get_l2_cache(&(supp->rs_limits)));
+		strlcat(nm, default_buf , BUF_SIZE);
+		break;
+	}
+
+	snprintf(default_buf, sizeof(default_buf),
+		"Vdd_mem : %d ", msm_pm_get_vdd_mem(&(supp->rs_limits)));
+	strlcat(nm, default_buf , BUF_SIZE);
+
+	snprintf(default_buf, sizeof(default_buf),
+		"Vdd_dig : %d ", msm_pm_get_vdd_dig(&(supp->rs_limits)));
+	strlcat(nm, default_buf , BUF_SIZE);
+
+	strlcpy(stat->level_name, nm, strnlen(nm, BUF_SIZE));
+}
+
+static int64_t msm_lpm_get_time(void)
+{
+	if (msm_lpm_use_qtimer)
+		return ktime_to_ns(ktime_get());
+
+	return msm_timer_get_sclk_time(NULL);
+}
+
+static bool lpm_get_level(void *v, unsigned int *ct)
+{
+	bool ret = false;
+	int it;
+	struct msm_rpmrs_level *level_enter;
+
+	level_enter = container_of(((struct msm_lpm_sleep_data *)v)->limits,
+			struct msm_rpmrs_level, rs_limits);
+	if (level_enter) {
+		for (it = 0; it < lpm_level_count; it++)
+			if (!memcmp(level_enter , lpm_supp_level + it,
+					sizeof(struct msm_rpmrs_level))) {
+				*ct = it;
+				ret = true;
+				break;
+			}
+	}
+	return ret;
+}
+
+static int lpm_callback(struct notifier_block *self, unsigned long cmd,
+				void *sleep_data)
+{
+	static int64_t time;
+	unsigned int ct;
+	struct lpm_level_stat *stats;
+	stats = per_cpu(lpm_levels, cpu_to_debug);
+	/* Update the stats and get the start/stop time */
+	if (cmd == MSM_LPM_STATE_ENTER && !lpm_latency_test) {
+		time = msm_lpm_get_time();
+		stats[lpm_level_iter].entered = true;
+	} else if ((cmd == MSM_LPM_STATE_EXIT) && (time)
+			&& (!lpm_latency_test)) {
+		int64_t time1;
+		time1 = msm_lpm_get_time();
+		time = time1 - time;
+
+		if ((time < stats[lpm_level_iter].min_time) ||
+			(!stats[lpm_level_iter].min_time))
+			stats[lpm_level_iter].min_time = time;
+
+		if (time > stats[lpm_level_iter].max_time)
+			stats[lpm_level_iter].max_time = time;
+
+		time1 = stats[lpm_level_iter].avg_time *
+			stats[lpm_level_iter].count + time;
+		do_div(time1, ++(stats[lpm_level_iter].count));
+
+		stats[lpm_level_iter].avg_time = time1;
+		do_div(time, NSEC_PER_USEC);
+		if (time < lpm_supp_level[lpm_level_iter].
+				time_overhead_us)
+			stats[lpm_level_iter].exit_early++;
+		time = 0;
+	} else if (cmd == MSM_LPM_STATE_ENTER && lpm_latency_test) {
+
+		struct msm_lpm_sleep_data *data = sleep_data;
+		if ((lpm_get_level(sleep_data, &ct)) &&
+		(stats[ct].min_threshold == 0) &&
+		data->kernel_sleep <= lpm_sleep_time) {
+
+			stats[ct].min_threshold = lpm_sleep_time;
+			stats[ct].kernel_sleep_time =
+				data->kernel_sleep;
+		}
+	}
+	return 0;
+}
+
+static struct notifier_block lpm_idle_nb = {
+	.notifier_call = lpm_callback,
+};
+
+static void lpm_test_initiate(int lpm_level_test)
+{
+	int test_ret;
+
+	/* This will communicate to 'stat' debugfs to skip latency printing*/
+	lpm_sleep_time = 0;
+	lpm_latency_test = false;
+	/* Unregister any infinitely registered level*/
+	msm_lpm_unregister_notifier(cpu_to_debug, &lpm_idle_nb);
+
+	/* Register/Unregister for Notification */
+	while (lpm_level_iter < lpm_level_count) {
+		test_ret = msm_lpm_register_notifier(cpu_to_debug,
+				lpm_level_iter, &lpm_idle_nb, false);
+		if (test_ret < 0) {
+			pr_err("%s: Registering notifier failed\n", __func__);
+			return;
+		}
+		if (!timer_interval)
+			break;
+		msleep(timer_interval);
+		msm_lpm_unregister_notifier(cpu_to_debug, &lpm_idle_nb);
+		if (lpm_level_test == lpm_level_count)
+			lpm_level_iter++;
+		else
+			break;
+	}
+}
+
+static void lpm_latency_test_initiate(unsigned long max_time)
+{
+	int test_ret;
+	lpm_latency_test = true;
+	lpm_sleep_time = latency_test_interval;
+
+	msm_lpm_unregister_notifier(cpu_to_debug, &lpm_idle_nb);
+	if (max_time > lpm_sleep_time) {
+
+		do {
+			test_ret = msm_lpm_register_notifier(cpu_to_debug,
+					lpm_level_count + 1,
+					&lpm_idle_nb, true);
+			if (test_ret) {
+				pr_err("%s: Registering notifier failed\n",
+						__func__);
+				return;
+			}
+			usleep(lpm_sleep_time);
+			/*Unregister to ensure that we dont update the latency
+			during the timer value transistion*/
+			msm_lpm_unregister_notifier(cpu_to_debug,
+				&lpm_idle_nb);
+			lpm_sleep_time += latency_test_interval;
+		} while (lpm_sleep_time < max_time);
+	} else
+		pr_err("%s: Invalid time interval specified\n", __func__);
+
+	lpm_latency_test = false;
+}
+
+static ssize_t lpm_test_comm_read(struct file *fp, char __user *user_buffer,
+				size_t buffer_length, loff_t *position)
+{
+	int i = 0;
+	int count = buffer_length;
+	int alloc_size = 100 * lpm_level_count;
+	char *temp_buf;
+	char *comm_buf;
+	ssize_t ret;
+
+	comm_buf = kzalloc(alloc_size, GFP_KERNEL);
+	if (!comm_buf) {
+		pr_err("%s:Memory alloc failed\n", __func__);
+		ret = 0;
+		goto com_read_failed;
+	}
+	temp_buf = comm_buf;
+
+	SNPRINTF(temp_buf, count, "Low power modes available:\n");
+
+	for (i = 0; i < lpm_level_count; i++)
+		SNPRINTF(temp_buf, count, "%d. %s\n", i,
+			per_cpu(lpm_levels, cpu_to_debug)[i].level_name);
+
+	SNPRINTF(temp_buf, count, "%d. MSM test all lpm\n", i++);
+	SNPRINTF(temp_buf, count, "%d. MSM determine latency\n", i);
+
+	ret = simple_read_from_buffer(user_buffer, buffer_length - count,
+					position, comm_buf, alloc_size);
+	kfree(comm_buf);
+
+com_read_failed:
+	return ret;
+}
+
+char *trimspaces(char *time_buf)
+{
+	int len;
+	char *tail;
+
+	len = strnlen(time_buf, INPUT_COUNT_BUF);
+	tail = time_buf + len;
+	while (isspace(*time_buf) && (time_buf != tail))
+		time_buf++;
+	if (time_buf == tail) {
+		time_buf = NULL;
+		goto exit_trim_spaces;
+	}
+	len = strnlen(time_buf, INPUT_COUNT_BUF);
+	tail = time_buf + len - 1;
+	while (isspace(*tail) && tail != time_buf) {
+		*tail = '\0';
+		tail--;
+	}
+exit_trim_spaces:
+	return time_buf;
+}
+
+static ssize_t lpm_test_comm_write(struct file *fp, const char __user
+			*user_buffer, size_t count, loff_t *position)
+{
+	ssize_t ret;
+	int str_ret;
+	int lpm_level_test;
+	char *new_ptr;
+	char *comm_buf;
+
+	comm_buf = kzalloc(COMM_BUF_SIZE, GFP_KERNEL);
+	if (!comm_buf) {
+		pr_err("\'%s\': kzalloc failed\n", __func__);
+		return -EINVAL;
+	}
+
+	memset(comm_buf, '\0', COMM_BUF_SIZE);
+
+	ret = simple_write_to_buffer(comm_buf, COMM_BUF_SIZE, position,
+					user_buffer, count);
+	new_ptr = trimspaces(comm_buf);
+	if (!new_ptr) {
+		pr_err("%s: Test case number input invalid\n", __func__);
+		goto write_com_failed;
+	}
+
+	if (!memcmp(comm_buf, LPM_TEST_ALL_LEVELS,
+			sizeof(LPM_TEST_ALL_LEVELS) - 1)) {
+		lpm_level_test = lpm_level_count;
+		lpm_level_iter = 0;
+		lpm_test_initiate(lpm_level_test);
+		goto write_com_success;
+	} else if (!memcmp(comm_buf, LPM_TEST_LATENCIES,
+			sizeof(LPM_TEST_LATENCIES) - 1)) {
+		lpm_level_test = lpm_level_count + 1;
+		lpm_latency_test_initiate(timer_interval * USEC_PER_MSEC);
+		goto write_com_success;
+	} else if (!memcmp(comm_buf, LPM_TEST_CLEAR,
+			sizeof(LPM_TEST_CLEAR) - 1)) {
+		msm_lpm_unregister_notifier(cpu_to_debug, &lpm_idle_nb);
+		goto write_com_success;
+	}
+
+	str_ret = kstrtoint(new_ptr, 10, &lpm_level_test);
+	if ((str_ret) || (lpm_level_test > (lpm_level_count + 1)) ||
+		(lpm_level_test < 0))
+		goto write_com_failed;
+
+	lpm_level_iter = lpm_level_test;
+	lpm_test_initiate(lpm_level_test);
+	goto write_com_success;
+
+write_com_failed:
+	ret = -EINVAL;
+write_com_success:
+	kfree(comm_buf);
+	return ret;
+}
+
+static ssize_t lpm_test_stat_read(struct file *fp, char __user *user_buffer,
+				size_t buffer_length, loff_t *position)
+{
+	int i = 0;
+	int j = 0;
+	int count = buffer_length;
+	char *stat_buf;
+	char *stat_buf_start;
+	size_t stat_buf_size;
+	ssize_t ret;
+	int64_t min_ns;
+	int64_t max_ns;
+	int64_t avg_ns;
+	uint32_t min_ms;
+	uint32_t max_ms;
+	uint32_t avg_ms;
+
+	stat_buf_size = ((sizeof(struct lpm_level_stat) * lpm_level_count) +
+				STAT_BUF_EXTRA_SIZE);
+	stat_buf = kzalloc(stat_buf_size, GFP_KERNEL);
+	if (!stat_buf) {
+		pr_err("\'%s\': kzalloc failed\n", __func__);
+		return -EINVAL;
+	}
+	stat_buf_start = stat_buf;
+	mutex_lock(&lpm_stats_mutex);
+	memset(stat_buf, '\0', stat_buf_size);
+	SNPRINTF(stat_buf, count, "\n\nStats for CPU: %d\nTotal Levels: %d\n",
+			cpu_to_debug, lpm_level_count);
+	if (!lpm_sleep_time) {
+		SNPRINTF(stat_buf, count, "Level(s) failed: ");
+		for (i = 0 ; i < lpm_level_count; i++) {
+			if (per_cpu(lpm_levels, cpu_to_debug)[i].entered)
+				continue;
+			else {
+				SNPRINTF(stat_buf, count,
+					"\n%d. %s", ++j, per_cpu(lpm_levels,
+					cpu_to_debug)[i].level_name);
+			}
+		}
+		SNPRINTF(stat_buf, count, "\n\nSTATS:");
+		for (i = 0; i < lpm_level_count; i++) {
+			min_ns = per_cpu(lpm_levels, cpu_to_debug)[i].min_time;
+			min_ms = do_div(min_ns, NSEC_PER_MSEC);
+			max_ns = per_cpu(lpm_levels, cpu_to_debug)[i].max_time;
+			max_ms = do_div(max_ns, NSEC_PER_MSEC);
+			avg_ns = per_cpu(lpm_levels, cpu_to_debug)[i].avg_time;
+			avg_ms = do_div(avg_ns, NSEC_PER_MSEC);
+			SNPRINTF(stat_buf, count, "\nLEVEL: %s\n"
+				"Entered : %lld\n"
+				"Early wakeup : %lld\n"
+				"Min Time (mSec): %lld.%06u\n"
+				"Max Time (mSec): %lld.%06u\n"
+				"Avg Time (mSec): %lld.%06u\n",
+				per_cpu(lpm_levels, cpu_to_debug)[i].level_name,
+				per_cpu(lpm_levels, cpu_to_debug)[i].count,
+				per_cpu(lpm_levels, cpu_to_debug)[i].exit_early,
+				min_ns, min_ms,
+				max_ns, max_ms,
+				avg_ns, avg_ms);
+		}
+	} else {
+		for (i = 0; i < lpm_level_count; i++) {
+			SNPRINTF(stat_buf, count, "\nLEVEL: %s\n"
+				"Min Timer value (uSec): %lu\n"
+				"Kernel sleep time (uSec): %u\n",
+				per_cpu(lpm_levels, cpu_to_debug)[i].level_name,
+				per_cpu(lpm_levels, cpu_to_debug)[i].
+				min_threshold,
+				per_cpu(lpm_levels,
+				cpu_to_debug)[i].kernel_sleep_time);
+		}
+	}
+
+	ret = simple_read_from_buffer(user_buffer, buffer_length - count,
+				position, stat_buf_start, stat_buf_size);
+
+	mutex_unlock(&lpm_stats_mutex);
+	kfree(stat_buf_start);
+	return ret;
+}
+
+static ssize_t lpm_test_stat_write(struct file *fp, const char __user
+				*user_buffer, size_t count, loff_t *position)
+{
+	char buf[sizeof(LPM_STATS_RESET)];
+	int ret;
+	int i;
+	struct lpm_level_stat *stats;
+
+	if (count > sizeof(LPM_STATS_RESET)) {
+		ret = -EINVAL;
+		goto write_debug_failed;
+	}
+
+	simple_write_to_buffer(buf, sizeof(LPM_STATS_RESET), position,
+				user_buffer, count);
+
+	if (memcmp(buf, LPM_STATS_RESET, sizeof(LPM_STATS_RESET) - 1)) {
+		ret = -EINVAL;
+		goto write_debug_failed;
+	}
+
+	mutex_lock(&lpm_stats_mutex);
+	stats = per_cpu(lpm_levels, cpu_to_debug);
+	for (i = 0 ; i < lpm_level_count; i++) {
+		stats[i].entered = 0;
+		stats[i].min_time = 0;
+		stats[i].max_time = 0;
+		stats[i].avg_time = 0;
+		stats[i].count = 0;
+		stats[i].exit_early = 0;
+		stats[i].min_threshold = 0;
+		stats[i].kernel_sleep_time = 0;
+	}
+	mutex_unlock(&lpm_stats_mutex);
+	return count;
+write_debug_failed:
+	return ret;
+}
+
+static void lpm_init_rpm_levels(int test_lpm_level_count,
+		struct msm_rpmrs_level *test_levels)
+{
+	int i = 0;
+	unsigned int m_cpu = 0;
+	struct lpm_level_stat *stat_levels = NULL;
+
+	if (test_lpm_level_count < 0)
+		return;
+
+	lpm_level_count = test_lpm_level_count;
+
+	lpm_supp_level = test_levels;
+	for_each_possible_cpu(m_cpu) {
+		stat_levels = kzalloc(sizeof(struct lpm_level_stat) *
+				lpm_level_count, GFP_KERNEL);
+		if (!stat_levels) {
+			for (i = m_cpu - 1; i >= 0; i--)
+				kfree(per_cpu(lpm_levels, i));
+			return;
+		}
+
+		for (i = 0; i < lpm_level_count; i++)
+			lpm_populate_name(&stat_levels[i], &lpm_supp_level[i]);
+
+		per_cpu(lpm_levels, m_cpu) = stat_levels;
+	}
+}
+
+static const struct file_operations fops_stat = {
+	.read = lpm_test_stat_read,
+	.write = lpm_test_stat_write,
+};
+
+static const struct file_operations fops_comm = {
+	.read = lpm_test_comm_read,
+	.write = lpm_test_comm_write,
+};
+
+static int __devinit lpm_test_init(int test_lpm_level_count,
+		struct msm_rpmrs_level *test_levels)
+{
+	int filevalue;
+	int lpm_comm;
+	int ret = -EINVAL;
+	struct dentry *parent_dir = NULL;
+
+	parent_dir = debugfs_create_dir("msm_lpm_debug", NULL);
+	if (!parent_dir) {
+		pr_err("%s: debugfs directory creation failed\n",
+				__func__);
+		goto init_err;
+	}
+
+	lpm_stat = debugfs_create_file("stat",
+			S_IRUGO | S_IWUSR | S_IWGRP, parent_dir,
+			&filevalue, &fops_stat);
+	if (!lpm_stat) {
+		pr_err("%s: lpm_stats debugfs creation failed\n",
+				__func__);
+		goto init_err;
+	}
+
+	lpm_ext_comm = debugfs_create_file("comm",
+			S_IRUGO | S_IWUSR | S_IWGRP, parent_dir, &lpm_comm,
+			&fops_comm);
+	if (!lpm_ext_comm) {
+		pr_err("%s: lpm_comm debugfs creation failed\n",
+			__func__);
+		debugfs_remove(lpm_stat);
+		goto init_err;
+	}
+
+	/*Query RPM resources and allocate the data sturctures*/
+	lpm_init_rpm_levels(test_lpm_level_count, test_levels);
+	ret = 0;
+
+init_err:
+	return ret;
+}
+
+static int  __devexit lpm_test_exit(struct platform_device *pdev)
+{
+	unsigned int m_cpu = 0;
+
+	kfree(lpm_supp_level);
+	for_each_possible_cpu(m_cpu)
+		kfree(per_cpu(lpm_levels, m_cpu));
+	debugfs_remove(lpm_stat);
+	debugfs_remove(lpm_ext_comm);
+	return 0;
+}
+
+static int __devinit lpm_test_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct lpm_test_platform_data *pdata;
+	struct msm_rpmrs_level *test_levels;
+	int test_lpm_level_count;
+
+	pdata = pdev->dev.platform_data;
+
+	if (!pdata) {
+		dev_err(dev, "no platform data specified\n");
+		return -EINVAL;
+	}
+
+	test_levels = pdata->msm_lpm_test_levels;
+	test_lpm_level_count = pdata->msm_lpm_test_level_count;
+
+	if (pdata->use_qtimer)
+		msm_lpm_use_qtimer = true;
+
+	lpm_test_init(test_lpm_level_count, test_levels);
+
+	return 0;
+}
+
+static struct platform_driver lpm_test_driver = {
+	.probe = lpm_test_probe,
+	.remove = lpm_test_exit,
+	.driver = {
+		.name = "lpm_test",
+		.owner = THIS_MODULE,
+	},
+};
+
+static int __init lpm_test_platform_driver_init(void)
+{
+	return platform_driver_register(&lpm_test_driver);
+}
+
+late_initcall(lpm_test_platform_driver_init);
diff --git a/arch/arm/mach-msm/test-lpm.h b/arch/arm/mach-msm/test-lpm.h
new file mode 100644
index 0000000..1486f88
--- /dev/null
+++ b/arch/arm/mach-msm/test-lpm.h
@@ -0,0 +1,22 @@
+/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#ifndef __ARCH_ARM_MACH_MSM_TEST_LPM_H
+#define __ARCH_ARM_MACH_MSM_TEST_LPM_H
+
+struct lpm_test_platform_data {
+	struct msm_rpmrs_level *msm_lpm_test_levels;
+	int msm_lpm_test_level_count;
+	bool use_qtimer;
+};
+#endif
diff --git a/arch/arm/mach-msm/test_qmi_client.c b/arch/arm/mach-msm/test_qmi_client.c
new file mode 100644
index 0000000..d070e37
--- /dev/null
+++ b/arch/arm/mach-msm/test_qmi_client.c
@@ -0,0 +1,344 @@
+/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/errno.h>
+#include <linux/delay.h>
+#include <linux/debugfs.h>
+#include <linux/qmi_encdec.h>
+
+#include <asm/uaccess.h>
+
+#include <mach/msm_qmi_interface.h>
+
+#include "kernel_test_service_v01.h"
+
+#define TEST_SERVICE_SVC_ID 0x0000000f
+#define TEST_SERVICE_INS_ID 1
+
+static int test_rep_cnt = 10;
+module_param_named(rep_cnt, test_rep_cnt, int, S_IRUGO | S_IWUSR | S_IWGRP);
+
+static int test_data_sz = 50;
+module_param_named(data_sz, test_data_sz, int, S_IRUGO | S_IWUSR | S_IWGRP);
+
+static int test_clnt_debug_mask;
+module_param_named(debug_mask, test_clnt_debug_mask,
+		   int, S_IRUGO | S_IWUSR | S_IWGRP);
+
+#define D(x...) do { \
+	if (test_clnt_debug_mask) \
+		pr_debug(x); \
+} while (0)
+
+/* Variable to initiate the test through debugfs interface */
+static struct dentry *test_dent;
+
+/* Test client port for IPC Router */
+static struct qmi_handle *test_clnt;
+static int test_clnt_reset;
+
+/* Reader thread to receive responses & indications */
+static void test_clnt_recv_msg(struct work_struct *work);
+static DECLARE_DELAYED_WORK(work_recv_msg, test_clnt_recv_msg);
+static void test_clnt_svc_arrive(struct work_struct *work);
+static DECLARE_DELAYED_WORK(work_svc_arrive, test_clnt_svc_arrive);
+static void test_clnt_svc_exit(struct work_struct *work);
+static DECLARE_DELAYED_WORK(work_svc_exit, test_clnt_svc_exit);
+static struct workqueue_struct *test_clnt_workqueue;
+
+/* Variable to hold the test result */
+static int test_res;
+
+static int test_qmi_ping_pong_send_sync_msg(void)
+{
+	struct test_ping_req_msg_v01 req;
+	struct test_ping_resp_msg_v01 resp;
+	struct msg_desc req_desc, resp_desc;
+	int rc;
+
+	memcpy(req.ping, "ping", sizeof(req.ping));
+	req.client_name_valid = 0;
+
+	req_desc.max_msg_len = TEST_PING_REQ_MAX_MSG_LEN_V01;
+	req_desc.msg_id = TEST_PING_REQ_MSG_ID_V01;
+	req_desc.ei_array = test_ping_req_msg_v01_ei;
+
+	resp_desc.max_msg_len = TEST_PING_REQ_MAX_MSG_LEN_V01;
+	resp_desc.msg_id = TEST_PING_REQ_MSG_ID_V01;
+	resp_desc.ei_array = test_ping_resp_msg_v01_ei;
+
+	rc = qmi_send_req_wait(test_clnt, &req_desc, &req, sizeof(req),
+			       &resp_desc, &resp, sizeof(resp), 0);
+	if (rc < 0) {
+		pr_err("%s: send req failed %d\n", __func__, rc);
+		return rc;
+	}
+
+	D("%s: Received %s response\n", __func__, resp.pong);
+	return rc;
+}
+
+static int test_qmi_data_send_sync_msg(unsigned int data_len)
+{
+	struct test_data_req_msg_v01 *req;
+	struct test_data_resp_msg_v01 *resp;
+	struct msg_desc req_desc, resp_desc;
+	int rc, i;
+
+	req = kzalloc(sizeof(struct test_data_req_msg_v01), GFP_KERNEL);
+	if (!req) {
+		pr_err("%s: Data req msg alloc failed\n", __func__);
+		return -ENOMEM;
+	}
+
+	resp = kzalloc(sizeof(struct test_data_resp_msg_v01), GFP_KERNEL);
+	if (!resp) {
+		pr_err("%s: Data resp msg alloc failed\n", __func__);
+		kfree(req);
+		return -ENOMEM;
+	}
+
+	req->data_len = data_len;
+	for (i = 0; i < data_len; i = i + sizeof(int))
+		memcpy(req->data + i, (uint8_t *)&i, sizeof(int));
+	req->client_name_valid = 0;
+
+	req_desc.max_msg_len = TEST_DATA_REQ_MAX_MSG_LEN_V01;
+	req_desc.msg_id = TEST_DATA_REQ_MSG_ID_V01;
+	req_desc.ei_array = test_data_req_msg_v01_ei;
+
+	resp_desc.max_msg_len = TEST_DATA_REQ_MAX_MSG_LEN_V01;
+	resp_desc.msg_id = TEST_DATA_REQ_MSG_ID_V01;
+	resp_desc.ei_array = test_data_resp_msg_v01_ei;
+
+	rc = qmi_send_req_wait(test_clnt, &req_desc, req, sizeof(*req),
+			       &resp_desc, resp, sizeof(*resp), 0);
+	if (rc < 0) {
+		pr_err("%s: send req failed\n", __func__);
+		goto data_send_err;
+	}
+
+	D("%s: data_valid %d\n", __func__, resp->data_valid);
+	D("%s: data_len %d\n", __func__, resp->data_len);
+data_send_err:
+	kfree(resp);
+	kfree(req);
+	return rc;
+}
+
+static void test_clnt_recv_msg(struct work_struct *work)
+{
+	int rc;
+
+	rc = qmi_recv_msg(test_clnt);
+	if (rc < 0)
+		pr_err("%s: Error receiving message\n", __func__);
+}
+
+static void test_clnt_notify(struct qmi_handle *handle,
+			     enum qmi_event_type event, void *notify_priv)
+{
+	switch (event) {
+	case QMI_RECV_MSG:
+		queue_delayed_work(test_clnt_workqueue,
+				   &work_recv_msg, 0);
+		break;
+	default:
+		break;
+	}
+}
+
+static void test_clnt_svc_arrive(struct work_struct *work)
+{
+	int rc;
+
+	D("%s begins\n", __func__);
+
+	/* Create a Local client port for QMI communication */
+	test_clnt = qmi_handle_create(test_clnt_notify, NULL);
+	if (!test_clnt) {
+		pr_err("%s: QMI client handle alloc failed\n", __func__);
+		return;
+	}
+
+	D("%s: Lookup server name\n", __func__);
+	rc = qmi_connect_to_service(test_clnt, TEST_SERVICE_SVC_ID,
+				    TEST_SERVICE_INS_ID);
+	if (rc < 0) {
+		pr_err("%s: Server not found\n", __func__);
+		qmi_handle_destroy(test_clnt);
+		test_clnt = NULL;
+		return;
+	}
+	test_clnt_reset = 0;
+	D("%s complete\n", __func__);
+}
+
+static void test_clnt_svc_exit(struct work_struct *work)
+{
+	D("%s begins\n", __func__);
+
+	qmi_handle_destroy(test_clnt);
+	test_clnt_reset = 1;
+	test_clnt = NULL;
+
+	D("%s complete\n", __func__);
+}
+
+static int test_clnt_svc_event_notify(struct notifier_block *this,
+				      unsigned long code,
+				      void *_cmd)
+{
+	D("%s: event %ld\n", __func__, code);
+	switch (code) {
+	case QMI_SERVER_ARRIVE:
+		queue_delayed_work(test_clnt_workqueue,
+				   &work_svc_arrive, 0);
+		break;
+	case QMI_SERVER_EXIT:
+		queue_delayed_work(test_clnt_workqueue,
+				   &work_svc_exit, 0);
+		break;
+	default:
+		break;
+	}
+	return 0;
+}
+
+static int test_qmi_open(struct inode *ip, struct file *fp)
+{
+	if (!test_clnt) {
+		pr_err("%s Test client is not initialized\n", __func__);
+		return -ENODEV;
+	}
+	return 0;
+}
+
+static ssize_t test_qmi_read(struct file *fp, char __user *buf,
+		size_t count, loff_t *pos)
+{
+	char _buf[16];
+	snprintf(_buf, sizeof(_buf), "%d\n", test_res);
+	test_res = 0;
+	return simple_read_from_buffer(buf, count, pos,
+				       _buf, strnlen(_buf, 16));
+}
+
+static int test_qmi_release(struct inode *ip, struct file *fp)
+{
+	return 0;
+}
+
+static ssize_t test_qmi_write(struct file *fp, const char __user *buf,
+			size_t count, loff_t *pos)
+{
+	unsigned char cmd[64];
+	int len;
+	int i;
+
+	if (count < 1)
+		return 0;
+
+	len = min(count, (sizeof(cmd) - 1));
+
+	if (copy_from_user(cmd, buf, len))
+		return -EFAULT;
+
+	cmd[len] = 0;
+	if (cmd[len-1] == '\n') {
+		cmd[len-1] = 0;
+		len--;
+	}
+
+	if (!strncmp(cmd, "ping_pong", sizeof(cmd))) {
+		for (i = 0; i < test_rep_cnt; i++) {
+			test_res = test_qmi_ping_pong_send_sync_msg();
+			if (test_res == -ENETRESET || test_clnt_reset) {
+				do {
+					msleep(50);
+				} while (test_clnt_reset);
+			}
+		}
+	} else if (!strncmp(cmd, "data", sizeof(cmd))) {
+		for (i = 0; i < test_rep_cnt; i++) {
+			test_res = test_qmi_data_send_sync_msg(test_data_sz);
+			if (test_res == -ENETRESET || test_clnt_reset) {
+				do {
+					msleep(50);
+				} while (test_clnt_reset);
+			}
+		}
+	} else {
+		test_res = -EINVAL;
+	}
+	return count;
+}
+
+static struct notifier_block test_clnt_nb = {
+	.notifier_call = test_clnt_svc_event_notify,
+};
+
+static const struct file_operations debug_ops = {
+	.owner = THIS_MODULE,
+	.open = test_qmi_open,
+	.read = test_qmi_read,
+	.write = test_qmi_write,
+	.release = test_qmi_release,
+};
+
+static int __init test_qmi_init(void)
+{
+	int rc;
+
+	test_clnt_workqueue = create_singlethread_workqueue("test_clnt");
+	if (!test_clnt_workqueue)
+		return -EFAULT;
+
+	rc = qmi_svc_event_notifier_register(TEST_SERVICE_SVC_ID,
+				TEST_SERVICE_INS_ID, &test_clnt_nb);
+	if (rc < 0) {
+		pr_err("%s: notifier register failed\n", __func__);
+		destroy_workqueue(test_clnt_workqueue);
+		return rc;
+	}
+
+	test_dent = debugfs_create_file("test_qmi_client", 0444, 0,
+					 NULL, &debug_ops);
+	if (IS_ERR(test_dent)) {
+		pr_err("%s: unable to create debugfs %ld\n",
+			__func__, IS_ERR(test_dent));
+		test_dent = NULL;
+		qmi_svc_event_notifier_unregister(TEST_SERVICE_SVC_ID,
+					TEST_SERVICE_INS_ID, &test_clnt_nb);
+		destroy_workqueue(test_clnt_workqueue);
+		return -EFAULT;
+	}
+
+	return 0;
+}
+
+static void __exit test_qmi_exit(void)
+{
+	qmi_svc_event_notifier_unregister(TEST_SERVICE_SVC_ID,
+					TEST_SERVICE_INS_ID, &test_clnt_nb);
+	destroy_workqueue(test_clnt_workqueue);
+	debugfs_remove(test_dent);
+}
+
+module_init(test_qmi_init);
+module_exit(test_qmi_exit);
+
+MODULE_DESCRIPTION("TEST QMI Client Driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/char/diag/diagchar_core.c b/drivers/char/diag/diagchar_core.c
index f6c26c3..8a3a645 100644
--- a/drivers/char/diag/diagchar_core.c
+++ b/drivers/char/diag/diagchar_core.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2008-2012, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2008-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -1273,6 +1273,13 @@
 		ret = -ENOMEM;
 		goto fail_free_hdlc;
 	}
+	if (HDLC_OUT_BUF_SIZE < (2*payload_size) + 3) {
+		pr_err("diag: Dropping packet, HDLC encoded packet payload size crosses buffer limit. Current payload size %d\n",
+				((2*payload_size) + 3));
+		driver->dropped_count++;
+		ret = -EBADMSG;
+		goto fail_free_hdlc;
+	}
 	if (HDLC_OUT_BUF_SIZE - driver->used <= (2*payload_size) + 3) {
 		err = diag_device_write(buf_hdlc, APPS_DATA, NULL);
 		if (err) {
@@ -1343,8 +1350,8 @@
 		driver->used = 0;
 	}
 
-	mutex_unlock(&driver->diagchar_mutex);
 	diagmem_free(driver, buf_copy, POOL_TYPE_COPY);
+	mutex_unlock(&driver->diagchar_mutex);
 	if (!timer_in_progress)	{
 		timer_in_progress = 1;
 		ret = mod_timer(&drain_timer, jiffies + msecs_to_jiffies(500));
diff --git a/drivers/coresight/coresight-etm.c b/drivers/coresight/coresight-etm.c
index 9f96b19..b569aed 100644
--- a/drivers/coresight/coresight-etm.c
+++ b/drivers/coresight/coresight-etm.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011-2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2011-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -91,75 +91,87 @@
  */
 
 /* Trace registers (0x000-0x2FC) */
-#define ETMCR			(0x000)
-#define ETMCCR			(0x004)
-#define ETMTRIGGER		(0x008)
-#define ETMSR			(0x010)
-#define ETMSCR			(0x014)
-#define ETMTSSCR		(0x018)
-#define ETMTEEVR		(0x020)
-#define ETMTECR1		(0x024)
-#define ETMFFLR			(0x02C)
-#define ETMACVRn(n)		(0x040 + (n * 4))
-#define ETMACTRn(n)		(0x080 + (n * 4))
-#define ETMCNTRLDVRn(n)		(0x140 + (n * 4))
-#define ETMCNTENRn(n)		(0x150 + (n * 4))
-#define ETMCNTRLDEVRn(n)	(0x160 + (n * 4))
-#define ETMCNTVRn(n)		(0x170 + (n * 4))
-#define ETMSQ12EVR		(0x180)
-#define ETMSQ21EVR		(0x184)
-#define ETMSQ23EVR		(0x188)
-#define ETMSQ31EVR		(0x18C)
-#define ETMSQ32EVR		(0x190)
-#define ETMSQ13EVR		(0x194)
-#define ETMSQR			(0x19C)
-#define ETMEXTOUTEVRn(n)	(0x1A0 + (n * 4))
-#define ETMCIDCVRn(n)		(0x1B0 + (n * 4))
-#define ETMCIDCMR		(0x1BC)
-#define ETMIMPSPEC0		(0x1C0)
-#define ETMIMPSPEC1		(0x1C4)
-#define ETMIMPSPEC2		(0x1C8)
-#define ETMIMPSPEC3		(0x1CC)
-#define ETMIMPSPEC4		(0x1D0)
-#define ETMIMPSPEC5		(0x1D4)
-#define ETMIMPSPEC6		(0x1D8)
-#define ETMIMPSPEC7		(0x1DC)
-#define ETMSYNCFR		(0x1E0)
-#define ETMIDR			(0x1E4)
-#define ETMCCER			(0x1E8)
-#define ETMEXTINSELR		(0x1EC)
-#define ETMTESSEICR		(0x1F0)
-#define ETMEIBCR		(0x1F4)
-#define ETMTSEVR		(0x1F8)
-#define ETMAUXCR		(0x1FC)
-#define ETMTRACEIDR		(0x200)
-#define ETMVMIDCVR		(0x240)
+#define ETMCR				(0x000)
+#define ETMCCR				(0x004)
+#define ETMTRIGGER			(0x008)
+#define ETMASSICCTLR			(0x00C)
+#define ETMSR				(0x010)
+#define ETMSCR				(0x014)
+#define ETMTSSCR			(0x018)
+#define ETMTECR2			(0x01C)
+#define ETMTEEVR			(0x020)
+#define ETMTECR1			(0x024)
+#define ETMFFLR				(0x02C)
+#define ETMVDEVR			(0x030)
+#define ETMVDCR1			(0x034)
+#define ETMVDCR3			(0x03C)
+#define ETMACVRn(n)			(0x040 + (n * 4))
+#define ETMACTRn(n)			(0x080 + (n * 4))
+#define ETMDCVRn(n)			(0x0C0 + (n * 8))
+#define ETMDCMRn(n)			(0x100 + (n * 8))
+#define ETMCNTRLDVRn(n)			(0x140 + (n * 4))
+#define ETMCNTENRn(n)			(0x150 + (n * 4))
+#define ETMCNTRLDEVRn(n)		(0x160 + (n * 4))
+#define ETMCNTVRn(n)			(0x170 + (n * 4))
+#define ETMSQ12EVR			(0x180)
+#define ETMSQ21EVR			(0x184)
+#define ETMSQ23EVR			(0x188)
+#define ETMSQ31EVR			(0x18C)
+#define ETMSQ32EVR			(0x190)
+#define ETMSQ13EVR			(0x194)
+#define ETMSQR				(0x19C)
+#define ETMEXTOUTEVRn(n)		(0x1A0 + (n * 4))
+#define ETMCIDCVRn(n)			(0x1B0 + (n * 4))
+#define ETMCIDCMR			(0x1BC)
+#define ETMIMPSPEC0			(0x1C0)
+#define ETMIMPSPEC1			(0x1C4)
+#define ETMIMPSPEC2			(0x1C8)
+#define ETMIMPSPEC3			(0x1CC)
+#define ETMIMPSPEC4			(0x1D0)
+#define ETMIMPSPEC5			(0x1D4)
+#define ETMIMPSPEC6			(0x1D8)
+#define ETMIMPSPEC7			(0x1DC)
+#define ETMSYNCFR			(0x1E0)
+#define ETMIDR				(0x1E4)
+#define ETMCCER				(0x1E8)
+#define ETMEXTINSELR			(0x1EC)
+#define ETMTESSEICR			(0x1F0)
+#define ETMEIBCR			(0x1F4)
+#define ETMTSEVR			(0x1F8)
+#define ETMAUXCR			(0x1FC)
+#define ETMTRACEIDR			(0x200)
+#define ETMIDR2				(0x208)
+#define ETMVMIDCVR			(0x240)
 /* Management registers (0x300-0x314) */
-#define ETMOSLAR		(0x300)
-#define ETMOSLSR		(0x304)
-#define ETMOSSRR		(0x308)
-#define ETMPDCR			(0x310)
-#define ETMPDSR			(0x314)
+#define ETMOSLAR			(0x300)
+#define ETMOSLSR			(0x304)
+#define ETMOSSRR			(0x308)
+#define ETMPDCR				(0x310)
+#define ETMPDSR				(0x314)
 
-#define ETM_MAX_ADDR_CMP	(16)
-#define ETM_MAX_CNTR		(4)
-#define ETM_MAX_CTXID_CMP	(3)
+#define ETM_MAX_ADDR_CMP		(16)
+#define ETM_MAX_CNTR			(4)
+#define ETM_MAX_CTXID_CMP		(3)
 
-#define ETM_MODE_EXCLUDE	BIT(0)
-#define ETM_MODE_CYCACC		BIT(1)
-#define ETM_MODE_STALL		BIT(2)
-#define ETM_MODE_TIMESTAMP	BIT(3)
-#define ETM_MODE_CTXID		BIT(4)
-#define ETM_MODE_ALL		(0x1F)
+#define ETM_MODE_EXCLUDE		BIT(0)
+#define ETM_MODE_CYCACC			BIT(1)
+#define ETM_MODE_STALL			BIT(2)
+#define ETM_MODE_TIMESTAMP		BIT(3)
+#define ETM_MODE_CTXID			BIT(4)
+#define ETM_MODE_DATA_TRACE_VAL		BIT(5)
+#define ETM_MODE_DATA_TRACE_ADDR	BIT(6)
+#define ETM_MODE_ALL			(0x7F)
 
-#define ETM_EVENT_MASK		(0x1FFFF)
-#define ETM_SYNC_MASK		(0xFFF)
-#define ETM_ALL_MASK		(0xFFFFFFFF)
+#define ETM_DATACMP_ENABLE		(0x2)
 
-#define ETM_SEQ_STATE_MAX_VAL	(0x2)
+#define ETM_EVENT_MASK			(0x1FFFF)
+#define ETM_SYNC_MASK			(0xFFF)
+#define ETM_ALL_MASK			(0xFFFFFFFF)
 
-#define ETM_REG_DUMP_VER_OFF	(4)
-#define ETM_REG_DUMP_VER	(1)
+#define ETM_SEQ_STATE_MAX_VAL		(0x2)
+
+#define ETM_REG_DUMP_VER_OFF		(4)
+#define ETM_REG_DUMP_VER		(1)
 
 enum etm_addr_type {
 	ETM_ADDR_TYPE_NONE,
@@ -203,6 +215,7 @@
 	uint8_t				nr_ext_inp;
 	uint8_t				nr_ext_out;
 	uint8_t				nr_ctxid_cmp;
+	uint8_t				nr_data_cmp;
 	uint8_t				reset;
 	uint32_t			mode;
 	uint32_t			ctrl;
@@ -210,11 +223,18 @@
 	uint32_t			startstop_ctrl;
 	uint32_t			enable_event;
 	uint32_t			enable_ctrl1;
+	uint32_t			enable_ctrl2;
 	uint32_t			fifofull_level;
 	uint8_t				addr_idx;
 	uint32_t			addr_val[ETM_MAX_ADDR_CMP];
 	uint32_t			addr_acctype[ETM_MAX_ADDR_CMP];
 	uint32_t			addr_type[ETM_MAX_ADDR_CMP];
+	bool				data_trace_support;
+	uint32_t			data_val[ETM_MAX_ADDR_CMP];
+	uint32_t			data_mask[ETM_MAX_ADDR_CMP];
+	uint32_t			viewdata_event;
+	uint32_t			viewdata_ctrl1;
+	uint32_t			viewdata_ctrl3;
 	uint8_t				cntr_idx;
 	uint32_t			cntr_rld_val[ETM_MAX_CNTR];
 	uint32_t			cntr_event[ETM_MAX_CNTR];
@@ -247,8 +267,10 @@
  */
 static void etm_os_unlock(void *info)
 {
-	etm_writel_cp14(0x0, ETMOSLAR);
-	isb();
+	if (cpu_is_krait()) {
+		etm_writel_cp14(0x0, ETMOSLAR);
+		isb();
+	}
 }
 
 /*
@@ -382,6 +404,14 @@
 	ETM_LOCK(drvdata);
 }
 
+static bool etm_version_gte(uint8_t arch, uint8_t base_arch)
+{
+	if (arch >= base_arch && ((arch & PFT_ARCH_MAJOR) != PFT_ARCH_MAJOR))
+		return true;
+	else
+		return false;
+}
+
 static void __etm_enable(void *info)
 {
 	int i;
@@ -409,13 +439,24 @@
 	etm_writel(drvdata, drvdata->ctrl | etmcr, ETMCR);
 	etm_writel(drvdata, drvdata->trigger_event, ETMTRIGGER);
 	etm_writel(drvdata, drvdata->startstop_ctrl, ETMTSSCR);
+	if (etm_version_gte(drvdata->arch, ETM_ARCH_V1_2))
+		etm_writel(drvdata, drvdata->enable_ctrl2, ETMTECR2);
 	etm_writel(drvdata, drvdata->enable_event, ETMTEEVR);
 	etm_writel(drvdata, drvdata->enable_ctrl1, ETMTECR1);
 	etm_writel(drvdata, drvdata->fifofull_level, ETMFFLR);
+	if (drvdata->data_trace_support == true) {
+		etm_writel(drvdata, drvdata->viewdata_event, ETMVDEVR);
+		etm_writel(drvdata, drvdata->viewdata_ctrl1, ETMVDCR1);
+		etm_writel(drvdata, drvdata->viewdata_ctrl3, ETMVDCR3);
+	}
 	for (i = 0; i < drvdata->nr_addr_cmp; i++) {
 		etm_writel(drvdata, drvdata->addr_val[i], ETMACVRn(i));
 		etm_writel(drvdata, drvdata->addr_acctype[i], ETMACTRn(i));
 	}
+	for (i = 0; i < drvdata->nr_data_cmp; i++) {
+		etm_writel(drvdata, drvdata->data_val[i], ETMDCVRn(i));
+		etm_writel(drvdata, drvdata->data_mask[i], ETMDCMRn(i));
+	}
 	for (i = 0; i < drvdata->nr_cntr; i++) {
 		etm_writel(drvdata, drvdata->cntr_rld_val[i], ETMCNTRLDVRn(i));
 		etm_writel(drvdata, drvdata->cntr_event[i], ETMCNTENRn(i));
@@ -594,21 +635,37 @@
 	if (val) {
 		drvdata->mode = ETM_MODE_EXCLUDE;
 		drvdata->ctrl = 0x0;
+		if (etm_version_gte(drvdata->arch, ETM_ARCH_V1_0))
+			drvdata->ctrl |= BIT(11);
 		if (cpu_is_krait_v1()) {
 			drvdata->mode |= ETM_MODE_CYCACC;
 			drvdata->ctrl |= BIT(12);
 		}
 		drvdata->trigger_event = 0x406F;
 		drvdata->startstop_ctrl = 0x0;
+		if (etm_version_gte(drvdata->arch, ETM_ARCH_V1_2))
+			drvdata->enable_ctrl2 = 0x0;
 		drvdata->enable_event = 0x6F;
 		drvdata->enable_ctrl1 = 0x1000000;
 		drvdata->fifofull_level = 0x28;
+		if (drvdata->data_trace_support == true) {
+			drvdata->mode |= (ETM_MODE_DATA_TRACE_VAL |
+						ETM_MODE_DATA_TRACE_ADDR);
+			drvdata->ctrl |= BIT(2) | BIT(3);
+			drvdata->viewdata_event = 0x6F;
+			drvdata->viewdata_ctrl1 = 0x0;
+			drvdata->viewdata_ctrl3 = 0x10000;
+		}
 		drvdata->addr_idx = 0x0;
 		for (i = 0; i < drvdata->nr_addr_cmp; i++) {
 			drvdata->addr_val[i] = 0x0;
 			drvdata->addr_acctype[i] = 0x0;
 			drvdata->addr_type[i] = ETM_ADDR_TYPE_NONE;
 		}
+		for (i = 0; i < drvdata->nr_data_cmp; i++) {
+			drvdata->data_val[i] = 0;
+			drvdata->data_mask[i] = ~(0);
+		}
 		drvdata->cntr_idx = 0x0;
 		for (i = 0; i < drvdata->nr_cntr; i++) {
 			drvdata->cntr_rld_val[i] = 0x0;
@@ -684,6 +741,17 @@
 		drvdata->ctrl |= (BIT(14) | BIT(15));
 	else
 		drvdata->ctrl &= ~(BIT(14) | BIT(15));
+	if (etm_version_gte(drvdata->arch, ETM_ARCH_V1_0)) {
+		if (drvdata->mode & ETM_MODE_DATA_TRACE_VAL)
+			drvdata->ctrl |= BIT(2);
+		else
+			drvdata->ctrl &= ~(BIT(2));
+
+		if (drvdata->mode & ETM_MODE_DATA_TRACE_ADDR)
+			drvdata->ctrl |= (BIT(3));
+		else
+			drvdata->ctrl &= ~(BIT(3));
+	}
 	spin_unlock(&drvdata->spinlock);
 
 	return size;
@@ -839,6 +907,8 @@
 
 	drvdata->addr_val[idx] = val;
 	drvdata->addr_type[idx] = ETM_ADDR_TYPE_SINGLE;
+	if (etm_version_gte(drvdata->arch, ETM_ARCH_V1_2))
+		drvdata->enable_ctrl2 |= (1 << idx);
 	spin_unlock(&drvdata->spinlock);
 	return size;
 }
@@ -1039,6 +1109,138 @@
 static DEVICE_ATTR(addr_acctype, S_IRUGO | S_IWUSR, etm_show_addr_acctype,
 		   etm_store_addr_acctype);
 
+static ssize_t etm_show_data_val(struct device *dev,
+				struct device_attribute *attr, char *buf)
+{
+	struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
+	unsigned long val;
+	uint8_t idx;
+
+	spin_lock(&drvdata->spinlock);
+	idx = drvdata->addr_idx;
+	if (idx % 2 != 0) {
+		spin_unlock(&drvdata->spinlock);
+		return -EPERM;
+	}
+	idx = idx >> 1;
+	if (idx >= drvdata->nr_data_cmp) {
+		spin_unlock(&drvdata->spinlock);
+		return -EPERM;
+	}
+
+	val = drvdata->data_val[idx];
+	spin_unlock(&drvdata->spinlock);
+	return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
+}
+
+static ssize_t etm_store_data_val(struct device *dev,
+				struct device_attribute *attr,
+				const char *buf, size_t size)
+{
+	struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
+	unsigned long val;
+	uint8_t idx, data_idx;
+
+	if (sscanf(buf, "%lx", &val) != 1)
+		return -EINVAL;
+
+	spin_lock(&drvdata->spinlock);
+	idx = drvdata->addr_idx;
+	/* Adjust index to use the correct data comparator */
+	data_idx = idx >> 1;
+	/* Only idx = 0, 2, 4, 6... are valid */
+	if (idx % 2 != 0) {
+		spin_unlock(&drvdata->spinlock);
+		return -EPERM;
+	}
+	if (data_idx >= drvdata->nr_data_cmp) {
+		spin_unlock(&drvdata->spinlock);
+		return -EPERM;
+	}
+	if (!BVAL(drvdata->addr_acctype[idx], ETM_DATACMP_ENABLE)) {
+		spin_unlock(&drvdata->spinlock);
+		return -EPERM;
+	}
+	if (drvdata->addr_type[idx] == ETM_ADDR_TYPE_RANGE) {
+		if (!BVAL(drvdata->addr_acctype[idx + 1], ETM_DATACMP_ENABLE)) {
+			spin_unlock(&drvdata->spinlock);
+			return -EPERM;
+		}
+	}
+
+	drvdata->data_val[data_idx] = val;
+	spin_unlock(&drvdata->spinlock);
+	return size;
+}
+static DEVICE_ATTR(data_val, S_IRUGO | S_IWUSR, etm_show_data_val,
+			etm_store_data_val);
+
+static ssize_t etm_show_data_mask(struct device *dev,
+				struct device_attribute *attr, char *buf)
+{
+	struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
+	unsigned long mask;
+	uint8_t idx;
+
+	spin_lock(&drvdata->spinlock);
+	idx = drvdata->addr_idx;
+	if (idx % 2 != 0) {
+		spin_unlock(&drvdata->spinlock);
+		return -EPERM;
+	}
+	idx = idx >> 1;
+	if (idx >= drvdata->nr_data_cmp) {
+		spin_unlock(&drvdata->spinlock);
+		return -EPERM;
+	}
+
+	mask = drvdata->data_mask[idx];
+	spin_unlock(&drvdata->spinlock);
+	return scnprintf(buf, PAGE_SIZE, "%#lx\n", mask);
+}
+
+static ssize_t etm_store_data_mask(struct device *dev,
+				struct device_attribute *attr,
+				const char *buf, size_t size)
+{
+	struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
+	unsigned long mask;
+	uint8_t idx, data_idx;
+
+	if (sscanf(buf, "%lx", &mask) != 1)
+		return -EINVAL;
+
+	spin_lock(&drvdata->spinlock);
+	idx = drvdata->addr_idx;
+	/* Adjust index to use the correct data comparator */
+	data_idx = idx >> 1;
+	/* Only idx = 0, 2, 4, 6... are valid */
+	if (idx % 2 != 0) {
+		spin_unlock(&drvdata->spinlock);
+		return -EPERM;
+	}
+	if (data_idx >= drvdata->nr_data_cmp) {
+		spin_unlock(&drvdata->spinlock);
+		return -EPERM;
+	}
+	if (!BVAL(drvdata->addr_acctype[idx], ETM_DATACMP_ENABLE)) {
+		spin_unlock(&drvdata->spinlock);
+		return -EPERM;
+	}
+	if (drvdata->addr_type[idx] == ETM_ADDR_TYPE_RANGE) {
+		if (!BVAL(drvdata->addr_acctype[idx + 1], ETM_DATACMP_ENABLE)) {
+			spin_unlock(&drvdata->spinlock);
+			return -EPERM;
+		}
+	}
+
+	drvdata->data_mask[data_idx] = mask;
+	spin_unlock(&drvdata->spinlock);
+	return size;
+}
+static DEVICE_ATTR(data_mask, S_IRUGO | S_IWUSR, etm_show_data_mask,
+			etm_store_data_mask);
+
 static ssize_t etm_show_cntr_idx(struct device *dev,
 				 struct device_attribute *attr, char *buf)
 {
@@ -1604,6 +1806,8 @@
 	&dev_attr_addr_start.attr,
 	&dev_attr_addr_stop.attr,
 	&dev_attr_addr_acctype.attr,
+	&dev_attr_data_val.attr,
+	&dev_attr_data_mask.attr,
 	&dev_attr_cntr_idx.attr,
 	&dev_attr_cntr_rld_val.attr,
 	&dev_attr_cntr_event.attr,
@@ -1681,6 +1885,8 @@
 	switch (arch) {
 	case PFT_ARCH_V1_1:
 		break;
+	case ETM_ARCH_V3_5:
+		break;
 	default:
 		return false;
 	}
@@ -1691,6 +1897,7 @@
 {
 	uint32_t etmidr;
 	uint32_t etmccr;
+	uint32_t etmcr;
 	struct etm_drvdata *drvdata = info;
 
 	ETM_UNLOCK(drvdata);
@@ -1721,6 +1928,19 @@
 	drvdata->nr_ext_inp = BMVAL(etmccr, 17, 19);
 	drvdata->nr_ext_out = BMVAL(etmccr, 20, 22);
 	drvdata->nr_ctxid_cmp = BMVAL(etmccr, 24, 25);
+	drvdata->nr_data_cmp = BMVAL(etmccr, 4, 7);
+
+	if (etm_version_gte(drvdata->arch, ETM_ARCH_V1_0)) {
+		etmcr = etm_readl(drvdata, ETMCR);
+		etmcr |= (BIT(2) | BIT(3));
+		etm_writel(drvdata, etmcr, ETMCR);
+		etmcr = etm_readl(drvdata, ETMCR);
+		if (BVAL(etmcr, 2) || BVAL(etmcr, 3))
+			drvdata->data_trace_support = true;
+		else
+			drvdata->data_trace_support = false;
+	} else
+		drvdata->data_trace_support = false;
 
 	etm_set_pwrdwn(drvdata);
 	ETM_LOCK(drvdata);
@@ -1734,6 +1954,8 @@
 	drvdata->nr_ext_inp = etmdrvdata[0]->nr_ext_inp;
 	drvdata->nr_ext_out = etmdrvdata[0]->nr_ext_out;
 	drvdata->nr_ctxid_cmp = etmdrvdata[0]->nr_ctxid_cmp;
+	drvdata->nr_data_cmp = etmdrvdata[0]->nr_data_cmp;
+	drvdata->data_trace_support = etmdrvdata[0]->data_trace_support;
 }
 
 static void __devinit etm_init_default_data(struct etm_drvdata *drvdata)
@@ -1749,6 +1971,10 @@
 		drvdata->addr_val[1] = (uint32_t) _etext;
 		drvdata->addr_type[0] = ETM_ADDR_TYPE_RANGE;
 		drvdata->addr_type[1] = ETM_ADDR_TYPE_RANGE;
+		if (etm_version_gte(drvdata->arch, ETM_ARCH_V1_0)) {
+			drvdata->addr_acctype[0] = 0x19;
+			drvdata->addr_acctype[1] = 0x19;
+		}
 	}
 	for (i = 0; i < drvdata->nr_cntr; i++) {
 		drvdata->cntr_event[i] = 0x406F;
@@ -1781,6 +2007,23 @@
 			drvdata->addr_type[i] = ETM_ADDR_TYPE_NONE;
 		}
 	}
+
+	if (etm_version_gte(drvdata->arch, ETM_ARCH_V1_0))
+		drvdata->ctrl |= BIT(11);
+	if (etm_version_gte(drvdata->arch, ETM_ARCH_V1_2))
+		drvdata->enable_ctrl2 = 0x0;
+	if (drvdata->data_trace_support == true) {
+		drvdata->mode |= (ETM_MODE_DATA_TRACE_VAL |
+						ETM_MODE_DATA_TRACE_ADDR);
+		drvdata->ctrl |= BIT(2) | BIT(3);
+		drvdata->viewdata_ctrl1 = 0x0;
+		drvdata->viewdata_ctrl3 = 0x10000;
+		drvdata->viewdata_event = 0x6F;
+	}
+	for (i = 0; i < drvdata->nr_data_cmp; i++) {
+		drvdata->data_val[i] = 0;
+		drvdata->data_mask[i] = ~(0);
+	}
 }
 
 static int __devinit etm_probe(struct platform_device *pdev)
diff --git a/drivers/gpu/ion/ion_cp_heap.c b/drivers/gpu/ion/ion_cp_heap.c
index d96b755..8f5addd 100644
--- a/drivers/gpu/ion/ion_cp_heap.c
+++ b/drivers/gpu/ion/ion_cp_heap.c
@@ -2,7 +2,7 @@
  * drivers/gpu/ion/ion_cp_heap.c
  *
  * Copyright (C) 2011 Google, Inc.
- * Copyright (c) 2011-2012, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2011-2013, The Linux Foundation. All rights reserved.
  *
  * This software is licensed under the terms of the GNU General Public
  * License version 2, as published by the Free Software Foundation, and
@@ -469,6 +469,7 @@
 {
 	unsigned long offset;
 	unsigned long secure_allocation = flags & ION_SECURE;
+	unsigned long force_contig = flags & ION_FORCE_CONTIGUOUS;
 
 	struct ion_cp_heap *cp_heap =
 		container_of(heap, struct ion_cp_heap, heap);
@@ -481,7 +482,8 @@
 		return ION_CP_ALLOCATE_FAIL;
 	}
 
-	if (!secure_allocation && cp_heap->disallow_non_secure_allocation) {
+	if (!force_contig && !secure_allocation &&
+	     cp_heap->disallow_non_secure_allocation) {
 		mutex_unlock(&cp_heap->lock);
 		pr_debug("%s: non-secure allocation disallowed from this heap\n",
 			__func__);
diff --git a/drivers/hwmon/pm8xxx-adc-scale.c b/drivers/hwmon/pm8xxx-adc-scale.c
index 4a1f58c..56c352a 100644
--- a/drivers/hwmon/pm8xxx-adc-scale.c
+++ b/drivers/hwmon/pm8xxx-adc-scale.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2011-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -271,172 +271,174 @@
 };
 
 static const struct pm8xxx_adc_map_pt adcmap_ntcg_104ef_104fb[] = {
-	{696483,	-40960},
-	{649148,	-39936},
-	{605368,	-38912},
-	{564809,	-37888},
-	{527215,	-36864},
-	{492322,	-35840},
-	{460007,	-34816},
-	{429982,	-33792},
-	{402099,	-32768},
-	{376192,	-31744},
-	{352075,	-30720},
-	{329714,	-29696},
-	{308876,	-28672},
-	{289480,	-27648},
-	{271417,	-26624},
-	{254574,	-25600},
-	{238903,	-24576},
-	{224276,	-23552},
-	{210631,	-22528},
-	{197896,	-21504},
-	{186007,	-20480},
-	{174899,	-19456},
-	{164521,	-18432},
-	{154818,	-17408},
-	{145744,	-16384},
-	{137265,	-15360},
-	{129307,	-14336},
-	{121866,	-13312},
-	{114896,	-12288},
-	{108365,	-11264},
-	{102252,	-10240},
-	{96499,		-9216},
-	{91111,		-8192},
-	{86055,		-7168},
-	{81308,		-6144},
-	{76857,		-5120},
-	{72660,		-4096},
-	{68722,		-3072},
-	{65020,		-2048},
-	{61538,		-1024},
-	{58261,		0},
-	{55177,		1024},
-	{52274,		2048},
-	{49538,		3072},
-	{46962,		4096},
-	{44531,		5120},
-	{42243,		6144},
-	{40083,		7168},
-	{38045,		8192},
-	{36122,		9216},
-	{34308,		10240},
-	{32592,		11264},
-	{30972,		12288},
-	{29442,		13312},
-	{27995,		14336},
-	{26624,		15360},
-	{25333,		16384},
-	{24109,		17408},
-	{22951,		18432},
-	{21854,		19456},
-	{20807,		20480},
-	{19831,		21504},
-	{18899,		22528},
-	{18016,		23552},
-	{17178,		24576},
-	{16384,		25600},
-	{15631,		26624},
-	{14916,		27648},
-	{14237,		28672},
-	{13593,		29696},
-	{12976,		30720},
-	{12400,		31744},
-	{11848,		32768},
-	{11324,		33792},
-	{10825,		34816},
-	{10354,		35840},
-	{9900,		36864},
-	{9471,		37888},
-	{9062,		38912},
-	{8674,		39936},
-	{8306,		40960},
-	{7951,		41984},
-	{7616,		43008},
-	{7296,		44032},
-	{6991,		45056},
-	{6701,		46080},
-	{6424,		47104},
-	{6160,		48128},
-	{5908,		49152},
-	{5667,		50176},
-	{5439,		51200},
-	{5219,		52224},
-	{5010,		53248},
-	{4810,		54272},
-	{4619,		55296},
-	{4440,		56320},
-	{4263,		57344},
-	{4097,		58368},
-	{3938,		59392},
-	{3785,		60416},
-	{3637,		61440},
-	{3501,		62464},
-	{3368,		63488},
-	{3240,		64512},
-	{3118,		65536},
-	{2998,		66560},
-	{2889,		67584},
-	{2782,		68608},
-	{2680,		69632},
-	{2581,		70656},
-	{2490,		71680},
-	{2397,		72704},
-	{2310,		73728},
-	{2227,		74752},
-	{2147,		75776},
-	{2064,		76800},
-	{1998,		77824},
-	{1927,		78848},
-	{1860,		79872},
-	{1795,		80896},
-	{1736,		81920},
-	{1673,		82944},
-	{1615,		83968},
-	{1560,		84992},
-	{1507,		86016},
-	{1456,		87040},
-	{1407,		88064},
-	{1360,		89088},
-	{1314,		90112},
-	{1271,		91136},
-	{1228,		92160},
-	{1189,		93184},
-	{1150,		94208},
-	{1112,		95232},
-	{1076,		96256},
-	{1042,		97280},
-	{1008,		98304},
-	{976,		99328},
-	{945,		100352},
-	{915,		101376},
+	{374682,	-40960},
+	{360553,	-39936},
+	{346630,	-38912},
+	{332940,	-37888},
+	{319510,	-36864},
+	{306363,	-35840},
+	{293521,	-34816},
+	{281001,	-33792},
+	{268818,	-32768},
+	{256987,	-31744},
+	{245516,	-30720},
+	{234413,	-29696},
+	{223685,	-28672},
+	{213333,	-27648},
+	{203360,	-26624},
+	{193763,	-25600},
+	{184541,	-24576},
+	{175691,	-23552},
+	{167205,	-22528},
+	{159079,	-21504},
+	{151304,	-20480},
+	{143872,	-19456},
+	{136775,	-18432},
+	{130001,	-17408},
+	{123542,	-16384},
+	{117387,	-15360},
+	{111526,	-14336},
+	{105946,	-13312},
+	{100639,	-12288},
+	{95592,		-11264},
+	{90795,		-10240},
+	{86238,		-9216},
+	{81909,		-8192},
+	{77800,		-7168},
+	{73899,		-6144},
+	{70197,		-5120},
+	{66685,		-4096},
+	{63354,		-3072},
+	{60194,		-2048},
+	{57198,		-1024},
+	{54356,		0},
+	{51662,		1024},
+	{49108,		2048},
+	{46687,		3072},
+	{44391,		4096},
+	{42215,		5120},
+	{40151,		6144},
+	{38195,		7168},
+	{36340,		8192},
+	{34582,		9216},
+	{32914,		10240},
+	{31333,		11264},
+	{29833,		12288},
+	{28410,		13312},
+	{27061,		14336},
+	{25781,		15360},
+	{24566,		16384},
+	{23413,		17408},
+	{22319,		18432},
+	{21280,		19456},
+	{20294,		20480},
+	{19358,		21504},
+	{18469,		22528},
+	{17624,		23552},
+	{16822,		24576},
+	{16060,		25600},
+	{15335,		26624},
+	{14646,		27648},
+	{13992,		28672},
+	{13369,		29696},
+	{12777,		30720},
+	{12214,		31744},
+	{11678,		32768},
+	{11168,		33792},
+	{10682,		34816},
+	{10220,		35840},
+	{9780,		36864},
+	{9361,		37888},
+	{8962,		38912},
+	{8582,		39936},
+	{8219,		40960},
+	{7874,		41984},
+	{7545,		43008},
+	{7231,		44032},
+	{6931,		45056},
+	{6646,		46080},
+	{6373,		47104},
+	{6113,		48128},
+	{5865,		49152},
+	{5628,		50176},
+	{5402,		51200},
+	{5185,		52224},
+	{4979,		53248},
+	{4782,		54272},
+	{4593,		55296},
+	{4413,		56320},
+	{4241,		57344},
+	{4076,		58368},
+	{3919,		59392},
+	{3768,		60416},
+	{3624,		61440},
+	{3486,		62464},
+	{3354,		63488},
+	{3227,		64512},
+	{3106,		65536},
+	{2990,		66560},
+	{2879,		67584},
+	{2773,		68608},
+	{2671,		69632},
+	{2573,		70656},
+	{2479,		71680},
+	{2390,		72704},
+	{2303,		73728},
+	{2221,		74752},
+	{2142,		75776},
+	{2066,		76800},
+	{1993,		77824},
+	{1923,		78848},
+	{1855,		79872},
+	{1791,		80896},
+	{1729,		81920},
+	{1669,		82944},
+	{1612,		83968},
+	{1557,		84992},
+	{1504,		86016},
+	{1453,		87040},
+	{1404,		88064},
+	{1357,		89088},
+	{1312,		90112},
+	{1269,		91136},
+	{1227,		92160},
+	{1187,		93184},
+	{1148,		94208},
+	{1111,		95232},
+	{1075,		96256},
+	{1040,		97280},
+	{1007,		98304},
+	{975,		99328},
+	{944,		100352},
+	{914,		101376},
 	{886,		102400},
-	{859,		103424},
-	{832,		104448},
-	{807,		105472},
-	{782,		106496},
-	{756,		107520},
-	{735,		108544},
+	{858,		103424},
+	{831,		104448},
+	{806,		105472},
+	{781,		106496},
+	{757,		107520},
+	{734,		108544},
 	{712,		109568},
-	{691,		110592},
+	{690,		110592},
 	{670,		111616},
 	{650,		112640},
-	{631,		113664},
+	{630,		113664},
 	{612,		114688},
 	{594,		115712},
-	{577,		116736},
-	{560,		117760},
-	{544,		118784},
-	{528,		119808},
-	{513,		120832},
+	{576,		116736},
+	{559,		117760},
+	{543,		118784},
+	{527,		119808},
+	{512,		120832},
 	{498,		121856},
 	{483,		122880},
 	{470,		123904},
-	{457,		124928},
+	{456,		124928},
 	{444,		125952},
 	{431,		126976},
-	{419,		128000}
+	{419,		128000},
+	{408,		129024},
+	{396,		130048}
 };
 
 static int32_t pm8xxx_adc_map_linear(const struct pm8xxx_adc_map_pt *pts,
@@ -716,6 +718,10 @@
 		struct pm8xxx_adc_chan_result *adc_chan_result)
 {
 	int64_t xo_thm = 0;
+	uint32_t num1 = 0;
+	uint32_t num2 = 0;
+	uint32_t dnum = 0;
+	uint32_t rt_r25 = 0;
 
 	if (!chan_properties || !chan_properties->offset_gain_numerator ||
 		!chan_properties->offset_gain_denominator || !adc_properties
@@ -724,10 +730,21 @@
 
 	xo_thm = pm8xxx_adc_scale_ratiometric_calib(adc_code,
 			adc_properties, chan_properties);
-	xo_thm <<= 4;
+	if (xo_thm < 0)
+		xo_thm = -xo_thm;
+
+	num1 = xo_thm << 14;
+	num2 = (adc_properties->adc_vdd_reference - xo_thm) >> 1;
+	dnum = (adc_properties->adc_vdd_reference - xo_thm);
+
+	if (dnum == 0)
+		rt_r25 = 0x7FFFFFFF ;
+	else
+		rt_r25 = (num1 + num2)/dnum ;
+
 	pm8xxx_adc_map_linear(adcmap_ntcg_104ef_104fb,
 		ARRAY_SIZE(adcmap_ntcg_104ef_104fb),
-		xo_thm, &adc_chan_result->physical);
+		rt_r25, &adc_chan_result->physical);
 
 	return 0;
 }
diff --git a/drivers/hwmon/pm8xxx-adc.c b/drivers/hwmon/pm8xxx-adc.c
index 181a97e..1a163a4 100644
--- a/drivers/hwmon/pm8xxx-adc.c
+++ b/drivers/hwmon/pm8xxx-adc.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2011-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -1075,7 +1075,7 @@
 
 	return 0;
 }
-DEFINE_SIMPLE_ATTRIBUTE(reg_fops, get_adc, NULL, "%llu\n");
+DEFINE_SIMPLE_ATTRIBUTE(reg_fops, get_adc, NULL, "%lld\n");
 
 #ifdef CONFIG_DEBUG_FS
 static void create_debugfs_entries(void)
diff --git a/drivers/input/touchscreen/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/media/dvb/dvb-core/dmxdev.c b/drivers/media/dvb/dvb-core/dmxdev.c
index 9b66b05..82b6aa0 100644
--- a/drivers/media/dvb/dvb-core/dmxdev.c
+++ b/drivers/media/dvb/dvb-core/dmxdev.c
@@ -4,7 +4,7 @@
  * Copyright (C) 2000 Ralph Metzler & Marcus Metzler
  *		      for convergence integrated media GmbH
  *
- * Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public License
@@ -2255,6 +2255,7 @@
 
 	spin_lock_irq(&dmxdevfilter->dev->lock);
 	dvb_dmxdev_flush_output(&dmxdevfilter->buffer, &dmxdevfilter->events);
+	dvb_ringbuffer_reset(&dmxdevfilter->buffer);
 	spin_unlock_irq(&dmxdevfilter->dev->lock);
 
 	wake_up_all(&dmxdevfilter->buffer.queue);
diff --git a/drivers/media/video/msm_vidc/Makefile b/drivers/media/video/msm_vidc/Makefile
index c8e7076..da829cc 100644
--- a/drivers/media/video/msm_vidc/Makefile
+++ b/drivers/media/video/msm_vidc/Makefile
@@ -8,3 +8,4 @@
 				venus_hfi.o \
 				hfi_response_handler.o \
 				hfi_packetization.o \
+				vidc_hfi.o \
diff --git a/drivers/media/video/msm_vidc/hfi_packetization.h b/drivers/media/video/msm_vidc/hfi_packetization.h
index 541654f..a3edc7c 100644
--- a/drivers/media/video/msm_vidc/hfi_packetization.h
+++ b/drivers/media/video/msm_vidc/hfi_packetization.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -15,8 +15,8 @@
 
 #include <linux/types.h>
 #include "vidc_hfi_helper.h"
+#include "vidc_hfi.h"
 #include "vidc_hfi_api.h"
-#include "venus_hfi.h"
 
 int create_pkt_cmd_sys_init(struct hfi_cmd_sys_init_packet *pkt,
 							   u32 arch_type);
diff --git a/drivers/media/video/msm_vidc/hfi_response_handler.c b/drivers/media/video/msm_vidc/hfi_response_handler.c
index 50970cb..23829e5 100644
--- a/drivers/media/video/msm_vidc/hfi_response_handler.c
+++ b/drivers/media/video/msm_vidc/hfi_response_handler.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -14,9 +14,10 @@
 #include <linux/slab.h>
 #include <linux/list.h>
 #include <linux/interrupt.h>
-#include "venus_hfi.h"
+#include "vidc_hfi_helper.h"
 #include "vidc_hfi_io.h"
 #include "msm_vidc_debug.h"
+#include "vidc_hfi.h"
 
 static enum vidc_status hfi_map_err_status(int hfi_err)
 {
@@ -75,8 +76,9 @@
 	return vidc_err;
 }
 
-static void hfi_process_sess_evt_seq_changed(struct venus_hfi_device *device,
-	struct hfi_msg_event_notify_packet *pkt)
+static void hfi_process_sess_evt_seq_changed(
+		msm_vidc_callback callback, u32 device_id,
+		struct hfi_msg_event_notify_packet *pkt)
 {
 	struct msm_vidc_cb_cmd_done cmd_done;
 	struct msm_vidc_cb_event event_notify;
@@ -95,7 +97,7 @@
 	memset(&event_notify, 0, sizeof(struct
 				msm_vidc_cb_event));
 
-	cmd_done.device_id = device->device_id;
+	cmd_done.device_id = device_id;
 	cmd_done.session_id = ((struct hal_session *) pkt->session_id)->
 		session_id;
 	cmd_done.status = VIDC_ERR_NONE;
@@ -136,39 +138,35 @@
 		} while (num_properties_changed > 0);
 	}
 	cmd_done.data = &event_notify;
-	device->callback(VIDC_EVENT_CHANGE, &cmd_done);
+	callback(VIDC_EVENT_CHANGE, &cmd_done);
 }
-static void hfi_process_sys_watchdog_timeout(struct venus_hfi_device *device)
-{
-	struct msm_vidc_cb_cmd_done cmd_done;
-	device->intr_status &= ~VIDC_WRAPPER_INTR_STATUS_A2HWD_BMSK;
-	memset(&cmd_done, 0, sizeof(struct msm_vidc_cb_cmd_done));
-	cmd_done.device_id = device->device_id;
-	device->callback(SYS_WATCHDOG_TIMEOUT, &cmd_done);
-}
-static void hfi_process_sys_error(struct venus_hfi_device *device)
+
+static void hfi_process_sys_error(
+		msm_vidc_callback callback, u32 device_id)
 {
 	struct msm_vidc_cb_cmd_done cmd_done;
 	memset(&cmd_done, 0, sizeof(struct msm_vidc_cb_cmd_done));
-	cmd_done.device_id = device->device_id;
-	device->callback(SYS_ERROR, &cmd_done);
+	cmd_done.device_id = device_id;
+	callback(SYS_ERROR, &cmd_done);
 }
-static void hfi_process_session_error(struct venus_hfi_device *device,
+static void hfi_process_session_error(
+		msm_vidc_callback callback, u32 device_id,
 		struct hfi_msg_event_notify_packet *pkt)
 {
 	struct msm_vidc_cb_cmd_done cmd_done;
 	memset(&cmd_done, 0, sizeof(struct msm_vidc_cb_cmd_done));
-	cmd_done.device_id = device->device_id;
+	cmd_done.device_id = device_id;
 	cmd_done.session_id = ((struct hal_session *) pkt->session_id)->
 		session_id;
-	device->callback(SESSION_ERROR, &cmd_done);
+	callback(SESSION_ERROR, &cmd_done);
 }
-static void hfi_process_event_notify(struct venus_hfi_device *device,
-	struct hfi_msg_event_notify_packet *pkt)
+static void hfi_process_event_notify(
+		msm_vidc_callback callback, u32 device_id,
+		struct hfi_msg_event_notify_packet *pkt)
 {
 	dprintk(VIDC_DBG, "RECVD:EVENT_NOTIFY");
 
-	if (!device || !pkt ||
+	if (!callback || !pkt ||
 		pkt->size < sizeof(struct hfi_msg_event_notify_packet)) {
 		dprintk(VIDC_ERR, "Invalid Params");
 		return;
@@ -178,15 +176,15 @@
 	case HFI_EVENT_SYS_ERROR:
 		dprintk(VIDC_ERR, "HFI_EVENT_SYS_ERROR: %d\n",
 			pkt->event_data1);
-		hfi_process_sys_error(device);
+		hfi_process_sys_error(callback, device_id);
 		break;
 	case HFI_EVENT_SESSION_ERROR:
 		dprintk(VIDC_ERR, "HFI_EVENT_SESSION_ERROR");
-		hfi_process_session_error(device, pkt);
+		hfi_process_session_error(callback, device_id, pkt);
 		break;
 	case HFI_EVENT_SESSION_SEQUENCE_CHANGED:
 		dprintk(VIDC_INFO, "HFI_EVENT_SESSION_SEQUENCE_CHANGED");
-		hfi_process_sess_evt_seq_changed(device, pkt);
+		hfi_process_sess_evt_seq_changed(callback, device_id, pkt);
 		break;
 	case HFI_EVENT_SESSION_PROPERTY_CHANGED:
 		dprintk(VIDC_INFO, "HFI_EVENT_SESSION_PROPERTY_CHANGED");
@@ -196,7 +194,8 @@
 		break;
 	}
 }
-static void hfi_process_sys_init_done(struct venus_hfi_device *device,
+static void hfi_process_sys_init_done(
+		msm_vidc_callback callback, u32 device_id,
 		struct hfi_msg_sys_init_done_packet *pkt)
 {
 	struct msm_vidc_cb_cmd_done cmd_done;
@@ -273,16 +272,17 @@
 		}
 	}
 err_no_prop:
-	cmd_done.device_id = device->device_id;
+	cmd_done.device_id = device_id;
 	cmd_done.session_id = 0;
 	cmd_done.status = (u32) status;
 	cmd_done.size = sizeof(struct vidc_hal_sys_init_done);
 	cmd_done.data = (void *) &sys_init_done;
-	device->callback(SYS_INIT_DONE, &cmd_done);
+	callback(SYS_INIT_DONE, &cmd_done);
 }
 
-static void hfi_process_sys_rel_resource_done(struct venus_hfi_device *device,
-	struct hfi_msg_sys_release_resource_done_packet *pkt)
+static void hfi_process_sys_rel_resource_done(
+		msm_vidc_callback callback, u32 device_id,
+		struct hfi_msg_sys_release_resource_done_packet *pkt)
 {
 	struct msm_vidc_cb_cmd_done cmd_done;
 	enum vidc_status status = VIDC_ERR_NONE;
@@ -297,12 +297,12 @@
 		return;
 	}
 	status = hfi_map_err_status((u32)pkt->error_type);
-	cmd_done.device_id = device->device_id;
+	cmd_done.device_id = device_id;
 	cmd_done.session_id = 0;
 	cmd_done.status = (u32) status;
 	cmd_done.size = 0;
 	cmd_done.data = NULL;
-	device->callback(RELEASE_RESOURCE_DONE, &cmd_done);
+	callback(RELEASE_RESOURCE_DONE, &cmd_done);
 }
 
 enum vidc_status hfi_process_sess_init_done_prop_read(
@@ -408,8 +408,9 @@
 	}
 }
 
-static void hfi_process_session_prop_info(struct venus_hfi_device *device,
-	struct hfi_msg_session_property_info_packet *pkt)
+static void hfi_process_session_prop_info(
+		msm_vidc_callback callback, u32 device_id,
+		struct hfi_msg_session_property_info_packet *pkt)
 {
 	struct msm_vidc_cb_cmd_done cmd_done;
 	struct buffer_requirements buff_req;
@@ -433,13 +434,13 @@
 	switch (pkt->rg_property_data[0]) {
 	case HFI_PROPERTY_CONFIG_BUFFER_REQUIREMENTS:
 		hfi_process_sess_get_prop_buf_req(pkt, &buff_req);
-		cmd_done.device_id = device->device_id;
+		cmd_done.device_id = device_id;
 		cmd_done.session_id =
 			((struct hal_session *) pkt->session_id)->session_id;
 		cmd_done.status = VIDC_ERR_NONE;
 		cmd_done.data = &buff_req;
 		cmd_done.size = sizeof(struct buffer_requirements);
-		device->callback(SESSION_PROPERTY_INFO, &cmd_done);
+		callback(SESSION_PROPERTY_INFO, &cmd_done);
 		break;
 	default:
 		dprintk(VIDC_ERR, "hal_process_session_prop_info:"
@@ -449,8 +450,9 @@
 	}
 }
 
-static void hfi_process_session_init_done(struct venus_hfi_device *device,
-	struct hfi_msg_sys_session_init_done_packet *pkt)
+static void hfi_process_session_init_done(
+		msm_vidc_callback callback, u32 device_id,
+		struct hfi_msg_sys_session_init_done_packet *pkt)
 {
 	struct msm_vidc_cb_cmd_done cmd_done;
 	struct vidc_hal_session_init_done session_init_done;
@@ -466,7 +468,7 @@
 	memset(&session_init_done, 0, sizeof(struct
 				vidc_hal_session_init_done));
 
-	cmd_done.device_id = device->device_id;
+	cmd_done.device_id = device_id;
 	cmd_done.session_id =
 		((struct hal_session *) pkt->session_id)->session_id;
 	cmd_done.status = hfi_map_err_status((u32)pkt->error_type);
@@ -476,11 +478,12 @@
 			pkt, &cmd_done);
 	}
 	cmd_done.size = sizeof(struct vidc_hal_session_init_done);
-	device->callback(SESSION_INIT_DONE, &cmd_done);
+	callback(SESSION_INIT_DONE, &cmd_done);
 }
 
-static void hfi_process_session_load_res_done(struct venus_hfi_device *device,
-	struct hfi_msg_session_load_resources_done_packet *pkt)
+static void hfi_process_session_load_res_done(
+		msm_vidc_callback callback, u32 device_id,
+		struct hfi_msg_session_load_resources_done_packet *pkt)
 {
 	struct msm_vidc_cb_cmd_done cmd_done;
 	dprintk(VIDC_DBG, "RECEIVED:SESSION_LOAD_RESOURCES_DONE");
@@ -494,17 +497,18 @@
 
 	memset(&cmd_done, 0, sizeof(struct msm_vidc_cb_cmd_done));
 
-	cmd_done.device_id = device->device_id;
+	cmd_done.device_id = device_id;
 	cmd_done.session_id =
 		((struct hal_session *) pkt->session_id)->session_id;
 	cmd_done.status = hfi_map_err_status((u32)pkt->error_type);
 	cmd_done.data = NULL;
 	cmd_done.size = 0;
-	device->callback(SESSION_LOAD_RESOURCE_DONE, &cmd_done);
+	callback(SESSION_LOAD_RESOURCE_DONE, &cmd_done);
 }
 
-static void hfi_process_session_flush_done(struct venus_hfi_device *device,
-	struct hfi_msg_session_flush_done_packet *pkt)
+static void hfi_process_session_flush_done(
+		msm_vidc_callback callback, u32 device_id,
+		struct hfi_msg_session_flush_done_packet *pkt)
 {
 	struct msm_vidc_cb_cmd_done cmd_done;
 
@@ -517,17 +521,18 @@
 	}
 
 	memset(&cmd_done, 0, sizeof(struct msm_vidc_cb_cmd_done));
-	cmd_done.device_id = device->device_id;
+	cmd_done.device_id = device_id;
 	cmd_done.session_id =
 		((struct hal_session *) pkt->session_id)->session_id;
 	cmd_done.status = hfi_map_err_status((u32)pkt->error_type);
 	cmd_done.data = (void *) pkt->flush_type;
 	cmd_done.size = sizeof(u32);
-	device->callback(SESSION_FLUSH_DONE, &cmd_done);
+	callback(SESSION_FLUSH_DONE, &cmd_done);
 }
 
-static void hfi_process_session_etb_done(struct venus_hfi_device *device,
-	struct hfi_msg_session_empty_buffer_done_packet *pkt)
+static void hfi_process_session_etb_done(
+		msm_vidc_callback callback, u32 device_id,
+		struct hfi_msg_session_empty_buffer_done_packet *pkt)
 {
 	struct msm_vidc_cb_data_done data_done;
 
@@ -541,7 +546,7 @@
 
 	memset(&data_done, 0, sizeof(struct msm_vidc_cb_data_done));
 
-	data_done.device_id = device->device_id;
+	data_done.device_id = device_id;
 	data_done.session_id =
 		((struct hal_session *) pkt->session_id)->session_id;
 	data_done.status = hfi_map_err_status((u32) pkt->error_type);
@@ -550,11 +555,12 @@
 	data_done.input_done.offset = pkt->offset;
 	data_done.input_done.filled_len = pkt->filled_len;
 	data_done.input_done.packet_buffer = pkt->packet_buffer;
-	device->callback(SESSION_ETB_DONE, &data_done);
+	callback(SESSION_ETB_DONE, &data_done);
 }
 
-static void hfi_process_session_ftb_done(struct venus_hfi_device *device,
-			void *msg_hdr)
+static void hfi_process_session_ftb_done(
+		msm_vidc_callback callback, u32 device_id,
+		void *msg_hdr)
 {
 	struct msm_vidc_cb_data_done data_done;
 	struct hfi_msg_session_fill_buffer_done_compressed_packet *pack =
@@ -590,7 +596,7 @@
 			/* Proceed with the FBD */
 		}
 
-		data_done.device_id = device->device_id;
+		data_done.device_id = device_id;
 		data_done.session_id = (u32) session;
 		data_done.status = hfi_map_err_status((u32)
 							pkt->error_type);
@@ -624,7 +630,7 @@
 			return;
 		}
 
-		data_done.device_id = device->device_id;
+		data_done.device_id = device_id;
 		data_done.session_id = (u32) session;
 		data_done.status = hfi_map_err_status((u32)
 			pkt->error_type);
@@ -657,11 +663,12 @@
 		else if (pkt->stream_id == 1)
 			data_done.output_done.buffer_type = HAL_BUFFER_OUTPUT2;
 		}
-	device->callback(SESSION_FTB_DONE, &data_done);
+	callback(SESSION_FTB_DONE, &data_done);
 }
 
-static void hfi_process_session_start_done(struct venus_hfi_device *device,
-	struct hfi_msg_session_start_done_packet *pkt)
+static void hfi_process_session_start_done(
+		msm_vidc_callback callback, u32 device_id,
+		struct hfi_msg_session_start_done_packet *pkt)
 {
 	struct msm_vidc_cb_cmd_done cmd_done;
 
@@ -675,17 +682,18 @@
 	}
 
 	memset(&cmd_done, 0, sizeof(struct msm_vidc_cb_cmd_done));
-	cmd_done.device_id = device->device_id;
+	cmd_done.device_id = device_id;
 	cmd_done.session_id =
 		((struct hal_session *) pkt->session_id)->session_id;
 	cmd_done.status = hfi_map_err_status((u32)pkt->error_type);
 	cmd_done.data = NULL;
 	cmd_done.size = 0;
-	device->callback(SESSION_START_DONE, &cmd_done);
+	callback(SESSION_START_DONE, &cmd_done);
 }
 
-static void hfi_process_session_stop_done(struct venus_hfi_device *device,
-	struct hfi_msg_session_stop_done_packet *pkt)
+static void hfi_process_session_stop_done(
+		msm_vidc_callback callback, u32 device_id,
+		struct hfi_msg_session_stop_done_packet *pkt)
 {
 	struct msm_vidc_cb_cmd_done cmd_done;
 
@@ -699,17 +707,18 @@
 	}
 
 	memset(&cmd_done, 0, sizeof(struct msm_vidc_cb_cmd_done));
-	cmd_done.device_id = device->device_id;
+	cmd_done.device_id = device_id;
 	cmd_done.session_id =
 		((struct hal_session *) pkt->session_id)->session_id;
 	cmd_done.status = hfi_map_err_status((u32)pkt->error_type);
 	cmd_done.data = NULL;
 	cmd_done.size = 0;
-	device->callback(SESSION_STOP_DONE, &cmd_done);
+	callback(SESSION_STOP_DONE, &cmd_done);
 }
 
-static void hfi_process_session_rel_res_done(struct venus_hfi_device *device,
-	struct hfi_msg_session_release_resources_done_packet *pkt)
+static void hfi_process_session_rel_res_done(
+		msm_vidc_callback callback, u32 device_id,
+		struct hfi_msg_session_release_resources_done_packet *pkt)
 {
 	struct msm_vidc_cb_cmd_done cmd_done;
 
@@ -723,17 +732,18 @@
 	}
 
 	memset(&cmd_done, 0, sizeof(struct msm_vidc_cb_cmd_done));
-	cmd_done.device_id = device->device_id;
+	cmd_done.device_id = device_id;
 	cmd_done.session_id =
 		((struct hal_session *) pkt->session_id)->session_id;
 	cmd_done.status = hfi_map_err_status((u32)pkt->error_type);
 	cmd_done.data = NULL;
 	cmd_done.size = 0;
-	device->callback(SESSION_RELEASE_RESOURCE_DONE, &cmd_done);
+	callback(SESSION_RELEASE_RESOURCE_DONE, &cmd_done);
 }
 
-static void hfi_process_session_rel_buf_done(struct venus_hfi_device *device,
-	struct hfi_msg_session_release_buffers_done_packet *pkt)
+static void hfi_process_session_rel_buf_done(
+		msm_vidc_callback callback, u32 device_id,
+		struct hfi_msg_session_release_buffers_done_packet *pkt)
 {
 	struct msm_vidc_cb_cmd_done cmd_done;
 	if (!pkt || pkt->size !=
@@ -743,7 +753,7 @@
 		return;
 	}
 	memset(&cmd_done, 0, sizeof(struct msm_vidc_cb_cmd_done));
-	cmd_done.device_id = device->device_id;
+	cmd_done.device_id = device_id;
 	cmd_done.size = sizeof(struct msm_vidc_cb_cmd_done);
 	cmd_done.session_id =
 		((struct hal_session *) pkt->session_id)->session_id;
@@ -754,11 +764,12 @@
 	} else {
 		dprintk(VIDC_ERR, "invalid payload in rel_buff_done\n");
 	}
-	device->callback(SESSION_RELEASE_BUFFER_DONE, &cmd_done);
+	callback(SESSION_RELEASE_BUFFER_DONE, &cmd_done);
 }
 
-static void hfi_process_session_end_done(struct venus_hfi_device *device,
-	struct hfi_msg_sys_session_end_done_packet *pkt)
+static void hfi_process_session_end_done(
+		msm_vidc_callback callback, u32 device_id,
+		struct hfi_msg_sys_session_end_done_packet *pkt)
 {
 	struct msm_vidc_cb_cmd_done cmd_done;
 	struct hal_session *sess_close;
@@ -779,17 +790,17 @@
 	kfree(sess_close);
 
 	memset(&cmd_done, 0, sizeof(struct msm_vidc_cb_cmd_done));
-	cmd_done.device_id = device->device_id;
+	cmd_done.device_id = device_id;
 	cmd_done.session_id =
 		((struct hal_session *) pkt->session_id)->session_id;
 	cmd_done.status = hfi_map_err_status((u32)pkt->error_type);
 	cmd_done.data = NULL;
 	cmd_done.size = 0;
-	device->callback(SESSION_END_DONE, &cmd_done);
+	callback(SESSION_END_DONE, &cmd_done);
 }
 
 static void hfi_process_session_get_seq_hdr_done(
-	struct venus_hfi_device *device,
+	msm_vidc_callback callback, u32 device_id,
 	struct hfi_msg_session_get_sequence_header_done_packet *pkt)
 {
 	struct msm_vidc_cb_data_done data_done;
@@ -800,7 +811,7 @@
 		return;
 	}
 	memset(&data_done, 0, sizeof(struct msm_vidc_cb_data_done));
-	data_done.device_id = device->device_id;
+	data_done.device_id = device_id;
 	data_done.size = sizeof(struct msm_vidc_cb_data_done);
 	data_done.session_id =
 		((struct hal_session *) pkt->session_id)->session_id;
@@ -809,121 +820,99 @@
 	data_done.output_done.filled_len1 = pkt->header_len;
 	dprintk(VIDC_INFO, "seq_hdr: %p, Length: %d",
 		   pkt->sequence_header, pkt->header_len);
-	device->callback(SESSION_GET_SEQ_HDR_DONE, &data_done);
+	callback(SESSION_GET_SEQ_HDR_DONE, &data_done);
 }
 
-static void hfi_process_msg_packet(struct venus_hfi_device *device,
-	struct vidc_hal_msg_pkt_hdr *msg_hdr)
+void hfi_process_msg_packet(
+		msm_vidc_callback callback, u32 device_id,
+		struct vidc_hal_msg_pkt_hdr *msg_hdr)
 {
-	if (!device || !msg_hdr || msg_hdr->size <
-		VIDC_IFACEQ_MIN_PKT_SIZE) {
+	if (!callback || !msg_hdr || msg_hdr->size <
+		HFI_MIN_PKT_SIZE) {
 		dprintk(VIDC_ERR, "hal_process_msg_packet:bad"
 			"packet/packet size: %d", msg_hdr->size);
 		return;
 	}
 
 	dprintk(VIDC_INFO, "Received: 0x%x in ", msg_hdr->packet);
-	if ((device->intr_status & VIDC_WRAPPER_INTR_CLEAR_A2HWD_BMSK)) {
-		dprintk(VIDC_ERR, "Received: Watchdog timeout %s", __func__);
-		hfi_process_sys_watchdog_timeout(device);
-		return;
-	}
 
 	switch (msg_hdr->packet) {
 	case HFI_MSG_EVENT_NOTIFY:
-		hfi_process_event_notify(device,
+		hfi_process_event_notify(callback, device_id,
 			(struct hfi_msg_event_notify_packet *) msg_hdr);
 		break;
 	case  HFI_MSG_SYS_INIT_DONE:
-		hfi_process_sys_init_done(device,
+		hfi_process_sys_init_done(callback, device_id,
 			(struct hfi_msg_sys_init_done_packet *)
 					msg_hdr);
 		break;
 	case HFI_MSG_SYS_SESSION_INIT_DONE:
-		hfi_process_session_init_done(device,
+		hfi_process_session_init_done(callback, device_id,
 			(struct hfi_msg_sys_session_init_done_packet *)
 					msg_hdr);
 		break;
 	case HFI_MSG_SYS_SESSION_END_DONE:
-		hfi_process_session_end_done(device,
+		hfi_process_session_end_done(callback, device_id,
 			(struct hfi_msg_sys_session_end_done_packet *)
 					msg_hdr);
 		break;
 	case HFI_MSG_SESSION_LOAD_RESOURCES_DONE:
-		hfi_process_session_load_res_done(device,
+		hfi_process_session_load_res_done(callback, device_id,
 			(struct hfi_msg_session_load_resources_done_packet *)
 					msg_hdr);
 		break;
 	case HFI_MSG_SESSION_START_DONE:
-		hfi_process_session_start_done(device,
+		hfi_process_session_start_done(callback, device_id,
 			(struct hfi_msg_session_start_done_packet *)
 					msg_hdr);
 		break;
 	case HFI_MSG_SESSION_STOP_DONE:
-		hfi_process_session_stop_done(device,
+		hfi_process_session_stop_done(callback, device_id,
 			(struct hfi_msg_session_stop_done_packet *)
 					msg_hdr);
 		break;
 	case HFI_MSG_SESSION_EMPTY_BUFFER_DONE:
-		hfi_process_session_etb_done(device,
+		hfi_process_session_etb_done(callback, device_id,
 			(struct hfi_msg_session_empty_buffer_done_packet *)
 					msg_hdr);
 		break;
 	case HFI_MSG_SESSION_FILL_BUFFER_DONE:
-		hfi_process_session_ftb_done(device, msg_hdr);
+		hfi_process_session_ftb_done(callback, device_id, msg_hdr);
 		break;
 	case HFI_MSG_SESSION_FLUSH_DONE:
-		hfi_process_session_flush_done(device,
+		hfi_process_session_flush_done(callback, device_id,
 			(struct hfi_msg_session_flush_done_packet *)
 					msg_hdr);
 		break;
 	case HFI_MSG_SESSION_PROPERTY_INFO:
-		hfi_process_session_prop_info(device,
+		hfi_process_session_prop_info(callback, device_id,
 			(struct hfi_msg_session_property_info_packet *)
 					msg_hdr);
 		break;
 	case HFI_MSG_SESSION_RELEASE_RESOURCES_DONE:
-		hfi_process_session_rel_res_done(device,
+		hfi_process_session_rel_res_done(callback, device_id,
 			(struct hfi_msg_session_release_resources_done_packet *)
 					msg_hdr);
 		break;
 	case HFI_MSG_SYS_RELEASE_RESOURCE:
-		hfi_process_sys_rel_resource_done(device,
+		hfi_process_sys_rel_resource_done(callback, device_id,
 			(struct hfi_msg_sys_release_resource_done_packet *)
 			msg_hdr);
 		break;
 	case HFI_MSG_SESSION_GET_SEQUENCE_HEADER_DONE:
-		hfi_process_session_get_seq_hdr_done(device, (struct
-			hfi_msg_session_get_sequence_header_done_packet
-			 *) msg_hdr);
+		hfi_process_session_get_seq_hdr_done(
+			callback, device_id, (struct
+			hfi_msg_session_get_sequence_header_done_packet*)
+			msg_hdr);
 		break;
 	case HFI_MSG_SESSION_RELEASE_BUFFERS_DONE:
-		hfi_process_session_rel_buf_done(device, (struct
-			hfi_msg_session_release_buffers_done_packet
-			*) msg_hdr);
+		hfi_process_session_rel_buf_done(
+			callback, device_id, (struct
+			hfi_msg_session_release_buffers_done_packet*)
+			msg_hdr);
 		break;
 	default:
 		dprintk(VIDC_ERR, "UNKNOWN_MSG_TYPE : %d", msg_hdr->packet);
 		break;
 	}
 }
-
-void hfi_response_handler(struct venus_hfi_device *device)
-{
-	u8 packet[VIDC_IFACEQ_MED_PKT_SIZE];
-
-	dprintk(VIDC_INFO, "#####vidc_hal_response_handler#####\n");
-	if (device) {
-		while (!venus_hfi_iface_msgq_read(device, packet)) {
-			hfi_process_msg_packet(device,
-				(struct vidc_hal_msg_pkt_hdr *) packet);
-		}
-		while (!venus_hfi_iface_dbgq_read(device, packet)) {
-			struct hfi_msg_sys_debug_packet *pkt =
-				(struct hfi_msg_sys_debug_packet *) packet;
-			dprintk(VIDC_FW, "FW-SAYS: %s", pkt->rg_msg_data);
-		}
-	} else {
-		dprintk(VIDC_ERR, "SPURIOUS_INTERRUPT");
-	}
-}
diff --git a/drivers/media/video/msm_vidc/msm_v4l2_vidc.c b/drivers/media/video/msm_vidc/msm_v4l2_vidc.c
index e51896c..4f39357 100644
--- a/drivers/media/video/msm_vidc/msm_v4l2_vidc.c
+++ b/drivers/media/video/msm_vidc/msm_v4l2_vidc.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -29,7 +29,7 @@
 #include "msm_vidc_debug.h"
 #include "vidc_hfi_api.h"
 #include "msm_smem.h"
-#include "venus_hfi.h"
+#include "vidc_hfi_api.h"
 
 #define BASE_DEVICE_NUMBER 32
 
@@ -355,7 +355,8 @@
 	int i, rc = 0;
 	int smem_flags = 0;
 	int domain;
-	struct venus_hfi_device *device;
+	struct hfi_device *hdev;
+
 	vidc_inst = get_vidc_inst(file, fh);
 	v4l2_inst = get_v4l2_inst(file, fh);
 	if (!v4l2_inst || !vidc_inst || !vidc_inst->core
@@ -364,7 +365,8 @@
 		goto exit;
 	}
 
-	device = vidc_inst->core->device;
+	hdev = vidc_inst->core->device;
+
 	if (!v4l2_inst->mem_client) {
 		dprintk(VIDC_ERR, "Failed to get memory client\n");
 		rc = -ENOMEM;
@@ -404,9 +406,11 @@
 				&& (!EXTRADATA_IDX(b->length)
 					|| (i != EXTRADATA_IDX(b->length)))) {
 			smem_flags |= SMEM_SECURE;
-			domain = venus_hfi_get_domain(device, CP_MAP);
+			domain = hdev->get_domain(hdev->hfi_device_data,
+						CP_MAP);
 		} else
-			domain = venus_hfi_get_domain(device, NS_MAP);
+			domain = hdev->get_domain(hdev->hfi_device_data,
+						NS_MAP);
 
 		if (b->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)
 			smem_flags |= SMEM_INPUT;
@@ -667,6 +671,30 @@
 {
 }
 
+static int msm_vidc_get_hfi(struct platform_device *pdev,
+			struct msm_vidc_core *core)
+{
+	struct device_node *np = pdev->dev.of_node;
+	int rc = 0;
+	const char *hfi_name = NULL;
+
+	rc = of_property_read_string(np, "hfi", &hfi_name);
+	if (rc) {
+		dprintk(VIDC_ERR, "Failed to read hfi from device tree\n");
+		goto err_hfi_read;
+	}
+
+	if (!strcmp(hfi_name, "venus"))
+		core->hfi_type = VIDC_HFI_VENUS;
+	else if (!strcmp(hfi_name, "q6"))
+		core->hfi_type = VIDC_HFI_Q6;
+
+	dprintk(VIDC_INFO, "hfi_type = %d\n", core->hfi_type);
+
+err_hfi_read:
+	return rc;
+}
+
 static int msm_vidc_initialize_core(struct platform_device *pdev,
 				struct msm_vidc_core *core)
 {
@@ -685,6 +713,11 @@
 		init_completion(&core->completions[i]);
 	}
 
+	rc = msm_vidc_get_hfi(pdev, core);
+	if (rc)
+		dprintk(VIDC_ERR,
+			"Failed to read Host-Firmware Interface rc: %d\n", rc);
+
 	return rc;
 }
 
@@ -736,8 +769,8 @@
 	}
 	video_set_drvdata(&core->vdev[MSM_VIDC_ENCODER].vdev, core);
 
-	core->device =
-		venus_hfi_get_device(core->id, pdev, &handle_cmd_response);
+	core->device = vidc_hfi_initialize(core->hfi_type, core->id,
+				pdev, &handle_cmd_response);
 	if (!core->device) {
 		dprintk(VIDC_ERR, "Failed to create HFI device\n");
 		goto err_cores_exceeded;
@@ -774,9 +807,20 @@
 static int __devexit msm_vidc_remove(struct platform_device *pdev)
 {
 	int rc = 0;
-	struct msm_vidc_core *core = pdev->dev.platform_data;
+	struct msm_vidc_core *core;
 
-	venus_hfi_delete_device(core->device);
+	if (!pdev) {
+		dprintk(VIDC_ERR, "%s invalid input %p", __func__, pdev);
+		return -EINVAL;
+	}
+	core = pdev->dev.platform_data;
+
+	if (!core) {
+		dprintk(VIDC_ERR, "%s invalid core", __func__);
+		return -EINVAL;
+	}
+
+	vidc_hfi_deinitialize(core->hfi_type, core->device);
 	video_unregister_device(&core->vdev[MSM_VIDC_ENCODER].vdev);
 	video_unregister_device(&core->vdev[MSM_VIDC_DECODER].vdev);
 	v4l2_device_unregister(&core->v4l2_dev);
diff --git a/drivers/media/video/msm_vidc/msm_vdec.c b/drivers/media/video/msm_vidc/msm_vdec.c
index 525bad8..24407dd 100644
--- a/drivers/media/video/msm_vidc/msm_vdec.c
+++ b/drivers/media/video/msm_vidc/msm_vdec.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -377,6 +377,14 @@
 	struct vidc_buffer_addr_info buffer_info;
 	int extra_idx = 0;
 	int i;
+	struct hfi_device *hdev;
+
+	if (!inst || !inst->core || !inst->core->device) {
+		dprintk(VIDC_ERR, "%s invalid parameters", __func__);
+		return -EINVAL;
+	}
+	hdev = inst->core->device;
+
 	switch (b->type) {
 	case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
 		break;
@@ -415,7 +423,7 @@
 				buffer_info.extradata_addr = 0;
 				buffer_info.extradata_size = 0;
 			}
-			rc = venus_hfi_session_set_buffers(
+			rc = hdev->session_set_buffers(
 				(void *)inst->session, &buffer_info);
 			if (rc)
 				dprintk(VIDC_ERR,
@@ -436,6 +444,15 @@
 	struct msm_vidc_core *core = inst->core;
 	int extra_idx = 0;
 	int i;
+	struct hfi_device *hdev;
+
+	if (!inst || !inst->core || !inst->core->device) {
+		dprintk(VIDC_ERR, "%s invalid parameters", __func__);
+		return -EINVAL;
+	}
+
+	hdev = inst->core->device;
+
 	if (inst->state == MSM_VIDC_CORE_INVALID ||
 			core->state == VIDC_CORE_INVALID) {
 		dprintk(VIDC_ERR,
@@ -484,7 +501,7 @@
 			else
 				buffer_info.extradata_addr = 0;
 			buffer_info.response_required = false;
-			rc = venus_hfi_session_release_buffers(
+			rc = hdev->session_release_buffers(
 					(void *)inst->session, &buffer_info);
 			if (rc)
 				dprintk(VIDC_ERR,
@@ -809,6 +826,7 @@
 	unsigned long flags;
 	struct hal_buffer_requirements *bufreq;
 	int extra_idx = 0;
+	struct hfi_device *hdev;
 	if (!q || !num_buffers || !num_planes
 		|| !sizes || !q->drv_priv) {
 		dprintk(VIDC_ERR, "Invalid input, q = %p, %p, %p\n",
@@ -816,6 +834,14 @@
 		return -EINVAL;
 	}
 	inst = q->drv_priv;
+
+	if (!inst || !inst->core || !inst->core->device) {
+		dprintk(VIDC_ERR, "%s invalid parameters", __func__);
+		return -EINVAL;
+	}
+
+	hdev = inst->core->device;
+
 	switch (q->type) {
 	case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
 		*num_planes = inst->fmts[OUTPUT_PORT]->num_planes;
@@ -851,7 +877,7 @@
 
 			new_buf_count.buffer_type = HAL_BUFFER_OUTPUT;
 			new_buf_count.buffer_count_actual = *num_buffers;
-			rc = venus_hfi_session_set_property(inst->session,
+			rc = hdev->session_set_property(inst->session,
 					property_id, &new_buf_count);
 
 		}
@@ -1088,6 +1114,13 @@
 	enum hal_property property_id = 0;
 	u32 property_val = 0;
 	void *pdata;
+	struct hfi_device *hdev;
+
+	if (!inst || !inst->core || !inst->core->device) {
+		dprintk(VIDC_ERR, "%s invalid parameters", __func__);
+		return -EINVAL;
+	}
+	hdev = inst->core->device;
 
 	switch (ctrl->id) {
 	case V4L2_CID_MPEG_VIDC_VIDEO_STREAM_FORMAT:
@@ -1166,7 +1199,7 @@
 			property_id,
 			msm_vdec_ctrls[control_idx].id,
 			control.value);
-			rc = venus_hfi_session_set_property((void *)
+			rc = hdev->session_set_property((void *)
 				inst->session, property_id,
 					pdata);
 	}
diff --git a/drivers/media/video/msm_vidc/msm_venc.c b/drivers/media/video/msm_vidc/msm_venc.c
index 341e06f..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
@@ -611,11 +611,19 @@
 	struct hal_buffer_count_actual new_buf_count;
 	enum hal_property property_id;
 	unsigned long flags;
+	struct hfi_device *hdev;
 	if (!q || !q->drv_priv) {
 		dprintk(VIDC_ERR, "Invalid input, q = %p\n", q);
 		return -EINVAL;
 	}
 	inst = q->drv_priv;
+
+	if (!inst || !inst->core || !inst->core->device) {
+		dprintk(VIDC_ERR, "%s invalid parameters", __func__);
+		return -EINVAL;
+	}
+	hdev = inst->core->device;
+
 	switch (q->type) {
 	case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
 		*num_planes = 1;
@@ -648,7 +656,7 @@
 		property_id = HAL_PARAM_BUFFER_COUNT_ACTUAL;
 		new_buf_count.buffer_type = HAL_BUFFER_INPUT;
 		new_buf_count.buffer_count_actual = *num_buffers;
-		rc = venus_hfi_session_set_property(inst->session,
+		rc = hdev->session_set_property(inst->session,
 					property_id, &new_buf_count);
 		dprintk(VIDC_DBG, "size = %d, alignment = %d, count = %d\n",
 				inst->buff_req.buffer[0].buffer_size,
@@ -966,6 +974,13 @@
 	u32 property_id = 0, property_val = 0;
 	void *pdata;
 	struct v4l2_ctrl *temp_ctrl = NULL;
+	struct hfi_device *hdev;
+
+	if (!inst || !inst->core || !inst->core->device) {
+		dprintk(VIDC_ERR, "%s invalid parameters", __func__);
+		return -EINVAL;
+	}
+	hdev = inst->core->device;
 
 	/* Small helper macro for quickly getting a control and err checking */
 #define TRY_GET_CTRL(__ctrl_id) ({ \
@@ -1405,7 +1420,7 @@
 		dprintk(VIDC_DBG, "Control: HAL property=%d,ctrl_value=%d\n",
 				property_id,
 				ctrl->val);
-		rc = venus_hfi_session_set_property((void *)inst->session,
+		rc = hdev->session_set_property((void *)inst->session,
 				property_id, pdata);
 	}
 
@@ -1570,6 +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 = venus_hfi_session_set_property((void *)inst->session,
+		rc = hdev->session_set_property((void *)inst->session,
 				property_id, pdata);
 		if (rc) {
 			dprintk(VIDC_WARN,
@@ -1614,11 +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 = venus_hfi_session_set_property((void *)inst->session,
+		rc = hdev->session_set_property((void *)inst->session,
 				HAL_PARAM_FRAME_SIZE, &frame_sz);
 		if (rc) {
 			dprintk(VIDC_ERR,
@@ -1646,7 +1677,7 @@
 			goto exit;
 		}
 		frame_sz.buffer_type = HAL_BUFFER_OUTPUT;
-		rc = venus_hfi_session_set_property((void *)inst->session,
+		rc = hdev->session_set_property((void *)inst->session,
 				HAL_PARAM_FRAME_SIZE, &frame_sz);
 		if (rc) {
 			dprintk(VIDC_ERR,
@@ -1752,6 +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,7 +1808,7 @@
 				b->m.planes[i].m.userptr;
 			buffer_info.extradata_size = 0;
 			buffer_info.extradata_addr = 0;
-			rc = venus_hfi_session_set_buffers(
+			rc = hdev->session_set_buffers(
 				(void *)inst->session, &buffer_info);
 			if (rc)
 				dprintk(VIDC_ERR,
@@ -1790,6 +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 = venus_hfi_session_release_buffers(
+			rc = hdev->session_release_buffers(
 				(void *)inst->session, &buffer_info);
 			if (rc)
 				dprintk(VIDC_ERR,
diff --git a/drivers/media/video/msm_vidc/msm_vidc.c b/drivers/media/video/msm_vidc/msm_vidc.c
index b9f1508..73c9860 100644
--- a/drivers/media/video/msm_vidc/msm_vidc.c
+++ b/drivers/media/video/msm_vidc/msm_vidc.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -21,7 +21,7 @@
 #include "msm_vidc_common.h"
 #include "msm_smem.h"
 #include <linux/delay.h>
-#include "venus_hfi.h"
+#include "vidc_hfi_api.h"
 
 #define MAX_EVENTS 30
 
@@ -86,11 +86,14 @@
 		struct msm_vidc_iommu_info maps[MAX_MAP])
 {
 	struct msm_vidc_inst *inst = instance;
+	struct hfi_device *hdev;
 
-	if (!inst || !maps || !inst->core)
+	if (!inst || !maps || !inst->core || !inst->core->device)
 		return -EINVAL;
 
-	return venus_hfi_iommu_get_map(inst->core->device, maps);
+	hdev = inst->core->device;
+
+	return hdev->iommu_get_map(hdev->hfi_device_data, maps);
 }
 
 int msm_vidc_querycap(void *instance, struct v4l2_capability *cap)
diff --git a/drivers/media/video/msm_vidc/msm_vidc_common.c b/drivers/media/video/msm_vidc/msm_vidc_common.c
index eac715f..955f4ca 100644
--- a/drivers/media/video/msm_vidc/msm_vidc_common.c
+++ b/drivers/media/video/msm_vidc/msm_vidc_common.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -20,7 +20,6 @@
 #include "vidc_hfi_api.h"
 #include "msm_smem.h"
 #include "msm_vidc_debug.h"
-#include "venus_hfi.h"
 
 #define HW_RESPONSE_TIMEOUT (5 * 60 * 1000)
 
@@ -77,14 +76,22 @@
 {
 	int load;
 	int rc = 0;
+	struct hfi_device *hdev;
 
 	if (!core || type >= MSM_VIDC_MAX_DEVICES) {
 		dprintk(VIDC_ERR, "Invalid args: %p, %d\n", core, type);
 		return -EINVAL;
 	}
+
+	hdev = core->device;
+	if (!hdev) {
+		dprintk(VIDC_ERR, "Invalid device handle %p\n", hdev);
+		return -EINVAL;
+	}
+
 	load = msm_comm_get_load(core, type);
 
-	rc = venus_hfi_scale_bus(core->device, load, type, mtype);
+	rc = hdev->scale_bus(hdev->hfi_device_data, load, type, mtype);
 	if (rc)
 		dprintk(VIDC_ERR, "Failed to scale bus: %d\n", rc);
 
@@ -95,14 +102,23 @@
 	enum mem_type mtype)
 {
 	int i;
+	struct hfi_device *hdev;
+
+	if (!core || !core->device) {
+		dprintk(VIDC_ERR, "%s invalid parameters", __func__);
+		return;
+	}
+	hdev = core->device;
+
 	for (i = 0; i < MSM_VIDC_MAX_DEVICES; i++) {
 		if ((mtype & DDR_MEM) &&
-			venus_hfi_scale_bus(core->device, 0, i, DDR_MEM)) {
+			hdev->scale_bus(hdev->hfi_device_data, 0, i, DDR_MEM)) {
 			dprintk(VIDC_WARN,
 				"Failed to unvote for DDR accesses\n");
 		}
 		if ((mtype & OCMEM_MEM) &&
-			venus_hfi_scale_bus(core->device, 0, i, OCMEM_MEM)) {
+			hdev->scale_bus(hdev->hfi_device_data, 0, i,
+					OCMEM_MEM)) {
 			dprintk(VIDC_WARN,
 				"Failed to unvote for OCMEM accesses\n");
 		}
@@ -876,15 +892,23 @@
 {
 	int num_mbs_per_sec;
 	int rc = 0;
+	struct hfi_device *hdev;
 	if (!core) {
-		dprintk(VIDC_ERR, "Invalid args: %p\n", core);
+		dprintk(VIDC_ERR, "%s Invalid args: %p\n", __func__, core);
+		return -EINVAL;
+	}
+
+	hdev = core->device;
+	if (!hdev) {
+		dprintk(VIDC_ERR, "%s Invalid device handle: %p\n",
+			__func__, hdev);
 		return -EINVAL;
 	}
 	num_mbs_per_sec = msm_comm_get_load(core, MSM_VIDC_ENCODER);
 	num_mbs_per_sec += msm_comm_get_load(core, MSM_VIDC_DECODER);
 
 	dprintk(VIDC_INFO, "num_mbs_per_sec = %d\n", num_mbs_per_sec);
-	rc = venus_hfi_scale_clocks(core->device, num_mbs_per_sec);
+	rc = hdev->scale_clocks(hdev->hfi_device_data, num_mbs_per_sec);
 	if (rc)
 		dprintk(VIDC_ERR, "Failed to set clock rate: %d\n", rc);
 	return rc;
@@ -892,12 +916,16 @@
 
 void msm_comm_scale_clocks_and_bus(struct msm_vidc_inst *inst)
 {
-	struct msm_vidc_core *core = inst->core;
+	struct msm_vidc_core *core;
+	struct hfi_device *hdev;
 
-	if (!inst) {
-		dprintk(VIDC_WARN, "Invalid params\n");
+	if (!inst || !inst->core || !inst->core->device) {
+		dprintk(VIDC_ERR, "%s Invalid params\n", __func__);
 		return;
 	}
+	core = inst->core;
+	hdev = core->device;
+
 	if (msm_comm_scale_clocks(core)) {
 		dprintk(VIDC_WARN,
 				"Failed to scale clocks. Performance might be impacted\n");
@@ -906,7 +934,7 @@
 		dprintk(VIDC_WARN,
 				"Failed to scale DDR bus. Performance might be impacted\n");
 	}
-	if (venus_hfi_is_ocmem_present(core->device)) {
+	if (hdev->is_ocmem_present(hdev->hfi_device_data)) {
 		if (msm_comm_scale_bus(core, inst->session_type,
 					OCMEM_MEM))
 			dprintk(VIDC_WARN,
@@ -926,6 +954,14 @@
 static int msm_comm_unset_ocmem(struct msm_vidc_core *core)
 {
 	int rc = 0;
+	struct hfi_device *hdev;
+
+	if (!core || !core->device) {
+		dprintk(VIDC_ERR, "%s invalid parameters", __func__);
+		return -EINVAL;
+	}
+	hdev = core->device;
+
 	if (core->state == VIDC_CORE_INVALID) {
 		dprintk(VIDC_ERR,
 				"Core is in bad state. Cannot unset ocmem\n");
@@ -935,7 +971,7 @@
 	init_completion(
 		&core->completions[SYS_MSG_INDEX(RELEASE_RESOURCE_DONE)]);
 
-	rc = venus_hfi_unset_ocmem(core->device);
+	rc = hdev->unset_ocmem(hdev->hfi_device_data);
 	if (rc) {
 		dprintk(VIDC_ERR, "Failed to set OCMEM on driver\n");
 		goto release_ocmem_failed;
@@ -951,39 +987,6 @@
 	return rc;
 }
 
-int msm_vidc_ocmem_notify_handler(struct notifier_block *this,
-		unsigned long event, void *data)
-{
-	struct ocmem_buf *buff = data;
-	struct msm_vidc_core *core;
-	struct venus_hfi_device *device;
-	struct venus_resources *resources;
-	struct on_chip_mem *ocmem;
-	int rc = NOTIFY_DONE;
-	if (event == OCMEM_ALLOC_GROW) {
-		ocmem = container_of(this, struct on_chip_mem, vidc_ocmem_nb);
-		if (!ocmem) {
-			dprintk(VIDC_ERR, "Wrong handler passed\n");
-			rc = NOTIFY_BAD;
-			goto bad_notfier;
-		}
-		resources = container_of(ocmem,
-			struct venus_resources, ocmem);
-		device = container_of(resources,
-			struct venus_hfi_device, resources);
-		core = container_of((void *)device,
-			struct msm_vidc_core, device);
-		if (venus_hfi_set_ocmem(core->device, buff)) {
-			dprintk(VIDC_ERR, "Failed to set ocmem: %d\n", rc);
-			goto ocmem_set_failed;
-		}
-		rc = NOTIFY_OK;
-	}
-ocmem_set_failed:
-bad_notfier:
-	return rc;
-}
-
 static int msm_comm_init_core_done(struct msm_vidc_inst *inst)
 {
 	struct msm_vidc_core *core = inst->core;
@@ -1022,11 +1025,11 @@
 	int rc = 0;
 	struct msm_vidc_core *core = inst->core;
 	unsigned long flags;
-	struct venus_hfi_device *device;
+	struct hfi_device *hdev;
 
 	if (!core || !core->device)
 		return -EINVAL;
-	device = core->device;
+	hdev = core->device;
 
 	mutex_lock(&core->sync_lock);
 	if (core->state >= VIDC_CORE_INIT) {
@@ -1041,7 +1044,7 @@
 		goto fail_scale_bus;
 	}
 
-	rc = venus_hfi_load_fw(core->device);
+	rc = hdev->load_fw(hdev->hfi_device_data);
 	if (rc) {
 		dprintk(VIDC_ERR, "Failed to load video firmware\n");
 		goto fail_load_fw;
@@ -1053,7 +1056,7 @@
 	}
 
 	init_completion(&core->completions[SYS_MSG_INDEX(SYS_INIT_DONE)]);
-	rc = venus_hfi_core_init(core->device);
+	rc = hdev->core_init(hdev->hfi_device_data);
 	if (rc) {
 		dprintk(VIDC_ERR, "Failed to init core, id = %d\n", core->id);
 		goto fail_core_init;
@@ -1066,7 +1069,7 @@
 	mutex_unlock(&core->sync_lock);
 	return rc;
 fail_core_init:
-	venus_hfi_unload_fw(core->device);
+	hdev->unload_fw(hdev->hfi_device_data);
 fail_load_fw:
 	msm_comm_unvote_buses(core, DDR_MEM);
 fail_scale_bus:
@@ -1077,8 +1080,18 @@
 static int msm_vidc_deinit_core(struct msm_vidc_inst *inst)
 {
 	int rc = 0;
-	struct msm_vidc_core *core = inst->core;
+	struct msm_vidc_core *core;
+	struct hfi_device *hdev;
 	unsigned long flags;
+
+	if (!inst || !inst->core || !inst->core->device) {
+		dprintk(VIDC_ERR, "%s invalid parameters", __func__);
+		return -EINVAL;
+	}
+
+	core = inst->core;
+	hdev = core->device;
+
 	mutex_lock(&core->sync_lock);
 	if (core->state == VIDC_CORE_UNINIT) {
 		dprintk(VIDC_INFO, "Video core: %d is already in state: %d\n",
@@ -1088,9 +1101,9 @@
 	msm_comm_scale_clocks_and_bus(inst);
 	if (list_empty(&core->instances)) {
 		msm_comm_unset_ocmem(core);
-		venus_hfi_free_ocmem(core->device);
+		hdev->free_ocmem(hdev->hfi_device_data);
 		dprintk(VIDC_DBG, "Calling vidc_hal_core_release\n");
-		rc = venus_hfi_core_release(core->device);
+		rc = hdev->core_release(hdev->hfi_device_data);
 		if (rc) {
 			dprintk(VIDC_ERR, "Failed to release core, id = %d\n",
 							core->id);
@@ -1099,7 +1112,7 @@
 		spin_lock_irqsave(&core->lock, flags);
 		core->state = VIDC_CORE_UNINIT;
 		spin_unlock_irqrestore(&core->lock, flags);
-		venus_hfi_unload_fw(core->device);
+		hdev->unload_fw(hdev->hfi_device_data);
 		msm_comm_unvote_buses(core, DDR_MEM|OCMEM_MEM);
 	}
 core_already_uninited:
@@ -1182,6 +1195,14 @@
 {
 	int rc = 0;
 	int fourcc = 0;
+	struct hfi_device *hdev;
+
+	if (!inst || !inst->core || !inst->core->device) {
+		dprintk(VIDC_ERR, "%s invalid parameters", __func__);
+		return -EINVAL;
+	}
+	hdev = inst->core->device;
+
 	if (IS_ALREADY_IN_STATE(flipped_state, MSM_VIDC_OPEN)) {
 		dprintk(VIDC_INFO, "inst: %p is already in state: %d\n",
 						inst, inst->state);
@@ -1197,7 +1218,7 @@
 	}
 	init_completion(
 		&inst->completions[SESSION_MSG_INDEX(SESSION_INIT_DONE)]);
-	inst->session = venus_hfi_session_init(inst->core->device, (u32) inst,
+	inst->session = hdev->session_init(hdev->hfi_device_data, (u32) inst,
 					get_hal_domain(inst->session_type),
 					get_hal_codec_type(fourcc));
 	if (!inst->session) {
@@ -1218,6 +1239,14 @@
 {
 	int rc = 0;
 	u32 ocmem_sz = 0;
+	struct hfi_device *hdev;
+
+	if (!inst || !inst->core || !inst->core->device) {
+		dprintk(VIDC_ERR, "%s invalid parameters", __func__);
+		return -EINVAL;
+	}
+	hdev = inst->core->device;
+
 	if (IS_ALREADY_IN_STATE(flipped_state, MSM_VIDC_LOAD_RESOURCES)) {
 		dprintk(VIDC_INFO, "inst: %p is already in state: %d\n",
 						inst, inst->state);
@@ -1227,7 +1256,7 @@
 	rc = msm_comm_scale_bus(inst->core, inst->session_type, OCMEM_MEM);
 	if (!rc) {
 		mutex_lock(&inst->core->sync_lock);
-		rc = venus_hfi_alloc_ocmem(inst->core->device, ocmem_sz);
+		rc = hdev->alloc_ocmem(hdev->hfi_device_data, ocmem_sz);
 		mutex_unlock(&inst->core->sync_lock);
 		if (rc) {
 			dprintk(VIDC_WARN,
@@ -1238,7 +1267,7 @@
 		dprintk(VIDC_WARN,
 		"Failed to vote for OCMEM BW. Performance will be impacted\n");
 	}
-	rc = venus_hfi_session_load_res((void *) inst->session);
+	rc = hdev->session_load_res((void *) inst->session);
 	if (rc) {
 		dprintk(VIDC_ERR,
 			"Failed to send load resources\n");
@@ -1252,6 +1281,15 @@
 static int msm_vidc_start(int flipped_state, struct msm_vidc_inst *inst)
 {
 	int rc = 0;
+	struct hfi_device *hdev;
+
+	if (!inst || !inst->core || !inst->core->device) {
+		dprintk(VIDC_ERR, "%s invalid parameters", __func__);
+		return -EINVAL;
+	}
+
+	hdev = inst->core->device;
+
 	if (IS_ALREADY_IN_STATE(flipped_state, MSM_VIDC_START)) {
 		dprintk(VIDC_INFO,
 			"inst: %p is already in state: %d\n",
@@ -1260,7 +1298,7 @@
 	}
 	init_completion(
 		&inst->completions[SESSION_MSG_INDEX(SESSION_START_DONE)]);
-	rc = venus_hfi_session_start((void *) inst->session);
+	rc = hdev->session_start((void *) inst->session);
 	if (rc) {
 		dprintk(VIDC_ERR,
 			"Failed to send start\n");
@@ -1274,6 +1312,14 @@
 static int msm_vidc_stop(int flipped_state, struct msm_vidc_inst *inst)
 {
 	int rc = 0;
+	struct hfi_device *hdev;
+
+	if (!inst || !inst->core || !inst->core->device) {
+		dprintk(VIDC_ERR, "%s invalid parameters", __func__);
+		return -EINVAL;
+	}
+	hdev = inst->core->device;
+
 	if (IS_ALREADY_IN_STATE(flipped_state, MSM_VIDC_STOP)) {
 		dprintk(VIDC_INFO,
 			"inst: %p is already in state: %d\n",
@@ -1283,7 +1329,7 @@
 	dprintk(VIDC_DBG, "Send Stop to hal\n");
 	init_completion(
 		&inst->completions[SESSION_MSG_INDEX(SESSION_STOP_DONE)]);
-	rc = venus_hfi_session_stop((void *) inst->session);
+	rc = hdev->session_stop((void *) inst->session);
 	if (rc) {
 		dprintk(VIDC_ERR, "Failed to send stop\n");
 		goto exit;
@@ -1296,6 +1342,14 @@
 static int msm_vidc_release_res(int flipped_state, struct msm_vidc_inst *inst)
 {
 	int rc = 0;
+	struct hfi_device *hdev;
+
+	if (!inst || !inst->core || !inst->core->device) {
+		dprintk(VIDC_ERR, "%s invalid parameters", __func__);
+		return -EINVAL;
+	}
+	hdev = inst->core->device;
+
 	if (IS_ALREADY_IN_STATE(flipped_state, MSM_VIDC_RELEASE_RESOURCES)) {
 		dprintk(VIDC_INFO,
 			"inst: %p is already in state: %d\n",
@@ -1306,7 +1360,7 @@
 		"Send release res to hal\n");
 	init_completion(
 	&inst->completions[SESSION_MSG_INDEX(SESSION_RELEASE_RESOURCE_DONE)]);
-	rc = venus_hfi_session_release_res((void *) inst->session);
+	rc = hdev->session_release_res((void *) inst->session);
 	if (rc) {
 		dprintk(VIDC_ERR,
 			"Failed to send release resources\n");
@@ -1317,9 +1371,17 @@
 	return rc;
 }
 
-static int msm_comm_session_close(int flipped_state, struct msm_vidc_inst *inst)
+static int msm_comm_session_close(int flipped_state,
+			struct msm_vidc_inst *inst)
 {
 	int rc = 0;
+	struct hfi_device *hdev;
+
+	if (!inst || !inst->core || !inst->core->device) {
+		dprintk(VIDC_ERR, "%s invalid params", __func__);
+		return -EINVAL;
+	}
+	hdev = inst->core->device;
 	if (IS_ALREADY_IN_STATE(flipped_state, MSM_VIDC_CLOSE)) {
 		dprintk(VIDC_INFO,
 			"inst: %p is already in state: %d\n",
@@ -1330,7 +1392,7 @@
 		"Send session close to hal\n");
 	init_completion(
 		&inst->completions[SESSION_MSG_INDEX(SESSION_END_DONE)]);
-	rc = venus_hfi_session_end((void *) inst->session);
+	rc = hdev->session_end((void *) inst->session);
 	if (rc) {
 		dprintk(VIDC_ERR,
 			"Failed to send close\n");
@@ -1479,6 +1541,7 @@
 	struct vb2_buf_entry *entry;
 	struct vidc_frame_data frame_data;
 	struct msm_vidc_core *core;
+	struct hfi_device *hdev;
 	q = vb->vb2_queue;
 	inst = q->drv_priv;
 	if (!inst || !vb) {
@@ -1491,6 +1554,11 @@
 			"Invalid input: %p, %p, %p\n", inst, core, vb);
 		return -EINVAL;
 	}
+	hdev = core->device;
+	if (!hdev) {
+		dprintk(VIDC_ERR, "Invalid input: %p", hdev);
+		return -EINVAL;
+	}
 
 	if (inst->state == MSM_VIDC_CORE_INVALID ||
 		core->state == VIDC_CORE_INVALID) {
@@ -1534,7 +1602,7 @@
 			dprintk(VIDC_DBG,
 				"Sending etb to hal: Alloc: %d :filled: %d\n",
 				frame_data.alloc_len, frame_data.filled_len);
-			rc = venus_hfi_session_etb((void *) inst->session,
+			rc = hdev->session_etb((void *) inst->session,
 					&frame_data);
 			if (!rc)
 				msm_vidc_debugfs_update(inst,
@@ -1564,7 +1632,7 @@
 				seq_hdr.seq_hdr = (u8 *) vb->v4l2_planes[0].
 					m.userptr;
 				seq_hdr.seq_hdr_len = vb->v4l2_planes[0].length;
-				rc = venus_hfi_session_get_seq_hdr((void *)
+				rc = hdev->session_get_seq_hdr((void *)
 						inst->session, &seq_hdr);
 				if (!rc) {
 					inst->vb2_seq_hdr = vb;
@@ -1572,7 +1640,7 @@
 						inst->vb2_seq_hdr);
 				}
 			} else {
-				rc = venus_hfi_session_ftb((void *)
+				rc = hdev->session_ftb((void *)
 					inst->session, &frame_data);
 			if (!rc)
 				msm_vidc_debugfs_update(inst,
@@ -1595,6 +1663,14 @@
 int msm_comm_try_get_bufreqs(struct msm_vidc_inst *inst)
 {
 	int rc = 0;
+	struct hfi_device *hdev;
+
+	if (!inst || !inst->core || !inst->core->device) {
+		dprintk(VIDC_ERR, "%s invalid parameters", __func__);
+		return -EINVAL;
+	}
+	hdev = inst->core->device;
+
 	mutex_lock(&inst->sync_lock);
 	if (inst->state < MSM_VIDC_OPEN_DONE || inst->state >= MSM_VIDC_CLOSE) {
 		dprintk(VIDC_ERR,
@@ -1604,7 +1680,7 @@
 	}
 	init_completion(
 		&inst->completions[SESSION_MSG_INDEX(SESSION_PROPERTY_INFO)]);
-	rc = venus_hfi_session_get_buf_req((void *) inst->session);
+	rc = hdev->session_get_buf_req((void *) inst->session);
 	if (rc) {
 		dprintk(VIDC_ERR, "Failed to get property\n");
 		goto exit;
@@ -1632,6 +1708,7 @@
 	int rc = 0;
 	unsigned long flags;
 	struct msm_vidc_core *core;
+	struct hfi_device *hdev;
 	if (!inst) {
 		dprintk(VIDC_ERR,
 				"Invalid instance pointer = %p\n", inst);
@@ -1643,6 +1720,11 @@
 				"Invalid core pointer = %p\n", core);
 		return -EINVAL;
 	}
+	hdev = core->device;
+	if (!hdev) {
+		dprintk(VIDC_ERR, "Invalid device pointer = %p\n", hdev);
+		return -EINVAL;
+	}
 	spin_lock_irqsave(&inst->lock, flags);
 	if (!list_empty(&inst->internalbufs)) {
 		list_for_each_safe(ptr, next, &inst->internalbufs) {
@@ -1659,7 +1741,7 @@
 				init_completion(
 				   &inst->completions[SESSION_MSG_INDEX
 				   (SESSION_RELEASE_BUFFER_DONE)]);
-				rc = venus_hfi_session_release_buffers(
+				rc = hdev->session_release_buffers(
 						(void *) inst->session,
 							&buffer_info);
 				if (rc)
@@ -1692,6 +1774,7 @@
 	int rc = 0;
 	unsigned long flags;
 	struct msm_vidc_core *core;
+	struct hfi_device *hdev;
 	if (!inst) {
 		dprintk(VIDC_ERR,
 				"Invalid instance pointer = %p\n", inst);
@@ -1703,6 +1786,11 @@
 				"Invalid core pointer = %p\n", core);
 		return -EINVAL;
 	}
+	hdev = core->device;
+	if (!hdev) {
+		dprintk(VIDC_ERR, "Invalid device pointer = %p\n", hdev);
+		return -EINVAL;
+	}
 	spin_lock_irqsave(&inst->lock, flags);
 	if (!list_empty(&inst->persistbufs)) {
 		list_for_each_safe(ptr, next, &inst->persistbufs) {
@@ -1719,7 +1807,7 @@
 				init_completion(
 				   &inst->completions[SESSION_MSG_INDEX
 				   (SESSION_RELEASE_BUFFER_DONE)]);
-				rc = venus_hfi_session_release_buffers(
+				rc = hdev->session_release_buffers(
 						(void *) inst->session,
 							&buffer_info);
 				if (rc)
@@ -1747,17 +1835,25 @@
 	enum hal_property ptype, void *pdata)
 {
 	int rc = 0;
+	struct hfi_device *hdev;
 	if (!inst) {
 		dprintk(VIDC_ERR, "Invalid input: %p\n", inst);
 		return -EINVAL;
 	}
+
+	if (!inst->core || !inst->core->device) {
+		dprintk(VIDC_ERR, "%s invalid parameters", __func__);
+		return -EINVAL;
+	}
+	hdev = inst->core->device;
+
 	mutex_lock(&inst->sync_lock);
 	if (inst->state < MSM_VIDC_OPEN_DONE || inst->state >= MSM_VIDC_CLOSE) {
 		dprintk(VIDC_ERR, "Not in proper state to set property\n");
 		rc = -EAGAIN;
 		goto exit;
 	}
-	rc = venus_hfi_session_set_property((void *)inst->session,
+	rc = hdev->session_set_property((void *)inst->session,
 			ptype, pdata);
 	if (rc)
 		dprintk(VIDC_ERR, "Failed to set hal property for framesize\n");
@@ -1777,12 +1873,15 @@
 	unsigned long smem_flags = 0;
 	struct hal_buffer_requirements *scratch_buf;
 	int i;
-	struct venus_hfi_device *device;
+	struct hfi_device *hdev;
 
-	if (!inst || !inst->core || !inst->core->device)
+	if (!inst || !inst->core || !inst->core->device) {
+		dprintk(VIDC_ERR, "%s invalid parameters", __func__);
 		return -EINVAL;
+	}
 
-	device = inst->core->device;
+	hdev = inst->core->device;
+
 	scratch_buf =
 		&inst->buff_req.buffer[HAL_BUFFER_INTERNAL_SCRATCH];
 	dprintk(VIDC_DBG,
@@ -1792,10 +1891,10 @@
 	if (msm_comm_release_scratch_buffers(inst))
 		dprintk(VIDC_WARN, "Failed to release scratch buffers\n");
 	if (inst->mode == VIDC_SECURE) {
-		domain = venus_hfi_get_domain(device, CP_MAP);
+		domain = hdev->get_domain(hdev->hfi_device_data, CP_MAP);
 		smem_flags |= SMEM_SECURE;
 	} else
-		domain = venus_hfi_get_domain(device, NS_MAP);
+		domain = hdev->get_domain(hdev->hfi_device_data, NS_MAP);
 
 	if (scratch_buf->buffer_size) {
 		for (i = 0; i < scratch_buf->buffer_count_actual;
@@ -1822,7 +1921,7 @@
 			buffer_info.align_device_addr = handle->device_addr;
 			dprintk(VIDC_DBG, "Scratch buffer address: %x",
 					buffer_info.align_device_addr);
-			rc = venus_hfi_session_set_buffers(
+			rc = hdev->session_set_buffers(
 					(void *) inst->session,	&buffer_info);
 			if (rc) {
 				dprintk(VIDC_ERR,
@@ -1854,12 +1953,14 @@
 	int domain;
 	struct hal_buffer_requirements *persist_buf;
 	int i;
-	struct venus_hfi_device *device;
+	struct hfi_device *hdev;
 
-	if (!inst || !inst->core || !inst->core->device)
+	if (!inst || !inst->core || !inst->core->device) {
+		dprintk(VIDC_ERR, "%s invalid parameters", __func__);
 		return -EINVAL;
+	}
 
-	device = inst->core->device;
+	hdev = inst->core->device;
 
 	persist_buf =
 		&inst->buff_req.buffer[HAL_BUFFER_INTERNAL_PERSIST];
@@ -1874,10 +1975,10 @@
 	}
 
 	if (inst->mode == VIDC_SECURE) {
-		domain = venus_hfi_get_domain(device, CP_MAP);
+		domain = hdev->get_domain(hdev->hfi_device_data, CP_MAP);
 		flags |= SMEM_SECURE;
 	} else
-		domain = venus_hfi_get_domain(device, NS_MAP);
+		domain = hdev->get_domain(hdev->hfi_device_data, NS_MAP);
 
 	if (persist_buf->buffer_size) {
 		for (i = 0;	i <	persist_buf->buffer_count_actual; i++) {
@@ -1903,7 +2004,7 @@
 			buffer_info.align_device_addr = handle->device_addr;
 			dprintk(VIDC_DBG, "Persist buffer address: %x",
 					buffer_info.align_device_addr);
-			rc = venus_hfi_session_set_buffers(
+			rc = hdev->session_set_buffers(
 				(void *) inst->session, &buffer_info);
 			if (rc) {
 				dprintk(VIDC_ERR,
@@ -1977,6 +2078,7 @@
 	struct vb2_buf_entry *temp;
 	struct mutex *lock;
 	struct msm_vidc_core *core;
+	struct hfi_device *hdev;
 	if (!inst) {
 		dprintk(VIDC_ERR,
 				"Invalid instance pointer = %p\n", inst);
@@ -1988,6 +2090,11 @@
 				"Invalid core pointer = %p\n", core);
 		return -EINVAL;
 	}
+	hdev = core->device;
+	if (!hdev) {
+		dprintk(VIDC_ERR, "Invalid device pointer = %p", hdev);
+		return -EINVAL;
+	}
 
 	ip_flush = flags & V4L2_QCOM_CMD_FLUSH_OUTPUT;
 	op_flush = flags & V4L2_QCOM_CMD_FLUSH_CAPTURE;
@@ -2014,7 +2121,7 @@
 			dprintk(VIDC_WARN,
 			"FLUSH BUG: Pending q not empty! It should be empty\n");
 		}
-		rc = venus_hfi_session_flush(inst->session,
+		rc = hdev->session_flush(inst->session,
 				HAL_FLUSH_OUTPUT);
 	} else {
 		if (!list_empty(&inst->pendingq)) {
@@ -2035,7 +2142,7 @@
 				kfree(temp);
 			}
 		}
-		rc = venus_hfi_session_flush(inst->session,
+		rc = hdev->session_flush(inst->session,
 				HAL_FLUSH_ALL);
 	}
 	mutex_unlock(&inst->sync_lock);
diff --git a/drivers/media/video/msm_vidc/msm_vidc_debug.c b/drivers/media/video/msm_vidc/msm_vidc_debug.c
index bdf146e..ff829d7 100644
--- a/drivers/media/video/msm_vidc/msm_vidc_debug.c
+++ b/drivers/media/video/msm_vidc/msm_vidc_debug.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -12,7 +12,7 @@
  */
 
 #include "msm_vidc_debug.h"
-#include "venus_hfi.h"
+#include "vidc_hfi_api.h"
 
 #define MAX_DBG_BUF_SIZE 4096
 int msm_vidc_debug = 0x3;
@@ -53,22 +53,26 @@
 		size_t count, loff_t *ppos)
 {
 	struct msm_vidc_core *core = file->private_data;
-	struct venus_hfi_device *device;
+	struct hfi_device *hdev;
 	int i = 0;
 	if (!core || !core->device) {
 		dprintk(VIDC_ERR, "Invalid params, core: %p\n", core);
 		return 0;
 	}
-	device = core->device;
+	hdev = core->device;
 	INIT_DBG_BUF(dbg_buf);
 	write_str(&dbg_buf, "===============================\n");
 	write_str(&dbg_buf, "CORE %d: 0x%p\n", core->id, core);
 	write_str(&dbg_buf, "===============================\n");
 	write_str(&dbg_buf, "state: %d\n", core->state);
-	write_str(&dbg_buf, "base addr: 0x%x\n", device->base_addr);
-	write_str(&dbg_buf, "register_base: 0x%x\n", device->register_base);
-	write_str(&dbg_buf, "register_size: %u\n", device->register_size);
-	write_str(&dbg_buf, "irq: %u\n", device->irq);
+	write_str(&dbg_buf, "base addr: 0x%x\n",
+		hdev->get_fw_info(hdev->hfi_device_data, FW_BASE_ADDRESS));
+	write_str(&dbg_buf, "register_base: 0x%x\n",
+		hdev->get_fw_info(hdev->hfi_device_data, FW_REGISTER_BASE));
+	write_str(&dbg_buf, "register_size: %u\n",
+		hdev->get_fw_info(hdev->hfi_device_data, FW_REGISTER_SIZE));
+	write_str(&dbg_buf, "irq: %u\n",
+		hdev->get_fw_info(hdev->hfi_device_data, FW_IRQ));
 	for (i = SYS_MSG_START; i < SYS_MSG_END; i++) {
 		write_str(&dbg_buf, "completions[%d]: %s\n", i,
 			completion_done(&core->completions[SYS_MSG_INDEX(i)]) ?
diff --git a/drivers/media/video/msm_vidc/msm_vidc_internal.h b/drivers/media/video/msm_vidc/msm_vidc_internal.h
index 14cef1e..52c1de8 100644
--- a/drivers/media/video/msm_vidc/msm_vidc_internal.h
+++ b/drivers/media/video/msm_vidc/msm_vidc_internal.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -32,6 +32,7 @@
 #include <media/msm_media_info.h>
 
 #include "vidc_hfi_api.h"
+#include "vidc_hfi_api.h"
 
 #define MSM_VIDC_DRV_NAME "msm_vidc_driver"
 #define MSM_VIDC_VERSION KERNEL_VERSION(0, 0, 1);
@@ -177,6 +178,7 @@
 	struct dentry *debugfs_root;
 	enum vidc_core_state state;
 	struct completion completions[SYS_MSG_END - SYS_MSG_START + 1];
+	enum msm_vidc_hfi_type hfi_type;
 };
 
 struct msm_vidc_inst {
@@ -235,6 +237,4 @@
 };
 
 void handle_cmd_response(enum command_response cmd, void *data);
-int msm_vidc_ocmem_notify_handler(struct notifier_block *this,
-		unsigned long event, void *data);
 #endif
diff --git a/drivers/media/video/msm_vidc/venus_hfi.c b/drivers/media/video/msm_vidc/venus_hfi.c
index 8f0902f..015ed11 100644
--- a/drivers/media/video/msm_vidc/venus_hfi.c
+++ b/drivers/media/video/msm_vidc/venus_hfi.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -37,8 +37,6 @@
 
 #define SHARED_QSIZE 0x1000000
 
-struct hal_device_data hal_ctxt;
-
 static struct msm_bus_vectors enc_ocmem_init_vectors[]  = {
 	{
 		.src = MSM_BUS_MASTER_VIDEO_P0_OCMEM,
@@ -840,7 +838,7 @@
 	return result;
 }
 
-int venus_hfi_iface_msgq_read(struct venus_hfi_device *device, void *pkt)
+static int venus_hfi_iface_msgq_read(struct venus_hfi_device *device, void *pkt)
 {
 	u32 tx_req_is_set = 0;
 	int rc = 0;
@@ -875,7 +873,7 @@
 	return rc;
 }
 
-int venus_hfi_iface_dbgq_read(struct venus_hfi_device *device, void *pkt)
+static int venus_hfi_iface_dbgq_read(struct venus_hfi_device *device, void *pkt)
 {
 	u32 tx_req_is_set = 0;
 	int rc = 0;
@@ -1146,7 +1144,7 @@
 	return 0;
 }
 
-int venus_hfi_core_init(void *device)
+static int venus_hfi_core_init(void *device)
 {
 	struct hfi_cmd_sys_init_packet pkt;
 	int rc = 0;
@@ -1214,7 +1212,7 @@
 	return rc;
 }
 
-int venus_hfi_core_release(void *device)
+static int venus_hfi_core_release(void *device)
 {
 	struct venus_hfi_device *dev;
 	if (device) {
@@ -1288,7 +1286,7 @@
 	dprintk(VIDC_DBG, "Cleared WRAPPER/A2H interrupt");
 }
 
-int venus_hfi_core_set_resource(void *device,
+static int venus_hfi_core_set_resource(void *device,
 		struct vidc_resource_hdr *resource_hdr, void *resource_value)
 {
 	struct hfi_cmd_sys_set_resource_packet *pkt;
@@ -1318,7 +1316,7 @@
 	return rc;
 }
 
-int venus_hfi_core_release_resource(void *device,
+static int venus_hfi_core_release_resource(void *device,
 			struct vidc_resource_hdr *resource_hdr)
 {
 	struct hfi_cmd_sys_release_resource_packet pkt;
@@ -1345,7 +1343,7 @@
 	return rc;
 }
 
-int venus_hfi_core_ping(void *device)
+static int venus_hfi_core_ping(void *device)
 {
 	struct hfi_cmd_sys_ping_packet pkt;
 	int rc = 0;
@@ -1371,8 +1369,8 @@
 	return rc;
 }
 
-int venus_hfi_session_set_property(void *sess,
-	enum hal_property ptype, void *pdata)
+static int venus_hfi_session_set_property(void *sess,
+					enum hal_property ptype, void *pdata)
 {
 	u8 packet[VIDC_IFACEQ_VAR_LARGE_PKT_SIZE];
 	struct hfi_cmd_session_set_property_packet *pkt =
@@ -1401,8 +1399,8 @@
 	return rc;
 }
 
-int venus_hfi_session_get_property(void *sess,
-	enum hal_property ptype, void *pdata)
+static int venus_hfi_session_get_property(void *sess,
+				enum hal_property ptype, void *pdata)
 {
 	struct hal_session *session;
 
@@ -1524,8 +1522,8 @@
 	return 0;
 }
 
-void *venus_hfi_session_init(void *device, u32 session_id,
-	enum hal_domain session_type, enum hal_video_codec codec_type)
+static void *venus_hfi_session_init(void *device, u32 session_id,
+		enum hal_domain session_type, enum hal_video_codec codec_type)
 {
 	struct hfi_cmd_sys_session_init_packet pkt;
 	struct hal_session *new_session;
@@ -1592,20 +1590,20 @@
 	return rc;
 }
 
-int venus_hfi_session_end(void *session)
+static int venus_hfi_session_end(void *session)
 {
 	return venus_hfi_send_session_cmd(session,
 		HFI_CMD_SYS_SESSION_END);
 }
 
-int venus_hfi_session_abort(void *session)
+static int venus_hfi_session_abort(void *session)
 {
 	return venus_hfi_send_session_cmd(session,
 		HFI_CMD_SYS_SESSION_ABORT);
 }
 
-int venus_hfi_session_set_buffers(void *sess,
-	struct vidc_buffer_addr_info *buffer_info)
+static int venus_hfi_session_set_buffers(void *sess,
+				struct vidc_buffer_addr_info *buffer_info)
 {
 	struct hfi_cmd_session_set_buffers_packet *pkt;
 	u8 packet[VIDC_IFACEQ_VAR_LARGE_PKT_SIZE];
@@ -1638,8 +1636,8 @@
 	return rc;
 }
 
-int venus_hfi_session_release_buffers(void *sess,
-	struct vidc_buffer_addr_info *buffer_info)
+static int venus_hfi_session_release_buffers(void *sess,
+				struct vidc_buffer_addr_info *buffer_info)
 {
 	struct hfi_cmd_session_release_buffer_packet *pkt;
 	u8 packet[VIDC_IFACEQ_VAR_LARGE_PKT_SIZE];
@@ -1672,43 +1670,44 @@
 	return rc;
 }
 
-int venus_hfi_session_load_res(void *sess)
+static int venus_hfi_session_load_res(void *sess)
 {
 	return venus_hfi_send_session_cmd(sess,
 		HFI_CMD_SESSION_LOAD_RESOURCES);
 }
 
-int venus_hfi_session_release_res(void *sess)
+static int venus_hfi_session_release_res(void *sess)
 {
 	return venus_hfi_send_session_cmd(sess,
 		HFI_CMD_SESSION_RELEASE_RESOURCES);
 }
 
-int venus_hfi_session_start(void *sess)
+static int venus_hfi_session_start(void *sess)
 {
 	return venus_hfi_send_session_cmd(sess,
 		HFI_CMD_SESSION_START);
 }
 
-int venus_hfi_session_stop(void *sess)
+static int venus_hfi_session_stop(void *sess)
 {
 	return venus_hfi_send_session_cmd(sess,
 		HFI_CMD_SESSION_STOP);
 }
 
-int venus_hfi_session_suspend(void *sess)
+static int venus_hfi_session_suspend(void *sess)
 {
 	return venus_hfi_send_session_cmd(sess,
 		HFI_CMD_SESSION_SUSPEND);
 }
 
-int venus_hfi_session_resume(void *sess)
+static int venus_hfi_session_resume(void *sess)
 {
 	return venus_hfi_send_session_cmd(sess,
 		HFI_CMD_SESSION_RESUME);
 }
 
-int venus_hfi_session_etb(void *sess, struct vidc_frame_data *input_frame)
+static int venus_hfi_session_etb(void *sess,
+				struct vidc_frame_data *input_frame)
 {
 	int rc = 0;
 	struct hal_session *session;
@@ -1752,8 +1751,8 @@
 	return rc;
 }
 
-int venus_hfi_session_ftb(void *sess,
-	struct vidc_frame_data *output_frame)
+static int venus_hfi_session_ftb(void *sess,
+				struct vidc_frame_data *output_frame)
 {
 	struct hfi_cmd_session_fill_buffer_packet pkt;
 	int rc = 0;
@@ -1778,8 +1777,8 @@
 	return rc;
 }
 
-int venus_hfi_session_parse_seq_hdr(void *sess,
-	struct vidc_seq_hdr *seq_hdr)
+static int venus_hfi_session_parse_seq_hdr(void *sess,
+					struct vidc_seq_hdr *seq_hdr)
 {
 	struct hfi_cmd_session_parse_sequence_header_packet *pkt;
 	int rc = 0;
@@ -1809,8 +1808,8 @@
 	return rc;
 }
 
-int venus_hfi_session_get_seq_hdr(void *sess,
-	struct vidc_seq_hdr *seq_hdr)
+static int venus_hfi_session_get_seq_hdr(void *sess,
+				struct vidc_seq_hdr *seq_hdr)
 {
 	struct hfi_cmd_session_get_sequence_header_packet *pkt;
 	int rc = 0;
@@ -1837,7 +1836,7 @@
 	return rc;
 }
 
-int venus_hfi_session_get_buf_req(void *sess)
+static int venus_hfi_session_get_buf_req(void *sess)
 {
 	struct hfi_cmd_session_get_property_packet pkt;
 	int rc = 0;
@@ -1862,7 +1861,7 @@
 	return rc;
 }
 
-int venus_hfi_session_flush(void *sess, enum hal_flush flush_mode)
+static int venus_hfi_session_flush(void *sess, enum hal_flush flush_mode)
 {
 	struct hfi_cmd_session_flush_packet pkt;
 	int rc = 0;
@@ -1937,6 +1936,44 @@
 	return -EINVAL;
 }
 
+static void venus_hfi_process_sys_watchdog_timeout(
+				struct venus_hfi_device *device)
+{
+	struct msm_vidc_cb_cmd_done cmd_done;
+	device->intr_status &= ~VIDC_WRAPPER_INTR_STATUS_A2HWD_BMSK;
+	memset(&cmd_done, 0, sizeof(struct msm_vidc_cb_cmd_done));
+	cmd_done.device_id = device->device_id;
+	device->callback(SYS_WATCHDOG_TIMEOUT, &cmd_done);
+}
+
+static void venus_hfi_response_handler(struct venus_hfi_device *device)
+{
+	u8 packet[VIDC_IFACEQ_MED_PKT_SIZE];
+
+	dprintk(VIDC_INFO, "#####venus_hfi_response_handler#####\n");
+	if (device) {
+		if ((device->intr_status &
+			VIDC_WRAPPER_INTR_CLEAR_A2HWD_BMSK)) {
+			dprintk(VIDC_ERR, "Received: Watchdog timeout %s",
+				__func__);
+			venus_hfi_process_sys_watchdog_timeout(device);
+		}
+
+		while (!venus_hfi_iface_msgq_read(device, packet)) {
+			hfi_process_msg_packet(device->callback,
+				device->device_id,
+				(struct vidc_hal_msg_pkt_hdr *) packet);
+		}
+		while (!venus_hfi_iface_dbgq_read(device, packet)) {
+			struct hfi_msg_sys_debug_packet *pkt =
+				(struct hfi_msg_sys_debug_packet *) packet;
+			dprintk(VIDC_FW, "FW-SAYS: %s", pkt->rg_msg_data);
+		}
+	} else {
+		dprintk(VIDC_ERR, "SPURIOUS_INTERRUPT");
+	}
+}
+
 static void venus_hfi_core_work_handler(struct work_struct *work)
 {
 	struct venus_hfi_device *device = list_first_entry(
@@ -1949,7 +1986,7 @@
 		return;
 	}
 	venus_hfi_core_clear_interrupt(device);
-	hfi_response_handler(device);
+	venus_hfi_response_handler(device);
 	enable_irq(device->hal_data->irq);
 }
 static DECLARE_WORK(venus_hfi_work, venus_hfi_core_work_handler);
@@ -2157,9 +2194,10 @@
 	return ret;
 }
 
-int venus_hfi_scale_clocks(struct venus_hfi_device *device, int load)
+static int venus_hfi_scale_clocks(void *dev, int load)
 {
 	int rc = 0;
+	struct venus_hfi_device *device = dev;
 	if (!device) {
 		dprintk(VIDC_ERR, "Invalid args: %p\n", device);
 		return -EINVAL;
@@ -2374,11 +2412,18 @@
 	return i;
 }
 
-int venus_hfi_scale_bus(struct venus_hfi_device *device, int load,
+static int venus_hfi_scale_bus(void *dev, int load,
 				enum session_type type, enum mem_type mtype)
 {
 	int rc = 0;
 	u32 handle = 0;
+	struct venus_hfi_device *device = dev;
+
+	if (!device) {
+		dprintk(VIDC_ERR, "%s invalid device handle %p",
+			__func__, device);
+		return -EINVAL;
+	}
 
 	if (mtype & DDR_MEM)
 		handle = device->resources.bus_info.ddr_handle[type];
@@ -2399,24 +2444,10 @@
 	return rc;
 }
 
-static void venus_hfi_ocmem_init(struct venus_hfi_device *device)
-{
-	struct on_chip_mem *ocmem;
-
-	ocmem = &device->resources.ocmem;
-	ocmem->vidc_ocmem_nb.notifier_call = msm_vidc_ocmem_notify_handler;
-	ocmem->handle =
-		ocmem_notifier_register(OCMEM_VIDEO, &ocmem->vidc_ocmem_nb);
-	if (!ocmem->handle) {
-		dprintk(VIDC_WARN, "Failed to register OCMEM notifier.");
-		dprintk(VIDC_INFO, " Performance will be impacted\n");
-	}
-}
-
-int venus_hfi_set_ocmem(struct venus_hfi_device *device,
-	struct ocmem_buf *ocmem)
+static int venus_hfi_set_ocmem(void *dev, struct ocmem_buf *ocmem)
 {
 	struct vidc_resource_hdr rhdr;
+	struct venus_hfi_device *device = dev;
 	int rc = 0;
 	if (!device || !ocmem) {
 		dprintk(VIDC_ERR, "Invalid params, core:%p, ocmem: %p\n",
@@ -2437,12 +2468,14 @@
 	return rc;
 }
 
-int venus_hfi_unset_ocmem(struct venus_hfi_device *device)
+static int venus_hfi_unset_ocmem(void *dev)
 {
 	struct vidc_resource_hdr rhdr;
+	struct venus_hfi_device *device = dev;
 	int rc = 0;
 	if (!device || !device->resources.ocmem.buf) {
-		dprintk(VIDC_ERR, "Invalid params, device:%p\n", device);
+		dprintk(VIDC_ERR, "%s Invalid params, device:%p\n",
+			__func__, device);
 		return -EINVAL;
 	}
 	rhdr.resource_id = VIDC_RESOURCE_OCMEM;
@@ -2454,15 +2487,59 @@
 	return rc;
 }
 
-int venus_hfi_alloc_ocmem(struct venus_hfi_device *device,
-		unsigned long size)
+static int venus_hfi_ocmem_notify_handler(struct notifier_block *this,
+		unsigned long event, void *data)
+{
+	struct ocmem_buf *buff = data;
+	struct venus_hfi_device *device;
+	struct venus_resources *resources;
+	struct on_chip_mem *ocmem;
+	int rc = NOTIFY_DONE;
+	if (event == OCMEM_ALLOC_GROW) {
+		ocmem = container_of(this, struct on_chip_mem, vidc_ocmem_nb);
+		if (!ocmem) {
+			dprintk(VIDC_ERR, "Wrong handler passed\n");
+			rc = NOTIFY_BAD;
+			goto err_ocmem_notify;
+		}
+		resources = container_of(ocmem,
+			struct venus_resources, ocmem);
+		device = container_of(resources,
+			struct venus_hfi_device, resources);
+		if (venus_hfi_set_ocmem(device, buff)) {
+			dprintk(VIDC_ERR, "Failed to set ocmem: %d\n", rc);
+			goto err_ocmem_notify;
+		}
+		rc = NOTIFY_OK;
+	}
+
+err_ocmem_notify:
+	return rc;
+}
+
+static void venus_hfi_ocmem_init(struct venus_hfi_device *device)
+{
+	struct on_chip_mem *ocmem;
+
+	ocmem = &device->resources.ocmem;
+	ocmem->vidc_ocmem_nb.notifier_call = venus_hfi_ocmem_notify_handler;
+	ocmem->handle =
+		ocmem_notifier_register(OCMEM_VIDEO, &ocmem->vidc_ocmem_nb);
+	if (!ocmem->handle) {
+		dprintk(VIDC_WARN, "Failed to register OCMEM notifier.");
+		dprintk(VIDC_INFO, " Performance will be impacted\n");
+	}
+}
+
+static int venus_hfi_alloc_ocmem(void *dev, unsigned long size)
 {
 	int rc = 0;
 	struct ocmem_buf *ocmem_buffer;
+	struct venus_hfi_device *device = dev;
 
 	if (!device || !size) {
-		dprintk(VIDC_ERR,
-			"Invalid param, core: %p, size: %lu\n", device, size);
+		dprintk(VIDC_ERR, "%s Invalid param, core: %p, size: %lu\n",
+			__func__, device, size);
 		return -EINVAL;
 	}
 	ocmem_buffer = device->resources.ocmem.buf;
@@ -2490,21 +2567,35 @@
 	return rc;
 }
 
-int venus_hfi_free_ocmem(struct venus_hfi_device *device)
+static int venus_hfi_free_ocmem(void *dev)
 {
+	struct venus_hfi_device *device = dev;
 	int rc = 0;
 
+	if (!device) {
+		dprintk(VIDC_ERR, "%s invalid device handle %p",
+			__func__, device);
+		return -EINVAL;
+	}
+
 	if (device->resources.ocmem.buf) {
 		rc = ocmem_free(OCMEM_VIDEO, device->resources.ocmem.buf);
 		if (rc)
 			dprintk(VIDC_ERR, "Failed to free ocmem\n");
+		device->resources.ocmem.buf = NULL;
 	}
-	device->resources.ocmem.buf = NULL;
 	return rc;
 }
 
-int venus_hfi_is_ocmem_present(struct venus_hfi_device *device)
+static int venus_hfi_is_ocmem_present(void *dev)
 {
+	struct venus_hfi_device *device = dev;
+	if (!device) {
+		dprintk(VIDC_ERR, "%s invalid device handle %p",
+			__func__, device);
+		return -EINVAL;
+	}
+
 	return device->resources.ocmem.buf ? 1 : 0;
 }
 
@@ -2515,6 +2606,7 @@
 				&device->resources.ocmem.vidc_ocmem_nb);
 }
 
+
 static int venus_hfi_init_resources(struct venus_hfi_device *device,
 				struct platform_device *pdev)
 {
@@ -2619,9 +2711,9 @@
 	}
 }
 
-int venus_hfi_get_domain(struct venus_hfi_device *device,
-						 enum msm_vidc_io_maps iomap)
+static int venus_hfi_get_domain(void *dev, enum msm_vidc_io_maps iomap)
 {
+	struct venus_hfi_device *device = dev;
 	if (!device || iomap < CP_MAP || iomap >= MAX_MAP) {
 		dprintk(VIDC_ERR, "%s: Invalid parameter: %p iomap: %d\n",
 				__func__, device, iomap);
@@ -2630,10 +2722,11 @@
 	return device->resources.io_map[iomap].domain;
 }
 
-int venus_hfi_iommu_get_map(struct venus_hfi_device *device,
+static int venus_hfi_iommu_get_map(void *dev,
 			struct msm_vidc_iommu_info maps[MAX_MAP])
 {
 	int i = 0;
+	struct venus_hfi_device *device = dev;
 
 	if (!device || !maps) {
 		dprintk(VIDC_ERR, "%s: Invalid param device: %p maps: %p\n",
@@ -2677,12 +2770,14 @@
 	return rc;
 }
 
-int venus_hfi_load_fw(struct venus_hfi_device *device)
+static int venus_hfi_load_fw(void *dev)
 {
 	int rc = 0;
+	struct venus_hfi_device *device = dev;
 
 	if (!device) {
-		dprintk(VIDC_ERR, "Invalid paramter: %p\n", device);
+		dprintk(VIDC_ERR, "%s Invalid paramter: %p\n",
+			__func__, device);
 		return -EINVAL;
 	}
 
@@ -2723,10 +2818,12 @@
 	return rc;
 }
 
-void venus_hfi_unload_fw(struct venus_hfi_device *device)
+static void venus_hfi_unload_fw(void *dev)
 {
+	struct venus_hfi_device *device = dev;
 	if (!device) {
-		dprintk(VIDC_ERR, "Invalid paramter: %p\n", device);
+		dprintk(VIDC_ERR, "%s Invalid paramter: %p\n",
+			__func__, device);
 		return;
 	}
 	if (device->resources.fw.cookie) {
@@ -2737,6 +2834,40 @@
 	}
 }
 
+static int venus_hfi_get_fw_info(void *dev, enum fw_info info)
+{
+	int rc = 0;
+	struct venus_hfi_device *device = dev;
+
+	if (!device) {
+		dprintk(VIDC_ERR, "%s Invalid paramter: %p\n",
+			__func__, device);
+		return -EINVAL;
+	}
+
+	switch (info) {
+	case FW_BASE_ADDRESS:
+		rc = device->base_addr;
+		break;
+
+	case FW_REGISTER_BASE:
+		rc = device->register_base;
+		break;
+
+	case FW_REGISTER_SIZE:
+		rc = device->register_size;
+		break;
+
+	case FW_IRQ:
+		rc = device->irq;
+		break;
+
+	default:
+		dprintk(VIDC_ERR, "Invalid fw info requested");
+	}
+	return rc;
+}
+
 static void *venus_hfi_add_device(u32 device_id, struct platform_device *pdev,
 		void (*callback) (enum command_response cmd, void *data))
 {
@@ -2786,9 +2917,9 @@
 	return NULL;
 }
 
-void *venus_hfi_get_device(u32 device_id,
-	struct platform_device *pdev,
-	void (*callback) (enum command_response cmd, void *data))
+static void *venus_hfi_get_device(u32 device_id,
+				struct platform_device *pdev,
+				hfi_cmd_response_callback callback)
 {
 	struct venus_hfi_device *device;
 	int rc = 0;
@@ -2837,3 +2968,60 @@
 
 	}
 }
+
+static void venus_init_hfi_callbacks(struct hfi_device *hdev)
+{
+	hdev->core_init = venus_hfi_core_init;
+	hdev->core_release = venus_hfi_core_release;
+	hdev->core_pc_prep = venus_hfi_core_pc_prep;
+	hdev->core_ping = venus_hfi_core_ping;
+	hdev->session_init = venus_hfi_session_init;
+	hdev->session_end = venus_hfi_session_end;
+	hdev->session_abort = venus_hfi_session_abort;
+	hdev->session_set_buffers = venus_hfi_session_set_buffers;
+	hdev->session_release_buffers = venus_hfi_session_release_buffers;
+	hdev->session_load_res = venus_hfi_session_load_res;
+	hdev->session_release_res = venus_hfi_session_release_res;
+	hdev->session_start = venus_hfi_session_start;
+	hdev->session_stop = venus_hfi_session_stop;
+	hdev->session_suspend = venus_hfi_session_suspend;
+	hdev->session_resume = venus_hfi_session_resume;
+	hdev->session_etb = venus_hfi_session_etb;
+	hdev->session_ftb = venus_hfi_session_ftb;
+	hdev->session_parse_seq_hdr = venus_hfi_session_parse_seq_hdr;
+	hdev->session_get_seq_hdr = venus_hfi_session_get_seq_hdr;
+	hdev->session_get_buf_req = venus_hfi_session_get_buf_req;
+	hdev->session_flush = venus_hfi_session_flush;
+	hdev->session_set_property = venus_hfi_session_set_property;
+	hdev->session_get_property = venus_hfi_session_get_property;
+	hdev->scale_clocks = venus_hfi_scale_clocks;
+	hdev->scale_bus = venus_hfi_scale_bus;
+	hdev->unset_ocmem = venus_hfi_unset_ocmem;
+	hdev->alloc_ocmem = venus_hfi_alloc_ocmem;
+	hdev->free_ocmem = venus_hfi_free_ocmem;
+	hdev->is_ocmem_present = venus_hfi_is_ocmem_present;
+	hdev->get_domain = venus_hfi_get_domain;
+	hdev->iommu_get_map = venus_hfi_iommu_get_map;
+	hdev->load_fw = venus_hfi_load_fw;
+	hdev->unload_fw = venus_hfi_unload_fw;
+	hdev->get_fw_info = venus_hfi_get_fw_info;
+}
+
+int venus_hfi_initialize(struct hfi_device *hdev, u32 device_id,
+	struct platform_device *pdev, hfi_cmd_response_callback callback)
+{
+	int rc = 0;
+
+	if (!hdev || !callback) {
+		dprintk(VIDC_ERR, "Invalid params: %p %p\n", pdev, callback);
+		rc = -EINVAL;
+		goto err_venus_hfi_init;
+	}
+	hdev->hfi_device_data = venus_hfi_get_device(device_id, pdev, callback);
+
+	venus_init_hfi_callbacks(hdev);
+
+err_venus_hfi_init:
+	return rc;
+}
+
diff --git a/drivers/media/video/msm_vidc/venus_hfi.h b/drivers/media/video/msm_vidc/venus_hfi.h
index 93b9ae3..f825c20 100644
--- a/drivers/media/video/msm_vidc/venus_hfi.h
+++ b/drivers/media/video/msm_vidc/venus_hfi.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -19,10 +19,12 @@
 #include <linux/platform_device.h>
 #include <linux/spinlock.h>
 #include <mach/ocmem.h>
-#include <media/msm_vidc.h>
+
 #include "vidc_hfi_api.h"
 #include "msm_smem.h"
 #include "vidc_hfi_helper.h"
+#include "vidc_hfi_api.h"
+#include "vidc_hfi.h"
 
 #define HFI_MASK_QHDR_TX_TYPE			0xFF000000
 #define HFI_MASK_QHDR_RX_TYPE			0x00FF0000
@@ -106,793 +108,6 @@
 	VIDC_HWREG_HVI_SOFTINTEN =  0xA,
 };
 
-#define HFI_EVENT_SESSION_SEQUENCE_CHANGED (HFI_OX_BASE + 0x3)
-#define HFI_EVENT_SESSION_PROPERTY_CHANGED (HFI_OX_BASE + 0x4)
-
-#define HFI_EVENT_DATA_SEQUENCE_CHANGED_SUFFICIENT_BUFFER_RESOURCES	\
-	(HFI_OX_BASE + 0x1)
-#define HFI_EVENT_DATA_SEQUENCE_CHANGED_INSUFFICIENT_BUFFER_RESOURCES	\
-	(HFI_OX_BASE + 0x2)
-
-#define HFI_BUFFERFLAG_EOS				0x00000001
-#define HFI_BUFFERFLAG_STARTTIME		0x00000002
-#define HFI_BUFFERFLAG_DECODEONLY		0x00000004
-#define HFI_BUFFERFLAG_DATACORRUPT		0x00000008
-#define HFI_BUFFERFLAG_ENDOFFRAME		0x00000010
-#define HFI_BUFFERFLAG_SYNCFRAME		0x00000020
-#define HFI_BUFFERFLAG_EXTRADATA		0x00000040
-#define HFI_BUFFERFLAG_CODECCONFIG		0x00000080
-#define HFI_BUFFERFLAG_TIMESTAMPINVALID	0x00000100
-#define HFI_BUFFERFLAG_READONLY			0x00000200
-#define HFI_BUFFERFLAG_ENDOFSUBFRAME	0x00000400
-#define HFI_BUFFERFLAG_EOSEQ			0x00200000
-#define HFI_BUFFERFLAG_DISCONTINUITY	0x80000000
-#define HFI_BUFFERFLAG_TEI				0x40000000
-
-#define HFI_ERR_SESSION_EMPTY_BUFFER_DONE_OUTPUT_PENDING	\
-	(HFI_OX_BASE + 0x1001)
-#define HFI_ERR_SESSION_SAME_STATE_OPERATION		\
-	(HFI_OX_BASE + 0x1002)
-#define HFI_ERR_SESSION_SYNC_FRAME_NOT_DETECTED		\
-	(HFI_OX_BASE + 0x1003)
-#define  HFI_ERR_SESSION_START_CODE_NOT_FOUND		\
-	(HFI_OX_BASE + 0x1004)
-
-#define HFI_BUFFER_INTERNAL_SCRATCH (HFI_OX_BASE + 0x1)
-#define HFI_BUFFER_EXTRADATA_INPUT (HFI_OX_BASE + 0x2)
-#define HFI_BUFFER_EXTRADATA_OUTPUT (HFI_OX_BASE + 0x3)
-#define HFI_BUFFER_EXTRADATA_OUTPUT2 (HFI_OX_BASE + 0x4)
-
-#define HFI_BUFFER_MODE_STATIC (HFI_OX_BASE + 0x1)
-#define HFI_BUFFER_MODE_RING (HFI_OX_BASE + 0x2)
-
-struct hfi_buffer_alloc_mode {
-	u32 buffer_type;
-	u32 buffer_mode;
-};
-
-#define HFI_FLUSH_INPUT (HFI_OX_BASE + 0x1)
-#define HFI_FLUSH_OUTPUT (HFI_OX_BASE + 0x2)
-#define HFI_FLUSH_OUTPUT2 (HFI_OX_BASE + 0x3)
-#define HFI_FLUSH_ALL (HFI_OX_BASE + 0x4)
-
-#define HFI_EXTRADATA_NONE					0x00000000
-#define HFI_EXTRADATA_MB_QUANTIZATION		0x00000001
-#define HFI_EXTRADATA_INTERLACE_VIDEO		0x00000002
-#define HFI_EXTRADATA_VC1_FRAMEDISP			0x00000003
-#define HFI_EXTRADATA_VC1_SEQDISP			0x00000004
-#define HFI_EXTRADATA_TIMESTAMP				0x00000005
-#define HFI_EXTRADATA_S3D_FRAME_PACKING		0x00000006
-#define HFI_EXTRADATA_FRAME_RATE			0x00000007
-#define HFI_EXTRADATA_PANSCAN_WINDOW		0x00000008
-#define HFI_EXTRADATA_RECOVERY_POINT_SEI	0x00000009
-#define HFI_EXTRADATA_CLOSED_CAPTION_UD		0x0000000A
-#define HFI_EXTRADATA_AFD_UD				0x0000000B
-#define HFI_EXTRADATA_MULTISLICE_INFO		0x7F100000
-#define HFI_EXTRADATA_NUM_CONCEALED_MB		0x7F100001
-#define HFI_EXTRADATA_INDEX					0x7F100002
-#define HFI_EXTRADATA_METADATA_FILLER		0x7FE00002
-
-#define HFI_INDEX_EXTRADATA_INPUT_CROP		0x0700000E
-#define HFI_INDEX_EXTRADATA_DIGITAL_ZOOM	0x07000010
-#define HFI_INDEX_EXTRADATA_ASPECT_RATIO	0x7F100003
-
-struct hfi_index_extradata_config {
-	int enable;
-	u32 index_extra_data_id;
-};
-
-struct hfi_extradata_header {
-	u32 size;
-	u32 version;
-	u32 port_index;
-	u32 type;
-	u32 data_size;
-	u8 rg_data[1];
-};
-
-#define HFI_INTERLACE_FRAME_PROGRESSIVE					0x01
-#define HFI_INTERLACE_INTERLEAVE_FRAME_TOPFIELDFIRST	0x02
-#define HFI_INTERLACE_INTERLEAVE_FRAME_BOTTOMFIELDFIRST	0x04
-#define HFI_INTERLACE_FRAME_TOPFIELDFIRST				0x08
-#define HFI_INTERLACE_FRAME_BOTTOMFIELDFIRST			0x10
-
-#define HFI_PROPERTY_SYS_OX_START			\
-	(HFI_DOMAIN_BASE_COMMON + HFI_ARCH_OX_OFFSET + 0x0000)
-#define HFI_PROPERTY_SYS_IDLE_INDICATOR		\
-	(HFI_PROPERTY_SYS_OX_START + 0x001)
-
-#define HFI_PROPERTY_PARAM_OX_START				\
-	(HFI_DOMAIN_BASE_COMMON + HFI_ARCH_OX_OFFSET + 0x1000)
-#define HFI_PROPERTY_PARAM_BUFFER_COUNT_ACTUAL			\
-	(HFI_PROPERTY_PARAM_OX_START + 0x001)
-#define HFI_PROPERTY_PARAM_UNCOMPRESSED_PLANE_ACTUAL_CONSTRAINTS_INFO	\
-	(HFI_PROPERTY_PARAM_OX_START + 0x002)
-#define HFI_PROPERTY_PARAM_INTERLACE_FORMAT_SUPPORTED	\
-	(HFI_PROPERTY_PARAM_OX_START + 0x003)
-#define HFI_PROPERTY_PARAM_CHROMA_SITE					\
-(HFI_PROPERTY_PARAM_OX_START + 0x004)
-#define HFI_PROPERTY_PARAM_EXTRA_DATA_HEADER_CONFIG		\
-	(HFI_PROPERTY_PARAM_OX_START + 0x005)
-#define HFI_PROPERTY_PARAM_INDEX_EXTRADATA             \
-	(HFI_PROPERTY_PARAM_OX_START + 0x006)
-#define HFI_PROPERTY_PARAM_DIVX_FORMAT					\
-	(HFI_PROPERTY_PARAM_OX_START + 0x007)
-#define HFI_PROPERTY_PARAM_BUFFER_ALLOC_MODE			\
-	(HFI_PROPERTY_PARAM_OX_START + 0x008)
-#define HFI_PROPERTY_PARAM_S3D_FRAME_PACKING_EXTRADATA	\
-	(HFI_PROPERTY_PARAM_OX_START + 0x009)
-
-#define HFI_PROPERTY_CONFIG_OX_START					\
-	(HFI_DOMAIN_BASE_COMMON + HFI_ARCH_OX_OFFSET + 0x02000)
-#define HFI_PROPERTY_CONFIG_BUFFER_REQUIREMENTS			\
-	(HFI_PROPERTY_CONFIG_OX_START + 0x001)
-#define HFI_PROPERTY_CONFIG_REALTIME					\
-	(HFI_PROPERTY_CONFIG_OX_START + 0x002)
-#define HFI_PROPERTY_CONFIG_PRIORITY					\
-	(HFI_PROPERTY_CONFIG_OX_START + 0x003)
-#define HFI_PROPERTY_CONFIG_BATCH_INFO					\
-	(HFI_PROPERTY_CONFIG_OX_START + 0x004)
-
-#define HFI_PROPERTY_PARAM_VDEC_OX_START				\
-	(HFI_DOMAIN_BASE_VDEC + HFI_ARCH_OX_OFFSET + 0x3000)
-#define HFI_PROPERTY_PARAM_VDEC_CONTINUE_DATA_TRANSFER	\
-	(HFI_PROPERTY_PARAM_VDEC_OX_START + 0x001)
-#define HFI_PROPERTY_PARAM_VDEC_DISPLAY_PICTURE_BUFFER_COUNT\
-	(HFI_PROPERTY_PARAM_VDEC_OX_START + 0x002)
-#define HFI_PROPERTY_PARAM_VDEC_MULTI_VIEW_SELECT		\
-	(HFI_PROPERTY_PARAM_VDEC_OX_START + 0x003)
-#define HFI_PROPERTY_PARAM_VDEC_PICTURE_TYPE_DECODE		\
-	(HFI_PROPERTY_PARAM_VDEC_OX_START + 0x004)
-#define HFI_PROPERTY_PARAM_VDEC_OUTPUT_ORDER			\
-	(HFI_PROPERTY_PARAM_VDEC_OX_START + 0x005)
-#define HFI_PROPERTY_PARAM_VDEC_MB_QUANTIZATION			\
-	(HFI_PROPERTY_PARAM_VDEC_OX_START + 0x006)
-#define HFI_PROPERTY_PARAM_VDEC_NUM_CONCEALED_MB		\
-	(HFI_PROPERTY_PARAM_VDEC_OX_START + 0x007)
-#define HFI_PROPERTY_PARAM_VDEC_H264_ENTROPY_SWITCHING	\
-	(HFI_PROPERTY_PARAM_VDEC_OX_START + 0x008)
-#define HFI_PROPERTY_PARAM_VDEC_OUTPUT2_KEEP_ASPECT_RATIO\
-	(HFI_PROPERTY_PARAM_VDEC_OX_START + 0x009)
-#define HFI_PROPERTY_PARAM_VDEC_FRAME_RATE_EXTRADATA  \
-	(HFI_PROPERTY_PARAM_VDEC_OX_START + 0x00A)
-#define HFI_PROPERTY_PARAM_VDEC_PANSCAN_WNDW_EXTRADATA \
-	(HFI_PROPERTY_PARAM_VDEC_OX_START + 0x00B)
-#define HFI_PROPERTY_PARAM_VDEC_RECOVERY_POINT_SEI_EXTRADATA \
-	(HFI_PROPERTY_PARAM_VDEC_OX_START + 0x00C)
-#define HFI_PROPERTY_PARAM_VDEC_THUMBNAIL_MODE   \
-	(HFI_PROPERTY_PARAM_VDEC_OX_START + 0x00D)
-
-#define HFI_PROPERTY_PARAM_VDEC_FRAME_ASSEMBLY		\
-	(HFI_PROPERTY_PARAM_VDEC_OX_START + 0x00E)
-#define HFI_PROPERTY_PARAM_VDEC_CLOSED_CAPTION_EXTRADATA	\
-	(HFI_PROPERTY_PARAM_VDEC_OX_START + 0x00F)
-#define HFI_PROPERTY_PARAM_VDEC_AFD_EXTRADATA		\
-	(HFI_PROPERTY_PARAM_VDEC_OX_START + 0x010)
-#define HFI_PROPERTY_PARAM_VDEC_VC1_FRAMEDISP_EXTRADATA		\
-	(HFI_PROPERTY_PARAM_VDEC_OX_START + 0x011)
-#define HFI_PROPERTY_PARAM_VDEC_VC1_SEQDISP_EXTRADATA		\
-	(HFI_PROPERTY_PARAM_VDEC_OX_START + 0x012)
-#define HFI_PROPERTY_PARAM_VDEC_TIMESTAMP_EXTRADATA			\
-	(HFI_PROPERTY_PARAM_VDEC_OX_START + 0x013)
-#define HFI_PROPERTY_PARAM_VDEC_INTERLACE_VIDEO_EXTRADATA	\
-	(HFI_PROPERTY_PARAM_VDEC_OX_START + 0x014)
-#define HFI_PROPERTY_PARAM_VDEC_AVC_SESSION_SELECT \
-	(HFI_PROPERTY_PARAM_VDEC_OX_START + 0x015)
-
-#define HFI_PROPERTY_CONFIG_VDEC_OX_START				\
-	(HFI_DOMAIN_BASE_VDEC + HFI_ARCH_OX_OFFSET + 0x0000)
-#define HFI_PROPERTY_CONFIG_VDEC_POST_LOOP_DEBLOCKER	\
-	(HFI_PROPERTY_CONFIG_VDEC_OX_START + 0x001)
-#define HFI_PROPERTY_CONFIG_VDEC_MB_ERROR_MAP_REPORTING	\
-	(HFI_PROPERTY_CONFIG_VDEC_OX_START + 0x002)
-#define HFI_PROPERTY_CONFIG_VDEC_MB_ERROR_MAP			\
-	(HFI_PROPERTY_CONFIG_VDEC_OX_START + 0x003)
-
-#define HFI_PROPERTY_PARAM_VENC_OX_START				\
-	(HFI_DOMAIN_BASE_VENC + HFI_ARCH_OX_OFFSET + 0x5000)
-#define  HFI_PROPERTY_PARAM_VENC_MULTI_SLICE_INFO       \
-	(HFI_PROPERTY_PARAM_VENC_OX_START + 0x001)
-#define  HFI_PROPERTY_PARAM_VENC_H264_IDR_S3D_FRAME_PACKING_NAL \
-	(HFI_PROPERTY_PARAM_VENC_OX_START + 0x002)
-
-#define HFI_PROPERTY_CONFIG_VENC_OX_START				\
-	(HFI_DOMAIN_BASE_VENC + HFI_ARCH_OX_OFFSET + 0x6000)
-#define  HFI_PROPERTY_CONFIG_VENC_FRAME_QP				\
-	(HFI_PROPERTY_CONFIG_VENC_OX_START + 0x001)
-
-#define HFI_PROPERTY_PARAM_VPE_OX_START					\
-	(HFI_DOMAIN_BASE_VPE + HFI_ARCH_OX_OFFSET + 0x7000)
-#define HFI_PROPERTY_CONFIG_VPE_OX_START				\
-	(HFI_DOMAIN_BASE_VPE + HFI_ARCH_OX_OFFSET + 0x8000)
-
-struct hfi_batch_info {
-	u32 input_batch_count;
-	u32 output_batch_count;
-};
-
-struct hfi_buffer_count_actual {
-	u32 buffer_type;
-	u32 buffer_count_actual;
-};
-
-struct hfi_buffer_requirements {
-	u32 buffer_type;
-	u32 buffer_size;
-	u32 buffer_region_size;
-	u32 buffer_hold_count;
-	u32 buffer_count_min;
-	u32 buffer_count_actual;
-	u32 contiguous;
-	u32 buffer_alignment;
-};
-
-#define HFI_CHROMA_SITE_0			(HFI_OX_BASE + 0x1)
-#define HFI_CHROMA_SITE_1			(HFI_OX_BASE + 0x2)
-#define HFI_CHROMA_SITE_2			(HFI_OX_BASE + 0x3)
-#define HFI_CHROMA_SITE_3			(HFI_OX_BASE + 0x4)
-#define HFI_CHROMA_SITE_4			(HFI_OX_BASE + 0x5)
-#define HFI_CHROMA_SITE_5			(HFI_OX_BASE + 0x6)
-
-struct hfi_data_payload {
-	u32 size;
-	u8 rg_data[1];
-};
-
-struct hfi_enable_picture {
-	u32 picture_type;
-};
-
-struct hfi_display_picture_buffer_count {
-	int enable;
-	u32 count;
-};
-
-struct hfi_extra_data_header_config {
-	u32 type;
-	u32 buffer_type;
-	u32 version;
-	u32 port_index;
-	u32 client_extra_data_id;
-};
-
-struct hfi_interlace_format_supported {
-	u32 buffer_type;
-	u32 format;
-};
-
-struct hfi_mb_error_map {
-	u32 error_map_size;
-	u8 rg_error_map[1];
-};
-
-struct hfi_metadata_pass_through {
-	int enable;
-	u32 size;
-};
-
-struct hfi_multi_view_select {
-	u32 view_index;
-};
-
-#define HFI_PRIORITY_LOW		10
-#define HFI_PRIOIRTY_MEDIUM		20
-#define HFI_PRIORITY_HIGH		30
-
-#define HFI_OUTPUT_ORDER_DISPLAY	(HFI_OX_BASE + 0x1)
-#define HFI_OUTPUT_ORDER_DECODE		(HFI_OX_BASE + 0x2)
-
-#define HFI_RATE_CONTROL_OFF		(HFI_OX_BASE + 0x1)
-#define HFI_RATE_CONTROL_VBR_VFR	(HFI_OX_BASE + 0x2)
-#define HFI_RATE_CONTROL_VBR_CFR	(HFI_OX_BASE + 0x3)
-#define HFI_RATE_CONTROL_CBR_VFR	(HFI_OX_BASE + 0x4)
-#define HFI_RATE_CONTROL_CBR_CFR	(HFI_OX_BASE + 0x5)
-
-struct hfi_uncompressed_plane_actual_constraints_info {
-	u32 buffer_type;
-	u32 num_planes;
-	struct hfi_uncompressed_plane_constraints rg_plane_format[1];
-};
-
-#define HFI_CMD_SYS_OX_START		\
-(HFI_DOMAIN_BASE_COMMON + HFI_ARCH_OX_OFFSET + HFI_CMD_START_OFFSET + 0x0000)
-#define HFI_CMD_SYS_SESSION_ABORT	(HFI_CMD_SYS_OX_START + 0x001)
-#define HFI_CMD_SYS_PING		(HFI_CMD_SYS_OX_START + 0x002)
-
-#define HFI_CMD_SESSION_OX_START	\
-(HFI_DOMAIN_BASE_COMMON + HFI_ARCH_OX_OFFSET + HFI_CMD_START_OFFSET + 0x1000)
-#define HFI_CMD_SESSION_LOAD_RESOURCES	(HFI_CMD_SESSION_OX_START + 0x001)
-#define HFI_CMD_SESSION_START		(HFI_CMD_SESSION_OX_START + 0x002)
-#define HFI_CMD_SESSION_STOP		(HFI_CMD_SESSION_OX_START + 0x003)
-#define HFI_CMD_SESSION_EMPTY_BUFFER	(HFI_CMD_SESSION_OX_START + 0x004)
-#define HFI_CMD_SESSION_FILL_BUFFER	(HFI_CMD_SESSION_OX_START + 0x005)
-#define HFI_CMD_SESSION_SUSPEND		(HFI_CMD_SESSION_OX_START + 0x006)
-#define HFI_CMD_SESSION_RESUME		(HFI_CMD_SESSION_OX_START + 0x007)
-#define HFI_CMD_SESSION_FLUSH		(HFI_CMD_SESSION_OX_START + 0x008)
-#define HFI_CMD_SESSION_GET_PROPERTY	(HFI_CMD_SESSION_OX_START + 0x009)
-#define HFI_CMD_SESSION_PARSE_SEQUENCE_HEADER	\
-	(HFI_CMD_SESSION_OX_START + 0x00A)
-#define HFI_CMD_SESSION_RELEASE_BUFFERS		\
-	(HFI_CMD_SESSION_OX_START + 0x00B)
-#define HFI_CMD_SESSION_RELEASE_RESOURCES	\
-	(HFI_CMD_SESSION_OX_START + 0x00C)
-
-#define HFI_MSG_SYS_OX_START			\
-(HFI_DOMAIN_BASE_COMMON + HFI_ARCH_OX_OFFSET + HFI_MSG_START_OFFSET + 0x0000)
-#define HFI_MSG_SYS_IDLE		(HFI_MSG_SYS_OX_START + 0x1)
-#define HFI_MSG_SYS_PING_ACK	(HFI_MSG_SYS_OX_START + 0x2)
-#define HFI_MSG_SYS_PROPERTY_INFO	(HFI_MSG_SYS_OX_START + 0x3)
-#define HFI_MSG_SYS_SESSION_ABORT_DONE	(HFI_MSG_SYS_OX_START + 0x4)
-
-#define HFI_MSG_SESSION_OX_START		\
-(HFI_DOMAIN_BASE_COMMON + HFI_ARCH_OX_OFFSET + HFI_MSG_START_OFFSET + 0x1000)
-#define HFI_MSG_SESSION_LOAD_RESOURCES_DONE	(HFI_MSG_SESSION_OX_START + 0x1)
-#define HFI_MSG_SESSION_START_DONE		(HFI_MSG_SESSION_OX_START + 0x2)
-#define HFI_MSG_SESSION_STOP_DONE		(HFI_MSG_SESSION_OX_START + 0x3)
-#define HFI_MSG_SESSION_SUSPEND_DONE	(HFI_MSG_SESSION_OX_START + 0x4)
-#define HFI_MSG_SESSION_RESUME_DONE		(HFI_MSG_SESSION_OX_START + 0x5)
-#define HFI_MSG_SESSION_FLUSH_DONE		(HFI_MSG_SESSION_OX_START + 0x6)
-#define HFI_MSG_SESSION_EMPTY_BUFFER_DONE	(HFI_MSG_SESSION_OX_START + 0x7)
-#define HFI_MSG_SESSION_FILL_BUFFER_DONE	(HFI_MSG_SESSION_OX_START + 0x8)
-#define HFI_MSG_SESSION_PROPERTY_INFO		(HFI_MSG_SESSION_OX_START + 0x9)
-#define HFI_MSG_SESSION_RELEASE_RESOURCES_DONE	\
-	(HFI_MSG_SESSION_OX_START + 0xA)
-#define HFI_MSG_SESSION_PARSE_SEQUENCE_HEADER_DONE		\
-	(HFI_MSG_SESSION_OX_START + 0xB)
-#define  HFI_MSG_SESSION_RELEASE_BUFFERS_DONE			\
-	(HFI_MSG_SESSION_OX_START + 0xC)
-
-struct hfi_cmd_sys_session_abort_packet {
-	u32 size;
-	u32 packet_type;
-	u32 session_id;
-};
-
-struct hfi_cmd_sys_ping_packet {
-	u32 size;
-	u32 packet_type;
-	u32 client_data;
-};
-
-struct hfi_cmd_session_load_resources_packet {
-	u32 size;
-	u32 packet_type;
-	u32 session_id;
-};
-
-struct hfi_cmd_session_start_packet {
-	u32 size;
-	u32 packet_type;
-	u32 session_id;
-};
-
-struct hfi_cmd_session_stop_packet {
-	u32 size;
-	u32 packet_type;
-	u32 session_id;
-};
-
-struct hfi_cmd_session_empty_buffer_compressed_packet {
-	u32 size;
-	u32 packet_type;
-	u32 session_id;
-	u32 time_stamp_hi;
-	u32 time_stamp_lo;
-	u32 flags;
-	u32 mark_target;
-	u32 mark_data;
-	u32 offset;
-	u32 alloc_len;
-	u32 filled_len;
-	u32 input_tag;
-	u8 *packet_buffer;
-	u8 *extra_data_buffer;
-	u32 rgData[0];
-};
-
-struct hfi_cmd_session_empty_buffer_uncompressed_plane0_packet {
-	u32 size;
-	u32 packet_type;
-	u32 session_id;
-	u32 view_id;
-	u32 time_stamp_hi;
-	u32 time_stamp_lo;
-	u32 flags;
-	u32 mark_target;
-	u32 mark_data;
-	u32 alloc_len;
-	u32 filled_len;
-	u32 offset;
-	u32 input_tag;
-	u8 *packet_buffer;
-	u8 *extra_data_buffer;
-	u32 rgData[0];
-};
-
-struct hfi_cmd_session_empty_buffer_uncompressed_plane1_packet {
-	u32 flags;
-	u32 alloc_len;
-	u32 filled_len;
-	u32 offset;
-	u8 *packet_buffer2;
-	u32 rgData[0];
-};
-
-struct hfi_cmd_session_empty_buffer_uncompressed_plane2_packet {
-	u32 flags;
-	u32 alloc_len;
-	u32 filled_len;
-	u32 offset;
-	u8 *packet_buffer3;
-	u32 rgData[0];
-};
-
-struct hfi_cmd_session_fill_buffer_packet {
-	u32 size;
-	u32 packet_type;
-	u32 session_id;
-	u32 stream_id;
-	u32 offset;
-	u32 alloc_len;
-	u32 filled_len;
-	u32 output_tag;
-	u8 *packet_buffer;
-	u8 *extra_data_buffer;
-	u32 rgData[0];
-};
-
-struct hfi_cmd_session_flush_packet {
-	u32 size;
-	u32 packet_type;
-	u32 session_id;
-	u32 flush_type;
-};
-
-struct hfi_cmd_session_suspend_packet {
-	u32 size;
-	u32 packet_type;
-	u32 session_id;
-};
-
-struct hfi_cmd_session_resume_packet {
-	u32 size;
-	u32 packet_type;
-	u32 session_id;
-};
-
-struct hfi_cmd_session_get_property_packet {
-	u32 size;
-	u32 packet_type;
-	u32 session_id;
-	u32 num_properties;
-	u32 rg_property_data[1];
-};
-
-struct hfi_cmd_session_release_buffer_packet {
-	u32 size;
-	u32 packet_type;
-	u32 session_id;
-	u32 buffer_type;
-	u32 buffer_size;
-	u32 extra_data_size;
-	int response_req;
-	u32 num_buffers;
-	u32 rg_buffer_info[1];
-};
-
-struct hfi_cmd_session_release_resources_packet {
-	u32 size;
-	u32 packet_type;
-	u32 session_id;
-};
-
-struct hfi_cmd_session_parse_sequence_header_packet {
-	u32 size;
-	u32 packet_type;
-	u32 session_id;
-	u32 header_len;
-	u8 *packet_buffer;
-};
-
-struct hfi_msg_sys_session_abort_done_packet {
-	u32 size;
-	u32 packet_type;
-	u32 session_id;
-	u32 error_type;
-};
-
-struct hfi_msg_sys_idle_packet {
-	u32 size;
-	u32 packet_type;
-};
-
-struct hfi_msg_sys_ping_ack_packet {
-	u32 size;
-	u32 packet_type;
-	u32 client_data;
-};
-
-struct hfi_msg_sys_property_info_packet {
-	u32 size;
-	u32 packet_type;
-	u32 num_properties;
-	u32 rg_property_data[1];
-};
-
-struct hfi_msg_session_load_resources_done_packet {
-	u32 size;
-	u32 packet_type;
-	u32 session_id;
-	u32 error_type;
-};
-
-struct hfi_msg_session_start_done_packet {
-	u32 size;
-	u32 packet_type;
-	u32 session_id;
-	u32 error_type;
-};
-
-struct hfi_msg_session_stop_done_packet {
-	u32 size;
-	u32 packet_type;
-	u32 session_id;
-	u32 error_type;
-};
-
-struct hfi_msg_session_suspend_done_packet {
-	u32 size;
-	u32 packet_type;
-	u32 session_id;
-	u32 error_type;
-};
-
-struct hfi_msg_session_resume_done_packet {
-	u32 size;
-	u32 packet_type;
-	u32 session_id;
-	u32 error_type;
-};
-
-struct hfi_msg_session_flush_done_packet {
-	u32 size;
-	u32 packet_type;
-	u32 session_id;
-	u32 error_type;
-	u32 flush_type;
-};
-
-struct hfi_msg_session_empty_buffer_done_packet {
-	u32 size;
-	u32 packet_type;
-	u32 session_id;
-	u32 error_type;
-	u32 offset;
-	u32 filled_len;
-	u32 input_tag;
-	u8 *packet_buffer;
-	u8 *extra_data_buffer;
-	u32 rgData[0];
-};
-
-struct hfi_msg_session_fill_buffer_done_compressed_packet {
-	u32 size;
-	u32 packet_type;
-	u32 session_id;
-	u32 time_stamp_hi;
-	u32 time_stamp_lo;
-	u32 error_type;
-	u32 flags;
-	u32 mark_target;
-	u32 mark_data;
-	u32 stats;
-	u32 offset;
-	u32 alloc_len;
-	u32 filled_len;
-	u32 input_tag;
-	u32 output_tag;
-	u32 picture_type;
-	u8 *packet_buffer;
-	u8 *extra_data_buffer;
-	u32 rgData[0];
-};
-
-struct hfi_msg_session_fbd_uncompressed_plane0_packet {
-	u32 size;
-	u32 packet_type;
-	u32 session_id;
-	u32 stream_id;
-	u32 view_id;
-	u32 error_type;
-	u32 time_stamp_hi;
-	u32 time_stamp_lo;
-	u32 flags;
-	u32 mark_target;
-	u32 mark_data;
-	u32 stats;
-	u32 alloc_len;
-	u32 filled_len;
-	u32 offset;
-	u32 frame_width;
-	u32 frame_height;
-	u32 start_x_coord;
-	u32 start_y_coord;
-	u32 input_tag;
-	u32 input_tag2;
-	u32 output_tag;
-	u32 picture_type;
-	u8 *packet_buffer;
-	u8 *extra_data_buffer;
-	u32 rgData[0];
-};
-
-struct hfi_msg_session_fill_buffer_done_uncompressed_plane1_packet {
-	u32 flags;
-	u32 alloc_len;
-	u32 filled_len;
-	u32 offset;
-	u8 *packet_buffer2;
-	u32 rgData[0];
-};
-
-struct hfi_msg_session_fill_buffer_done_uncompressed_plane2_packet {
-	u32 flags;
-	u32 alloc_len;
-	u32 filled_len;
-	u32 offset;
-	u8 *packet_buffer3;
-	u32 rgData[0];
-};
-
-struct hfi_msg_session_parse_sequence_header_done_packet {
-	u32 size;
-	u32 packet_type;
-	u32 session_id;
-	u32 error_type;
-	u32 num_properties;
-	u32 rg_property_data[1];
-};
-
-struct hfi_msg_session_property_info_packet {
-	u32 size;
-	u32 packet_type;
-	u32 session_id;
-	u32 num_properties;
-	u32 rg_property_data[1];
-};
-
-struct hfi_msg_session_release_resources_done_packet {
-	u32 size;
-	u32 packet_type;
-	u32 session_id;
-	u32 error_type;
-};
-
-struct hfi_msg_session_release_buffers_done_packet {
-	u32 size;
-	u32 packet_type;
-	u32 session_id;
-	u32 error_type;
-	u32 num_buffers;
-	u32 rg_buffer_info[1];
-};
-
-struct hfi_extradata_mb_quantization_payload {
-	u8 rg_mb_qp[1];
-};
-
-struct hfi_extradata_vc1_pswnd {
-	u32 ps_wnd_h_offset;
-	u32 ps_wnd_v_offset;
-	u32 ps_wnd_width;
-	u32 ps_wnd_height;
-};
-
-struct hfi_extradata_vc1_framedisp_payload {
-	u32 res_pic;
-	u32 ref;
-	u32 range_map_present;
-	u32 range_map_y;
-	u32 range_map_uv;
-	u32 num_pan_scan_wnds;
-	struct hfi_extradata_vc1_pswnd rg_ps_wnd[1];
-};
-
-struct hfi_extradata_vc1_seqdisp_payload {
-	u32 prog_seg_frm;
-	u32 uv_sampling_fmt;
-	u32 color_fmt_flag;
-	u32 color_primaries;
-	u32 transfer_char;
-	u32 mat_coeff;
-	u32 aspect_ratio;
-	u32 aspect_horiz;
-	u32 aspect_vert;
-};
-
-struct hfi_extradata_timestamp_payload {
-	u32 time_stamp_low;
-	u32 time_stamp_high;
-};
-
-
-struct hfi_extradata_s3d_frame_packing_payload {
-	u32 fpa_id;
-	int cancel_flag;
-	u32 fpa_type;
-	int quin_cunx_flag;
-	u32 content_interprtation_type;
-	int spatial_flipping_flag;
-	int frame0_flipped_flag;
-	int field_views_flag;
-	int current_frame_isFrame0_flag;
-	int frame0_self_contained_flag;
-	int frame1_self_contained_flag;
-	u32 frame0_graid_pos_x;
-	u32 frame0_graid_pos_y;
-	u32 frame1_graid_pos_x;
-	u32 frame1_graid_pos_y;
-	u32 fpa_reserved_byte;
-	u32 fpa_repetition_period;
-	int fpa_extension_flag;
-};
-
-struct hfi_extradata_interlace_video_payload {
-	u32 format;
-};
-
-struct hfi_extradata_num_concealed_mb_payload {
-	u32 num_mb_concealed;
-};
-
-struct hfi_extradata_sliceinfo {
-	u32 offset_in_stream;
-	u32 slice_length;
-};
-
-struct hfi_extradata_multislice_info_payload {
-	u32 num_slices;
-	struct hfi_extradata_sliceinfo rg_slice_info[1];
-};
-
-struct hfi_index_extradata_input_crop_payload {
-	u32 size;
-	u32 version;
-	u32 port_index;
-	u32 left;
-	u32 top;
-	u32 width;
-	u32 height;
-};
-
-struct hfi_index_extradata_digital_zoom_payload {
-	u32 size;
-	u32 version;
-	u32 port_index;
-	int width;
-	int height;
-};
-
-struct hfi_index_extradata_aspect_ratio_payload {
-	u32 size;
-	u32 version;
-	u32 port_index;
-	u32 aspect_width;
-	u32 aspect_height;
-};
-struct hfi_extradata_panscan_wndw_payload {
-	u32 num_window;
-	struct hfi_extradata_vc1_pswnd wnd[1];
-};
-
-struct hfi_extradata_frame_type_payload {
-	u32 frame_rate;
-};
-
-struct hfi_extradata_recovery_point_sei_payload {
-	u32 flag;
-};
-
 struct vidc_mem_addr {
 	u8 *align_device_addr;
 	u8 *align_virtual_addr;
@@ -921,11 +136,6 @@
 	VCODEC_MAX_CLKS
 };
 
-enum mem_type {
-	DDR_MEM = 0x1,
-	OCMEM_MEM = 0x2,
-};
-
 struct load_freq_table {
 	u32 load;
 	u32 freq;
@@ -968,7 +178,7 @@
 	u32 device_id;
 	spinlock_t read_lock;
 	spinlock_t write_lock;
-	void (*callback) (u32 response, void *callback);
+	msm_vidc_callback callback;
 	struct vidc_mem_addr iface_q_table;
 	struct vidc_mem_addr qdss;
 	struct vidc_mem_addr sfr;
@@ -986,49 +196,7 @@
 	struct venus_resources resources;
 };
 
-struct hal_session {
-	struct list_head list;
-	u32 session_id;
-	u32 is_decoder;
-	struct venus_hfi_device *device;
-};
-
-struct hal_device_data {
-	struct list_head dev_head;
-	int dev_count;
-};
-
-extern struct hal_device_data hal_ctxt;
-
-int venus_hfi_iface_msgq_read(struct venus_hfi_device *device, void *pkt);
-int venus_hfi_iface_dbgq_read(struct venus_hfi_device *device, void *pkt);
-
-/* Interrupt Processing:*/
-void hfi_response_handler(struct venus_hfi_device *device);
-
 void venus_hfi_delete_device(void *device);
-
-int venus_hfi_scale_clocks(struct venus_hfi_device *device, int load);
-
-void *venus_hfi_get_device(u32 device_id,
-	struct platform_device *pdev,
-	void (*callback) (enum command_response cmd, void *data));
-
-int venus_hfi_scale_bus(struct venus_hfi_device *device, int load,
-				enum session_type type, enum mem_type mtype);
-int venus_hfi_set_ocmem(struct venus_hfi_device *device,
-	struct ocmem_buf *ocmem);
-int venus_hfi_unset_ocmem(struct venus_hfi_device *device);
-int venus_hfi_alloc_ocmem(struct venus_hfi_device *device,
-		unsigned long size);
-int venus_hfi_free_ocmem(struct venus_hfi_device *device);
-int venus_hfi_is_ocmem_present(struct venus_hfi_device *device);
-
-int venus_hfi_get_domain(struct venus_hfi_device *device,
-						 enum msm_vidc_io_maps iomap);
-int venus_hfi_iommu_get_map(struct venus_hfi_device *device,
-			struct msm_vidc_iommu_info maps[MAX_MAP]);
-int venus_hfi_load_fw(struct venus_hfi_device *device);
-void venus_hfi_unload_fw(struct venus_hfi_device *device);
-
+int venus_hfi_initialize(struct hfi_device *hdev, u32 device_id,
+	struct platform_device *pdev, hfi_cmd_response_callback callback);
 #endif
diff --git a/drivers/media/video/msm_vidc/vidc_hfi.c b/drivers/media/video/msm_vidc/vidc_hfi.c
new file mode 100644
index 0000000..f09d3d5
--- /dev/null
+++ b/drivers/media/video/msm_vidc/vidc_hfi.c
@@ -0,0 +1,68 @@
+/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+#include <linux/slab.h>
+#include "msm_vidc_debug.h"
+#include "vidc_hfi_api.h"
+#include "venus_hfi.h"
+
+struct hal_device_data hal_ctxt;
+
+void *vidc_hfi_initialize(enum msm_vidc_hfi_type hfi_type, u32 device_id,
+			struct platform_device *pdev,
+			hfi_cmd_response_callback callback)
+{
+	struct hfi_device *hdev = NULL;
+	hdev = (struct hfi_device *)
+			kzalloc(sizeof(struct hfi_device), GFP_KERNEL);
+	if (!hdev) {
+		dprintk(VIDC_ERR, "%s: failed to allocate hdev\n", __func__);
+		return NULL;
+	}
+
+	switch (hfi_type) {
+	case VIDC_HFI_VENUS:
+		venus_hfi_initialize(hdev, device_id, pdev, callback);
+		break;
+
+	case VIDC_HFI_Q6:
+	default:
+		dprintk(VIDC_ERR, "Unsupported host-firmware interface\n");
+		goto err_hfi_init;
+	}
+	return hdev;
+
+err_hfi_init:
+	kfree(hdev);
+	return NULL;
+}
+
+void vidc_hfi_deinitialize(enum msm_vidc_hfi_type hfi_type,
+			struct hfi_device *hdev)
+{
+	if (!hdev) {
+		dprintk(VIDC_ERR, "%s invalid device %p", __func__, hdev);
+		return;
+	}
+
+	switch (hfi_type) {
+	case VIDC_HFI_VENUS:
+		venus_hfi_delete_device(hdev->hfi_device_data);
+		break;
+
+	case VIDC_HFI_Q6:
+	default:
+		dprintk(VIDC_ERR, "Unsupported host-firmware interface\n");
+	}
+	kfree(hdev);
+}
+
diff --git a/drivers/media/video/msm_vidc/vidc_hfi.h b/drivers/media/video/msm_vidc/vidc_hfi.h
new file mode 100644
index 0000000..6ff0921
--- /dev/null
+++ b/drivers/media/video/msm_vidc/vidc_hfi.h
@@ -0,0 +1,826 @@
+/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+#ifndef __H_VIDC_HFI_H__
+#define __H_VIDC_HFI_H__
+
+#include "vidc_hfi_helper.h"
+#include "vidc_hfi_api.h"
+
+#define HFI_EVENT_SESSION_SEQUENCE_CHANGED (HFI_OX_BASE + 0x3)
+#define HFI_EVENT_SESSION_PROPERTY_CHANGED (HFI_OX_BASE + 0x4)
+
+#define HFI_EVENT_DATA_SEQUENCE_CHANGED_SUFFICIENT_BUFFER_RESOURCES	\
+	(HFI_OX_BASE + 0x1)
+#define HFI_EVENT_DATA_SEQUENCE_CHANGED_INSUFFICIENT_BUFFER_RESOURCES	\
+	(HFI_OX_BASE + 0x2)
+
+#define HFI_BUFFERFLAG_EOS				0x00000001
+#define HFI_BUFFERFLAG_STARTTIME		0x00000002
+#define HFI_BUFFERFLAG_DECODEONLY		0x00000004
+#define HFI_BUFFERFLAG_DATACORRUPT		0x00000008
+#define HFI_BUFFERFLAG_ENDOFFRAME		0x00000010
+#define HFI_BUFFERFLAG_SYNCFRAME		0x00000020
+#define HFI_BUFFERFLAG_EXTRADATA		0x00000040
+#define HFI_BUFFERFLAG_CODECCONFIG		0x00000080
+#define HFI_BUFFERFLAG_TIMESTAMPINVALID	0x00000100
+#define HFI_BUFFERFLAG_READONLY			0x00000200
+#define HFI_BUFFERFLAG_ENDOFSUBFRAME	0x00000400
+#define HFI_BUFFERFLAG_EOSEQ			0x00200000
+#define HFI_BUFFERFLAG_DISCONTINUITY	0x80000000
+#define HFI_BUFFERFLAG_TEI				0x40000000
+
+#define HFI_ERR_SESSION_EMPTY_BUFFER_DONE_OUTPUT_PENDING	\
+	(HFI_OX_BASE + 0x1001)
+#define HFI_ERR_SESSION_SAME_STATE_OPERATION		\
+	(HFI_OX_BASE + 0x1002)
+#define HFI_ERR_SESSION_SYNC_FRAME_NOT_DETECTED		\
+	(HFI_OX_BASE + 0x1003)
+#define  HFI_ERR_SESSION_START_CODE_NOT_FOUND		\
+	(HFI_OX_BASE + 0x1004)
+
+#define HFI_BUFFER_INTERNAL_SCRATCH (HFI_OX_BASE + 0x1)
+#define HFI_BUFFER_EXTRADATA_INPUT (HFI_OX_BASE + 0x2)
+#define HFI_BUFFER_EXTRADATA_OUTPUT (HFI_OX_BASE + 0x3)
+#define HFI_BUFFER_EXTRADATA_OUTPUT2 (HFI_OX_BASE + 0x4)
+
+#define HFI_BUFFER_MODE_STATIC (HFI_OX_BASE + 0x1)
+#define HFI_BUFFER_MODE_RING (HFI_OX_BASE + 0x2)
+
+#define HFI_FLUSH_INPUT (HFI_OX_BASE + 0x1)
+#define HFI_FLUSH_OUTPUT (HFI_OX_BASE + 0x2)
+#define HFI_FLUSH_OUTPUT2 (HFI_OX_BASE + 0x3)
+#define HFI_FLUSH_ALL (HFI_OX_BASE + 0x4)
+
+#define HFI_EXTRADATA_NONE					0x00000000
+#define HFI_EXTRADATA_MB_QUANTIZATION		0x00000001
+#define HFI_EXTRADATA_INTERLACE_VIDEO		0x00000002
+#define HFI_EXTRADATA_VC1_FRAMEDISP			0x00000003
+#define HFI_EXTRADATA_VC1_SEQDISP			0x00000004
+#define HFI_EXTRADATA_TIMESTAMP				0x00000005
+#define HFI_EXTRADATA_S3D_FRAME_PACKING		0x00000006
+#define HFI_EXTRADATA_FRAME_RATE			0x00000007
+#define HFI_EXTRADATA_PANSCAN_WINDOW		0x00000008
+#define HFI_EXTRADATA_RECOVERY_POINT_SEI	0x00000009
+#define HFI_EXTRADATA_CLOSED_CAPTION_UD		0x0000000A
+#define HFI_EXTRADATA_AFD_UD				0x0000000B
+#define HFI_EXTRADATA_MULTISLICE_INFO		0x7F100000
+#define HFI_EXTRADATA_NUM_CONCEALED_MB		0x7F100001
+#define HFI_EXTRADATA_INDEX					0x7F100002
+#define HFI_EXTRADATA_METADATA_FILLER		0x7FE00002
+
+#define HFI_INDEX_EXTRADATA_INPUT_CROP		0x0700000E
+#define HFI_INDEX_EXTRADATA_DIGITAL_ZOOM	0x07000010
+#define HFI_INDEX_EXTRADATA_ASPECT_RATIO	0x7F100003
+
+struct hfi_buffer_alloc_mode {
+	u32 buffer_type;
+	u32 buffer_mode;
+};
+
+
+struct hfi_index_extradata_config {
+	int enable;
+	u32 index_extra_data_id;
+};
+
+struct hfi_extradata_header {
+	u32 size;
+	u32 version;
+	u32 port_index;
+	u32 type;
+	u32 data_size;
+	u8 rg_data[1];
+};
+
+#define HFI_INTERLACE_FRAME_PROGRESSIVE					0x01
+#define HFI_INTERLACE_INTERLEAVE_FRAME_TOPFIELDFIRST	0x02
+#define HFI_INTERLACE_INTERLEAVE_FRAME_BOTTOMFIELDFIRST	0x04
+#define HFI_INTERLACE_FRAME_TOPFIELDFIRST				0x08
+#define HFI_INTERLACE_FRAME_BOTTOMFIELDFIRST			0x10
+
+#define HFI_PROPERTY_SYS_OX_START			\
+	(HFI_DOMAIN_BASE_COMMON + HFI_ARCH_OX_OFFSET + 0x0000)
+#define HFI_PROPERTY_SYS_IDLE_INDICATOR		\
+	(HFI_PROPERTY_SYS_OX_START + 0x001)
+
+#define HFI_PROPERTY_PARAM_OX_START				\
+	(HFI_DOMAIN_BASE_COMMON + HFI_ARCH_OX_OFFSET + 0x1000)
+#define HFI_PROPERTY_PARAM_BUFFER_COUNT_ACTUAL			\
+	(HFI_PROPERTY_PARAM_OX_START + 0x001)
+#define HFI_PROPERTY_PARAM_UNCOMPRESSED_PLANE_ACTUAL_CONSTRAINTS_INFO	\
+	(HFI_PROPERTY_PARAM_OX_START + 0x002)
+#define HFI_PROPERTY_PARAM_INTERLACE_FORMAT_SUPPORTED	\
+	(HFI_PROPERTY_PARAM_OX_START + 0x003)
+#define HFI_PROPERTY_PARAM_CHROMA_SITE					\
+(HFI_PROPERTY_PARAM_OX_START + 0x004)
+#define HFI_PROPERTY_PARAM_EXTRA_DATA_HEADER_CONFIG		\
+	(HFI_PROPERTY_PARAM_OX_START + 0x005)
+#define HFI_PROPERTY_PARAM_INDEX_EXTRADATA             \
+	(HFI_PROPERTY_PARAM_OX_START + 0x006)
+#define HFI_PROPERTY_PARAM_DIVX_FORMAT					\
+	(HFI_PROPERTY_PARAM_OX_START + 0x007)
+#define HFI_PROPERTY_PARAM_BUFFER_ALLOC_MODE			\
+	(HFI_PROPERTY_PARAM_OX_START + 0x008)
+#define HFI_PROPERTY_PARAM_S3D_FRAME_PACKING_EXTRADATA	\
+	(HFI_PROPERTY_PARAM_OX_START + 0x009)
+
+#define HFI_PROPERTY_CONFIG_OX_START					\
+	(HFI_DOMAIN_BASE_COMMON + HFI_ARCH_OX_OFFSET + 0x02000)
+#define HFI_PROPERTY_CONFIG_BUFFER_REQUIREMENTS			\
+	(HFI_PROPERTY_CONFIG_OX_START + 0x001)
+#define HFI_PROPERTY_CONFIG_REALTIME					\
+	(HFI_PROPERTY_CONFIG_OX_START + 0x002)
+#define HFI_PROPERTY_CONFIG_PRIORITY					\
+	(HFI_PROPERTY_CONFIG_OX_START + 0x003)
+#define HFI_PROPERTY_CONFIG_BATCH_INFO					\
+	(HFI_PROPERTY_CONFIG_OX_START + 0x004)
+
+#define HFI_PROPERTY_PARAM_VDEC_OX_START				\
+	(HFI_DOMAIN_BASE_VDEC + HFI_ARCH_OX_OFFSET + 0x3000)
+#define HFI_PROPERTY_PARAM_VDEC_CONTINUE_DATA_TRANSFER	\
+	(HFI_PROPERTY_PARAM_VDEC_OX_START + 0x001)
+#define HFI_PROPERTY_PARAM_VDEC_DISPLAY_PICTURE_BUFFER_COUNT\
+	(HFI_PROPERTY_PARAM_VDEC_OX_START + 0x002)
+#define HFI_PROPERTY_PARAM_VDEC_MULTI_VIEW_SELECT		\
+	(HFI_PROPERTY_PARAM_VDEC_OX_START + 0x003)
+#define HFI_PROPERTY_PARAM_VDEC_PICTURE_TYPE_DECODE		\
+	(HFI_PROPERTY_PARAM_VDEC_OX_START + 0x004)
+#define HFI_PROPERTY_PARAM_VDEC_OUTPUT_ORDER			\
+	(HFI_PROPERTY_PARAM_VDEC_OX_START + 0x005)
+#define HFI_PROPERTY_PARAM_VDEC_MB_QUANTIZATION			\
+	(HFI_PROPERTY_PARAM_VDEC_OX_START + 0x006)
+#define HFI_PROPERTY_PARAM_VDEC_NUM_CONCEALED_MB		\
+	(HFI_PROPERTY_PARAM_VDEC_OX_START + 0x007)
+#define HFI_PROPERTY_PARAM_VDEC_H264_ENTROPY_SWITCHING	\
+	(HFI_PROPERTY_PARAM_VDEC_OX_START + 0x008)
+#define HFI_PROPERTY_PARAM_VDEC_OUTPUT2_KEEP_ASPECT_RATIO\
+	(HFI_PROPERTY_PARAM_VDEC_OX_START + 0x009)
+#define HFI_PROPERTY_PARAM_VDEC_FRAME_RATE_EXTRADATA  \
+	(HFI_PROPERTY_PARAM_VDEC_OX_START + 0x00A)
+#define HFI_PROPERTY_PARAM_VDEC_PANSCAN_WNDW_EXTRADATA \
+	(HFI_PROPERTY_PARAM_VDEC_OX_START + 0x00B)
+#define HFI_PROPERTY_PARAM_VDEC_RECOVERY_POINT_SEI_EXTRADATA \
+	(HFI_PROPERTY_PARAM_VDEC_OX_START + 0x00C)
+#define HFI_PROPERTY_PARAM_VDEC_THUMBNAIL_MODE   \
+	(HFI_PROPERTY_PARAM_VDEC_OX_START + 0x00D)
+
+#define HFI_PROPERTY_PARAM_VDEC_FRAME_ASSEMBLY		\
+	(HFI_PROPERTY_PARAM_VDEC_OX_START + 0x00E)
+#define HFI_PROPERTY_PARAM_VDEC_CLOSED_CAPTION_EXTRADATA	\
+	(HFI_PROPERTY_PARAM_VDEC_OX_START + 0x00F)
+#define HFI_PROPERTY_PARAM_VDEC_AFD_EXTRADATA		\
+	(HFI_PROPERTY_PARAM_VDEC_OX_START + 0x010)
+#define HFI_PROPERTY_PARAM_VDEC_VC1_FRAMEDISP_EXTRADATA		\
+	(HFI_PROPERTY_PARAM_VDEC_OX_START + 0x011)
+#define HFI_PROPERTY_PARAM_VDEC_VC1_SEQDISP_EXTRADATA		\
+	(HFI_PROPERTY_PARAM_VDEC_OX_START + 0x012)
+#define HFI_PROPERTY_PARAM_VDEC_TIMESTAMP_EXTRADATA			\
+	(HFI_PROPERTY_PARAM_VDEC_OX_START + 0x013)
+#define HFI_PROPERTY_PARAM_VDEC_INTERLACE_VIDEO_EXTRADATA	\
+	(HFI_PROPERTY_PARAM_VDEC_OX_START + 0x014)
+#define HFI_PROPERTY_PARAM_VDEC_AVC_SESSION_SELECT \
+	(HFI_PROPERTY_PARAM_VDEC_OX_START + 0x015)
+
+#define HFI_PROPERTY_CONFIG_VDEC_OX_START				\
+	(HFI_DOMAIN_BASE_VDEC + HFI_ARCH_OX_OFFSET + 0x0000)
+#define HFI_PROPERTY_CONFIG_VDEC_POST_LOOP_DEBLOCKER	\
+	(HFI_PROPERTY_CONFIG_VDEC_OX_START + 0x001)
+#define HFI_PROPERTY_CONFIG_VDEC_MB_ERROR_MAP_REPORTING	\
+	(HFI_PROPERTY_CONFIG_VDEC_OX_START + 0x002)
+#define HFI_PROPERTY_CONFIG_VDEC_MB_ERROR_MAP			\
+	(HFI_PROPERTY_CONFIG_VDEC_OX_START + 0x003)
+
+#define HFI_PROPERTY_PARAM_VENC_OX_START				\
+	(HFI_DOMAIN_BASE_VENC + HFI_ARCH_OX_OFFSET + 0x5000)
+#define  HFI_PROPERTY_PARAM_VENC_MULTI_SLICE_INFO       \
+	(HFI_PROPERTY_PARAM_VENC_OX_START + 0x001)
+#define  HFI_PROPERTY_PARAM_VENC_H264_IDR_S3D_FRAME_PACKING_NAL \
+	(HFI_PROPERTY_PARAM_VENC_OX_START + 0x002)
+
+#define HFI_PROPERTY_CONFIG_VENC_OX_START				\
+	(HFI_DOMAIN_BASE_VENC + HFI_ARCH_OX_OFFSET + 0x6000)
+#define  HFI_PROPERTY_CONFIG_VENC_FRAME_QP				\
+	(HFI_PROPERTY_CONFIG_VENC_OX_START + 0x001)
+
+#define HFI_PROPERTY_PARAM_VPE_OX_START					\
+	(HFI_DOMAIN_BASE_VPE + HFI_ARCH_OX_OFFSET + 0x7000)
+#define HFI_PROPERTY_CONFIG_VPE_OX_START				\
+	(HFI_DOMAIN_BASE_VPE + HFI_ARCH_OX_OFFSET + 0x8000)
+
+struct hfi_batch_info {
+	u32 input_batch_count;
+	u32 output_batch_count;
+};
+
+struct hfi_buffer_count_actual {
+	u32 buffer_type;
+	u32 buffer_count_actual;
+};
+
+struct hfi_buffer_requirements {
+	u32 buffer_type;
+	u32 buffer_size;
+	u32 buffer_region_size;
+	u32 buffer_hold_count;
+	u32 buffer_count_min;
+	u32 buffer_count_actual;
+	u32 contiguous;
+	u32 buffer_alignment;
+};
+
+#define HFI_CHROMA_SITE_0			(HFI_OX_BASE + 0x1)
+#define HFI_CHROMA_SITE_1			(HFI_OX_BASE + 0x2)
+#define HFI_CHROMA_SITE_2			(HFI_OX_BASE + 0x3)
+#define HFI_CHROMA_SITE_3			(HFI_OX_BASE + 0x4)
+#define HFI_CHROMA_SITE_4			(HFI_OX_BASE + 0x5)
+#define HFI_CHROMA_SITE_5			(HFI_OX_BASE + 0x6)
+
+struct hfi_data_payload {
+	u32 size;
+	u8 rg_data[1];
+};
+
+struct hfi_enable_picture {
+	u32 picture_type;
+};
+
+struct hfi_display_picture_buffer_count {
+	int enable;
+	u32 count;
+};
+
+struct hfi_extra_data_header_config {
+	u32 type;
+	u32 buffer_type;
+	u32 version;
+	u32 port_index;
+	u32 client_extra_data_id;
+};
+
+struct hfi_interlace_format_supported {
+	u32 buffer_type;
+	u32 format;
+};
+
+struct hfi_mb_error_map {
+	u32 error_map_size;
+	u8 rg_error_map[1];
+};
+
+struct hfi_metadata_pass_through {
+	int enable;
+	u32 size;
+};
+
+struct hfi_multi_view_select {
+	u32 view_index;
+};
+
+#define HFI_PRIORITY_LOW		10
+#define HFI_PRIOIRTY_MEDIUM		20
+#define HFI_PRIORITY_HIGH		30
+
+#define HFI_OUTPUT_ORDER_DISPLAY	(HFI_OX_BASE + 0x1)
+#define HFI_OUTPUT_ORDER_DECODE		(HFI_OX_BASE + 0x2)
+
+#define HFI_RATE_CONTROL_OFF		(HFI_OX_BASE + 0x1)
+#define HFI_RATE_CONTROL_VBR_VFR	(HFI_OX_BASE + 0x2)
+#define HFI_RATE_CONTROL_VBR_CFR	(HFI_OX_BASE + 0x3)
+#define HFI_RATE_CONTROL_CBR_VFR	(HFI_OX_BASE + 0x4)
+#define HFI_RATE_CONTROL_CBR_CFR	(HFI_OX_BASE + 0x5)
+
+struct hfi_uncompressed_plane_actual_constraints_info {
+	u32 buffer_type;
+	u32 num_planes;
+	struct hfi_uncompressed_plane_constraints rg_plane_format[1];
+};
+
+#define HFI_CMD_SYS_OX_START		\
+(HFI_DOMAIN_BASE_COMMON + HFI_ARCH_OX_OFFSET + HFI_CMD_START_OFFSET + 0x0000)
+#define HFI_CMD_SYS_SESSION_ABORT	(HFI_CMD_SYS_OX_START + 0x001)
+#define HFI_CMD_SYS_PING		(HFI_CMD_SYS_OX_START + 0x002)
+
+#define HFI_CMD_SESSION_OX_START	\
+(HFI_DOMAIN_BASE_COMMON + HFI_ARCH_OX_OFFSET + HFI_CMD_START_OFFSET + 0x1000)
+#define HFI_CMD_SESSION_LOAD_RESOURCES	(HFI_CMD_SESSION_OX_START + 0x001)
+#define HFI_CMD_SESSION_START		(HFI_CMD_SESSION_OX_START + 0x002)
+#define HFI_CMD_SESSION_STOP		(HFI_CMD_SESSION_OX_START + 0x003)
+#define HFI_CMD_SESSION_EMPTY_BUFFER	(HFI_CMD_SESSION_OX_START + 0x004)
+#define HFI_CMD_SESSION_FILL_BUFFER	(HFI_CMD_SESSION_OX_START + 0x005)
+#define HFI_CMD_SESSION_SUSPEND		(HFI_CMD_SESSION_OX_START + 0x006)
+#define HFI_CMD_SESSION_RESUME		(HFI_CMD_SESSION_OX_START + 0x007)
+#define HFI_CMD_SESSION_FLUSH		(HFI_CMD_SESSION_OX_START + 0x008)
+#define HFI_CMD_SESSION_GET_PROPERTY	(HFI_CMD_SESSION_OX_START + 0x009)
+#define HFI_CMD_SESSION_PARSE_SEQUENCE_HEADER	\
+	(HFI_CMD_SESSION_OX_START + 0x00A)
+#define HFI_CMD_SESSION_RELEASE_BUFFERS		\
+	(HFI_CMD_SESSION_OX_START + 0x00B)
+#define HFI_CMD_SESSION_RELEASE_RESOURCES	\
+	(HFI_CMD_SESSION_OX_START + 0x00C)
+
+#define HFI_MSG_SYS_OX_START			\
+(HFI_DOMAIN_BASE_COMMON + HFI_ARCH_OX_OFFSET + HFI_MSG_START_OFFSET + 0x0000)
+#define HFI_MSG_SYS_IDLE		(HFI_MSG_SYS_OX_START + 0x1)
+#define HFI_MSG_SYS_PING_ACK	(HFI_MSG_SYS_OX_START + 0x2)
+#define HFI_MSG_SYS_PROPERTY_INFO	(HFI_MSG_SYS_OX_START + 0x3)
+#define HFI_MSG_SYS_SESSION_ABORT_DONE	(HFI_MSG_SYS_OX_START + 0x4)
+
+#define HFI_MSG_SESSION_OX_START		\
+(HFI_DOMAIN_BASE_COMMON + HFI_ARCH_OX_OFFSET + HFI_MSG_START_OFFSET + 0x1000)
+#define HFI_MSG_SESSION_LOAD_RESOURCES_DONE	(HFI_MSG_SESSION_OX_START + 0x1)
+#define HFI_MSG_SESSION_START_DONE		(HFI_MSG_SESSION_OX_START + 0x2)
+#define HFI_MSG_SESSION_STOP_DONE		(HFI_MSG_SESSION_OX_START + 0x3)
+#define HFI_MSG_SESSION_SUSPEND_DONE	(HFI_MSG_SESSION_OX_START + 0x4)
+#define HFI_MSG_SESSION_RESUME_DONE		(HFI_MSG_SESSION_OX_START + 0x5)
+#define HFI_MSG_SESSION_FLUSH_DONE		(HFI_MSG_SESSION_OX_START + 0x6)
+#define HFI_MSG_SESSION_EMPTY_BUFFER_DONE	(HFI_MSG_SESSION_OX_START + 0x7)
+#define HFI_MSG_SESSION_FILL_BUFFER_DONE	(HFI_MSG_SESSION_OX_START + 0x8)
+#define HFI_MSG_SESSION_PROPERTY_INFO		(HFI_MSG_SESSION_OX_START + 0x9)
+#define HFI_MSG_SESSION_RELEASE_RESOURCES_DONE	\
+	(HFI_MSG_SESSION_OX_START + 0xA)
+#define HFI_MSG_SESSION_PARSE_SEQUENCE_HEADER_DONE		\
+	(HFI_MSG_SESSION_OX_START + 0xB)
+#define  HFI_MSG_SESSION_RELEASE_BUFFERS_DONE			\
+	(HFI_MSG_SESSION_OX_START + 0xC)
+
+#define HFI_MIN_PKT_SIZE			8
+
+struct hfi_cmd_sys_session_abort_packet {
+	u32 size;
+	u32 packet_type;
+	u32 session_id;
+};
+
+struct hfi_cmd_sys_ping_packet {
+	u32 size;
+	u32 packet_type;
+	u32 client_data;
+};
+
+struct hfi_cmd_session_load_resources_packet {
+	u32 size;
+	u32 packet_type;
+	u32 session_id;
+};
+
+struct hfi_cmd_session_start_packet {
+	u32 size;
+	u32 packet_type;
+	u32 session_id;
+};
+
+struct hfi_cmd_session_stop_packet {
+	u32 size;
+	u32 packet_type;
+	u32 session_id;
+};
+
+struct hfi_cmd_session_empty_buffer_compressed_packet {
+	u32 size;
+	u32 packet_type;
+	u32 session_id;
+	u32 time_stamp_hi;
+	u32 time_stamp_lo;
+	u32 flags;
+	u32 mark_target;
+	u32 mark_data;
+	u32 offset;
+	u32 alloc_len;
+	u32 filled_len;
+	u32 input_tag;
+	u8 *packet_buffer;
+	u8 *extra_data_buffer;
+	u32 rgData[0];
+};
+
+struct hfi_cmd_session_empty_buffer_uncompressed_plane0_packet {
+	u32 size;
+	u32 packet_type;
+	u32 session_id;
+	u32 view_id;
+	u32 time_stamp_hi;
+	u32 time_stamp_lo;
+	u32 flags;
+	u32 mark_target;
+	u32 mark_data;
+	u32 alloc_len;
+	u32 filled_len;
+	u32 offset;
+	u32 input_tag;
+	u8 *packet_buffer;
+	u8 *extra_data_buffer;
+	u32 rgData[0];
+};
+
+struct hfi_cmd_session_empty_buffer_uncompressed_plane1_packet {
+	u32 flags;
+	u32 alloc_len;
+	u32 filled_len;
+	u32 offset;
+	u8 *packet_buffer2;
+	u32 rgData[0];
+};
+
+struct hfi_cmd_session_empty_buffer_uncompressed_plane2_packet {
+	u32 flags;
+	u32 alloc_len;
+	u32 filled_len;
+	u32 offset;
+	u8 *packet_buffer3;
+	u32 rgData[0];
+};
+
+struct hfi_cmd_session_fill_buffer_packet {
+	u32 size;
+	u32 packet_type;
+	u32 session_id;
+	u32 stream_id;
+	u32 offset;
+	u32 alloc_len;
+	u32 filled_len;
+	u32 output_tag;
+	u8 *packet_buffer;
+	u8 *extra_data_buffer;
+	u32 rgData[0];
+};
+
+struct hfi_cmd_session_flush_packet {
+	u32 size;
+	u32 packet_type;
+	u32 session_id;
+	u32 flush_type;
+};
+
+struct hfi_cmd_session_suspend_packet {
+	u32 size;
+	u32 packet_type;
+	u32 session_id;
+};
+
+struct hfi_cmd_session_resume_packet {
+	u32 size;
+	u32 packet_type;
+	u32 session_id;
+};
+
+struct hfi_cmd_session_get_property_packet {
+	u32 size;
+	u32 packet_type;
+	u32 session_id;
+	u32 num_properties;
+	u32 rg_property_data[1];
+};
+
+struct hfi_cmd_session_release_buffer_packet {
+	u32 size;
+	u32 packet_type;
+	u32 session_id;
+	u32 buffer_type;
+	u32 buffer_size;
+	u32 extra_data_size;
+	int response_req;
+	u32 num_buffers;
+	u32 rg_buffer_info[1];
+};
+
+struct hfi_cmd_session_release_resources_packet {
+	u32 size;
+	u32 packet_type;
+	u32 session_id;
+};
+
+struct hfi_cmd_session_parse_sequence_header_packet {
+	u32 size;
+	u32 packet_type;
+	u32 session_id;
+	u32 header_len;
+	u8 *packet_buffer;
+};
+
+struct hfi_msg_sys_session_abort_done_packet {
+	u32 size;
+	u32 packet_type;
+	u32 session_id;
+	u32 error_type;
+};
+
+struct hfi_msg_sys_idle_packet {
+	u32 size;
+	u32 packet_type;
+};
+
+struct hfi_msg_sys_ping_ack_packet {
+	u32 size;
+	u32 packet_type;
+	u32 client_data;
+};
+
+struct hfi_msg_sys_property_info_packet {
+	u32 size;
+	u32 packet_type;
+	u32 num_properties;
+	u32 rg_property_data[1];
+};
+
+struct hfi_msg_session_load_resources_done_packet {
+	u32 size;
+	u32 packet_type;
+	u32 session_id;
+	u32 error_type;
+};
+
+struct hfi_msg_session_start_done_packet {
+	u32 size;
+	u32 packet_type;
+	u32 session_id;
+	u32 error_type;
+};
+
+struct hfi_msg_session_stop_done_packet {
+	u32 size;
+	u32 packet_type;
+	u32 session_id;
+	u32 error_type;
+};
+
+struct hfi_msg_session_suspend_done_packet {
+	u32 size;
+	u32 packet_type;
+	u32 session_id;
+	u32 error_type;
+};
+
+struct hfi_msg_session_resume_done_packet {
+	u32 size;
+	u32 packet_type;
+	u32 session_id;
+	u32 error_type;
+};
+
+struct hfi_msg_session_flush_done_packet {
+	u32 size;
+	u32 packet_type;
+	u32 session_id;
+	u32 error_type;
+	u32 flush_type;
+};
+
+struct hfi_msg_session_empty_buffer_done_packet {
+	u32 size;
+	u32 packet_type;
+	u32 session_id;
+	u32 error_type;
+	u32 offset;
+	u32 filled_len;
+	u32 input_tag;
+	u8 *packet_buffer;
+	u8 *extra_data_buffer;
+	u32 rgData[0];
+};
+
+struct hfi_msg_session_fill_buffer_done_compressed_packet {
+	u32 size;
+	u32 packet_type;
+	u32 session_id;
+	u32 time_stamp_hi;
+	u32 time_stamp_lo;
+	u32 error_type;
+	u32 flags;
+	u32 mark_target;
+	u32 mark_data;
+	u32 stats;
+	u32 offset;
+	u32 alloc_len;
+	u32 filled_len;
+	u32 input_tag;
+	u32 output_tag;
+	u32 picture_type;
+	u8 *packet_buffer;
+	u8 *extra_data_buffer;
+	u32 rgData[0];
+};
+
+struct hfi_msg_session_fbd_uncompressed_plane0_packet {
+	u32 size;
+	u32 packet_type;
+	u32 session_id;
+	u32 stream_id;
+	u32 view_id;
+	u32 error_type;
+	u32 time_stamp_hi;
+	u32 time_stamp_lo;
+	u32 flags;
+	u32 mark_target;
+	u32 mark_data;
+	u32 stats;
+	u32 alloc_len;
+	u32 filled_len;
+	u32 offset;
+	u32 frame_width;
+	u32 frame_height;
+	u32 start_x_coord;
+	u32 start_y_coord;
+	u32 input_tag;
+	u32 input_tag2;
+	u32 output_tag;
+	u32 picture_type;
+	u8 *packet_buffer;
+	u8 *extra_data_buffer;
+	u32 rgData[0];
+};
+
+struct hfi_msg_session_fill_buffer_done_uncompressed_plane1_packet {
+	u32 flags;
+	u32 alloc_len;
+	u32 filled_len;
+	u32 offset;
+	u8 *packet_buffer2;
+	u32 rgData[0];
+};
+
+struct hfi_msg_session_fill_buffer_done_uncompressed_plane2_packet {
+	u32 flags;
+	u32 alloc_len;
+	u32 filled_len;
+	u32 offset;
+	u8 *packet_buffer3;
+	u32 rgData[0];
+};
+
+struct hfi_msg_session_parse_sequence_header_done_packet {
+	u32 size;
+	u32 packet_type;
+	u32 session_id;
+	u32 error_type;
+	u32 num_properties;
+	u32 rg_property_data[1];
+};
+
+struct hfi_msg_session_property_info_packet {
+	u32 size;
+	u32 packet_type;
+	u32 session_id;
+	u32 num_properties;
+	u32 rg_property_data[1];
+};
+
+struct hfi_msg_session_release_resources_done_packet {
+	u32 size;
+	u32 packet_type;
+	u32 session_id;
+	u32 error_type;
+};
+
+struct hfi_msg_session_release_buffers_done_packet {
+	u32 size;
+	u32 packet_type;
+	u32 session_id;
+	u32 error_type;
+	u32 num_buffers;
+	u32 rg_buffer_info[1];
+};
+
+struct hfi_extradata_mb_quantization_payload {
+	u8 rg_mb_qp[1];
+};
+
+struct hfi_extradata_vc1_pswnd {
+	u32 ps_wnd_h_offset;
+	u32 ps_wnd_v_offset;
+	u32 ps_wnd_width;
+	u32 ps_wnd_height;
+};
+
+struct hfi_extradata_vc1_framedisp_payload {
+	u32 res_pic;
+	u32 ref;
+	u32 range_map_present;
+	u32 range_map_y;
+	u32 range_map_uv;
+	u32 num_pan_scan_wnds;
+	struct hfi_extradata_vc1_pswnd rg_ps_wnd[1];
+};
+
+struct hfi_extradata_vc1_seqdisp_payload {
+	u32 prog_seg_frm;
+	u32 uv_sampling_fmt;
+	u32 color_fmt_flag;
+	u32 color_primaries;
+	u32 transfer_char;
+	u32 mat_coeff;
+	u32 aspect_ratio;
+	u32 aspect_horiz;
+	u32 aspect_vert;
+};
+
+struct hfi_extradata_timestamp_payload {
+	u32 time_stamp_low;
+	u32 time_stamp_high;
+};
+
+
+struct hfi_extradata_s3d_frame_packing_payload {
+	u32 fpa_id;
+	int cancel_flag;
+	u32 fpa_type;
+	int quin_cunx_flag;
+	u32 content_interprtation_type;
+	int spatial_flipping_flag;
+	int frame0_flipped_flag;
+	int field_views_flag;
+	int current_frame_isFrame0_flag;
+	int frame0_self_contained_flag;
+	int frame1_self_contained_flag;
+	u32 frame0_graid_pos_x;
+	u32 frame0_graid_pos_y;
+	u32 frame1_graid_pos_x;
+	u32 frame1_graid_pos_y;
+	u32 fpa_reserved_byte;
+	u32 fpa_repetition_period;
+	int fpa_extension_flag;
+};
+
+struct hfi_extradata_interlace_video_payload {
+	u32 format;
+};
+
+struct hfi_extradata_num_concealed_mb_payload {
+	u32 num_mb_concealed;
+};
+
+struct hfi_extradata_sliceinfo {
+	u32 offset_in_stream;
+	u32 slice_length;
+};
+
+struct hfi_extradata_multislice_info_payload {
+	u32 num_slices;
+	struct hfi_extradata_sliceinfo rg_slice_info[1];
+};
+
+struct hfi_index_extradata_input_crop_payload {
+	u32 size;
+	u32 version;
+	u32 port_index;
+	u32 left;
+	u32 top;
+	u32 width;
+	u32 height;
+};
+
+struct hfi_index_extradata_digital_zoom_payload {
+	u32 size;
+	u32 version;
+	u32 port_index;
+	int width;
+	int height;
+};
+
+struct hfi_index_extradata_aspect_ratio_payload {
+	u32 size;
+	u32 version;
+	u32 port_index;
+	u32 aspect_width;
+	u32 aspect_height;
+};
+struct hfi_extradata_panscan_wndw_payload {
+	u32 num_window;
+	struct hfi_extradata_vc1_pswnd wnd[1];
+};
+
+struct hfi_extradata_frame_type_payload {
+	u32 frame_rate;
+};
+
+struct hfi_extradata_recovery_point_sei_payload {
+	u32 flag;
+};
+
+struct hal_session {
+	struct list_head list;
+	u32 session_id;
+	u32 is_decoder;
+	void *device;
+};
+
+struct hal_device_data {
+	struct list_head dev_head;
+	int dev_count;
+};
+
+extern struct hal_device_data hal_ctxt;
+
+void hfi_process_msg_packet(msm_vidc_callback callback,
+		u32 device_id, struct vidc_hal_msg_pkt_hdr *msg_hdr);
+#endif
+
diff --git a/drivers/media/video/msm_vidc/vidc_hfi_api.h b/drivers/media/video/msm_vidc/vidc_hfi_api.h
index 79fee90..9366e0a 100644
--- a/drivers/media/video/msm_vidc/vidc_hfi_api.h
+++ b/drivers/media/video/msm_vidc/vidc_hfi_api.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -14,7 +14,9 @@
 #ifndef __VIDC_HFI_API_H__
 #define __VIDC_HFI_API_H__
 
+#include <linux/platform_device.h>
 #include <linux/types.h>
+#include <media/msm_vidc.h>
 
 #define CONTAINS(__a, __sz, __t) ({\
 	int __rc = __t >= __a && \
@@ -979,44 +981,84 @@
 	struct hal_buffer_requirements buffer[HAL_BUFFER_MAX];
 };
 
-/* VIDC_HAL CORE API's */
-int venus_hfi_core_init(void *device);
-int venus_hfi_core_release(void *device);
-int venus_hfi_core_pc_prep(void *device);
-int venus_hfi_core_set_resource(void *device,
-	struct vidc_resource_hdr *resource_hdr, void *resource_value);
-int venus_hfi_core_release_resource(void *device,
-	struct vidc_resource_hdr *resource_hdr);
-int venus_hfi_core_ping(void *device);
+enum msm_vidc_hfi_type {
+	VIDC_HFI_VENUS,
+	VIDC_HFI_Q6,
+};
 
-/* VIDC_HAL SESSION API's */
-void *venus_hfi_session_init(void *device, u32 session_id,
-	enum hal_domain session_type, enum hal_video_codec codec_type);
-int venus_hfi_session_end(void *session);
-int venus_hfi_session_abort(void *session);
-int venus_hfi_session_set_buffers(void *sess,
-	struct vidc_buffer_addr_info *buffer_info);
-int venus_hfi_session_release_buffers(void *sess,
-	struct vidc_buffer_addr_info *buffer_info);
-int venus_hfi_session_load_res(void *sess);
-int venus_hfi_session_release_res(void *sess);
-int venus_hfi_session_start(void *sess);
-int venus_hfi_session_stop(void *sess);
-int venus_hfi_session_suspend(void *sess);
-int venus_hfi_session_resume(void *sess);
-int venus_hfi_session_etb(void *sess,
-	struct vidc_frame_data *input_frame);
-int venus_hfi_session_ftb(void *sess,
-	struct vidc_frame_data *output_frame);
-int venus_hfi_session_parse_seq_hdr(void *sess,
-	struct vidc_seq_hdr *seq_hdr);
-int venus_hfi_session_get_seq_hdr(void *sess,
-	struct vidc_seq_hdr *seq_hdr);
-int venus_hfi_session_get_buf_req(void *sess);
-int venus_hfi_session_flush(void *sess, enum hal_flush flush_mode);
-int venus_hfi_session_set_property(void *sess, enum hal_property ptype,
-								  void *pdata);
-int venus_hfi_session_get_property(void *sess, enum hal_property ptype,
-								  void *pdata);
+enum mem_type {
+	DDR_MEM = 0x1,
+	OCMEM_MEM = 0x2,
+};
+
+enum fw_info {
+	FW_BASE_ADDRESS,
+	FW_REGISTER_BASE,
+	FW_REGISTER_SIZE,
+	FW_IRQ,
+	FW_INFO_MAX,
+};
+
+struct hfi_device {
+	void *hfi_device_data;
+
+	/*Add function pointers for all the hfi functions below*/
+	int (*core_init)(void *device);
+	int (*core_release)(void *device);
+	int (*core_pc_prep)(void *device);
+	int (*core_ping)(void *device);
+	void *(*session_init)(void *device, u32 session_id,
+		enum hal_domain session_type, enum hal_video_codec codec_type);
+	int (*session_end)(void *session);
+	int (*session_abort)(void *session);
+	int (*session_set_buffers)(void *sess,
+				struct vidc_buffer_addr_info *buffer_info);
+	int (*session_release_buffers)(void *sess,
+				struct vidc_buffer_addr_info *buffer_info);
+	int (*session_load_res)(void *sess);
+	int (*session_release_res)(void *sess);
+	int (*session_start)(void *sess);
+	int (*session_stop)(void *sess);
+	int (*session_suspend)(void *sess);
+	int (*session_resume)(void *sess);
+	int (*session_etb)(void *sess,
+			struct vidc_frame_data *input_frame);
+	int (*session_ftb)(void *sess,
+			struct vidc_frame_data *output_frame);
+	int (*session_parse_seq_hdr)(void *sess,
+			struct vidc_seq_hdr *seq_hdr);
+	int (*session_get_seq_hdr)(void *sess,
+			struct vidc_seq_hdr *seq_hdr);
+	int (*session_get_buf_req)(void *sess);
+	int (*session_flush)(void *sess, enum hal_flush flush_mode);
+	int (*session_set_property)(void *sess, enum hal_property ptype,
+			void *pdata);
+	int (*session_get_property)(void *sess, enum hal_property ptype,
+			void *pdata);
+	int (*scale_clocks)(void *dev, int load);
+	int (*scale_bus)(void *dev, int load,
+			enum session_type type, enum mem_type mtype);
+	int (*unset_ocmem)(void *dev);
+	int (*alloc_ocmem)(void *dev, unsigned long size);
+	int (*free_ocmem)(void *dev);
+	int (*is_ocmem_present)(void *dev);
+	int (*get_domain)(void *dev, enum msm_vidc_io_maps iomap);
+	int (*iommu_get_map)(void *dev,
+			struct msm_vidc_iommu_info maps[MAX_MAP]);
+	int (*load_fw)(void *dev);
+	void (*unload_fw)(void *dev);
+	int (*get_fw_info)(void *dev, enum fw_info info);
+};
+
+typedef void (*hfi_cmd_response_callback) (enum command_response cmd,
+			void *data);
+typedef void (*msm_vidc_callback) (u32 response, void *callback);
+
+void *vidc_hfi_initialize(enum msm_vidc_hfi_type hfi_type, u32 device_id,
+			struct platform_device *pdev,
+			hfi_cmd_response_callback callback);
+void vidc_hfi_deinitialize(enum msm_vidc_hfi_type hfi_type,
+			struct hfi_device *hdev);
+
 
 #endif /*__VIDC_HFI_API_H__ */
diff --git a/drivers/media/video/vcap_vc.c b/drivers/media/video/vcap_vc.c
index 642074f..5760fba 100644
--- a/drivers/media/video/vcap_vc.c
+++ b/drivers/media/video/vcap_vc.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2012-2013, Code Aurora Forum. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -132,23 +132,25 @@
 inline void vc_isr_error_checking(struct vcap_dev *dev,
 		struct v4l2_event v4l2_evt, uint32_t irq)
 {
-	if (irq & 0x8000200) {
-		writel_iowmb(0x00000102, VCAP_VC_NPL_CTRL);
-		v4l2_evt.type = V4L2_EVENT_PRIVATE_START +
-			VCAP_VC_PIX_ERR_EVENT;
-		v4l2_event_queue(dev->vfd, &v4l2_evt);
-	}
-	if (irq & 0x40000200) {
-		writel_iowmb(0x00000102, VCAP_VC_NPL_CTRL);
-		v4l2_evt.type = V4L2_EVENT_PRIVATE_START +
-			VCAP_VC_LINE_ERR_EVENT;
-		v4l2_event_queue(dev->vfd, &v4l2_evt);
-	}
-	if (irq & 0x20000200) {
-		writel_iowmb(0x00000102, VCAP_VC_NPL_CTRL);
-		v4l2_evt.type = V4L2_EVENT_PRIVATE_START +
-			VCAP_VC_VSYNC_ERR_EVENT;
-		v4l2_event_queue(dev->vfd, &v4l2_evt);
+	if (irq & 0x200) {
+		if (irq & 0x80000000) {
+			writel_iowmb(0x00000102, VCAP_VC_NPL_CTRL);
+			v4l2_evt.type = V4L2_EVENT_PRIVATE_START +
+				VCAP_VC_PIX_ERR_EVENT;
+			v4l2_event_queue(dev->vfd, &v4l2_evt);
+		}
+		if (irq & 0x40000000) {
+			writel_iowmb(0x00000102, VCAP_VC_NPL_CTRL);
+			v4l2_evt.type = V4L2_EVENT_PRIVATE_START +
+				VCAP_VC_LINE_ERR_EVENT;
+			v4l2_event_queue(dev->vfd, &v4l2_evt);
+		}
+		if (irq & 0x20000000) {
+			writel_iowmb(0x00000102, VCAP_VC_NPL_CTRL);
+			v4l2_evt.type = V4L2_EVENT_PRIVATE_START +
+				VCAP_VC_VSYNC_ERR_EVENT;
+			v4l2_event_queue(dev->vfd, &v4l2_evt);
+		}
 	}
 	if (irq & 0x00001000) {
 		writel_iowmb(0x00000102, VCAP_VC_NPL_CTRL);
diff --git a/drivers/misc/qseecom.c b/drivers/misc/qseecom.c
index c415952..f4fc7b6 100644
--- a/drivers/misc/qseecom.c
+++ b/drivers/misc/qseecom.c
@@ -2,7 +2,7 @@
 
 /*Qualcomm Secure Execution Environment Communicator (QSEECOM) driver
  *
- * Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -1463,7 +1463,7 @@
 	struct qseecom_command_scm_resp resp;
 	u8 *img_data = NULL;
 
-	if (__qseecom_get_fw_size("commonlib", &fw_size))
+	if (__qseecom_get_fw_size("cmnlib", &fw_size))
 		return -EIO;
 
 	img_data = kzalloc(fw_size, GFP_KERNEL);
@@ -1471,7 +1471,7 @@
 		pr_err("Mem allocation for lib image data failed\n");
 		return -ENOMEM;
 	}
-	ret = __qseecom_get_fw_data("commonlib", img_data, &load_req);
+	ret = __qseecom_get_fw_data("cmnlib", img_data, &load_req);
 	if (ret) {
 		kzfree(img_data);
 		return -EIO;
diff --git a/drivers/misc/tspp.c b/drivers/misc/tspp.c
index d4ff38b..563a013 100644
--- a/drivers/misc/tspp.c
+++ b/drivers/misc/tspp.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2011-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -25,6 +25,7 @@
 #include <linux/slab.h>          /* kfree, kzalloc */
 #include <linux/ioport.h>        /* XXX_ mem_region */
 #include <linux/dma-mapping.h>   /* dma_XXX */
+#include <linux/dmapool.h>       /* DMA pools */
 #include <linux/delay.h>         /* msleep */
 #include <linux/platform_device.h>
 #include <linux/clk.h>
@@ -65,6 +66,14 @@
 #define TSPP_MAX_BUFFER_SIZE           (32 * 1024 - 1)
 
 /*
+ * Returns whether to use DMA pool for TSPP output buffers.
+ * For buffers smaller than page size, using DMA pool
+ * provides better memory utilization as dma_alloc_coherent
+ * allocates minimum of page size.
+ */
+#define TSPP_USE_DMA_POOL(buff_size)   ((buff_size) < PAGE_SIZE)
+
+/*
  * Max allowed TSPP buffers/descriptors.
  * If SPS desc FIFO holds X descriptors, we can queue up to X-1 descriptors.
  */
@@ -398,6 +407,7 @@
 	void *notify_data;       /* data to be passed with the notifier */
 	u32 expiration_period_ms; /* notification on partially filled buffers */
 	struct timer_list expiration_timer;
+	struct dma_pool *dma_pool;
 	tspp_memfree *memfree;   /* user defined memory free function */
 	void *user_info; /* user cookie passed to memory alloc/free function */
 };
@@ -898,7 +908,7 @@
 }
 
 static int tspp_alloc_buffer(u32 channel_id, struct tspp_data_descriptor *desc,
-	u32 size, tspp_allocator *alloc, void *user)
+	u32 size, struct dma_pool *dma_pool, tspp_allocator *alloc, void *user)
 {
 	if (size < TSPP_MIN_BUFFER_SIZE ||
 		size > TSPP_MAX_BUFFER_SIZE) {
@@ -911,10 +921,15 @@
 		desc->virt_base = alloc(channel_id, size,
 			&desc->phys_base, user);
 	} else {
-		desc->virt_base = dma_alloc_coherent(NULL, size,
-			&desc->phys_base, GFP_KERNEL);
+		if (!dma_pool)
+			desc->virt_base = dma_alloc_coherent(NULL, size,
+				&desc->phys_base, GFP_KERNEL);
+		else
+			desc->virt_base = dma_pool_alloc(dma_pool, GFP_KERNEL,
+				&desc->phys_base);
+
 		if (desc->virt_base == 0) {
-			pr_err("tspp dma alloc coherent failed %i", size);
+			pr_err("tspp: dma buffer allocation failed %i\n", size);
 			return -ENOMEM;
 		}
 	}
@@ -1225,10 +1240,15 @@
 					pbuf->desc.phys_base,
 					channel->user_info);
 			} else {
-				dma_free_coherent(NULL,
-					pbuf->desc.size,
-					pbuf->desc.virt_base,
-					pbuf->desc.phys_base);
+				if (!channel->dma_pool)
+					dma_free_coherent(NULL,
+						pbuf->desc.size,
+						pbuf->desc.virt_base,
+						pbuf->desc.phys_base);
+				else
+					dma_pool_free(channel->dma_pool,
+						pbuf->desc.virt_base,
+						pbuf->desc.phys_base);
 			}
 			pbuf->desc.phys_base = 0;
 		}
@@ -1568,6 +1588,10 @@
 		config->desc.phys_base);
 
 	tspp_destroy_buffers(channel_id, channel);
+	if (channel->dma_pool) {
+		dma_pool_destroy(channel->dma_pool);
+		channel->dma_pool = NULL;
+	}
 
 	channel->src = TSPP_SOURCE_NONE;
 	channel->mode = TSPP_MODE_DISABLED;
@@ -1704,7 +1728,7 @@
 	 */
 	if (channel->buffer_count == 0) {
 		channel->buffer_size =
-			tspp_align_buffer_size_by_mode(channel->buffer_size,
+		tspp_align_buffer_size_by_mode(channel->buffer_size,
 							channel->mode);
 		rc = tspp_allocate_buffers(dev, channel->id,
 					channel->max_buffers,
@@ -2072,6 +2096,7 @@
 	}
 
 	channel = &pdev->channels[channel_id];
+
 	/* allow buffer allocation only if there was no previous buffer
 	 * allocation for this channel.
 	 */
@@ -2101,6 +2126,22 @@
 	channel->memfree = memfree;
 	channel->user_info = user;
 
+	/*
+	 * For small buffers, create a DMA pool so that memory
+	 * is not wasted through dma_alloc_coherent.
+	 */
+	if (TSPP_USE_DMA_POOL(channel->buffer_size)) {
+		channel->dma_pool = dma_pool_create("tspp",
+			NULL, channel->buffer_size, 0, 0);
+		if (!channel->dma_pool) {
+			pr_err("%s: Can't allocate memory pool\n", __func__);
+			return -ENOMEM;
+		}
+	} else {
+		channel->dma_pool = NULL;
+	}
+
+
 	for (channel->buffer_count = 0;
 		channel->buffer_count < channel->max_buffers;
 		channel->buffer_count++) {
@@ -2117,7 +2158,8 @@
 		desc->desc.id = channel->buffer_count;
 		/* allocate the buffer */
 		if (tspp_alloc_buffer(channel_id, &desc->desc,
-			channel->buffer_size, alloc, user) != 0) {
+			channel->buffer_size, channel->dma_pool,
+			alloc, user) != 0) {
 			kfree(desc);
 			pr_warn("%s: Can't allocate buffer %i",
 				__func__, channel->buffer_count);
@@ -2154,6 +2196,11 @@
 		 */
 		tspp_destroy_buffers(channel_id, channel);
 		channel->buffer_count = 0;
+
+		if (channel->dma_pool) {
+			dma_pool_destroy(channel->dma_pool);
+			channel->dma_pool = NULL;
+		}
 		return -ENOMEM;
 	}
 
@@ -2292,8 +2339,10 @@
 		 */
 		if (buffer->read_index == buffer->filled) {
 			buffer->state = TSPP_BUF_STATE_WAITING;
+
 			if (tspp_queue_buffer(channel, buffer))
 				pr_err("tspp: can't submit transfer");
+
 			channel->locked = channel->read;
 			channel->read = channel->read->next;
 		}
diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c
index 0f4cc6d..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;
 };
 
@@ -331,6 +332,114 @@
 	return ret;
 }
 
+static ssize_t
+bkops_check_threshold_show(struct device *dev,
+				  struct device_attribute *attr, char *buf)
+{
+	struct mmc_blk_data *md = mmc_blk_get(dev_to_disk(dev));
+	struct mmc_card *card = md->queue.card;
+	int ret;
+
+	if (!card)
+		ret = -EINVAL;
+	else
+	    ret = snprintf(buf, PAGE_SIZE, "%d\n",
+		card->bkops_info.size_percentage_to_queue_delayed_work);
+
+	mmc_blk_put(md);
+	return ret;
+}
+
+static ssize_t
+bkops_check_threshold_store(struct device *dev,
+				 struct device_attribute *attr,
+				 const char *buf, size_t count)
+{
+	int value;
+	struct mmc_blk_data *md = mmc_blk_get(dev_to_disk(dev));
+	struct mmc_card *card = md->queue.card;
+	unsigned int card_size;
+	int ret = count;
+
+	if (!card) {
+		ret = -EINVAL;
+		goto exit;
+	}
+
+	sscanf(buf, "%d", &value);
+	if ((value <= 0) || (value >= 100)) {
+		ret = -EINVAL;
+		goto exit;
+	}
+
+	card_size = (unsigned int)get_capacity(md->disk);
+	if (card_size <= 0) {
+		ret = -EINVAL;
+		goto exit;
+	}
+	card->bkops_info.size_percentage_to_queue_delayed_work = value;
+	card->bkops_info.min_sectors_to_queue_delayed_work =
+		(card_size * value) / 100;
+
+	pr_debug("%s: size_percentage = %d, min_sectors = %d",
+			mmc_hostname(card->host),
+			card->bkops_info.size_percentage_to_queue_delayed_work,
+			card->bkops_info.min_sectors_to_queue_delayed_work);
+
+exit:
+	mmc_blk_put(md);
+	return count;
+}
+
+static ssize_t
+no_pack_for_random_show(struct device *dev,
+				  struct device_attribute *attr, char *buf)
+{
+	struct mmc_blk_data *md = mmc_blk_get(dev_to_disk(dev));
+	int ret;
+
+	ret = snprintf(buf, PAGE_SIZE, "%d\n", md->queue.no_pack_for_random);
+
+	mmc_blk_put(md);
+	return ret;
+}
+
+static ssize_t
+no_pack_for_random_store(struct device *dev,
+				 struct device_attribute *attr,
+				 const char *buf, size_t count)
+{
+	int value;
+	struct mmc_blk_data *md = mmc_blk_get(dev_to_disk(dev));
+	struct mmc_card *card = md->queue.card;
+	int ret = count;
+
+	if (!card) {
+		ret = -EINVAL;
+		goto exit;
+	}
+
+	sscanf(buf, "%d", &value);
+
+	if (value < 0) {
+		pr_err("%s: value %d is not valid. old value remains = %d",
+			mmc_hostname(card->host), value,
+			md->queue.no_pack_for_random);
+		ret = -EINVAL;
+		goto exit;
+	}
+
+	md->queue.no_pack_for_random = (value > 0) ?  true : false;
+
+	pr_debug("%s: no_pack_for_random: new value = %d",
+		mmc_hostname(card->host),
+		md->queue.no_pack_for_random);
+
+exit:
+	mmc_blk_put(md);
+	return ret;
+}
+
 static int mmc_blk_open(struct block_device *bdev, fmode_t mode)
 {
 	struct mmc_blk_data *md = mmc_blk_get(bdev->bd_disk);
@@ -958,6 +1067,9 @@
 	from = blk_rq_pos(req);
 	nr = blk_rq_sectors(req);
 
+	if (card->ext_csd.bkops_en)
+		card->bkops_info.sectors_changed += blk_rq_sectors(req);
+
 	if (mmc_can_discard(card))
 		arg = MMC_DISCARD_ARG;
 	else if (mmc_can_trim(card))
@@ -1657,8 +1769,21 @@
 			break;
 		}
 
-		if (rq_data_dir(next) == WRITE)
+		if (mq->no_pack_for_random) {
+			if ((blk_rq_pos(cur) + blk_rq_sectors(cur)) !=
+			    blk_rq_pos(next)) {
+				MMC_BLK_UPDATE_STOP_REASON(stats, RANDOM);
+				put_back = 1;
+				break;
+			}
+		}
+
+		if (rq_data_dir(next) == WRITE) {
 			mq->num_of_potential_packed_wr_reqs++;
+			if (card->ext_csd.bkops_en)
+				card->bkops_info.sectors_changed +=
+					blk_rq_sectors(next);
+		}
 		list_add_tail(&next->queuelist, &mq->mqrq_cur->packed_list);
 		cur = next;
 		reqs++;
@@ -1891,6 +2016,8 @@
 		return 0;
 
 	if (rqc) {
+		if ((card->ext_csd.bkops_en) && (rq_data_dir(rqc) == WRITE))
+			card->bkops_info.sectors_changed += blk_rq_sectors(rqc);
 		reqs = mmc_blk_prep_packed_list(mq, rqc);
 	}
 
@@ -1922,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:
 			/*
@@ -1996,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) {
@@ -2051,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)) {
@@ -2062,11 +2194,8 @@
 	if (req && !mq->mqrq_prev->req) {
 		/* claim host only for the first request */
 		mmc_claim_host(card->host);
-		if (card->ext_csd.bkops_en &&
-		    card->bkops_info.started_delayed_bkops) {
-			card->bkops_info.started_delayed_bkops = false;
+		if (card->ext_csd.bkops_en)
 			mmc_stop_bkops(card);
-		}
 	}
 
 	ret = mmc_blk_part_switch(card, md);
@@ -2101,13 +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;
 }
 
@@ -2126,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)
@@ -2205,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) &&
@@ -2397,8 +2540,34 @@
 	if (ret)
 		goto num_wr_reqs_to_start_packing_fail;
 
+	md->bkops_check_threshold.show = bkops_check_threshold_show;
+	md->bkops_check_threshold.store = bkops_check_threshold_store;
+	sysfs_attr_init(&md->bkops_check_threshold.attr);
+	md->bkops_check_threshold.attr.name = "bkops_check_threshold";
+	md->bkops_check_threshold.attr.mode = S_IRUGO | S_IWUSR;
+	ret = device_create_file(disk_to_dev(md->disk),
+				 &md->bkops_check_threshold);
+	if (ret)
+		goto bkops_check_threshold_fails;
+
+	md->no_pack_for_random.show = no_pack_for_random_show;
+	md->no_pack_for_random.store = no_pack_for_random_store;
+	sysfs_attr_init(&md->no_pack_for_random.attr);
+	md->no_pack_for_random.attr.name = "no_pack_for_random";
+	md->no_pack_for_random.attr.mode = S_IRUGO | S_IWUSR;
+	ret = device_create_file(disk_to_dev(md->disk),
+				 &md->no_pack_for_random);
+	if (ret)
+		goto no_pack_for_random_fails;
+
 	return ret;
 
+no_pack_for_random_fails:
+	device_remove_file(disk_to_dev(md->disk),
+			   &md->bkops_check_threshold);
+bkops_check_threshold_fails:
+	device_remove_file(disk_to_dev(md->disk),
+			   &md->num_wr_reqs_to_start_packing);
 num_wr_reqs_to_start_packing_fail:
 	device_remove_file(disk_to_dev(md->disk), &md->power_ro_lock);
 power_ro_lock_fail:
diff --git a/drivers/mmc/card/mmc_block_test.c b/drivers/mmc/card/mmc_block_test.c
index 5d571a5..4a21fd4 100644
--- a/drivers/mmc/card/mmc_block_test.c
+++ b/drivers/mmc/card/mmc_block_test.c
@@ -1893,6 +1893,8 @@
 	case BKOPS_DELAYED_WORK_LEVEL_1:
 		bkops_stat->ignore_card_bkops_status = true;
 		card->ext_csd.raw_bkops_status = 1;
+		card->bkops_info.sectors_changed =
+			card->bkops_info.min_sectors_to_queue_delayed_work + 1;
 		mbtd->bkops_stage = BKOPS_STAGE_1;
 
 		__blk_run_queue(q);
@@ -1909,6 +1911,8 @@
 	case BKOPS_DELAYED_WORK_LEVEL_1_HPI:
 		bkops_stat->ignore_card_bkops_status = true;
 		card->ext_csd.raw_bkops_status = 1;
+		card->bkops_info.sectors_changed =
+			card->bkops_info.min_sectors_to_queue_delayed_work + 1;
 		mbtd->bkops_stage = BKOPS_STAGE_1;
 
 		__blk_run_queue(q);
@@ -1937,6 +1941,8 @@
 	case BKOPS_CANCEL_DELAYED_WORK:
 		bkops_stat->ignore_card_bkops_status = true;
 		card->ext_csd.raw_bkops_status = 1;
+		card->bkops_info.sectors_changed =
+			card->bkops_info.min_sectors_to_queue_delayed_work + 1;
 		mbtd->bkops_stage = BKOPS_STAGE_1;
 
 		__blk_run_queue(q);
diff --git a/drivers/mmc/card/queue.c b/drivers/mmc/card/queue.c
index dc27db6..9babeab 100644
--- a/drivers/mmc/card/queue.c
+++ b/drivers/mmc/card/queue.c
@@ -78,14 +78,6 @@
 		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) {
@@ -97,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);
@@ -107,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 cb1b1aa..47a21cd 100644
--- a/drivers/mmc/core/core.c
+++ b/drivers/mmc/core/core.c
@@ -357,6 +357,10 @@
 	if (!card || !card->ext_csd.bkops_en || mmc_card_doing_bkops(card))
 		return;
 
+	if (card->bkops_info.sectors_changed <
+	    card->bkops_info.min_sectors_to_queue_delayed_work)
+		return;
+
 	pr_debug("%s: %s: queueing delayed_bkops_work\n",
 		 mmc_hostname(card->host), __func__);
 
@@ -366,7 +370,6 @@
 	 * it was removed from the queue work but not started yet
 	 */
 	card->bkops_info.cancel_delayed_work = false;
-	card->bkops_info.started_delayed_bkops = true;
 	queue_delayed_work(system_nrt_wq, &card->bkops_info.dw,
 			   msecs_to_jiffies(
 				   card->bkops_info.delay_ms));
@@ -386,8 +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)
@@ -408,43 +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, use_busy_signal);
+			EXT_CSD_BKOPS_START, 1, 0, false, false);
 	if (err) {
 		pr_warn("%s: %s: Error %d when starting bkops\n",
 			mmc_hostname(card->host), __func__, err);
@@ -452,19 +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);
@@ -518,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;
 		}
 
@@ -563,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
@@ -626,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;
@@ -668,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;
@@ -782,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;
 			/*
@@ -940,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)
 {
@@ -3314,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 ae8a619..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);
 
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 574629f..ec30cad 100644
--- a/drivers/mmc/core/mmc.c
+++ b/drivers/mmc/core/mmc.c
@@ -1412,7 +1412,6 @@
 			if (card->bkops_info.host_delay_ms)
 				card->bkops_info.delay_ms =
 					card->bkops_info.host_delay_ms;
-
 		}
 	}
 
diff --git a/drivers/mmc/host/msm_sdcc.c b/drivers/mmc/host/msm_sdcc.c
index f1ba8ad..91720ee 100644
--- a/drivers/mmc/host/msm_sdcc.c
+++ b/drivers/mmc/host/msm_sdcc.c
@@ -236,14 +236,6 @@
 {
 	int rc;
 
-	/* Reset and init DML */
-	rc = msmsdcc_dml_init(host);
-	if (rc) {
-		pr_err("%s: msmsdcc_dml_init error=%d\n",
-				mmc_hostname(host->mmc), rc);
-		goto out;
-	}
-
 	/* Reset all SDCC BAM pipes */
 	rc = msmsdcc_sps_reset_ep(host, &host->sps.prod);
 	if (rc) {
@@ -276,13 +268,21 @@
 	}
 
 	rc = msmsdcc_sps_restore_ep(host, &host->sps.cons);
-	if (rc)
+	if (rc) {
 		pr_err("%s: msmsdcc_sps_restore_ep(cons) error=%d\n",
 				mmc_hostname(host->mmc), rc);
-	else
-		host->sps.reset_bam = false;
+		goto out;
+	}
+
+	/* Reset and init DML */
+	rc = msmsdcc_dml_init(host);
+	if (rc)
+		pr_err("%s: msmsdcc_dml_init error=%d\n",
+				mmc_hostname(host->mmc), rc);
 
 out:
+	if (!rc)
+		host->sps.reset_bam = false;
 	return rc;
 }
 
diff --git a/drivers/power/qpnp-charger.c b/drivers/power/qpnp-charger.c
index 510071a..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,
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/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/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/mdss/Kconfig b/drivers/video/msm/mdss/Kconfig
index 56eb90c..7682a49 100644
--- a/drivers/video/msm/mdss/Kconfig
+++ b/drivers/video/msm/mdss/Kconfig
@@ -12,7 +12,7 @@
 	The MDSS HDMI Panel provides support for transmitting TMDS signals of
 	MDSS frame buffer data to connected hdmi compliant TVs, monitors etc.
 
-config FB_MSM_MDSS_HDMI_MHL_8334
+config FB_MSM_MDSS_HDMI_MHL_SII8334
 	depends on FB_MSM_MDSS_HDMI_PANEL
 	bool 'MHL SII8334 support '
 	default n
diff --git a/drivers/video/msm/mdss/Makefile b/drivers/video/msm/mdss/Makefile
index 4deaa8c..17987d4 100644
--- a/drivers/video/msm/mdss/Makefile
+++ b/drivers/video/msm/mdss/Makefile
@@ -19,7 +19,7 @@
 obj-$(CONFIG_FB_MSM_MDSS_HDMI_PANEL) += mdss_hdmi_tx.o
 obj-$(CONFIG_FB_MSM_MDSS_HDMI_PANEL) += mdss_hdmi_util.o
 obj-$(CONFIG_FB_MSM_MDSS_HDMI_PANEL) += mdss_hdmi_edid.o
-obj-$(CONFIG_FB_MSM_MDSS_HDMI_MHL_8334) += mhl_sii8334.o
+obj-$(CONFIG_FB_MSM_MDSS_HDMI_MHL_SII8334) += mhl_sii8334.o mhl_msc.o
 obj-$(CONFIG_FB_MSM_MDSS_HDMI_PANEL) += mdss_hdmi_hdcp.o
 
 obj-$(CONFIG_FB_MSM_MDSS_WRITEBACK) += mdss_wb.o
diff --git a/drivers/video/msm/mdss/mdss_mdp.h b/drivers/video/msm/mdss/mdss_mdp.h
index 9503489..e9427da 100644
--- a/drivers/video/msm/mdss/mdss_mdp.h
+++ b/drivers/video/msm/mdss/mdss_mdp.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -235,7 +235,6 @@
 
 	struct msm_fb_data_type *mfd;
 	struct mdss_mdp_mixer *mixer;
-	struct mutex lock;
 
 	struct mdp_overlay req_data;
 	u32 params_changed;
@@ -326,10 +325,10 @@
 
 
 struct mdss_mdp_pipe *mdss_mdp_pipe_alloc_pnum(u32 pnum);
-struct mdss_mdp_pipe *mdss_mdp_pipe_alloc_locked(u32 type);
-struct mdss_mdp_pipe *mdss_mdp_pipe_get_locked(u32 ndx);
-int mdss_mdp_pipe_lock(struct mdss_mdp_pipe *pipe);
-void mdss_mdp_pipe_unlock(struct mdss_mdp_pipe *pipe);
+struct mdss_mdp_pipe *mdss_mdp_pipe_alloc(u32 type);
+struct mdss_mdp_pipe *mdss_mdp_pipe_get(u32 ndx);
+int mdss_mdp_pipe_map(struct mdss_mdp_pipe *pipe);
+void mdss_mdp_pipe_unmap(struct mdss_mdp_pipe *pipe);
 
 int mdss_mdp_pipe_destroy(struct mdss_mdp_pipe *pipe);
 int mdss_mdp_pipe_queue_data(struct mdss_mdp_pipe *pipe,
diff --git a/drivers/video/msm/mdss/mdss_mdp_ctl.c b/drivers/video/msm/mdss/mdss_mdp_ctl.c
index f62dd24..2f4c2ed 100644
--- a/drivers/video/msm/mdss/mdss_mdp_ctl.c
+++ b/drivers/video/msm/mdss/mdss_mdp_ctl.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -784,6 +784,14 @@
 					stage);
 		}
 
+		if (mixercfg == MDSS_MDP_LM_BORDER_COLOR &&
+				pipe->src_fmt->alpha_enable &&
+				pipe->dst.w == mixer->width &&
+				pipe->dst.h == mixer->height) {
+			pr_debug("setting pipe=%d as BG_PIPE\n", pipe->num);
+			bgalpha = 1;
+		}
+
 		mixercfg |= stage << (3 * pipe->num);
 
 		MDSS_MDP_REG_WRITE(off + MDSS_MDP_REG_LM_OP_MODE, blend_op);
diff --git a/drivers/video/msm/mdss/mdss_mdp_overlay.c b/drivers/video/msm/mdss/mdss_mdp_overlay.c
index d278554..338cf87 100644
--- a/drivers/video/msm/mdss/mdss_mdp_overlay.c
+++ b/drivers/video/msm/mdss/mdss_mdp_overlay.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -39,14 +39,14 @@
 {
 	struct mdss_mdp_pipe *pipe;
 
-	pipe = mdss_mdp_pipe_get_locked(req->id);
-	if (pipe == NULL) {
+	pipe = mdss_mdp_pipe_get(req->id);
+	if (IS_ERR_OR_NULL(pipe)) {
 		pr_err("invalid pipe ndx=%x\n", req->id);
-		return -ENODEV;
+		return pipe ? PTR_ERR(pipe) : -ENODEV;
 	}
 
 	*req = pipe->req_data;
-	mdss_mdp_pipe_unlock(pipe);
+	mdss_mdp_pipe_unmap(pipe);
 
 	return 0;
 }
@@ -280,12 +280,12 @@
 		else
 			pipe_type = MDSS_MDP_PIPE_TYPE_RGB;
 
-		pipe = mdss_mdp_pipe_alloc_locked(pipe_type);
+		pipe = mdss_mdp_pipe_alloc(pipe_type);
 
 		/* VIG pipes can also support RGB format */
 		if (!pipe && pipe_type == MDSS_MDP_PIPE_TYPE_RGB) {
 			pipe_type = MDSS_MDP_PIPE_TYPE_VIG;
-			pipe = mdss_mdp_pipe_alloc_locked(pipe_type);
+			pipe = mdss_mdp_pipe_alloc(pipe_type);
 		}
 
 		if (pipe == NULL) {
@@ -293,16 +293,23 @@
 			return -ENOMEM;
 		}
 
+		ret = mdss_mdp_pipe_map(pipe);
+		if (ret) {
+			pr_err("unable to map pipe=%d\n", pipe->num);
+			return ret;
+		}
+
 		mutex_lock(&mfd->lock);
 		list_add(&pipe->used_list, &mfd->pipes_used);
 		mutex_unlock(&mfd->lock);
 		pipe->mixer = mixer;
 		pipe->mfd = mfd;
+		pipe->play_cnt = 0;
 	} else {
-		pipe = mdss_mdp_pipe_get_locked(req->id);
-		if (pipe == NULL) {
+		pipe = mdss_mdp_pipe_get(req->id);
+		if (IS_ERR_OR_NULL(pipe)) {
 			pr_err("invalid pipe ndx=%x\n", req->id);
-			return -ENODEV;
+			return pipe ? PTR_ERR(pipe) : -ENODEV;
 		}
 	}
 
@@ -353,7 +360,7 @@
 
 	*ppipe = pipe;
 
-	mdss_mdp_pipe_unlock(pipe);
+	mdss_mdp_pipe_unmap(pipe);
 
 	return ret;
 }
@@ -498,8 +505,8 @@
 		pipe_ndx = BIT(i);
 		if (pipe_ndx & ndx) {
 			unset_ndx |= pipe_ndx;
-			pipe = mdss_mdp_pipe_get_locked(pipe_ndx);
-			if (!pipe) {
+			pipe = mdss_mdp_pipe_get(pipe_ndx);
+			if (IS_ERR_OR_NULL(pipe)) {
 				pr_warn("unknown pipe ndx=%x\n", pipe_ndx);
 				continue;
 			}
@@ -508,6 +515,7 @@
 			list_add(&pipe->cleanup_list, &mfd->pipes_cleanup);
 			mutex_unlock(&mfd->lock);
 			mdss_mdp_mixer_pipe_unstage(pipe);
+			mdss_mdp_pipe_unmap(pipe);
 		}
 	}
 	return 0;
@@ -638,10 +646,10 @@
 	int ret;
 	u32 flags;
 
-	pipe = mdss_mdp_pipe_get_locked(req->id);
-	if (pipe == NULL) {
+	pipe = mdss_mdp_pipe_get(req->id);
+	if (IS_ERR_OR_NULL(pipe)) {
 		pr_err("pipe ndx=%x doesn't exist\n", req->id);
-		return -ENODEV;
+		return pipe ? PTR_ERR(pipe) : -ENODEV;
 	}
 
 	pr_debug("ov queue pnum=%d\n", pipe->num);
@@ -664,7 +672,7 @@
 			mdss_mdp_overlay_free_buf(src_data);
 	}
 	ctl = pipe->mixer->ctl;
-	mdss_mdp_pipe_unlock(pipe);
+	mdss_mdp_pipe_unmap(pipe);
 
 	return ret;
 }
@@ -844,9 +852,12 @@
 		return;
 	}
 
-	mdss_mdp_pipe_lock(pipe);
+	if (mdss_mdp_pipe_map(pipe)) {
+		pr_err("unable to map base pipe\n");
+		return;
+	}
 	ret = mdss_mdp_pipe_queue_data(pipe, &data);
-	mdss_mdp_pipe_unlock(pipe);
+	mdss_mdp_pipe_unmap(pipe);
 	if (ret) {
 		pr_err("unable to queue data\n");
 		return;
@@ -859,9 +870,12 @@
 			pr_err("unable to allocate right base pipe\n");
 			return;
 		}
-		mdss_mdp_pipe_lock(pipe);
+		if (mdss_mdp_pipe_map(pipe)) {
+			pr_err("unable to map right base pipe\n");
+			return;
+		}
 		ret = mdss_mdp_pipe_queue_data(pipe, &data);
-		mdss_mdp_pipe_unlock(pipe);
+		mdss_mdp_pipe_unmap(pipe);
 		if (ret) {
 			pr_err("unable to queue right data\n");
 			return;
@@ -901,10 +915,15 @@
 	if (!ctl->set_vsync_handler)
 		return -ENOTSUPP;
 
+	rc = mutex_lock_interruptible(&ctl->lock);
+	if (rc)
+		return rc;
+
 	if (!ctl->power_on) {
 		pr_debug("fb%d vsync pending first update en=%d\n",
 				mfd->index, en);
 		mfd->vsync_pending = en;
+		mutex_unlock(&ctl->lock);
 		return 0;
 	}
 
@@ -925,6 +944,8 @@
 		rc = ctl->set_vsync_handler(ctl, NULL);
 	mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_OFF, false);
 
+	mutex_unlock(&ctl->lock);
+
 	return rc;
 }
 
@@ -935,13 +956,20 @@
 	struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)fbi->par;
 	unsigned long flags;
 	u64 vsync_ticks;
+	unsigned long timeout;
 	int ret;
 
 	if (!mfd->ctl || !mfd->ctl->power_on)
 		return 0;
 
+	timeout = msecs_to_jiffies(VSYNC_PERIOD * 5);
+	if (mfd->ctl->play_cnt == 0) {
+		pr_debug("timegen enable still pending on fb%d\n", mfd->index);
+		timeout <<= 5;
+	}
+
 	ret = wait_for_completion_interruptible_timeout(&mfd->vsync_comp,
-			msecs_to_jiffies(VSYNC_PERIOD * 5));
+			timeout);
 	if (ret <= 0) {
 		pr_warn("vsync wait on fb%d interrupted (%d)\n",
 			mfd->index, ret);
diff --git a/drivers/video/msm/mdss/mdss_mdp_pipe.c b/drivers/video/msm/mdss/mdss_mdp_pipe.c
index ade7cb4..89f3405 100644
--- a/drivers/video/msm/mdss/mdss_mdp_pipe.c
+++ b/drivers/video/msm/mdss/mdss_mdp_pipe.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -27,6 +27,8 @@
 
 static struct mdss_mdp_pipe mdss_mdp_pipe_list[MDSS_MDP_MAX_SSPP];
 
+static int mdss_mdp_pipe_free(struct mdss_mdp_pipe *pipe);
+
 static u32 mdss_mdp_smp_mmb_reserve(unsigned long *smp, size_t n)
 {
 	u32 i, mmb;
@@ -157,47 +159,43 @@
 	return 0;
 }
 
-void mdss_mdp_pipe_unlock(struct mdss_mdp_pipe *pipe)
+void mdss_mdp_pipe_unmap(struct mdss_mdp_pipe *pipe)
 {
-	atomic_dec(&pipe->ref_cnt);
-	mutex_unlock(&pipe->lock);
+	int tmp;
+
+	tmp = atomic_dec_return(&pipe->ref_cnt);
+
+	WARN(tmp < 0, "Invalid unmap with ref_cnt=%d", tmp);
+	if (tmp == 0)
+		mdss_mdp_pipe_free(pipe);
 }
 
-int mdss_mdp_pipe_lock(struct mdss_mdp_pipe *pipe)
+int mdss_mdp_pipe_map(struct mdss_mdp_pipe *pipe)
 {
-	if (atomic_inc_not_zero(&pipe->ref_cnt)) {
-		if (mutex_lock_interruptible(&pipe->lock)) {
-			atomic_dec(&pipe->ref_cnt);
-			return -EINTR;
-		}
-		return 0;
+	if (!atomic_inc_not_zero(&pipe->ref_cnt)) {
+		pr_err("attempting to map unallocated pipe (%d)", pipe->num);
+		return -EINVAL;
 	}
-	return -EINVAL;
+	return 0;
 }
 
 static struct mdss_mdp_pipe *mdss_mdp_pipe_init(u32 pnum)
 {
-	struct mdss_mdp_pipe *pipe = NULL;
+	struct mdss_mdp_pipe *pipe;
 
-	if (atomic_read(&mdss_mdp_pipe_list[pnum].ref_cnt) == 0) {
-		pipe = &mdss_mdp_pipe_list[pnum];
-		memset(pipe, 0, sizeof(*pipe));
+	pipe = &mdss_mdp_pipe_list[pnum];
 
-		mutex_init(&pipe->lock);
-		atomic_set(&pipe->ref_cnt, 1);
+	if (atomic_cmpxchg(&pipe->ref_cnt, 0, 1) == 0) {
+		pipe->num = pnum;
+		pipe->type = mdss_res->pipe_type_map[pnum];
+		pipe->ndx = BIT(pnum);
 
-		if (mdss_mdp_pipe_lock(pipe) == 0) {
-			pipe->num = pnum;
-			pipe->type = mdss_res->pipe_type_map[pnum];
-			pipe->ndx = BIT(pnum);
+		pr_debug("ndx=%x pnum=%d\n", pipe->ndx, pipe->num);
 
-			pr_debug("ndx=%x pnum=%d\n", pipe->ndx, pipe->num);
-		} else {
-			atomic_set(&pipe->ref_cnt, 0);
-			pipe = NULL;
-		}
+		return pipe;
 	}
-	return pipe;
+
+	return NULL;
 }
 
 struct mdss_mdp_pipe *mdss_mdp_pipe_alloc_pnum(u32 pnum)
@@ -210,7 +208,7 @@
 	return pipe;
 }
 
-struct mdss_mdp_pipe *mdss_mdp_pipe_alloc_locked(u32 type)
+struct mdss_mdp_pipe *mdss_mdp_pipe_alloc(u32 type)
 {
 	struct mdss_mdp_pipe *pipe = NULL;
 	int pnum;
@@ -228,57 +226,60 @@
 	return pipe;
 }
 
-struct mdss_mdp_pipe *mdss_mdp_pipe_get_locked(u32 ndx)
+struct mdss_mdp_pipe *mdss_mdp_pipe_get(u32 ndx)
 {
 	struct mdss_mdp_pipe *pipe = NULL;
 	int i;
 
 	if (!ndx)
-		return NULL;
+		return ERR_PTR(-EINVAL);
 
 	mutex_lock(&mdss_mdp_sspp_lock);
 	for (i = 0; i < MDSS_MDP_MAX_SSPP; i++) {
 		pipe = &mdss_mdp_pipe_list[i];
-		if (ndx == pipe->ndx)
+		if (ndx == pipe->ndx) {
+			if (mdss_mdp_pipe_map(pipe))
+				pipe = ERR_PTR(-EACCES);
 			break;
+		}
 	}
 	mutex_unlock(&mdss_mdp_sspp_lock);
 
 	if (i == MDSS_MDP_MAX_SSPP)
-		return NULL;
-
-	if (mdss_mdp_pipe_lock(pipe))
-		return NULL;
-
-	if (pipe->ndx != ndx) {
-		mdss_mdp_pipe_unlock(pipe);
-		pipe = NULL;
-	}
+		return ERR_PTR(-ENODEV);
 
 	return pipe;
 }
 
-
-static void mdss_mdp_pipe_free(struct mdss_mdp_pipe *pipe)
-{
-	mdss_mdp_smp_free(pipe);
-	pipe->ndx = 0;
-	atomic_dec(&pipe->ref_cnt);
-	mdss_mdp_pipe_unlock(pipe);
-}
-
-int mdss_mdp_pipe_destroy(struct mdss_mdp_pipe *pipe)
+static int mdss_mdp_pipe_free(struct mdss_mdp_pipe *pipe)
 {
 	pr_debug("ndx=%x pnum=%d ref_cnt=%d\n", pipe->ndx, pipe->num,
 			atomic_read(&pipe->ref_cnt));
 
 	mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_ON, false);
-	mdss_mdp_pipe_free(pipe);
+	mdss_mdp_smp_free(pipe);
 	mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_OFF, false);
 
 	return 0;
 }
 
+int mdss_mdp_pipe_destroy(struct mdss_mdp_pipe *pipe)
+{
+	int tmp;
+
+	tmp = atomic_dec_return(&pipe->ref_cnt);
+
+	if (tmp != 0) {
+		pr_err("unable to free pipe %d while still in use (%d)\n",
+				pipe->num, tmp);
+		return -EBUSY;
+	}
+	mdss_mdp_pipe_free(pipe);
+
+	return 0;
+
+}
+
 static inline void mdss_mdp_pipe_write(struct mdss_mdp_pipe *pipe,
 				       u32 reg, u32 val)
 {
diff --git a/drivers/video/msm/mdss/mdss_mdp_rotator.c b/drivers/video/msm/mdss/mdss_mdp_rotator.c
index 1e58269..a151b38 100644
--- a/drivers/video/msm/mdss/mdss_mdp_rotator.c
+++ b/drivers/video/msm/mdss/mdss_mdp_rotator.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -89,7 +89,7 @@
 
 	pipe = mdss_mdp_pipe_alloc_pnum(pnum);
 
-	if (pipe)
+	if (!IS_ERR_OR_NULL(pipe))
 		pipe->mixer = mixer;
 done:
 	if (!pipe)
diff --git a/drivers/video/msm/mdss/mhl_msc.c b/drivers/video/msm/mdss/mhl_msc.c
new file mode 100644
index 0000000..94f6d2b
--- /dev/null
+++ b/drivers/video/msm/mdss/mhl_msc.c
@@ -0,0 +1,489 @@
+/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/types.h>
+#include <linux/mhl_8334.h>
+#include <linux/vmalloc.h>
+#include <linux/input.h>
+#include "mhl_msc.h"
+
+static struct mhl_tx_ctrl *mhl_ctrl;
+static DEFINE_MUTEX(msc_send_workqueue_mutex);
+
+const char *devcap_reg_name[] = {
+	"DEV_STATE       ",
+	"MHL_VERSION     ",
+	"DEV_CAT         ",
+	"ADOPTER_ID_H    ",
+	"ADOPTER_ID_L    ",
+	"VID_LINK_MODE   ",
+	"AUD_LINK_MODE   ",
+	"VIDEO_TYPE      ",
+	"LOG_DEV_MAP     ",
+	"BANDWIDTH       ",
+	"FEATURE_FLAG    ",
+	"DEVICE_ID_H     ",
+	"DEVICE_ID_L     ",
+	"SCRATCHPAD_SIZE ",
+	"INT_STAT_SIZE   ",
+	"Reserved        ",
+};
+
+static void mhl_print_devcap(u8 offset, u8 devcap)
+{
+	switch (offset) {
+	case DEVCAP_OFFSET_DEV_CAT:
+		pr_debug("DCAP: %02X %s: %02X DEV_TYPE=%X POW=%s\n",
+			offset, devcap_reg_name[offset], devcap,
+			devcap & 0x0F, (devcap & 0x10) ? "y" : "n");
+		break;
+	case DEVCAP_OFFSET_FEATURE_FLAG:
+		pr_debug("DCAP: %02X %s: %02X RCP=%s RAP=%s SP=%s\n",
+			offset, devcap_reg_name[offset], devcap,
+			(devcap & 0x01) ? "y" : "n",
+			(devcap & 0x02) ? "y" : "n",
+			(devcap & 0x04) ? "y" : "n");
+		break;
+	default:
+		pr_debug("DCAP: %02X %s: %02X\n",
+			offset, devcap_reg_name[offset], devcap);
+		break;
+	}
+}
+
+void mhl_register_msc(struct mhl_tx_ctrl *ctrl)
+{
+	if (ctrl)
+		mhl_ctrl = ctrl;
+}
+
+void mhl_msc_send_work(struct work_struct *work)
+{
+	struct mhl_tx_ctrl *mhl_ctrl =
+		container_of(work, struct mhl_tx_ctrl, mhl_msc_send_work);
+	struct msc_cmd_envelope *cmd_env;
+	int ret;
+	/*
+	 * Remove item from the queue
+	 * and schedule it
+	 */
+	mutex_lock(&msc_send_workqueue_mutex);
+	while (!list_empty(&mhl_ctrl->list_cmd)) {
+		cmd_env = list_first_entry(&mhl_ctrl->list_cmd,
+					   struct msc_cmd_envelope,
+					   msc_queue_envelope);
+		list_del(&cmd_env->msc_queue_envelope);
+		mutex_unlock(&msc_send_workqueue_mutex);
+
+		ret = mhl_send_msc_command(mhl_ctrl, &cmd_env->msc_cmd_msg);
+		if (ret == -EAGAIN) {
+			int retry = 2;
+			while (retry--) {
+				ret = mhl_send_msc_command(
+					mhl_ctrl,
+					&cmd_env->msc_cmd_msg);
+				if (ret != -EAGAIN)
+					break;
+			}
+		}
+		if (ret == -EAGAIN)
+			pr_err("%s: send_msc_command retry out!\n", __func__);
+
+		vfree(cmd_env);
+		mutex_lock(&msc_send_workqueue_mutex);
+	}
+	mutex_unlock(&msc_send_workqueue_mutex);
+}
+
+int mhl_queue_msc_command(struct mhl_tx_ctrl *mhl_ctrl,
+			  struct msc_command_struct *req,
+			  int priority_send)
+{
+	struct msc_cmd_envelope *cmd_env;
+
+	mutex_lock(&msc_send_workqueue_mutex);
+	cmd_env = vmalloc(sizeof(struct msc_cmd_envelope));
+	if (!cmd_env) {
+		pr_err("%s: out of memory!\n", __func__);
+		return -ENOMEM;
+	}
+
+	memcpy(&cmd_env->msc_cmd_msg, req,
+	       sizeof(struct msc_command_struct));
+
+	if (priority_send)
+		list_add(&cmd_env->msc_queue_envelope,
+			 &mhl_ctrl->list_cmd);
+	else
+		list_add_tail(&cmd_env->msc_queue_envelope,
+			      &mhl_ctrl->list_cmd);
+	mutex_unlock(&msc_send_workqueue_mutex);
+	queue_work(mhl_ctrl->msc_send_workqueue, &mhl_ctrl->mhl_msc_send_work);
+
+	return 0;
+}
+
+static int mhl_update_devcap(struct mhl_tx_ctrl *mhl_ctrl,
+	int offset, u8 devcap)
+{
+	if (!mhl_ctrl)
+		return -EFAULT;
+	if (offset < 0 || offset > 15)
+		return -EFAULT;
+	mhl_ctrl->devcap[offset] = devcap;
+	mhl_print_devcap(offset, mhl_ctrl->devcap[offset]);
+
+	return 0;
+}
+
+
+int mhl_msc_command_done(struct mhl_tx_ctrl *mhl_ctrl,
+			 struct msc_command_struct *req)
+{
+	switch (req->command) {
+	case MHL_WRITE_STAT:
+		if (req->offset == MHL_STATUS_REG_LINK_MODE) {
+			if (req->payload.data[0]
+			    & MHL_STATUS_PATH_ENABLED)
+				/* Enable TMDS output */
+				mhl_tmds_ctrl(mhl_ctrl, TMDS_ENABLE);
+			else
+				/* Disable TMDS output */
+				mhl_tmds_ctrl(mhl_ctrl, TMDS_DISABLE);
+		}
+		break;
+	case MHL_READ_DEVCAP:
+		mhl_update_devcap(mhl_ctrl,
+			req->offset, req->retval);
+		mhl_ctrl->devcap_state |= BIT(req->offset);
+		switch (req->offset) {
+		case MHL_DEV_CATEGORY_OFFSET:
+			if (req->retval & MHL_DEV_CATEGORY_POW_BIT)
+				pr_debug("%s: devcap pow bit set\n",
+					 __func__);
+			else
+				pr_debug("%s: devcap pow bit unset\n",
+					 __func__);
+			break;
+		case DEVCAP_OFFSET_MHL_VERSION:
+		case DEVCAP_OFFSET_INT_STAT_SIZE:
+			break;
+		}
+
+		break;
+	}
+	return 0;
+}
+
+int mhl_msc_send_set_int(struct mhl_tx_ctrl *mhl_ctrl,
+			 u8 offset, u8 mask)
+{
+	struct msc_command_struct req;
+	req.command = MHL_SET_INT;
+	req.offset = offset;
+	req.payload.data[0] = mask;
+	return mhl_queue_msc_command(mhl_ctrl, &req, MSC_NORMAL_SEND);
+}
+
+int mhl_msc_send_write_stat(struct mhl_tx_ctrl *mhl_ctrl,
+			    u8 offset, u8 value)
+{
+	struct msc_command_struct req;
+	req.command = MHL_WRITE_STAT;
+	req.offset = offset;
+	req.payload.data[0] = value;
+	return mhl_queue_msc_command(mhl_ctrl, &req, MSC_NORMAL_SEND);
+}
+
+int mhl_msc_send_msc_msg(struct mhl_tx_ctrl *mhl_ctrl,
+			 u8 sub_cmd, u8 cmd_data)
+{
+	struct msc_command_struct req;
+	req.command = MHL_MSC_MSG;
+	req.payload.data[0] = sub_cmd;
+	req.payload.data[1] = cmd_data;
+	return mhl_queue_msc_command(mhl_ctrl, &req, MSC_NORMAL_SEND);
+}
+
+/*
+ * Certain MSC msgs such as RCPK, RCPE and RAPK
+ * should be transmitted as a high priority
+ * because these msgs should be sent within
+ * 1000ms of a receipt of RCP/RAP. So such msgs can
+ * be added to the head of msc cmd queue.
+ */
+static int mhl_msc_send_prior_msc_msg(struct mhl_tx_ctrl *mhl_ctrl,
+				      u8 sub_cmd, u8 cmd_data)
+{
+	struct msc_command_struct req;
+	req.command = MHL_MSC_MSG;
+	req.payload.data[0] = sub_cmd;
+	req.payload.data[1] = cmd_data;
+	return mhl_queue_msc_command(mhl_ctrl, &req, MSC_PRIORITY_SEND);
+}
+
+
+int mhl_msc_read_devcap(struct mhl_tx_ctrl *mhl_ctrl, u8 offset)
+{
+	struct msc_command_struct req;
+	if (offset < 0 || offset > 15)
+		return -EFAULT;
+	req.command = MHL_READ_DEVCAP;
+	req.offset = offset;
+	req.payload.data[0] = 0;
+	return mhl_queue_msc_command(mhl_ctrl, &req, MSC_NORMAL_SEND);
+}
+
+int mhl_msc_read_devcap_all(struct mhl_tx_ctrl *mhl_ctrl)
+{
+	int offset;
+	int ret;
+
+	for (offset = 0; offset < DEVCAP_SIZE; offset++) {
+		ret = mhl_msc_read_devcap(mhl_ctrl, offset);
+		if (ret == -EBUSY)
+			pr_err("%s: queue busy!\n", __func__);
+	}
+	return ret;
+}
+
+
+static void mhl_handle_input(struct mhl_tx_ctrl *mhl_ctrl,
+			     u8 key_code, u16 input_key_code)
+{
+	int key_press = (key_code & 0x80) == 0;
+
+	pr_debug("%s: send key events[%x][%d]\n",
+		 __func__, key_code, key_press);
+	input_report_key(mhl_ctrl->input, input_key_code, key_press);
+	input_sync(mhl_ctrl->input);
+}
+
+
+
+int mhl_rcp_recv(struct mhl_tx_ctrl *mhl_ctrl, u8 key_code)
+{
+	u8 index = key_code & 0x7f;
+	u16 input_key_code;
+
+	if (!mhl_ctrl->rcp_key_code_tbl) {
+		pr_err("%s: RCP Key Code Table not initialized\n", __func__);
+		return -EINVAL;
+	}
+
+	input_key_code = mhl_ctrl->rcp_key_code_tbl[index];
+
+	if ((index < mhl_ctrl->rcp_key_code_tbl_len) &&
+	    (input_key_code > 0)) {
+		/* prior send rcpk */
+		mhl_msc_send_prior_msc_msg(
+			mhl_ctrl,
+			MHL_MSC_MSG_RCPK,
+			key_code);
+
+		if (mhl_ctrl->input)
+			mhl_handle_input(mhl_ctrl, key_code, input_key_code);
+	} else {
+		/* prior send rcpe */
+		mhl_msc_send_prior_msc_msg(
+			mhl_ctrl,
+			MHL_MSC_MSG_RCPE,
+			MHL_RCPE_INEFFECTIVE_KEY_CODE);
+
+		/* send rcpk after rcpe send */
+		mhl_msc_send_prior_msc_msg(
+			mhl_ctrl,
+			MHL_MSC_MSG_RCPK,
+			key_code);
+	}
+	return 0;
+}
+
+
+static int mhl_rap_action(struct mhl_tx_ctrl *mhl_ctrl, u8 action_code)
+{
+	switch (action_code) {
+	case MHL_RAP_CONTENT_ON:
+		mhl_tmds_ctrl(mhl_ctrl, TMDS_ENABLE);
+		break;
+	case MHL_RAP_CONTENT_OFF:
+		mhl_tmds_ctrl(mhl_ctrl, TMDS_DISABLE);
+		break;
+	default:
+		break;
+	}
+	return 0;
+}
+
+static int mhl_rap_recv(struct mhl_tx_ctrl *mhl_ctrl, u8 action_code)
+{
+	u8 error_code;
+
+	switch (action_code) {
+	case MHL_RAP_POLL:
+		if (mhl_ctrl->tmds_enabled())
+			error_code = MHL_RAPK_NO_ERROR;
+		else
+			error_code = MHL_RAPK_UNSUPPORTED_ACTION_CODE;
+		break;
+	case MHL_RAP_CONTENT_ON:
+	case MHL_RAP_CONTENT_OFF:
+		mhl_rap_action(mhl_ctrl, action_code);
+		error_code = MHL_RAPK_NO_ERROR;
+		break;
+	default:
+		error_code = MHL_RAPK_UNRECOGNIZED_ACTION_CODE;
+		break;
+	}
+	/* prior send rapk */
+	return mhl_msc_send_prior_msc_msg(
+		mhl_ctrl,
+		MHL_MSC_MSG_RAPK,
+		error_code);
+}
+
+
+int mhl_msc_recv_msc_msg(struct mhl_tx_ctrl *mhl_ctrl,
+			 u8 sub_cmd, u8 cmd_data)
+{
+	int rc = 0;
+	switch (sub_cmd) {
+	case MHL_MSC_MSG_RCP:
+		pr_debug("MHL: receive RCP(0x%02x)\n", cmd_data);
+		rc = mhl_rcp_recv(mhl_ctrl, cmd_data);
+		break;
+	case MHL_MSC_MSG_RCPK:
+		pr_debug("MHL: receive RCPK(0x%02x)\n", cmd_data);
+		break;
+	case MHL_MSC_MSG_RCPE:
+		pr_debug("MHL: receive RCPE(0x%02x)\n", cmd_data);
+		break;
+	case MHL_MSC_MSG_RAP:
+		pr_debug("MHL: receive RAP(0x%02x)\n", cmd_data);
+		rc = mhl_rap_recv(mhl_ctrl, cmd_data);
+		break;
+	case MHL_MSC_MSG_RAPK:
+		pr_debug("MHL: receive RAPK(0x%02x)\n", cmd_data);
+		break;
+	default:
+		break;
+	}
+	return rc;
+}
+
+int mhl_msc_recv_set_int(struct mhl_tx_ctrl *mhl_ctrl,
+			 u8 offset, u8 set_int)
+{
+	if (offset >= 2)
+		return -EFAULT;
+
+	switch (offset) {
+	case 0:
+		if (set_int & MHL_INT_DCAP_CHG) {
+			/* peer dcap has changed */
+			mhl_ctrl->devcap_state = 0;
+			mhl_msc_read_devcap_all(mhl_ctrl);
+		}
+		if (set_int & MHL_INT_DSCR_CHG)
+			pr_debug("%s: dscr chg\n", __func__);
+		if (set_int & MHL_INT_REQ_WRT) {
+			/* SET_INT: GRT_WRT */
+			mhl_msc_send_set_int(
+				mhl_ctrl,
+				MHL_RCHANGE_INT,
+				MHL_INT_GRT_WRT);
+		}
+		if (set_int & MHL_INT_GRT_WRT)
+			pr_debug("%s: recvd req to permit/grant write",
+				 __func__);
+		break;
+	case 1:
+		if (set_int & MHL_INT_EDID_CHG) {
+			/* peer EDID has changed
+			 * toggle HPD to read EDID
+			 */
+			pr_debug("%s: EDID CHG\n", __func__);
+			mhl_drive_hpd(mhl_ctrl, HPD_DOWN);
+			msleep(110);
+			mhl_drive_hpd(mhl_ctrl, HPD_UP);
+		}
+	}
+	return 0;
+}
+
+int mhl_msc_recv_write_stat(struct mhl_tx_ctrl *mhl_ctrl,
+			    u8 offset, u8 value)
+{
+	if (offset >= 2)
+		return -EFAULT;
+
+	switch (offset) {
+	case 0:
+		/*
+		 * connected device bits
+		 * changed and DEVCAP READY
+		 */
+		if (((value ^ mhl_ctrl->devcap_state) &
+		     MHL_STATUS_DCAP_RDY)) {
+			if (value & MHL_STATUS_DCAP_RDY) {
+				mhl_ctrl->devcap_state = 0;
+				mhl_msc_read_devcap_all(mhl_ctrl);
+			} else {
+				/*
+				 * peer dcap turned not ready
+				 * use old devap state
+				 */
+				pr_debug("%s: DCAP RDY bit cleared\n",
+					 __func__);
+			}
+		}
+		break;
+	case 1:
+		/*
+		 * connected device bits
+		 * changed and PATH ENABLED
+		 * bit set
+		 */
+		if ((value ^ mhl_ctrl->path_en_state)
+		    & MHL_STATUS_PATH_ENABLED) {
+			if (value & MHL_STATUS_PATH_ENABLED) {
+				if (mhl_ctrl->tmds_enabled() &&
+				    (mhl_ctrl->devcap[offset] &
+				     MHL_FEATURE_RAP_SUPPORT)) {
+					mhl_msc_send_msc_msg(
+						mhl_ctrl,
+						MHL_MSC_MSG_RAP,
+						MHL_RAP_CONTENT_ON);
+				}
+				mhl_ctrl->path_en_state
+					|= (MHL_STATUS_PATH_ENABLED |
+					    MHL_STATUS_CLK_MODE_NORMAL);
+				mhl_msc_send_write_stat(
+					mhl_ctrl,
+					MHL_STATUS_REG_LINK_MODE,
+					mhl_ctrl->path_en_state);
+			} else {
+				mhl_ctrl->path_en_state
+					&= ~(MHL_STATUS_PATH_ENABLED |
+					     MHL_STATUS_CLK_MODE_NORMAL);
+				mhl_msc_send_write_stat(
+					mhl_ctrl,
+					MHL_STATUS_REG_LINK_MODE,
+					mhl_ctrl->path_en_state);
+			}
+		}
+		break;
+	}
+	mhl_ctrl->path_en_state = value;
+	return 0;
+}
diff --git a/drivers/video/msm/mdss/mhl_msc.h b/drivers/video/msm/mdss/mhl_msc.h
new file mode 100644
index 0000000..9a7b3d6
--- /dev/null
+++ b/drivers/video/msm/mdss/mhl_msc.h
@@ -0,0 +1,57 @@
+/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#ifndef __MHL_MSC_H__
+#define __MHL_MSC_H__
+#include <linux/mhl_8334.h>
+
+#define MAX_RCP_KEYS_SUPPORTED 256
+
+#define MSC_NORMAL_SEND 0
+#define MSC_PRIORITY_SEND 1
+
+#define TMDS_ENABLE 1
+#define TMDS_DISABLE 0
+
+/******************************************************************/
+/* the below APIs are implemented by the MSC functionality */
+int mhl_msc_command_done(struct mhl_tx_ctrl *mhl_ctrl,
+			 struct msc_command_struct *req);
+
+int mhl_msc_send_set_int(struct mhl_tx_ctrl *mhl_ctrl,
+			 u8 offset, u8 mask);
+
+int mhl_msc_send_write_stat(struct mhl_tx_ctrl *mhl_ctrl,
+			    u8 offset, u8 value);
+int mhl_msc_send_msc_msg(struct mhl_tx_ctrl *mhl_ctrl,
+			 u8 sub_cmd, u8 cmd_data);
+
+int mhl_msc_recv_set_int(struct mhl_tx_ctrl *mhl_ctrl, u8 offset, u8 set_int);
+
+int mhl_msc_recv_write_stat(struct mhl_tx_ctrl *mhl_ctrl,
+			    u8 offset, u8 value);
+int mhl_msc_recv_msc_msg(struct mhl_tx_ctrl *mhl_ctrl,
+			 u8 sub_cmd, u8 cmd_data);
+void mhl_msc_send_work(struct work_struct *work);
+
+/******************************************************************/
+/* Tx should implement these APIs */
+int mhl_send_msc_command(struct mhl_tx_ctrl *mhl_ctrl,
+			 struct msc_command_struct *req);
+void mhl_drive_hpd(struct mhl_tx_ctrl *mhl_ctrl, uint8_t to_state);
+void mhl_tmds_ctrl(struct mhl_tx_ctrl *ctrl, uint8_t on);
+/******************************************************************/
+/* MHL driver registers ctrl with MSC */
+void mhl_register_msc(struct mhl_tx_ctrl *ctrl);
+
+#endif /* __MHL_MSC_H__ */
diff --git a/drivers/video/msm/mdss/mhl_sii8334.c b/drivers/video/msm/mdss/mhl_sii8334.c
index f3be983..7baeef5 100644
--- a/drivers/video/msm/mdss/mhl_sii8334.c
+++ b/drivers/video/msm/mdss/mhl_sii8334.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -18,6 +18,8 @@
 #include <linux/of_address.h>
 #include <linux/of_gpio.h>
 #include <linux/types.h>
+#include <linux/vmalloc.h>
+#include <linux/input.h>
 #include <linux/usb/msm_hsusb.h>
 #include <linux/mhl_8334.h>
 
@@ -27,6 +29,7 @@
 #include "mdss.h"
 #include "mdss_panel.h"
 #include "mdss_io_util.h"
+#include "mhl_msc.h"
 
 #define MHL_DRIVER_NAME "sii8334"
 #define COMPATIBLE_NAME "qcom,mhl-sii8334"
@@ -34,39 +37,142 @@
 
 #define pr_debug_intr(...) pr_debug("\n")
 
-enum mhl_gpio_type {
-	MHL_TX_RESET_GPIO,
-	MHL_TX_INTR_GPIO,
-	MHL_TX_PMIC_PWR_GPIO,
-	MHL_TX_MAX_GPIO,
-};
+#define MSC_START_BIT_MSC_CMD        (0x01 << 0)
+#define MSC_START_BIT_VS_CMD        (0x01 << 1)
+#define MSC_START_BIT_READ_REG        (0x01 << 2)
+#define MSC_START_BIT_WRITE_REG        (0x01 << 3)
+#define MSC_START_BIT_WRITE_BURST        (0x01 << 4)
 
-enum mhl_vreg_type {
-	MHL_TX_3V_VREG,
-	MHL_TX_MAX_VREG,
-};
-
-struct mhl_tx_platform_data {
-	/* Data filled from device tree nodes */
-	struct dss_gpio *gpios[MHL_TX_MAX_GPIO];
-	struct dss_vreg *vregs[MHL_TX_MAX_VREG];
-	int irq;
-};
-
-struct mhl_tx_ctrl {
-	struct platform_device *pdev;
-	struct mhl_tx_platform_data *pdata;
-	struct i2c_client *i2c_handle;
-	uint8_t cur_state;
-	uint8_t chip_rev_id;
-	int mhl_mode;
-	struct completion rgnd_done;
-	void (*notify_usb_online)(int online);
-	struct usb_ext_notification *mhl_info;
-	bool disc_enabled;
-	struct power_supply mhl_psy;
-	bool vbus_active;
-	int current_val;
+/* supported RCP key code */
+u16 support_rcp_key_code_tbl[] = {
+	KEY_ENTER,		/* 0x00 Select */
+	KEY_UP,			/* 0x01 Up */
+	KEY_DOWN,		/* 0x02 Down */
+	KEY_LEFT,		/* 0x03 Left */
+	KEY_RIGHT,		/* 0x04 Right */
+	KEY_UNKNOWN,		/* 0x05 Right-up */
+	KEY_UNKNOWN,		/* 0x06 Right-down */
+	KEY_UNKNOWN,		/* 0x07 Left-up */
+	KEY_UNKNOWN,		/* 0x08 Left-down */
+	KEY_MENU,		/* 0x09 Root Menu */
+	KEY_OPTION,		/* 0x0A Setup Menu */
+	KEY_UNKNOWN,		/* 0x0B Contents Menu */
+	KEY_UNKNOWN,		/* 0x0C Favorite Menu */
+	KEY_EXIT,		/* 0x0D Exit */
+	KEY_RESERVED,		/* 0x0E */
+	KEY_RESERVED,
+	KEY_RESERVED,
+	KEY_RESERVED,
+	KEY_RESERVED,
+	KEY_RESERVED,
+	KEY_RESERVED,
+	KEY_RESERVED,
+	KEY_RESERVED,
+	KEY_RESERVED,
+	KEY_RESERVED,
+	KEY_RESERVED,
+	KEY_RESERVED,
+	KEY_RESERVED,
+	KEY_RESERVED,
+	KEY_RESERVED,
+	KEY_RESERVED,
+	KEY_RESERVED,		/* 0x1F */
+	KEY_NUMERIC_0,		/* 0x20 NUMERIC_0 */
+	KEY_NUMERIC_1,		/* 0x21 NUMERIC_1 */
+	KEY_NUMERIC_2,		/* 0x22 NUMERIC_2 */
+	KEY_NUMERIC_3,		/* 0x23 NUMERIC_3 */
+	KEY_NUMERIC_4,		/* 0x24 NUMERIC_4 */
+	KEY_NUMERIC_5,		/* 0x25 NUMERIC_5 */
+	KEY_NUMERIC_6,		/* 0x26 NUMERIC_6 */
+	KEY_NUMERIC_7,		/* 0x27 NUMERIC_7 */
+	KEY_NUMERIC_8,		/* 0x28 NUMERIC_8 */
+	KEY_NUMERIC_9,		/* 0x29 NUMERIC_9 */
+	KEY_DOT,		/* 0x2A Dot */
+	KEY_ENTER,		/* 0x2B Enter */
+	KEY_ESC,		/* 0x2C Clear */
+	KEY_RESERVED,		/* 0x2D */
+	KEY_RESERVED,		/* 0x2E */
+	KEY_RESERVED,		/* 0x2F */
+	KEY_UNKNOWN,		/* 0x30 Channel Up */
+	KEY_UNKNOWN,		/* 0x31 Channel Down */
+	KEY_UNKNOWN,		/* 0x32 Previous Channel */
+	KEY_UNKNOWN,		/* 0x33 Sound Select */
+	KEY_UNKNOWN,		/* 0x34 Input Select */
+	KEY_UNKNOWN,		/* 0x35 Show Information */
+	KEY_UNKNOWN,		/* 0x36 Help */
+	KEY_UNKNOWN,		/* 0x37 Page Up */
+	KEY_UNKNOWN,		/* 0x38 Page Down */
+	KEY_RESERVED,		/* 0x39 */
+	KEY_RESERVED,
+	KEY_RESERVED,
+	KEY_RESERVED,
+	KEY_RESERVED,
+	KEY_RESERVED,
+	KEY_RESERVED,		/* 0x3F */
+	KEY_RESERVED,		/* 0x40 */
+	KEY_VOLUMEUP,		/* 0x41 Volume Up */
+	KEY_VOLUMEDOWN,		/* 0x42 Volume Down */
+	KEY_MUTE,		/* 0x43 Mute */
+	KEY_PLAY,		/* 0x44 Play */
+	KEY_STOP,		/* 0x45 Stop */
+	KEY_PAUSE,		/* 0x46 Pause */
+	KEY_UNKNOWN,		/* 0x47 Record */
+	KEY_REWIND,		/* 0x48 Rewind */
+	KEY_FASTFORWARD,	/* 0x49 Fast Forward */
+	KEY_UNKNOWN,		/* 0x4A Eject */
+	KEY_FORWARD,		/* 0x4B Forward */
+	KEY_BACK,		/* 0x4C Backward */
+	KEY_RESERVED,		/* 0x4D */
+	KEY_RESERVED,
+	KEY_RESERVED,		/* 0x4F */
+	KEY_UNKNOWN,		/* 0x50 Angle */
+	KEY_UNKNOWN,		/* 0x51 Subtitle */
+	KEY_RESERVED,		/* 0x52 */
+	KEY_RESERVED,
+	KEY_RESERVED,
+	KEY_RESERVED,
+	KEY_RESERVED,
+	KEY_RESERVED,
+	KEY_RESERVED,
+	KEY_RESERVED,
+	KEY_RESERVED,
+	KEY_RESERVED,
+	KEY_RESERVED,
+	KEY_RESERVED,
+	KEY_RESERVED,
+	KEY_RESERVED,		/* 0x5F */
+	KEY_PLAYPAUSE,		/* 0x60 Play Function */
+	KEY_PLAYPAUSE,		/* 0x61 Pause_Play Function */
+	KEY_UNKNOWN,		/* 0x62 Record Function */
+	KEY_PAUSE,		/* 0x63 Pause Record Function */
+	KEY_STOP,		/* 0x64 Stop Function  */
+	KEY_MUTE,		/* 0x65 Mute Function */
+	KEY_UNKNOWN,		/* 0x66 Restore Volume Function */
+	KEY_UNKNOWN,		/* 0x67 Tune Function */
+	KEY_UNKNOWN,		/* 0x68 Select Media Function */
+	KEY_RESERVED,		/* 0x69 */
+	KEY_RESERVED,
+	KEY_RESERVED,
+	KEY_RESERVED,
+	KEY_RESERVED,
+	KEY_RESERVED,
+	KEY_RESERVED,
+	KEY_RESERVED,		/* 0x70 */
+	KEY_BLUE,			/* 0x71 F1 */
+	KEY_RED,			/* 0x72 F2 */
+	KEY_GREEN,			/* 0x73 F3 */
+	KEY_YELLOW,			/* 0x74 F4 */
+	KEY_UNKNOWN,		/* 0x75 F5 */
+	KEY_RESERVED,		/* 0x76 */
+	KEY_RESERVED,
+	KEY_RESERVED,
+	KEY_RESERVED,
+	KEY_RESERVED,
+	KEY_RESERVED,
+	KEY_RESERVED,
+	KEY_RESERVED,		/* 0x7D */
+	KEY_VENDOR,		/* Vendor Specific */
+	KEY_RESERVED,		/* 0x7F */
 };
 
 
@@ -84,13 +190,12 @@
 static irqreturn_t mhl_tx_isr(int irq, void *dev_id);
 static void switch_mode(struct mhl_tx_ctrl *mhl_ctrl,
 			enum mhl_st_type to_mode);
-static void mhl_drive_hpd(struct mhl_tx_ctrl *mhl_ctrl,
-			  uint8_t to_state);
-
 static void mhl_init_reg_settings(struct mhl_tx_ctrl *mhl_ctrl,
-	bool mhl_disc_en);
+				  bool mhl_disc_en);
 
-static int mhl_i2c_reg_read(struct i2c_client *client,
+static uint8_t store_tmds_state;
+
+int mhl_i2c_reg_read(struct i2c_client *client,
 			    uint8_t slave_addr_index, uint8_t reg_offset)
 {
 	int rc = -1;
@@ -107,7 +212,7 @@
 }
 
 
-static int mhl_i2c_reg_write(struct i2c_client *client,
+int mhl_i2c_reg_write(struct i2c_client *client,
 			     uint8_t slave_addr_index, uint8_t reg_offset,
 			     uint8_t value)
 {
@@ -115,7 +220,7 @@
 				 reg_offset, &value);
 }
 
-static void mhl_i2c_reg_modify(struct i2c_client *client,
+void mhl_i2c_reg_modify(struct i2c_client *client,
 			       uint8_t slave_addr_index, uint8_t reg_offset,
 			       uint8_t mask, uint8_t val)
 {
@@ -350,11 +455,11 @@
 	MHL_SII_REG_NAME_WR(REG_INTR5_MASK, 0x00);
 
 	/* Unmask CBUS1 Intrs */
-	MHL_SII_CBUS_WR(0x0009,
+	MHL_SII_REG_NAME_WR(REG_CBUS_INTR_ENABLE,
 		BIT2 | BIT3 | BIT4 | BIT5 | BIT6);
 
 	/* Unmask CBUS2 Intrs */
-	MHL_SII_CBUS_WR(0x001F, BIT2 | BIT3);
+	MHL_SII_REG_NAME_WR(REG_CBUS_MSC_INT2_ENABLE, BIT2 | BIT3);
 
 	for (i = 0; i < 4; i++) {
 		/*
@@ -369,7 +474,6 @@
 		 */
 		MHL_SII_CBUS_WR((0xF0 + i), 0xFF);
 	}
-	return;
 }
 
 static void init_cbus_regs(struct i2c_client *client)
@@ -576,6 +680,7 @@
 
 		/* Force HPD to 0 when not in MHL mode.  */
 		mhl_drive_hpd(mhl_ctrl, HPD_DOWN);
+		mhl_tmds_ctrl(mhl_ctrl, TMDS_DISABLE);
 		/*
 		 * Change TMDS termination to high impedance
 		 * on disconnection.
@@ -592,7 +697,31 @@
 	}
 }
 
-static void mhl_drive_hpd(struct mhl_tx_ctrl *mhl_ctrl, uint8_t to_state)
+uint8_t check_tmds_enabled(void)
+{
+	return store_tmds_state;
+}
+
+void mhl_tmds_ctrl(struct mhl_tx_ctrl *mhl_ctrl, uint8_t on)
+{
+	struct i2c_client *client = mhl_ctrl->i2c_handle;
+	if (on) {
+		MHL_SII_REG_NAME_MOD(REG_TMDS_CCTRL, BIT4, BIT4);
+		mhl_drive_hpd(mhl_ctrl, HPD_UP);
+		/*
+		 * store the state to be used
+		 * before responding to RAP msgs
+		 * this needs to be obtained from
+		 * hdmi driver
+		 */
+		store_tmds_state = 1;
+	} else {
+		MHL_SII_REG_NAME_MOD(REG_TMDS_CCTRL, BIT4, 0x00);
+		store_tmds_state = 0;
+	}
+}
+
+void mhl_drive_hpd(struct mhl_tx_ctrl *mhl_ctrl, uint8_t to_state)
 {
 	struct i2c_client *client = mhl_ctrl->i2c_handle;
 
@@ -600,15 +729,6 @@
 	if (to_state == HPD_UP) {
 		/*
 		 * Drive HPD to UP state
-		 *
-		 * The below two reg configs combined
-		 * enable TMDS output.
-		 */
-
-		/* Enable TMDS on TMDS_CCTRL */
-		MHL_SII_REG_NAME_MOD(REG_TMDS_CCTRL, BIT4, BIT4);
-
-		/*
 		 * Set HPD_OUT_OVR_EN = HPD State
 		 * EDID read and Un-force HPD (from low)
 		 * propogate to src let HPD float by clearing
@@ -616,15 +736,9 @@
 		 */
 		MHL_SII_REG_NAME_MOD(REG_INT_CTRL, BIT4, 0x00);
 	} else {
-		/*
-		 * Drive HPD to DOWN state
-		 * Disable TMDS Output on REG_TMDS_CCTRL
-		 * Enable/Disable TMDS output (MHL TMDS output only)
-		 */
+		/* Drive HPD to DOWN state */
 		MHL_SII_REG_NAME_MOD(REG_INT_CTRL, BIT4, BIT4);
-		MHL_SII_REG_NAME_MOD(REG_TMDS_CCTRL, BIT4, 0x00);
 	}
-	return;
 }
 
 static void mhl_msm_connection(struct mhl_tx_ctrl *mhl_ctrl)
@@ -655,7 +769,19 @@
 	val = MHL_SII_PAGE3_RD(0x10);
 	MHL_SII_PAGE3_WR(0x10, val | BIT0);
 
-	return;
+	/*
+	 * indicate DCAP_RDY and DCAP_CHG
+	 * to the peer only after
+	 * msm conn has been established
+	 */
+	mhl_msc_send_write_stat(mhl_ctrl,
+				MHL_STATUS_REG_CONNECTED_RDY,
+				MHL_STATUS_DCAP_RDY);
+
+	mhl_msc_send_set_int(mhl_ctrl,
+			     MHL_RCHANGE_INT,
+			     MHL_INT_DCAP_CHG);
+
 }
 
 static void mhl_msm_disconnection(struct mhl_tx_ctrl *mhl_ctrl)
@@ -668,7 +794,6 @@
 	MHL_SII_PAGE3_WR(0x30, 0xD0);
 
 	switch_mode(mhl_ctrl, POWER_STATE_D3);
-	return;
 }
 
 static int  mhl_msm_read_rgnd_int(struct mhl_tx_ctrl *mhl_ctrl)
@@ -676,8 +801,8 @@
 	uint8_t rgnd_imp;
 	struct i2c_client *client = mhl_ctrl->i2c_handle;
 	/* DISC STATUS REG 2 */
-	rgnd_imp = (mhl_i2c_reg_read(client,
-				     TX_PAGE_3, 0x001C) & (BIT1 | BIT0));
+	rgnd_imp = (mhl_i2c_reg_read(client, TX_PAGE_3, 0x001C) &
+		    (BIT1 | BIT0));
 	pr_debug("imp range read=%02X\n", (int)rgnd_imp);
 
 	if (0x02 == rgnd_imp) {
@@ -820,8 +945,6 @@
 		release_usb_switch_open(mhl_ctrl);
 	}
 	MHL_SII_REG_NAME_WR(REG_INTR4, status);
-
-	return;
 }
 
 static void mhl_misc_isr(struct mhl_tx_ctrl *mhl_ctrl)
@@ -861,9 +984,225 @@
 		 */
 		cbus_stat = MHL_SII_CBUS_RD(0x0D);
 		if (BIT6 & cbus_stat)
-			mhl_drive_hpd(mhl_ctrl, HPD_UP);
+			mhl_tmds_ctrl(mhl_ctrl, TMDS_ENABLE);
 	}
-	return;
+}
+
+static void mhl_sii_cbus_process_errors(struct i2c_client *client,
+					u8 int_status)
+{
+	u8 abort_reason = 0;
+
+	if (int_status & BIT2) {
+		abort_reason = MHL_SII_REG_NAME_RD(REG_DDC_ABORT_REASON);
+		pr_debug("%s: CBUS DDC Abort Reason(0x%02x)\n",
+			 __func__, abort_reason);
+	}
+	if (int_status & BIT5) {
+		abort_reason = MHL_SII_REG_NAME_RD(REG_PRI_XFR_ABORT_REASON);
+		pr_debug("%s: CBUS MSC Requestor Abort Reason(0x%02x)\n",
+			 __func__, abort_reason);
+		MHL_SII_REG_NAME_WR(REG_PRI_XFR_ABORT_REASON, 0xFF);
+	}
+	if (int_status & BIT6) {
+		abort_reason = MHL_SII_REG_NAME_RD(
+			REG_CBUS_PRI_FWR_ABORT_REASON);
+		pr_debug("%s: CBUS MSC Responder Abort Reason(0x%02x)\n",
+			 __func__, abort_reason);
+		MHL_SII_REG_NAME_WR(REG_CBUS_PRI_FWR_ABORT_REASON, 0xFF);
+	}
+}
+
+int mhl_send_msc_command(struct mhl_tx_ctrl *mhl_ctrl,
+			 struct msc_command_struct *req)
+{
+	int timeout;
+	u8 start_bit = 0x00;
+	u8 *burst_data;
+	int i;
+	struct i2c_client *client = mhl_ctrl->i2c_handle;
+
+	if (mhl_ctrl->cur_state != POWER_STATE_D0_MHL) {
+		pr_debug("%s: power_state:%02x CBUS(0x0A):%02x\n",
+			 __func__,
+			 mhl_ctrl->cur_state,
+			 MHL_SII_REG_NAME_RD(REG_CBUS_BUS_STATUS));
+		return -EFAULT;
+	}
+
+	if (!req)
+		return -EFAULT;
+
+	pr_debug("%s: command=0x%02x offset=0x%02x %02x %02x",
+		 __func__,
+		 req->command,
+		 req->offset,
+		 req->payload.data[0],
+		 req->payload.data[1]);
+
+	/* REG_CBUS_PRI_ADDR_CMD = REQ CBUS CMD or OFFSET */
+	MHL_SII_REG_NAME_WR(REG_CBUS_PRI_ADDR_CMD, req->offset);
+	MHL_SII_REG_NAME_WR(REG_CBUS_PRI_WR_DATA_1ST,
+			    req->payload.data[0]);
+
+	switch (req->command) {
+	case MHL_SET_INT:
+	case MHL_WRITE_STAT:
+		start_bit = MSC_START_BIT_WRITE_REG;
+		break;
+	case MHL_READ_DEVCAP:
+		start_bit = MSC_START_BIT_READ_REG;
+		break;
+	case MHL_GET_STATE:
+	case MHL_GET_VENDOR_ID:
+	case MHL_SET_HPD:
+	case MHL_CLR_HPD:
+	case MHL_GET_SC1_ERRORCODE:
+	case MHL_GET_DDC_ERRORCODE:
+	case MHL_GET_MSC_ERRORCODE:
+	case MHL_GET_SC3_ERRORCODE:
+		start_bit = MSC_START_BIT_MSC_CMD;
+		MHL_SII_REG_NAME_WR(REG_CBUS_PRI_ADDR_CMD, req->command);
+		break;
+	case MHL_MSC_MSG:
+		start_bit = MSC_START_BIT_VS_CMD;
+		MHL_SII_REG_NAME_WR(REG_CBUS_PRI_WR_DATA_2ND,
+				    req->payload.data[1]);
+		MHL_SII_REG_NAME_WR(REG_CBUS_PRI_ADDR_CMD, req->command);
+		break;
+	case MHL_WRITE_BURST:
+		start_bit = MSC_START_BIT_WRITE_BURST;
+		MHL_SII_REG_NAME_WR(REG_MSC_WRITE_BURST_LEN, req->length - 1);
+		if (!(req->payload.burst_data)) {
+			pr_err("%s: burst data is null!\n", __func__);
+			goto cbus_send_fail;
+		}
+		burst_data = req->payload.burst_data;
+		for (i = 0; i < req->length; i++, burst_data++)
+			MHL_SII_CBUS_WR(0xC0 + i, *burst_data);
+		break;
+	default:
+		pr_err("%s: unknown command! (%02x)\n",
+		       __func__, req->command);
+		goto cbus_send_fail;
+	}
+
+	INIT_COMPLETION(mhl_ctrl->msc_cmd_done);
+	MHL_SII_REG_NAME_WR(REG_CBUS_PRI_START, start_bit);
+	timeout = wait_for_completion_interruptible_timeout
+		(&mhl_ctrl->msc_cmd_done, msecs_to_jiffies(T_ABORT_NEXT));
+	if (!timeout) {
+		pr_err("%s: cbus_command_send timed out!\n", __func__);
+		goto cbus_send_fail;
+	}
+
+	switch (req->command) {
+	case MHL_READ_DEVCAP:
+		req->retval = MHL_SII_REG_NAME_RD(REG_CBUS_PRI_RD_DATA_1ST);
+		break;
+	case MHL_MSC_MSG:
+		/* check if MSC_MSG NACKed */
+		if (MHL_SII_REG_NAME_RD(REG_MSC_WRITE_BURST_LEN) & BIT6)
+			return -EAGAIN;
+	default:
+		req->retval = 0;
+		break;
+	}
+	mhl_msc_command_done(mhl_ctrl, req);
+	pr_debug("%s: msc cmd done\n", __func__);
+	return 0;
+
+cbus_send_fail:
+	return -EFAULT;
+}
+
+static void mhl_cbus_isr(struct mhl_tx_ctrl *mhl_ctrl)
+{
+	uint8_t regval;
+	int req_done = 0;
+	uint8_t sub_cmd = 0x0;
+	uint8_t cmd_data = 0x0;
+	int msc_msg_recved = 0;
+	int rc = -1;
+	struct i2c_client *client = mhl_ctrl->i2c_handle;
+
+	regval = MHL_SII_REG_NAME_RD(REG_CBUS_INTR_STATUS);
+	if (regval == 0xff)
+		return;
+
+	if (regval)
+		MHL_SII_REG_NAME_WR(REG_CBUS_INTR_STATUS, regval);
+
+	pr_debug("%s: CBUS_INT = %02x\n", __func__, regval);
+
+	/* MSC_MSG (RCP/RAP) */
+	if (regval & BIT3) {
+		sub_cmd = MHL_SII_REG_NAME_RD(REG_CBUS_PRI_VS_CMD);
+		cmd_data = MHL_SII_REG_NAME_RD(REG_CBUS_PRI_VS_DATA);
+		msc_msg_recved = 1;
+	}
+	/* MSC_MT_ABRT/MSC_MR_ABRT/DDC_ABORT */
+	if (regval & (BIT6 | BIT5 | BIT2))
+		mhl_sii_cbus_process_errors(client, regval);
+
+	/* MSC_REQ_DONE */
+	if (regval & BIT4)
+		req_done = 1;
+
+	/* look for interrupts on CBUS_MSC_INT2 */
+	regval  = MHL_SII_REG_NAME_RD(REG_CBUS_MSC_INT2_STATUS);
+
+	/* clear all interrupts */
+	if (regval)
+		MHL_SII_REG_NAME_WR(REG_CBUS_MSC_INT2_STATUS, regval);
+
+	pr_debug("%s: CBUS_MSC_INT2 = %02x\n", __func__, regval);
+
+	/* received SET_INT */
+	if (regval & BIT2) {
+		uint8_t intr;
+		intr = MHL_SII_REG_NAME_RD(REG_CBUS_SET_INT_0);
+		MHL_SII_REG_NAME_WR(REG_CBUS_SET_INT_0, intr);
+		mhl_msc_recv_set_int(mhl_ctrl, 0, intr);
+
+		pr_debug("%s: MHL_INT_0 = %02x\n", __func__, intr);
+		intr = MHL_SII_REG_NAME_RD(REG_CBUS_SET_INT_1);
+		MHL_SII_REG_NAME_WR(REG_CBUS_SET_INT_1, intr);
+		mhl_msc_recv_set_int(mhl_ctrl, 1, intr);
+
+		pr_debug("%s: MHL_INT_1 = %02x\n", __func__, intr);
+		MHL_SII_REG_NAME_WR(REG_CBUS_SET_INT_2, 0xFF);
+		MHL_SII_REG_NAME_WR(REG_CBUS_SET_INT_3, 0xFF);
+	}
+
+	/* received WRITE_STAT */
+	if (regval & BIT3) {
+		uint8_t stat;
+		stat = MHL_SII_REG_NAME_RD(REG_CBUS_WRITE_STAT_0);
+		mhl_msc_recv_write_stat(mhl_ctrl, 0, stat);
+
+		pr_debug("%s: MHL_STATUS_0 = %02x\n", __func__, stat);
+		stat = MHL_SII_REG_NAME_RD(REG_CBUS_WRITE_STAT_1);
+		mhl_msc_recv_write_stat(mhl_ctrl, 1, stat);
+		pr_debug("%s: MHL_STATUS_1 = %02x\n", __func__, stat);
+
+		MHL_SII_REG_NAME_WR(REG_CBUS_WRITE_STAT_0, 0xFF);
+		MHL_SII_REG_NAME_WR(REG_CBUS_WRITE_STAT_1, 0xFF);
+		MHL_SII_REG_NAME_WR(REG_CBUS_WRITE_STAT_2, 0xFF);
+		MHL_SII_REG_NAME_WR(REG_CBUS_WRITE_STAT_3, 0xFF);
+	}
+
+	/* received MSC_MSG */
+	if (msc_msg_recved) {
+		/*mhl msc recv msc msg*/
+		rc = mhl_msc_recv_msc_msg(mhl_ctrl, sub_cmd, cmd_data);
+		if (rc)
+			pr_err("MHL: mhl msc recv msc msg failed(%d)!\n", rc);
+	}
+	/* complete last command */
+	if (req_done)
+		complete_all(&mhl_ctrl->msc_cmd_done);
+
 }
 
 static void clear_all_intrs(struct i2c_client *client)
@@ -1002,11 +1341,11 @@
 		mhl_misc_isr(mhl_ctrl);
 
 		/*
-		 * Check for any peer messages for DCAP_CHG etc
+		 * Check for any peer messages for DCAP_CHG, MSC etc
 		 * Dispatch to have the CBUS module working only
 		 * once connected.
-		mhl_cbus_isr(mhl_ctrl);
 		 */
+		mhl_cbus_isr(mhl_ctrl);
 		mhl_hpd_stat_isr(mhl_ctrl);
 	}
 
@@ -1296,6 +1635,59 @@
 	 * such tx specific
 	 */
 	mhl_ctrl->disc_enabled = false;
+	INIT_WORK(&mhl_ctrl->mhl_msc_send_work, mhl_msc_send_work);
+	mhl_ctrl->cur_state = POWER_STATE_D0_MHL;
+	INIT_LIST_HEAD(&mhl_ctrl->list_cmd);
+	init_completion(&mhl_ctrl->msc_cmd_done);
+	mhl_ctrl->msc_send_workqueue = create_singlethread_workqueue
+		("mhl_msc_cmd_queue");
+
+	mhl_ctrl->input = input_allocate_device();
+	if (mhl_ctrl->input) {
+		int i;
+		struct input_dev *input = mhl_ctrl->input;
+
+		mhl_ctrl->rcp_key_code_tbl = vmalloc(
+			ARRAY_SIZE(support_rcp_key_code_tbl));
+		if (!mhl_ctrl->rcp_key_code_tbl) {
+			pr_err("%s: no alloc mem for rcp keycode tbl\n",
+			       __func__);
+			return -ENOMEM;
+		}
+
+		memcpy(mhl_ctrl->rcp_key_code_tbl,
+		       &support_rcp_key_code_tbl[0],
+		       ARRAY_SIZE(support_rcp_key_code_tbl));
+		mhl_ctrl->rcp_key_code_tbl_len = ARRAY_SIZE(
+			support_rcp_key_code_tbl);
+
+		input->phys = "cbus/input0";
+		input->id.bustype = BUS_VIRTUAL;
+		input->id.vendor  = 0x1095;
+		input->id.product = 0x8334;
+		input->id.version = 0xA;
+
+		input->name = "mhl-rcp";
+
+		input->keycode = support_rcp_key_code_tbl;
+		input->keycodesize = sizeof(u16);
+		input->keycodemax = ARRAY_SIZE(support_rcp_key_code_tbl);
+
+		input->evbit[0] = EV_KEY;
+		for (i = 0; i < ARRAY_SIZE(support_rcp_key_code_tbl); i++) {
+			if (support_rcp_key_code_tbl[i] > 1)
+				input_set_capability(input, EV_KEY,
+					support_rcp_key_code_tbl[i]);
+		}
+
+		if (input_register_device(input) < 0) {
+			pr_warn("%s: failed to register input device\n",
+				__func__);
+			input_free_device(input);
+			mhl_ctrl->input = NULL;
+		}
+	}
+
 	rc = mhl_tx_chip_init(mhl_ctrl);
 	if (rc) {
 		pr_err("%s: tx chip init failed [%d]\n",
@@ -1315,7 +1707,7 @@
 				 client->dev.driver->name, mhl_ctrl);
 	if (rc) {
 		pr_err("request_threaded_irq failed, status: %d\n",
-			rc);
+		       rc);
 		goto failed_probe;
 	} else {
 		pr_debug("request_threaded_irq succeeded\n");
@@ -1353,6 +1745,8 @@
 		goto failed_probe;
 	}
 	mhl_ctrl->mhl_info = mhl_info;
+	mhl_register_msc(mhl_ctrl);
+	mhl_ctrl->tmds_enabled = check_tmds_enabled;
 	return 0;
 failed_probe:
 	mhl_gpio_config(mhl_ctrl, 0);
diff --git a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_properties.c b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_properties.c
index 95f4bf0..5cf2f9c 100644
--- a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_properties.c
+++ b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_properties.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2010-2013, Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -1115,14 +1115,21 @@
 				encoder->client_output_buf_req.sz/num_slices;
 				encoder->client_output_buf_req.sz =
 				DDL_ALIGN(output_buf_size, DDL_KILO_BYTE(4));
+				if (encoder->client_output_buf_req. \
+					actual_count < encoder-> \
+					client_output_buf_req.min_count) {
+					encoder->client_output_buf_req. \
+					actual_count = encoder-> \
+					client_output_buf_req.min_count;
+				}
 				encoder->output_buf_req =
 				encoder->client_output_buf_req;
-				DDL_MSG_HIGH("%s num_mb = %u num_slices = %u "
-				"output_buf_count = %u "
-				"output_buf_size = %u aligned size = %u\n",
+				DDL_MSG_HIGH("%s num_mb = %u num_slices = %u" \
+				" min_count = %u act_count = %u" \
+				" aligned size = %u\n",
 				__func__, num_mb, num_slices,
 				encoder->client_output_buf_req.min_count,
-				output_buf_size,
+				encoder->client_output_buf_req.actual_count,
 				encoder->client_output_buf_req.sz);
 				vcd_status = VCD_S_SUCCESS;
 			}
diff --git a/drivers/video/msm/vidc/common/vcd/vcd_client_sm.c b/drivers/video/msm/vidc/common/vcd/vcd_client_sm.c
index 983923b..884050b 100644
--- a/drivers/video/msm/vidc/common/vcd/vcd_client_sm.c
+++ b/drivers/video/msm/vidc/common/vcd/vcd_client_sm.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2010-2013, Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -1750,7 +1750,7 @@
 	 vcd_get_buffer_requirements_cmn,
 	 NULL,
 	 NULL,
-	 NULL,
+	 vcd_free_buffer_cmn,
 	 vcd_fill_output_buffer_cmn,
 	 vcd_clnt_cb_in_flushing,
 	 },
diff --git a/include/linux/coresight.h b/include/linux/coresight.h
index 0bdacffa..b167b44 100644
--- a/include/linux/coresight.h
+++ b/include/linux/coresight.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -30,7 +30,11 @@
 #define CORESIGHT_COMPIDR2	(0xFF8)
 #define CORESIGHT_COMPIDR3	(0xFFC)
 
+#define ETM_ARCH_V1_0		(0x00)
+#define ETM_ARCH_V1_2		(0x02)
 #define ETM_ARCH_V3_3		(0x23)
+#define ETM_ARCH_V3_5		(0x25)
+#define PFT_ARCH_MAJOR		(0x30)
 #define PFT_ARCH_V1_1		(0x31)
 
 enum coresight_clk_rate {
diff --git a/include/linux/diagchar.h b/include/linux/diagchar.h
index 43daaf2..4bd8885 100644
--- a/include/linux/diagchar.h
+++ b/include/linux/diagchar.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2008-2012, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2008-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -112,7 +112,7 @@
 /* This needs to be modified manually now, when we add
  a new RANGE of SSIDs to the msg_mask_tbl */
 #define MSG_MASK_TBL_CNT		24
-#define EVENT_LAST_ID			0x08C5
+#define EVENT_LAST_ID			0x099F
 
 #define MSG_SSID_0			0
 #define MSG_SSID_0_LAST			93
@@ -692,7 +692,7 @@
 /* LOG CODES */
 
 #define LOG_0	0x0
-#define LOG_1	0x1636
+#define LOG_1	0x1750
 #define LOG_2	0x0
 #define LOG_3	0x0
 #define LOG_4	0x4910
diff --git a/include/linux/mhl_8334.h b/include/linux/mhl_8334.h
index d3597dc..cb74b73 100644
--- a/include/linux/mhl_8334.h
+++ b/include/linux/mhl_8334.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -18,6 +18,7 @@
 #include <linux/platform_device.h>
 #include <mach/board.h>
 #include <linux/mhl_devcap.h>
+#include <linux/power_supply.h>
 #include <linux/mhl_defs.h>
 
 #define MHL_DEVICE_NAME "sii8334"
@@ -96,6 +97,65 @@
 	struct msc_command_struct* (*msc_command_get_work) (void);
 };
 
+#ifdef CONFIG_FB_MSM_MDSS_HDMI_MHL_SII8334
+enum mhl_gpio_type {
+	MHL_TX_RESET_GPIO,
+	MHL_TX_INTR_GPIO,
+	MHL_TX_PMIC_PWR_GPIO,
+	MHL_TX_MAX_GPIO,
+};
+
+enum mhl_vreg_type {
+	MHL_TX_3V_VREG,
+	MHL_TX_MAX_VREG,
+};
+
+
+struct mhl_tx_platform_data {
+	/* Data filled from device tree nodes */
+	struct dss_gpio *gpios[MHL_TX_MAX_GPIO];
+	struct dss_vreg *vregs[MHL_TX_MAX_VREG];
+	int irq;
+};
+
+struct mhl_tx_ctrl {
+	struct platform_device *pdev;
+	struct mhl_tx_platform_data *pdata;
+	struct i2c_client *i2c_handle;
+	uint8_t cur_state;
+	uint8_t chip_rev_id;
+	int mhl_mode;
+	struct completion rgnd_done;
+	void (*notify_usb_online)(int online);
+	struct usb_ext_notification *mhl_info;
+	bool disc_enabled;
+	struct power_supply mhl_psy;
+	bool vbus_active;
+	int current_val;
+	struct completion msc_cmd_done;
+	uint8_t devcap[16];
+	uint8_t devcap_state;
+	uint8_t path_en_state;
+	uint8_t (*tmds_enabled)(void);
+	struct work_struct mhl_msc_send_work;
+	struct list_head list_cmd;
+	struct input_dev *input;
+	struct workqueue_struct *msc_send_workqueue;
+	u16 *rcp_key_code_tbl;
+	size_t rcp_key_code_tbl_len;
+};
+
+int mhl_i2c_reg_read(struct i2c_client *client,
+		     uint8_t slave_addr_index, uint8_t reg_offset);
+int mhl_i2c_reg_write(struct i2c_client *client,
+		      uint8_t slave_addr_index, uint8_t reg_offset,
+		      uint8_t value);
+void mhl_i2c_reg_modify(struct i2c_client *client,
+			uint8_t slave_addr_index, uint8_t reg_offset,
+			uint8_t mask, uint8_t val);
+
+#endif /* CONFIG_FB_MSM_MDSS_HDMI_MHL_SII8334 */
+
 enum {
 	TX_PAGE_TPI          = 0x00,
 	TX_PAGE_L0           = 0x01,
@@ -204,6 +264,7 @@
 
 #define REG_TMDS_CSTAT	((TX_PAGE_3 << 16) | 0x0040)
 
+#define REG_CBUS_INTR_STATUS            ((TX_PAGE_CBUS << 16) | 0x0008)
 #define REG_CBUS_INTR_ENABLE            ((TX_PAGE_CBUS << 16) | 0x0009)
 
 #define REG_DDC_ABORT_REASON            ((TX_PAGE_CBUS << 16) | 0x000B)
diff --git a/include/linux/mhl_defs.h b/include/linux/mhl_defs.h
index 062bdf9..f23be79 100644
--- a/include/linux/mhl_defs.h
+++ b/include/linux/mhl_defs.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -149,6 +149,7 @@
 
 #define MHL_RCPE_NO_ERROR			0x00
 #define MHL_RCPE_UNSUPPORTED_KEY_CODE		0x01
+#define MHL_RCPE_INEFFECTIVE_KEY_CODE		0x01
 #define MHL_RCPE_BUSY				0x02
 
 #define MHL_RAPK_NO_ERROR			0x00
@@ -156,6 +157,8 @@
 #define MHL_RAPK_UNSUPPORTED_ACTION_CODE	0x02
 #define MHL_RAPK_BUSY				0x03
 
+#define T_ABORT_NEXT                    (2050)
+
 /* MHL spec related defines*/
 enum {
 	/* Command or Data byte acknowledge */
@@ -196,6 +199,8 @@
 	MHL_GET_SC3_ERRORCODE		= 0x6D,
 };
 
+/* Polling. */
+#define MHL_RAP_POLL                    0x00
 /* Turn content streaming ON. */
 #define	MHL_RAP_CONTENT_ON		0x10
 /* Turn content streaming OFF. */
diff --git a/include/linux/mmc/card.h b/include/linux/mmc/card.h
index a2405cf..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,
 };
 
@@ -264,17 +265,26 @@
  * @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_delay_ms;
 	unsigned int		delay_ms;
-	struct mmc_bkops_stats  bkops_stats;    /* BKOPS statistics */
+	unsigned int		min_sectors_to_queue_delayed_work;
+	unsigned int		size_percentage_to_queue_delayed_work;
+	struct mmc_bkops_stats  bkops_stats;
 /*
  * A default time for checking the need for non urgent BKOPS once mmcqd
  * is idle.
@@ -285,7 +295,15 @@
 #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
+ * performance of small requests we won't queue the delayed work every time
+ * mmcqd thread is idle.
+ * The delayed work for idle BKOPS will be scheduled only after a significant
+ * amount of write or discard data.
+ */
+#define BKOPS_SIZE_PERCENTAGE_TO_QUEUE_DELAYED_WORK 1 /* 1% */
 };
 
 /**
@@ -336,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 */
@@ -510,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)
@@ -523,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/host.h b/include/linux/mmc/host.h
index 6982c45..f9e0627 100644
--- a/include/linux/mmc/host.h
+++ b/include/linux/mmc/host.h
@@ -315,6 +315,7 @@
 
 	struct delayed_work	detect;
 	struct wake_lock	detect_wake_lock;
+	const char		*wlock_name;
 	int			detect_change;	/* card detect flag */
 	struct mmc_hotplug	hotplug;
 
diff --git a/include/linux/msm_ion.h b/include/linux/msm_ion.h
index d423b26..14492ea 100644
--- a/include/linux/msm_ion.h
+++ b/include/linux/msm_ion.h
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright (c) 2012, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
  *
  * This software is licensed under the terms of the GNU General Public
  * License version 2, as published by the Free Software Foundation, and
@@ -75,6 +75,13 @@
 #define ION_SECURE (1 << ION_HEAP_ID_RESERVED)
 
 /**
+ * Flag for clients to force contiguous memort allocation
+ *
+ * Use of this flag is carefully monitored!
+ */
+#define ION_FORCE_CONTIGUOUS (1 << 30)
+
+/**
  * Macro should be used with ion_heap_ids defined above.
  */
 #define ION_HEAP(bit) (1 << (bit))
diff --git a/include/linux/usb/msm_hsusb.h b/include/linux/usb/msm_hsusb.h
index bb2380e..9240277 100644
--- a/include/linux/usb/msm_hsusb.h
+++ b/include/linux/usb/msm_hsusb.h
@@ -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;
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/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/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));