Merge "usb: ks_bridge: Fix bug in partial read on data buffer"
diff --git a/Documentation/devicetree/bindings/media/video/msm-wfd.txt b/Documentation/devicetree/bindings/media/video/msm-wfd.txt
new file mode 100644
index 0000000..0cd8c9d
--- /dev/null
+++ b/Documentation/devicetree/bindings/media/video/msm-wfd.txt
@@ -0,0 +1,11 @@
+* Qualcomm MSM Wifi Display (WFD)
+
+Required properties:
+- compatible :
+	- "qcom,msm-wfd"
+
+Example:
+
+	qcom,wfd {
+		compatible = "qcom,msm-wfd";
+	};
diff --git a/Documentation/devicetree/bindings/power/qpnp-charger.txt b/Documentation/devicetree/bindings/power/qpnp-charger.txt
new file mode 100644
index 0000000..244e622
--- /dev/null
+++ b/Documentation/devicetree/bindings/power/qpnp-charger.txt
@@ -0,0 +1,209 @@
+Qualcomm QPNP Charger
+
+The charger supports the switch mode battery charger and boost (SMBB)
+peripherals on Qualcomm PMIC chips.
+
+There are seven different peripherals adding the following functionality.
+Each of these peripherals are implemented as subnodes in the example at the
+end of this file.
+
+- qcom,chg-chgr:	Supports charging control and status
+			reporting.
+- qcom,chg-bat-if:	Battery status reporting such as presence,
+			temperature reporting and voltage collapse
+			protection.
+- qcom,chg-buck:	Charger buck configuration and status
+			reporting with regards to several regulation
+			loops such as vdd, ibat etc.
+- qcom,usb-chgpth:	USB charge path detection and input current
+			limiting configuration.
+- qcom,dc-chgpth:	DC charge path detection and input current
+			limiting configuration.
+- qcom,chg-misc:	Miscellaneous features such as buck frequency
+			settings, comparator override features etc.
+
+Parent node required properties:
+- qcom,chg-vddmax-mv:	Target voltage of battery in mV
+- qcom,chg-vddsafe-mv:	Maximum Vdd voltage in mV
+- qcom,chg-vinmin-mv:	Minimum input voltage in mV
+- qcom,chg-ibatmax-ma:	Maximum battery charge current in mA
+- qcom,chg-ibatterm-ma:	Current at which charging is terminated in mA.
+
+Sub node required structure:
+- A qcom,chg node must be a child of an SPMI node that has specified
+	the spmi-dev-container property. Each subnode reflects
+	a hardware peripheral which adds a unique set of features
+	to the collective charging device. For example USB detection
+	and the battery interface are each seperate peripherals and
+	each should be their own subnode.
+
+Sub node required properties:
+- compatible:		Must be "qcom,charger".
+- reg:			Specifies the SPMI address and size for this peripheral.
+- interrupts:		Specifies the interrupt associated with the peripheral.
+- interrupt-names:	Specifies the interrupt names for the peripheral. Every
+			available interrupt needs to have an associated name
+			with it to indentify its purpose.
+
+			The following lists each subnode and their corresponding
+			required interrupt names:
+
+			qcom,usb-chgpth:
+			 - usbin-valid
+			qcom,chg-chgr:
+			 - chg-done
+			 - chg-failed
+
+			The following interrupts are available:
+
+			qcom,chg-chgr:
+			 - chg-done:		Triggers on charge completion.
+			 - chg-failed:		Notifies of charge failures.
+			 - fast-chg-on:		Notifies of fast charging state.
+			 - trkl-chg-on:		Indicates trickle charging.
+			 - state-change:	Notifies of a state change in
+						the charger state machine.
+			 - chgwdog:		Charger watchdog interrupt.
+			 - vbat-det-hi:		Triggers on vbat-det-hi voltage
+						setting,can be used as
+						battery alarm.
+			 - vbat-det-hi:		Triggers on vbat-det-low voltage
+						setting, can be used as
+						battery alarm.
+
+			qcom,chg-buck:
+			 - vdd-loop:		VDD loop change interrupt.
+			 - ibat-loop:		Ibat loop change interrupt.
+			 - ichg-loop:		Charge current loop change.
+			 - vchg-loop:		Charge voltage loop change.
+			 - overtemp:		Overtemperature interrupt.
+			 - vref-ov:		Reference overvoltage interrupt.
+			 - vbat-ov:		Battery overvoltage interrupt.
+
+			qcom,chg-bat-if:
+			 - psi:			PMIC serial interface interrupt.
+			 - vcp-on:		Voltage collapse protection
+						status interrupt.
+			 - bat-fet-on:		BATFET status interrupt.
+			 - bat-temp-ok:		Battery temperature status
+						interrupt.
+			 - batt-pres:		Battery presence status
+						interrupt.
+
+			qcom,usb-chgpth:
+			 - usbin-valid:		Indicates valid USB connection.
+			 - coarse-det-usb:	Coarse detect interrupt triggers
+						at low voltage on USB_IN.
+			 - chg-gone:		Triggers on VCHG line.
+
+			qcom,dc-chgpth:
+			 - dcin-valid:		Indicates a valid DC charger
+						connection.
+			 - coarse-det-dc:	Coarse detect interrupt triggers
+						at low voltage on DC_IN.
+
+			qcom,boost:
+			 - limit-error:		Limiting error on SMBB boost.
+			 - boost-pwr-ok:	Status of boost power.
+
+Example:
+	pm8941-chg {
+		spmi-dev-container;
+		compatible = "qcom,charger";
+		#address-cells = <1>;
+		#size-cells = <1>;
+
+		qcom,chg-vddmax-mv = <4200>;
+		qcom,chg-vddsafe-mv = <4200>;
+		qcom,chg-vinmin-mv = <4200>;
+		qcom,chg-ibatmax-mv = <1500>;
+		qcom,chg-ibatterm-mv = <200>;
+
+		qcom,chg-chgr@1000 {
+			reg = <0x1000 0x100>;
+			interrupts =	<0x0 0x10 0x0>,
+				<0x0 0x10 0x1>,
+					<0x0 0x10 0x2>,
+					<0x0 0x10 0x3>,
+					<0x0 0x10 0x4>,
+					<0x0 0x10 0x5>,
+					<0x0 0x10 0x6>,
+					<0x0 0x10 0x7>;
+
+			interrupt-names =	"chg-done",
+						"chg-failed",
+						"fast-chg-on",
+						"trkl-chg-on",
+						"state-change",
+						"chgwdog",
+						"vbat-det-hi",
+						"vbat-det-lo";
+		};
+
+		qcom,chg-buck@1100 {
+			reg = <0x1100 0x100>;
+			interrupts =	<0x0 0x11 0x0>,
+					<0x0 0x11 0x1>,
+					<0x0 0x11 0x2>,
+					<0x0 0x11 0x3>,
+					<0x0 0x11 0x4>,
+					<0x0 0x11 0x5>,
+					<0x0 0x11 0x6>;
+
+			interrupt-names =	"vdd-loop",
+						"ibat-loop",
+						"ichg-loop",
+						"vchg-loop",
+						"overtemp",
+						"vref-ov",
+						"vbat-ov";
+		};
+
+		qcom,chg-bat-if@1200 {
+			reg = <0x1200 0x100>;
+			interrupts =	<0x0 0x12 0x0>,
+					<0x0 0x12 0x1>,
+					<0x0 0x12 0x2>,
+					<0x0 0x12 0x3>,
+					<0x0 0x12 0x4>;
+
+			interrupt-names =	"psi",
+						"vcp-on",
+						"bat-fet-on",
+						"bat-temp-ok",
+						"batt-pres";
+		};
+
+		qcom,chg-usb-chgpth@1300 {
+			reg = <0x1300 0x100>;
+			interrupts =	<0 0x13 0x0>,
+					<0 0x13 0x1>,
+					<0x0 0x13 0x2>;
+
+			interrupt-names =	"usbin-valid",
+						"coarse-det-usb",
+						"chg-gone";
+		};
+
+		qcom,chg-dc-chgpth@1400 {
+			reg = <0x1400 0x100>;
+			interrupts =	<0x0 0x14 0x0>,
+					<0x0 0x14 0x1>;
+
+			interrupt-names =	"dcin-valid",
+						"coarse-det-dc";
+		};
+
+		qcom,chg-boost@1500 {
+			reg = <0x1500 0x100>;
+			interrupts =	<0x0 0x15 0x0>,
+					<0x0 0x15 0x1>;
+
+			interrupt-names =	"limit-error",
+						"boost-pwr-ok";
+		};
+
+		qcom,chg-misc@1600 {
+			reg = <0x1600 0x100>;
+		};
+	};
diff --git a/arch/arm/boot/dts/msm-pm8941.dtsi b/arch/arm/boot/dts/msm-pm8941.dtsi
index 869a357..8560f9f 100644
--- a/arch/arm/boot/dts/msm-pm8941.dtsi
+++ b/arch/arm/boot/dts/msm-pm8941.dtsi
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -49,6 +49,41 @@
 			};
 		};
 
+		bms@4000 {
+			#address-cells = <1>;
+			#size-cells = <1>;
+
+			compatible = "qcom,qpnp-bms";
+			reg = <0x4000 0x100>;
+
+			interrupts =	<0x0 0x40 0x0>,
+					<0x0 0x40 0x1>,
+					<0x0 0x40 0x2>,
+					<0x0 0x40 0x3>,
+					<0x0 0x40 0x4>,
+					<0x0 0x40 0x5>,
+					<0x0 0x40 0x6>,
+					<0x0 0x40 0x7>;
+
+			interrupt-names = "vsense_for_r",
+					  "vsense_avg",
+					  "sw_cc_thr",
+					  "ocv_thr",
+					  "charge_begin",
+					  "good_ocv",
+					  "ocv_for_r",
+					  "cc_thr";
+
+			qcom,bms-r-sense-mohm = <10>;
+			qcom,bms-v-cutoff-uv = <3400000>;
+			qcom,bms-max-voltage-uv = <4200000>;
+			qcom,bms-r-conn-mohm = <18>;
+			qcom,bms-shutdown-soc-valid-limit = <20>;
+			qcom,bms-adjust-soc-low-threshold = <25>;
+			qcom,bms-adjust-soc-high-threshold = <45>;
+			qcom,bms-chg-term-ua = <100000>;
+		};
+
 		clkdiv@5b00 {
 			reg = <0x5b00 0x100>;
 			compatible = "qcom,qpnp-clkdiv";
diff --git a/arch/arm/boot/dts/msm8974-camera.dtsi b/arch/arm/boot/dts/msm8974-camera.dtsi
index c92188a..010b2da 100644
--- a/arch/arm/boot/dts/msm8974-camera.dtsi
+++ b/arch/arm/boot/dts/msm8974-camera.dtsi
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2012, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -222,7 +222,7 @@
 			compatible = "qcom,ov2720";
 			reg = <0x6c 0x0>;
 			qcom,csi-if = <1>;
-			qcom,csid-core = <1>;
+			qcom,csid-core = <0>;
 			qcom,is-vpe = <1>;
 			qcom,flash-type = <0>;
 			qcom,mount-angle = <0>;
diff --git a/arch/arm/boot/dts/msm8974-mtp.dts b/arch/arm/boot/dts/msm8974-mtp.dts
index d3e0bc3..ed89368 100644
--- a/arch/arm/boot/dts/msm8974-mtp.dts
+++ b/arch/arm/boot/dts/msm8974-mtp.dts
@@ -18,7 +18,7 @@
 / {
 	model = "Qualcomm MSM 8974 MTP";
 	compatible = "qcom,msm8974-mtp", "qcom,msm8974";
-	qcom,msm-id = <126 8 0>;
+	qcom,msm-id = <126 8 0>, <126 3 0>;
 
 	serial@f991e000 {
 		status = "ok";
diff --git a/arch/arm/boot/dts/msm8974.dtsi b/arch/arm/boot/dts/msm8974.dtsi
index da0e1e5..0a4cdcb 100644
--- a/arch/arm/boot/dts/msm8974.dtsi
+++ b/arch/arm/boot/dts/msm8974.dtsi
@@ -306,7 +306,6 @@
 		qcom,audio-routing =
 			"RX_BIAS", "MCLK",
 			"LDO_H", "MCLK",
-			"HEADPHONE", "LDO_H",
 			"Ext Spk Bottom Pos", "LINEOUT1",
 			"Ext Spk Bottom Neg", "LINEOUT3",
 			"Ext Spk Top Pos", "LINEOUT2",
diff --git a/arch/arm/boot/dts/msm8974_pm.dtsi b/arch/arm/boot/dts/msm8974_pm.dtsi
index 8e3f4b8..77f2532 100644
--- a/arch/arm/boot/dts/msm8974_pm.dtsi
+++ b/arch/arm/boot/dts/msm8974_pm.dtsi
@@ -385,8 +385,8 @@
 			<40  95>;
 	};
 
-	qcom,pc-cntr@fe800000 {
+	qcom,pc-cntr@fe805664 {
 		compatible = "qcom,pc-cntr";
-		reg = <0xfe800664 0x40>;
+		reg = <0xfe805664 0x40>;
 	};
 };
diff --git a/arch/arm/configs/fsm9xxx-perf_defconfig b/arch/arm/configs/fsm9xxx-perf_defconfig
index 4ba55de..93e84e9 100644
--- a/arch/arm/configs/fsm9xxx-perf_defconfig
+++ b/arch/arm/configs/fsm9xxx-perf_defconfig
@@ -39,6 +39,9 @@
 # CONFIG_QSD_AUDIO is not set
 # CONFIG_SURF_FFA_GPIO_KEYPAD is not set
 CONFIG_MSM_WATCHDOG=y
+CONFIG_MSM_RPC_PMIC=y
+CONFIG_MSM_RPC_USB=y
+CONFIG_MSM_RPC_PMAPP=y
 CONFIG_NO_HZ=y
 CONFIG_HIGH_RES_TIMERS=y
 CONFIG_VMSPLIT_2G=y
diff --git a/arch/arm/configs/fsm9xxx_defconfig b/arch/arm/configs/fsm9xxx_defconfig
index ad1b6a6..c45063f 100644
--- a/arch/arm/configs/fsm9xxx_defconfig
+++ b/arch/arm/configs/fsm9xxx_defconfig
@@ -38,6 +38,9 @@
 # CONFIG_QSD_AUDIO is not set
 # CONFIG_SURF_FFA_GPIO_KEYPAD is not set
 CONFIG_MSM_WATCHDOG=y
+CONFIG_MSM_RPC_PMIC=y
+CONFIG_MSM_RPC_USB=y
+CONFIG_MSM_RPC_PMAPP=y
 CONFIG_NO_HZ=y
 CONFIG_HIGH_RES_TIMERS=y
 CONFIG_VMSPLIT_2G=y
diff --git a/arch/arm/configs/msm7627a-perf_defconfig b/arch/arm/configs/msm7627a-perf_defconfig
index 7f10641..9a0bfba 100644
--- a/arch/arm/configs/msm7627a-perf_defconfig
+++ b/arch/arm/configs/msm7627a-perf_defconfig
@@ -55,6 +55,9 @@
 CONFIG_MSM_MULTIMEDIA_USE_ION=y
 CONFIG_MSM_CPR=y
 CONFIG_MSM_VP_REGULATOR=y
+CONFIG_MSM_RPC_PMIC=y
+CONFIG_MSM_RPC_USB=y
+CONFIG_MSM_RPC_PMAPP=y
 CONFIG_ARM_THUMBEE=y
 CONFIG_NO_HZ=y
 CONFIG_HIGH_RES_TIMERS=y
diff --git a/arch/arm/configs/msm7627a_defconfig b/arch/arm/configs/msm7627a_defconfig
index 0e0653f..60a2d72 100644
--- a/arch/arm/configs/msm7627a_defconfig
+++ b/arch/arm/configs/msm7627a_defconfig
@@ -57,6 +57,9 @@
 CONFIG_MSM_RTB_SEPARATE_CPUS=y
 CONFIG_MSM_CPR=y
 CONFIG_MSM_VP_REGULATOR=y
+CONFIG_MSM_RPC_PMIC=y
+CONFIG_MSM_RPC_USB=y
+CONFIG_MSM_RPC_PMAPP=y
 CONFIG_ARM_THUMBEE=y
 CONFIG_NO_HZ=y
 CONFIG_HIGH_RES_TIMERS=y
diff --git a/arch/arm/configs/msm7630-perf_defconfig b/arch/arm/configs/msm7630-perf_defconfig
index 1bf888b..401654d 100644
--- a/arch/arm/configs/msm7630-perf_defconfig
+++ b/arch/arm/configs/msm7630-perf_defconfig
@@ -44,6 +44,9 @@
 CONFIG_MSM_IDLE_WAIT_ON_MODEM=2000
 CONFIG_MSM_STANDALONE_POWER_COLLAPSE=y
 CONFIG_MSM_MULTIMEDIA_USE_ION=y
+CONFIG_MSM_RPC_PMIC=y
+CONFIG_MSM_RPC_USB=y
+CONFIG_MSM_RPC_PMAPP=y
 CONFIG_NO_HZ=y
 CONFIG_HIGH_RES_TIMERS=y
 CONFIG_PREEMPT=y
@@ -278,6 +281,7 @@
 CONFIG_FB_MSM_MDP40=y
 CONFIG_FB_MSM_OVERLAY=y
 CONFIG_FB_MSM_OVERLAY0_WRITEBACK=y
+CONFIG_FB_MSM_NO_MDP_PIPE_CTRL=y
 CONFIG_FB_MSM_TRY_MDDI_CATCH_LCDC_PRISM=y
 CONFIG_FB_MSM_HDMI_ADV7520_PANEL=y
 CONFIG_BACKLIGHT_LCD_SUPPORT=y
diff --git a/arch/arm/configs/msm7630_defconfig b/arch/arm/configs/msm7630_defconfig
index 5c5a152..0e066d9 100644
--- a/arch/arm/configs/msm7630_defconfig
+++ b/arch/arm/configs/msm7630_defconfig
@@ -44,6 +44,9 @@
 CONFIG_MSM_IDLE_WAIT_ON_MODEM=2000
 CONFIG_MSM_STANDALONE_POWER_COLLAPSE=y
 CONFIG_MSM_MULTIMEDIA_USE_ION=y
+CONFIG_MSM_RPC_PMIC=y
+CONFIG_MSM_RPC_USB=y
+CONFIG_MSM_RPC_PMAPP=y
 CONFIG_STRICT_MEMORY_RWX=y
 CONFIG_NO_HZ=y
 CONFIG_HIGH_RES_TIMERS=y
diff --git a/arch/arm/configs/msm8960_defconfig b/arch/arm/configs/msm8960_defconfig
index 4c9383d..0758ede 100644
--- a/arch/arm/configs/msm8960_defconfig
+++ b/arch/arm/configs/msm8960_defconfig
@@ -513,6 +513,7 @@
 CONFIG_FAULT_INJECTION_STACKTRACE_FILTER=y
 CONFIG_DEBUG_PAGEALLOC=y
 CONFIG_ENABLE_DEFAULT_TRACERS=y
+CONFIG_CPU_FREQ_SWITCH_PROFILER=y
 CONFIG_DYNAMIC_DEBUG=y
 CONFIG_DEBUG_USER=y
 CONFIG_PID_IN_CONTEXTIDR=y
diff --git a/arch/arm/configs/msm8974_defconfig b/arch/arm/configs/msm8974_defconfig
index 7e3aad7..a160d5f 100644
--- a/arch/arm/configs/msm8974_defconfig
+++ b/arch/arm/configs/msm8974_defconfig
@@ -74,6 +74,8 @@
 CONFIG_MSM_L2_ERP_1BIT_PANIC=y
 CONFIG_MSM_L2_ERP_2BIT_PANIC=y
 CONFIG_STRICT_MEMORY_RWX=y
+CONFIG_MSM_CACHE_DUMP=y
+CONFIG_MSM_CACHE_DUMP_ON_PANIC=y
 CONFIG_NO_HZ=y
 CONFIG_HIGH_RES_TIMERS=y
 CONFIG_SMP=y
@@ -274,6 +276,7 @@
 # CONFIG_BATTERY_MSM is not set
 CONFIG_SENSORS_QPNP_ADC_VOLTAGE=y
 CONFIG_SENSORS_QPNP_ADC_CURRENT=y
+CONFIG_QPNP_BMS=y
 CONFIG_THERMAL=y
 CONFIG_THERMAL_TSENS8974=y
 CONFIG_WCD9320_CODEC=y
@@ -404,6 +407,7 @@
 CONFIG_FAULT_INJECTION_STACKTRACE_FILTER=y
 CONFIG_DEBUG_PAGEALLOC=y
 CONFIG_ENABLE_DEFAULT_TRACERS=y
+CONFIG_CPU_FREQ_SWITCH_PROFILER=y
 CONFIG_DYNAMIC_DEBUG=y
 CONFIG_DEBUG_USER=y
 CONFIG_PID_IN_CONTEXTIDR=y
diff --git a/arch/arm/mach-msm/cp14.h b/arch/arm/include/asm/hardware/cp14.h
similarity index 99%
rename from arch/arm/mach-msm/cp14.h
rename to arch/arm/include/asm/hardware/cp14.h
index d640412..8acf0c7 100644
--- a/arch/arm/mach-msm/cp14.h
+++ b/arch/arm/include/asm/hardware/cp14.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2011-2012, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -10,8 +10,8 @@
  * GNU General Public License for more details.
  */
 
-#ifndef _ARCH_ARM_MACH_MSM_CP14_H_
-#define _ARCH_ARM_MACH_MSM_CP14_H_
+#ifndef __ASM_HARDWARE_CP14_H
+#define __ASM_HARDWARE_CP14_H
 
 #include <linux/types.h>
 
diff --git a/arch/arm/mach-msm/Kconfig b/arch/arm/mach-msm/Kconfig
index c9b786c..6df6e13 100644
--- a/arch/arm/mach-msm/Kconfig
+++ b/arch/arm/mach-msm/Kconfig
@@ -2052,6 +2052,15 @@
 	 restarts the adsp or the 8974 when the adsp encounters a fatal error,
 	 depending on the restart level selected in the subsystem restart driver.
 
+config MSM_WCNSS_SSR_8974
+	tristate "MSM 8974 WCNSS restart module"
+	depends on (ARCH_MSM8974)
+	help
+	 This option enables the WCNSS restart module for MSM8974. It monitors
+	 WCNSS SMSM status bits and WCNSS hardware watchdog interrupt line; and
+	 depending on the restart level, it will restart WCNSS when a fatal error
+	 occurs at WCNSS.
+
 config SCORPION_Uni_45nm_BUG
 	bool "Scorpion Uni 45nm(SC45U): Workaround for ICIMVAU and BPIMVA"
 	depends on ARCH_MSM7X30 || (ARCH_QSD8X50 && MSM_SOC_REV_A)
@@ -2607,4 +2616,31 @@
 	  can be read and written to send character data to the sysmon port of
 	  the modem over USB.
 
+config MSM_RPC_PMIC
+	tristate "MSM RPC PMIC driver"
+	depends on MSM_ONCRPCROUTER
+	help
+	 This driver supports the PMIC functionality over RPC for those MSM's
+	 which do not have a direct access to PMIC. It supports ability to
+	 configure MPP, GPIO and all the other supported peripherals of the
+	 PMIC.
+
+config MSM_RPC_USB
+	tristate "MSM RPC USB driver"
+	depends on MSM_ONCRPCROUTER
+	help
+	 This driver supports the USB configuration support over the RPC
+	 interface. It support the HS USB module connected to the MSM
+	 and FS USB which is connected over the PMIC. This support is
+	 required for MSMs on which the APPS does not have a direct access
+	 to the PMIC.
+
+config MSM_RPC_PMAPP
+	tristate "MSM RPC PMIC APP driver"
+	depends on MSM_ONCRPCROUTER
+	help
+	 This driver supports the configuration of various PMIC APP modules
+	 such as display backlight, vreg pin-ctrl, smps clock over the RPC
+	 interface. This support is required for MSMs on which the APPS
+	 does not have a direct access to the PMIC.
 endif
diff --git a/arch/arm/mach-msm/Makefile b/arch/arm/mach-msm/Makefile
index d8e625a..3c44a06 100644
--- a/arch/arm/mach-msm/Makefile
+++ b/arch/arm/mach-msm/Makefile
@@ -98,20 +98,6 @@
 endif
 obj-$(CONFIG_MSM_SMD) += smd.o smd_debug.o remote_spinlock.o smd_private.o
 obj-y += socinfo.o
-ifndef CONFIG_ARCH_MSM9615
-ifndef CONFIG_ARCH_APQ8064
-ifndef CONFIG_ARCH_MSM8960
-ifndef CONFIG_ARCH_MSM8X60
-ifndef CONFIG_ARCH_MSM8974
-ifndef CONFIG_ARCH_MPQ8092
-	obj-$(CONFIG_MSM_SMD) += pmic.o
-	obj-$(CONFIG_MSM_ONCRPCROUTER) += rpc_hsusb.o rpc_pmapp.o rpc_fsusb.o
-endif
-endif
-endif
-endif
-endif
-endif
 ifndef CONFIG_ARCH_MSM8960
 ifndef CONFIG_ARCH_MSM8X60
 ifndef CONFIG_ARCH_APQ8064
@@ -393,6 +379,10 @@
 obj-$(CONFIG_MSM_RPM_SMD) += rpm-smd.o
 obj-$(CONFIG_MSM_CPR) += msm_cpr.o
 obj-$(CONFIG_MSM_VP_REGULATOR) += msm_vp.o
+obj-$(CONFIG_MSM_RPC_PMIC) += pmic.o
+obj-$(CONFIG_MSM_RPC_USB) += rpc_hsusb.o rpc_fsusb.o
+obj-$(CONFIG_MSM_RPC_PMAPP) += rpc_pmapp.o
+
 
 ifdef CONFIG_MSM_CPR
 obj-$(CONFIG_DEBUG_FS) += msm_cpr-debug.o
diff --git a/arch/arm/mach-msm/acpuclock-7627.c b/arch/arm/mach-msm/acpuclock-7627.c
index 1a2ae48..5c4a923 100644
--- a/arch/arm/mach-msm/acpuclock-7627.c
+++ b/arch/arm/mach-msm/acpuclock-7627.c
@@ -32,13 +32,13 @@
 
 #include <mach/board.h>
 #include <mach/msm_iomap.h>
+#include <mach/clk-provider.h>
 #include <mach/socinfo.h>
 #include <asm/mach-types.h>
 #include <asm/cpu.h>
 
 #include "smd_private.h"
 #include "acpuclock.h"
-#include "clock.h"
 
 #define A11S_CLK_CNTL_ADDR (MSM_CSR_BASE + 0x100)
 #define A11S_CLK_SEL_ADDR (MSM_CSR_BASE + 0x104)
@@ -719,6 +719,7 @@
 				 */
 				clk_enable(pll_clk[backup_s->pll].clk);
 				acpuclk_set_div(backup_s);
+				update_jiffies(cpu, backup_s->lpj);
 			}
 			/* Make sure PLL4 is off before reprogramming */
 			if ((plls_enabled & (1 << tgt_s->pll))) {
@@ -736,6 +737,7 @@
 				 */
 				clk_enable(pll_clk[backup_s->pll].clk);
 				acpuclk_set_div(backup_s);
+				update_jiffies(cpu, backup_s->lpj);
 			}
 		}
 
diff --git a/arch/arm/mach-msm/acpuclock-7x30.c b/arch/arm/mach-msm/acpuclock-7x30.c
index b49613e..5b947e6 100644
--- a/arch/arm/mach-msm/acpuclock-7x30.c
+++ b/arch/arm/mach-msm/acpuclock-7x30.c
@@ -32,7 +32,6 @@
 #include <asm/mach-types.h>
 
 #include "smd_private.h"
-#include "clock.h"
 #include "acpuclock.h"
 #include "spm.h"
 
diff --git a/arch/arm/mach-msm/board-8064.c b/arch/arm/mach-msm/board-8064.c
index 8755f08..07acac6 100644
--- a/arch/arm/mach-msm/board-8064.c
+++ b/arch/arm/mach-msm/board-8064.c
@@ -78,6 +78,7 @@
 
 #include "msm_watchdog.h"
 #include "board-8064.h"
+#include "clock.h"
 #include "spm.h"
 #include <mach/mpm.h>
 #include "rpm_resources.h"
diff --git a/arch/arm/mach-msm/board-8226.c b/arch/arm/mach-msm/board-8226.c
index c845a3a..9545c7a 100644
--- a/arch/arm/mach-msm/board-8226.c
+++ b/arch/arm/mach-msm/board-8226.c
@@ -40,6 +40,7 @@
 #include <mach/msm_memtypes.h>
 #include <mach/socinfo.h>
 #include <mach/board.h>
+#include <mach/clk-provider.h>
 #include "clock.h"
 
 static struct clk_lookup msm_clocks_dummy[] = {
diff --git a/arch/arm/mach-msm/board-8930.c b/arch/arm/mach-msm/board-8930.c
index aad0f3d..ab35948 100644
--- a/arch/arm/mach-msm/board-8930.c
+++ b/arch/arm/mach-msm/board-8930.c
@@ -96,6 +96,7 @@
 #include <mach/cpuidle.h>
 #include "rpm_resources.h"
 #include <mach/mpm.h>
+#include "clock.h"
 #include "smd_private.h"
 #include "pm-boot.h"
 #include "msm_watchdog.h"
diff --git a/arch/arm/mach-msm/board-8960-pmic.c b/arch/arm/mach-msm/board-8960-pmic.c
index 244125c..ae74285 100644
--- a/arch/arm/mach-msm/board-8960-pmic.c
+++ b/arch/arm/mach-msm/board-8960-pmic.c
@@ -249,8 +249,8 @@
 static const unsigned int keymap[] = {
 	KEY(0, 0, KEY_VOLUMEUP),
 	KEY(0, 1, KEY_VOLUMEDOWN),
-	KEY(0, 2, KEY_CAMERA_SNAPSHOT),
-	KEY(0, 3, KEY_CAMERA_FOCUS),
+	KEY(0, 2, KEY_CAMERA_FOCUS),
+	KEY(0, 3, KEY_CAMERA_SNAPSHOT),
 };
 
 static struct matrix_keymap_data keymap_data = {
diff --git a/arch/arm/mach-msm/board-8960.c b/arch/arm/mach-msm/board-8960.c
index 06efc03..8ed9666 100644
--- a/arch/arm/mach-msm/board-8960.c
+++ b/arch/arm/mach-msm/board-8960.c
@@ -98,6 +98,7 @@
 #include <mach/cpuidle.h>
 #include "rpm_resources.h"
 #include <mach/mpm.h>
+#include "clock.h"
 #include "smd_private.h"
 #include "pm-boot.h"
 #include "msm_watchdog.h"
diff --git a/arch/arm/mach-msm/board-9615.c b/arch/arm/mach-msm/board-9615.c
index 4523cf7..ca95b62 100644
--- a/arch/arm/mach-msm/board-9615.c
+++ b/arch/arm/mach-msm/board-9615.c
@@ -50,6 +50,7 @@
 #include "devices.h"
 #include "board-9615.h"
 #include "pm.h"
+#include "clock.h"
 #include "pm-boot.h"
 #include <mach/gpiomux.h>
 #include "ci13xxx_udc.h"
diff --git a/arch/arm/mach-msm/board-9625.c b/arch/arm/mach-msm/board-9625.c
index e7ef1a9..99b9f16 100644
--- a/arch/arm/mach-msm/board-9625.c
+++ b/arch/arm/mach-msm/board-9625.c
@@ -29,6 +29,7 @@
 #include <mach/socinfo.h>
 #include <mach/board.h>
 #include <mach/gpio.h>
+#include <mach/clk-provider.h>
 #include "clock.h"
 
 #define L2CC_AUX_CTRL	((0x1 << L2X0_AUX_CTRL_SHARE_OVERRIDE_SHIFT) | \
diff --git a/arch/arm/mach-msm/board-fsm9xxx.c b/arch/arm/mach-msm/board-fsm9xxx.c
index 24d54e4..b4f6968 100644
--- a/arch/arm/mach-msm/board-fsm9xxx.c
+++ b/arch/arm/mach-msm/board-fsm9xxx.c
@@ -38,6 +38,7 @@
 #include <mach/socinfo.h>
 #include "devices.h"
 #include "timer.h"
+#include "clock.h"
 #include "pm.h"
 #include "spm.h"
 #include <linux/regulator/consumer.h>
diff --git a/arch/arm/mach-msm/board-msm7x30.c b/arch/arm/mach-msm/board-msm7x30.c
index b3ce01c..205db58 100644
--- a/arch/arm/mach-msm/board-msm7x30.c
+++ b/arch/arm/mach-msm/board-msm7x30.c
@@ -82,6 +82,7 @@
 #include "pm-boot.h"
 #include "spm.h"
 #include "acpuclock.h"
+#include "clock.h"
 #include <mach/dal_axi.h>
 #include <mach/msm_serial_hs.h>
 #include <mach/qdsp5v2/mi2s.h>
diff --git a/arch/arm/mach-msm/board-msm8x60.c b/arch/arm/mach-msm/board-msm8x60.c
index 281d055..a889d39 100644
--- a/arch/arm/mach-msm/board-msm8x60.c
+++ b/arch/arm/mach-msm/board-msm8x60.c
@@ -100,6 +100,7 @@
 #include "peripheral-loader.h"
 #include <linux/platform_data/qcom_crypto_device.h>
 #include "rpm_resources.h"
+#include "clock.h"
 #include "pm-boot.h"
 #include "board-storage-common-a.h"
 
diff --git a/arch/arm/mach-msm/board-qsd8x50.c b/arch/arm/mach-msm/board-qsd8x50.c
index 4df4266..146c8a8 100644
--- a/arch/arm/mach-msm/board-qsd8x50.c
+++ b/arch/arm/mach-msm/board-qsd8x50.c
@@ -55,6 +55,7 @@
 #include "timer.h"
 #include "msm-keypad-devices.h"
 #include "acpuclock.h"
+#include "clock.h"
 #include "pm.h"
 #include "irq.h"
 #include "pm-boot.h"
diff --git a/arch/arm/mach-msm/clock-7x30.c b/arch/arm/mach-msm/clock-7x30.c
index 8cce34b..e42fe65 100644
--- a/arch/arm/mach-msm/clock-7x30.c
+++ b/arch/arm/mach-msm/clock-7x30.c
@@ -24,7 +24,6 @@
 #include <linux/string.h>
 
 #include <mach/msm_iomap.h>
-#include <mach/clk.h>
 #include <mach/proc_comm.h>
 
 #include "clock.h"
diff --git a/arch/arm/mach-msm/clock-8960.c b/arch/arm/mach-msm/clock-8960.c
index f6b1332..9ff039f0 100644
--- a/arch/arm/mach-msm/clock-8960.c
+++ b/arch/arm/mach-msm/clock-8960.c
@@ -24,10 +24,10 @@
 #include <asm/mach-types.h>
 
 #include <mach/msm_iomap.h>
-#include <mach/clk.h>
 #include <mach/rpm-regulator.h>
 #include <mach/socinfo.h>
 
+#include "clock.h"
 #include "clock-local.h"
 #include "clock-rpm.h"
 #include "clock-voter.h"
diff --git a/arch/arm/mach-msm/clock-8974.c b/arch/arm/mach-msm/clock-8974.c
index 62e8f0f..26e6ca6 100644
--- a/arch/arm/mach-msm/clock-8974.c
+++ b/arch/arm/mach-msm/clock-8974.c
@@ -20,7 +20,6 @@
 #include <linux/clk.h>
 #include <linux/iopoll.h>
 
-#include <mach/clk.h>
 #include <mach/rpm-regulator-smd.h>
 #include <mach/socinfo.h>
 #include <mach/rpm-smd.h>
@@ -30,6 +29,7 @@
 #include "clock-rpm.h"
 #include "clock-voter.h"
 #include "clock-mdss-8974.h"
+#include "clock.h"
 
 enum {
 	GCC_BASE,
@@ -2366,9 +2366,12 @@
 
 static struct clk_freq_tbl ftbl_mmss_axi_clk[] = {
 	F_MM( 19200000,    cxo,     1,   0,   0),
+	F_MM( 37500000,  gpll0,    16,   0,   0),
+	F_MM( 50000000,  gpll0,    12,   0,   0),
+	F_MM( 75000000,  gpll0,     8,   0,   0),
+	F_MM(100000000,  gpll0,     6,   0,   0),
 	F_MM(150000000,  gpll0,     4,   0,   0),
 	F_MM(282000000, mmpll1,     3,   0,   0),
-	F_MM(320000000, mmpll0,   2.5,   0,   0),
 	F_MM(400000000, mmpll0,     2,   0,   0),
 	F_END
 };
@@ -2390,6 +2393,10 @@
 
 static struct clk_freq_tbl ftbl_ocmemnoc_clk[] = {
 	F_MM( 19200000,    cxo,   1,   0,   0),
+	F_MM( 37500000,  gpll0,  16,   0,   0),
+	F_MM( 50000000,  gpll0,  12,   0,   0),
+	F_MM( 75000000,  gpll0,   8,   0,   0),
+	F_MM(100000000,  gpll0,   6,   0,   0),
 	F_MM(150000000,  gpll0,   4,   0,   0),
 	F_MM(282000000, mmpll1,   3,   0,   0),
 	F_MM(400000000, mmpll0,   2,   0,   0),
diff --git a/arch/arm/mach-msm/clock-8x60.c b/arch/arm/mach-msm/clock-8x60.c
index 24c06c9..6ae66fe 100644
--- a/arch/arm/mach-msm/clock-8x60.c
+++ b/arch/arm/mach-msm/clock-8x60.c
@@ -23,11 +23,11 @@
 #include <linux/clkdev.h>
 
 #include <mach/msm_iomap.h>
-#include <mach/clk.h>
 #include <mach/scm-io.h>
 #include <mach/rpm.h>
 #include <mach/rpm-regulator.h>
 
+#include "clock.h"
 #include "clock-local.h"
 #include "clock-rpm.h"
 #include "clock-voter.h"
diff --git a/arch/arm/mach-msm/clock-9615.c b/arch/arm/mach-msm/clock-9615.c
index 15eaa4b..fee8445 100644
--- a/arch/arm/mach-msm/clock-9615.c
+++ b/arch/arm/mach-msm/clock-9615.c
@@ -24,10 +24,10 @@
 #include <asm/mach-types.h>
 
 #include <mach/msm_iomap.h>
-#include <mach/clk.h>
 #include <mach/rpm-9615.h>
 #include <mach/rpm-regulator.h>
 
+#include "clock.h"
 #include "clock-local.h"
 #include "clock-voter.h"
 #include "clock-rpm.h"
diff --git a/arch/arm/mach-msm/clock-debug.c b/arch/arm/mach-msm/clock-debug.c
index c996ff4..e942173 100644
--- a/arch/arm/mach-msm/clock-debug.c
+++ b/arch/arm/mach-msm/clock-debug.c
@@ -21,6 +21,7 @@
 #include <linux/clk.h>
 #include <linux/list.h>
 #include <linux/clkdev.h>
+#include <mach/clk-provider.h>
 
 #include "clock.h"
 
@@ -145,74 +146,39 @@
 DEFINE_SIMPLE_ATTRIBUTE(clock_hwcg_fops, clock_debug_hwcg_get,
 			NULL, "%llu\n");
 
-static struct dentry *debugfs_base;
-static u32 debug_suspend;
-static struct clk_lookup *msm_clocks;
-static size_t num_msm_clocks;
-
-int __init clock_debug_init(struct clock_init_data *data)
+static int fmax_rates_show(struct seq_file *m, void *unused)
 {
-	debugfs_base = debugfs_create_dir("clk", NULL);
-	if (!debugfs_base)
-		return -ENOMEM;
-	if (!debugfs_create_u32("debug_suspend", S_IRUGO | S_IWUSR,
-				debugfs_base, &debug_suspend)) {
-		debugfs_remove_recursive(debugfs_base);
-		return -ENOMEM;
-	}
-	msm_clocks = data->table;
-	num_msm_clocks = data->size;
+	struct clk *clock = m->private;
+	int level = 0;
 
-	measure = clk_get_sys("debug", "measure");
-	if (IS_ERR(measure))
-		measure = NULL;
+	int vdd_level = find_vdd_level(clock, clock->rate);
+	if (vdd_level < 0) {
+		seq_printf(m, "could not find_vdd_level for %s, %ld\n",
+			   clock->dbg_name, clock->rate);
+		return 0;
+	}
+	for (level = 0; level < ARRAY_SIZE(clock->fmax); level++) {
+		if (vdd_level == level)
+			seq_printf(m, "[%lu] ", clock->fmax[level]);
+		else
+			seq_printf(m, "%lu ", clock->fmax[level]);
+	}
+	seq_printf(m, "\n");
 
 	return 0;
 }
 
-
-static int clock_debug_print_clock(struct clk *c)
+static int fmax_rates_open(struct inode *inode, struct file *file)
 {
-	char *start = "";
-
-	if (!c || !c->prepare_count)
-		return 0;
-
-	pr_info("\t");
-	do {
-		if (c->vdd_class)
-			pr_cont("%s%s:%u:%u [%ld, %lu]", start, c->dbg_name,
-				c->prepare_count, c->count, c->rate,
-				c->vdd_class->cur_level);
-		else
-			pr_cont("%s%s:%u:%u [%ld]", start, c->dbg_name,
-				c->prepare_count, c->count, c->rate);
-		start = " -> ";
-	} while ((c = clk_get_parent(c)));
-
-	pr_cont("\n");
-
-	return 1;
+	return single_open(file, fmax_rates_show, inode->i_private);
 }
 
-void clock_debug_print_enabled(void)
-{
-	unsigned i;
-	int cnt = 0;
-
-	if (likely(!debug_suspend))
-		return;
-
-	pr_info("Enabled clocks:\n");
-	for (i = 0; i < num_msm_clocks; i++)
-		cnt += clock_debug_print_clock(msm_clocks[i].clk);
-
-	if (cnt)
-		pr_info("Enabled clock count: %d\n", cnt);
-	else
-		pr_info("No clocks enabled.\n");
-
-}
+static const struct file_operations fmax_rates_fops = {
+	.open		= fmax_rates_open,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= seq_release,
+};
 
 static int list_rates_show(struct seq_file *m, void *unused)
 {
@@ -252,41 +218,16 @@
 	.release	= seq_release,
 };
 
-static int fmax_rates_show(struct seq_file *m, void *unused)
-{
-	struct clk *clock = m->private;
-	int level = 0;
+static struct dentry *debugfs_base;
+static u32 debug_suspend;
 
-	int vdd_level = find_vdd_level(clock, clock->rate);
-	if (vdd_level < 0) {
-		seq_printf(m, "could not find_vdd_level for %s, %ld\n",
-			clock->dbg_name, clock->rate);
-		return 0;
-	}
-	for (level = 0; level < ARRAY_SIZE(clock->fmax); level++) {
-		if (vdd_level == level)
-			seq_printf(m, "[%lu] ", clock->fmax[level]);
-		else
-			seq_printf(m, "%lu ", clock->fmax[level]);
-	}
-	seq_printf(m, "\n");
-
-	return 0;
-}
-
-static int fmax_rates_open(struct inode *inode, struct file *file)
-{
-	return single_open(file, fmax_rates_show, inode->i_private);
-}
-
-static const struct file_operations fmax_rates_fops = {
-	.open		= fmax_rates_open,
-	.read		= seq_read,
-	.llseek		= seq_lseek,
-	.release	= seq_release,
+struct clk_table {
+	struct list_head node;
+	struct clk_lookup *clocks;
+	size_t num_clocks;
 };
 
-int __init clock_debug_add(struct clk *clock)
+static int clock_debug_add(struct clk *clock)
 {
 	char temp[50], *ptr;
 	struct dentry *clk_dir;
@@ -333,9 +274,118 @@
 				S_IRUGO, clk_dir, clock, &fmax_rates_fops))
 			goto error;
 
-
 	return 0;
 error:
 	debugfs_remove_recursive(clk_dir);
 	return -ENOMEM;
 }
+static LIST_HEAD(clk_list);
+static DEFINE_SPINLOCK(clk_list_lock);
+
+/**
+ * clock_debug_register() - Add additional clocks to clock debugfs hierarchy
+ * @table: Table of clocks to create debugfs nodes for
+ * @size: Size of @table
+ *
+ * Use this function to register additional clocks in debugfs. The clock debugfs
+ * hierarchy must have already been initialized with clock_debug_init() prior to
+ * calling this function. Unlike clock_debug_init(), this may be called multiple
+ * times with different clock lists and can be used after the kernel has
+ * finished booting.
+ */
+int clock_debug_register(struct clk_lookup *table, size_t size)
+{
+	struct clk_table *clk_table;
+	unsigned long flags;
+	int i;
+
+	clk_table = kmalloc(sizeof(*clk_table), GFP_KERNEL);
+	if (!clk_table)
+		return -ENOMEM;
+
+	clk_table->clocks = table;
+	clk_table->num_clocks = size;
+
+	spin_lock_irqsave(&clk_list_lock, flags);
+	list_add_tail(&clk_table->node, &clk_list);
+	spin_unlock_irqrestore(&clk_list_lock, flags);
+
+	for (i = 0; i < size; i++)
+		clock_debug_add(table[i].clk);
+
+	return 0;
+}
+
+/**
+ * clock_debug_init() - Initialize clock debugfs
+ */
+int __init clock_debug_init(void)
+{
+	debugfs_base = debugfs_create_dir("clk", NULL);
+	if (!debugfs_base)
+		return -ENOMEM;
+	if (!debugfs_create_u32("debug_suspend", S_IRUGO | S_IWUSR,
+				debugfs_base, &debug_suspend)) {
+		debugfs_remove_recursive(debugfs_base);
+		return -ENOMEM;
+	}
+
+	measure = clk_get_sys("debug", "measure");
+	if (IS_ERR(measure))
+		measure = NULL;
+
+	return 0;
+}
+
+static int clock_debug_print_clock(struct clk *c)
+{
+	char *start = "";
+
+	if (!c || !c->prepare_count)
+		return 0;
+
+	pr_info("\t");
+	do {
+		if (c->vdd_class)
+			pr_cont("%s%s:%u:%u [%ld, %lu]", start, c->dbg_name,
+				c->prepare_count, c->count, c->rate,
+				c->vdd_class->cur_level);
+		else
+			pr_cont("%s%s:%u:%u [%ld]", start, c->dbg_name,
+				c->prepare_count, c->count, c->rate);
+		start = " -> ";
+	} while ((c = clk_get_parent(c)));
+
+	pr_cont("\n");
+
+	return 1;
+}
+
+/**
+ * clock_debug_print_enabled() - Print names of enabled clocks for suspend debug
+ *
+ * Print the names of enabled clocks and their parents if debug_suspend is set
+ */
+void clock_debug_print_enabled(void)
+{
+	struct clk_table *table;
+	unsigned long flags;
+	int i, cnt = 0;
+
+	if (likely(!debug_suspend))
+		return;
+
+	pr_info("Enabled clocks:\n");
+	spin_lock_irqsave(&clk_list_lock, flags);
+	list_for_each_entry(table, &clk_list, node) {
+		for (i = 0; i < table->num_clocks; i++)
+			cnt += clock_debug_print_clock(table->clocks[i].clk);
+	}
+	spin_unlock_irqrestore(&clk_list_lock, flags);
+
+	if (cnt)
+		pr_info("Enabled clock count: %d\n", cnt);
+	else
+		pr_info("No clocks enabled.\n");
+
+}
diff --git a/arch/arm/mach-msm/clock-dummy.c b/arch/arm/mach-msm/clock-dummy.c
index 54c9de8..fda7a92 100644
--- a/arch/arm/mach-msm/clock-dummy.c
+++ b/arch/arm/mach-msm/clock-dummy.c
@@ -10,7 +10,7 @@
  * GNU General Public License for more details.
  */
 
-#include "clock.h"
+#include <mach/clk-provider.h>
 
 static int dummy_clk_reset(struct clk *clk, enum clk_reset_action action)
 {
diff --git a/arch/arm/mach-msm/clock-fsm9xxx.c b/arch/arm/mach-msm/clock-fsm9xxx.c
index c188ba6..2900d45 100644
--- a/arch/arm/mach-msm/clock-fsm9xxx.c
+++ b/arch/arm/mach-msm/clock-fsm9xxx.c
@@ -12,9 +12,7 @@
  */
 #include <linux/kernel.h>
 #include <linux/clk.h>
-
-#include <mach/clk.h>
-
+#include <mach/clk-provider.h>
 #include "clock.h"
 
 /*
diff --git a/arch/arm/mach-msm/clock-local.c b/arch/arm/mach-msm/clock-local.c
index b952f2f..ca031ad 100644
--- a/arch/arm/mach-msm/clock-local.c
+++ b/arch/arm/mach-msm/clock-local.c
@@ -24,10 +24,10 @@
 #include <linux/clk.h>
 
 #include <mach/msm_iomap.h>
+#include <mach/clk-provider.h>
 #include <mach/clk.h>
 #include <mach/scm-io.h>
 
-#include "clock.h"
 #include "clock-local.h"
 
 #ifdef CONFIG_MSM_SECURE_IO
diff --git a/arch/arm/mach-msm/clock-local.h b/arch/arm/mach-msm/clock-local.h
index 81085ef..1873343 100644
--- a/arch/arm/mach-msm/clock-local.h
+++ b/arch/arm/mach-msm/clock-local.h
@@ -15,7 +15,7 @@
 #define __ARCH_ARM_MACH_MSM_CLOCK_LOCAL_H
 
 #include <linux/spinlock.h>
-#include "clock.h"
+#include <mach/clk-provider.h>
 
 #define MN_MODE_DUAL_EDGE 0x2
 
diff --git a/arch/arm/mach-msm/clock-local2.c b/arch/arm/mach-msm/clock-local2.c
index 2beb990..b9c3036 100644
--- a/arch/arm/mach-msm/clock-local2.c
+++ b/arch/arm/mach-msm/clock-local2.c
@@ -24,8 +24,8 @@
 #include <linux/clk.h>
 
 #include <mach/clk.h>
+#include <mach/clk-provider.h>
 
-#include "clock.h"
 #include "clock-local2.h"
 
 /*
diff --git a/arch/arm/mach-msm/clock-local2.h b/arch/arm/mach-msm/clock-local2.h
index 46e9e0c..101dc2d 100644
--- a/arch/arm/mach-msm/clock-local2.h
+++ b/arch/arm/mach-msm/clock-local2.h
@@ -15,7 +15,8 @@
 #define __ARCH_ARM_MACH_MSM_CLOCK_LOCAL_2_H
 
 #include <linux/spinlock.h>
-#include "clock.h"
+#include <mach/clk-provider.h>
+#include <mach/clk.h>
 
 /*
  * Generic frequency-definition structs and macros
diff --git a/arch/arm/mach-msm/clock-mdss-8974.c b/arch/arm/mach-msm/clock-mdss-8974.c
index 14e1185..1603c93 100644
--- a/arch/arm/mach-msm/clock-mdss-8974.c
+++ b/arch/arm/mach-msm/clock-mdss-8974.c
@@ -20,8 +20,8 @@
 
 #include <asm/processor.h>
 #include <mach/msm_iomap.h>
+#include <mach/clk-provider.h>
 
-#include "clock.h"
 #include "clock-mdss-8974.h"
 
 #define REG_R(addr)		readl_relaxed(addr)
diff --git a/arch/arm/mach-msm/clock-pcom.c b/arch/arm/mach-msm/clock-pcom.c
index 428423a..801b40a 100644
--- a/arch/arm/mach-msm/clock-pcom.c
+++ b/arch/arm/mach-msm/clock-pcom.c
@@ -17,6 +17,7 @@
 #include <linux/err.h>
 
 #include <mach/clk.h>
+#include <mach/clk-provider.h>
 #include <mach/socinfo.h>
 #include <mach/proc_comm.h>
 
diff --git a/arch/arm/mach-msm/clock-pcom.h b/arch/arm/mach-msm/clock-pcom.h
index 723c53c..82a90ab 100644
--- a/arch/arm/mach-msm/clock-pcom.h
+++ b/arch/arm/mach-msm/clock-pcom.h
@@ -13,6 +13,8 @@
 #ifndef __ARCH_ARM_MACH_MSM_CLOCK_PCOM_H
 #define __ARCH_ARM_MACH_MSM_CLOCK_PCOM_H
 
+#include <mach/clk-provider.h>
+
 /* clock IDs used by the modem processor */
 
 #define P_ACPU_CLK	0   /* Applications processor clock */
diff --git a/arch/arm/mach-msm/clock-pll.h b/arch/arm/mach-msm/clock-pll.h
index 30f595b..5c7c304 100644
--- a/arch/arm/mach-msm/clock-pll.h
+++ b/arch/arm/mach-msm/clock-pll.h
@@ -15,6 +15,8 @@
 #ifndef __ARCH_ARM_MACH_MSM_CLOCK_PLL_H
 #define __ARCH_ARM_MACH_MSM_CLOCK_PLL_H
 
+#include <mach/clk-provider.h>
+
 /**
  * enum - For PLL IDs
  */
diff --git a/arch/arm/mach-msm/clock-rpm.c b/arch/arm/mach-msm/clock-rpm.c
index 149a0511..e06eb4b 100644
--- a/arch/arm/mach-msm/clock-rpm.c
+++ b/arch/arm/mach-msm/clock-rpm.c
@@ -12,10 +12,9 @@
  */
 
 #include <linux/err.h>
-#include <mach/clk.h>
+#include <mach/clk-provider.h>
 
 #include "rpm_resources.h"
-#include "clock.h"
 #include "clock-rpm.h"
 
 #define __clk_rpmrs_set_rate(r, value, ctx, noirq) \
diff --git a/arch/arm/mach-msm/clock-rpm.h b/arch/arm/mach-msm/clock-rpm.h
index 7952a33..2f0b729 100644
--- a/arch/arm/mach-msm/clock-rpm.h
+++ b/arch/arm/mach-msm/clock-rpm.h
@@ -16,6 +16,7 @@
 
 #include <mach/rpm.h>
 #include <mach/rpm-smd.h>
+#include <mach/clk-provider.h>
 
 #define RPM_SMD_KEY_RATE	0x007A484B
 #define RPM_SMD_KEY_ENABLE	0x62616E45
diff --git a/arch/arm/mach-msm/clock-voter.c b/arch/arm/mach-msm/clock-voter.c
index 3e1cbb9..fa170bf4 100644
--- a/arch/arm/mach-msm/clock-voter.c
+++ b/arch/arm/mach-msm/clock-voter.c
@@ -14,8 +14,7 @@
 #include <linux/err.h>
 #include <linux/mutex.h>
 #include <linux/clk.h>
-
-#include "clock.h"
+#include <mach/clk-provider.h>
 #include "clock-voter.h"
 
 static DEFINE_MUTEX(voter_clk_lock);
diff --git a/arch/arm/mach-msm/clock-voter.h b/arch/arm/mach-msm/clock-voter.h
index 407aac6..82c071b 100644
--- a/arch/arm/mach-msm/clock-voter.h
+++ b/arch/arm/mach-msm/clock-voter.h
@@ -14,6 +14,8 @@
 #ifndef __ARCH_ARM_MACH_MSM_CLOCK_VOTER_H
 #define __ARCH_ARM_MACH_MSM_CLOCK_VOTER_H
 
+#include <mach/clk-provider.h>
+
 struct clk_ops;
 extern struct clk_ops clk_ops_voter;
 
diff --git a/arch/arm/mach-msm/clock.c b/arch/arm/mach-msm/clock.c
index 27f2405..1ea18f4 100644
--- a/arch/arm/mach-msm/clock.c
+++ b/arch/arm/mach-msm/clock.c
@@ -23,7 +23,7 @@
 #include <linux/clkdev.h>
 #include <linux/list.h>
 #include <trace/events/power.h>
-
+#include <mach/clk-provider.h>
 #include "clock.h"
 
 struct handoff_clk {
@@ -412,7 +412,32 @@
 }
 EXPORT_SYMBOL(clk_set_flags);
 
-static struct clock_init_data __initdata *clk_init_data;
+static struct clock_init_data *clk_init_data;
+
+/**
+ * msm_clock_register() - Register additional clock tables
+ * @table: Table of clocks
+ * @size: Size of @table
+ *
+ * Upon return, clock APIs may be used to control clocks registered using this
+ * function. This API may only be used after msm_clock_init() has completed.
+ * Unlike msm_clock_init(), this function may be called multiple times with
+ * different clock lists and used after the kernel has finished booting.
+ */
+int msm_clock_register(struct clk_lookup *table, size_t size)
+{
+	if (!clk_init_data)
+		return -ENODEV;
+
+	if (!table)
+		return -EINVAL;
+
+	clkdev_add_table(table, size);
+	clock_debug_register(table, size);
+
+	return 0;
+}
+EXPORT_SYMBOL(msm_clock_register);
 
 static enum handoff __init __handoff_clk(struct clk *clk)
 {
@@ -466,13 +491,23 @@
 	return ret;
 }
 
-void __init msm_clock_init(struct clock_init_data *data)
+/**
+ * msm_clock_init() - Register and initialize a clock driver
+ * @data: Driver-specific clock initialization data
+ *
+ * Upon return from this call, clock APIs may be used to control
+ * clocks registered with this API.
+ */
+int __init msm_clock_init(struct clock_init_data *data)
 {
 	unsigned n;
 	struct clk_lookup *clock_tbl;
 	size_t num_clocks;
 	struct clk *clk;
 
+	if (!data)
+		return -EINVAL;
+
 	clk_init_data = data;
 	if (clk_init_data->pre_init)
 		clk_init_data->pre_init();
@@ -499,16 +534,17 @@
 
 	if (clk_init_data->post_init)
 		clk_init_data->post_init();
+
+	clock_debug_init();
+	clock_debug_register(clock_tbl, num_clocks);
+
+	return 0;
 }
 
 static int __init clock_late_init(void)
 {
 	struct handoff_clk *h, *h_temp;
-	int n, ret = 0;
-
-	clock_debug_init(clk_init_data);
-	for (n = 0; n < clk_init_data->size; n++)
-		clock_debug_add(clk_init_data->table[n].clk);
+	int ret = 0;
 
 	pr_info("%s: Removing enables held for handed-off clocks\n", __func__);
 	list_for_each_entry_safe(h, h_temp, &handoff_list, list) {
diff --git a/arch/arm/mach-msm/clock.h b/arch/arm/mach-msm/clock.h
index 45d2f71..48f897b 100644
--- a/arch/arm/mach-msm/clock.h
+++ b/arch/arm/mach-msm/clock.h
@@ -1,7 +1,5 @@
-/* arch/arm/mach-msm/clock.h
- *
- * Copyright (C) 2007 Google, Inc.
- * Copyright (c) 2007-2012, Code Aurora Forum. All rights reserved.
+/*
+ * Copyright (c) 2012, Code Aurora Forum. All rights reserved.
  *
  * This software is licensed under the terms of the GNU General Public
  * License version 2, as published by the Free Software Foundation, and
@@ -17,127 +15,7 @@
 #ifndef __ARCH_ARM_MACH_MSM_CLOCK_H
 #define __ARCH_ARM_MACH_MSM_CLOCK_H
 
-#include <linux/types.h>
-#include <linux/list.h>
 #include <linux/clkdev.h>
-#include <linux/spinlock.h>
-#include <linux/mutex.h>
-
-#include <mach/clk.h>
-
-#define CLKFLAG_INVERT			0x00000001
-#define CLKFLAG_NOINVERT		0x00000002
-#define CLKFLAG_NONEST			0x00000004
-#define CLKFLAG_NORESET			0x00000008
-#define CLKFLAG_RETAIN			0x00000040
-#define CLKFLAG_NORETAIN		0x00000080
-#define CLKFLAG_SKIP_HANDOFF		0x00000100
-#define CLKFLAG_MIN			0x00000400
-#define CLKFLAG_MAX			0x00000800
-
-/*
- * Bit manipulation macros
- */
-#define BM(msb, lsb)	(((((uint32_t)-1) << (31-msb)) >> (31-msb+lsb)) << lsb)
-#define BVAL(msb, lsb, val)	(((val) << lsb) & BM(msb, lsb))
-
-/*
- * Halt/Status Checking Mode Macros
- */
-#define HALT		0	/* Bit pol: 1 = halted */
-#define NOCHECK		1	/* No bit to check, do nothing */
-#define HALT_VOTED	2	/* Bit pol: 1 = halted; delay on disable */
-#define ENABLE		3	/* Bit pol: 1 = running */
-#define ENABLE_VOTED	4	/* Bit pol: 1 = running; delay on disable */
-#define DELAY		5	/* No bit to check, just delay */
-
-#define MAX_VDD_LEVELS			4
-
-/**
- * struct clk_vdd_class - Voltage scaling class
- * @class_name: name of the class
- * @set_vdd: function to call when applying a new voltage setting
- * @level_votes: array of votes for each level
- * @cur_level: the currently set voltage level
- * @lock: lock to protect this struct
- */
-struct clk_vdd_class {
-	const char *class_name;
-	int (*set_vdd)(struct clk_vdd_class *v_class, int level);
-	int level_votes[MAX_VDD_LEVELS];
-	unsigned long cur_level;
-	spinlock_t lock;
-};
-
-#define DEFINE_VDD_CLASS(_name, _set_vdd) \
-	struct clk_vdd_class _name = { \
-		.class_name = #_name, \
-		.set_vdd = _set_vdd, \
-		.cur_level = ARRAY_SIZE(_name.level_votes), \
-		.lock = __SPIN_LOCK_UNLOCKED(lock) \
-	}
-
-enum handoff {
-	HANDOFF_ENABLED_CLK,
-	HANDOFF_DISABLED_CLK,
-	HANDOFF_UNKNOWN_RATE,
-};
-
-struct clk_ops {
-	int (*prepare)(struct clk *clk);
-	int (*enable)(struct clk *clk);
-	void (*disable)(struct clk *clk);
-	void (*unprepare)(struct clk *clk);
-	void (*enable_hwcg)(struct clk *clk);
-	void (*disable_hwcg)(struct clk *clk);
-	int (*in_hwcg_mode)(struct clk *clk);
-	enum handoff (*handoff)(struct clk *clk);
-	int (*reset)(struct clk *clk, enum clk_reset_action action);
-	int (*set_rate)(struct clk *clk, unsigned long rate);
-	int (*set_max_rate)(struct clk *clk, unsigned long rate);
-	int (*set_flags)(struct clk *clk, unsigned flags);
-	unsigned long (*get_rate)(struct clk *clk);
-	int (*list_rate)(struct clk *clk, unsigned n);
-	int (*is_enabled)(struct clk *clk);
-	long (*round_rate)(struct clk *clk, unsigned long rate);
-	int (*set_parent)(struct clk *clk, struct clk *parent);
-	struct clk *(*get_parent)(struct clk *clk);
-	bool (*is_local)(struct clk *clk);
-};
-
-/**
- * struct clk
- * @prepare_count: prepare refcount
- * @prepare_lock: protects clk_prepare()/clk_unprepare() path and @prepare_count
- * @count: enable refcount
- * @lock: protects clk_enable()/clk_disable() path and @count
- * @depends: non-direct parent of clock to enable when this clock is enabled
- * @vdd_class: voltage scaling requirement class
- * @fmax: maximum frequency in Hz supported at each voltage level
- */
-struct clk {
-	uint32_t flags;
-	struct clk_ops *ops;
-	const char *dbg_name;
-	struct clk *depends;
-	struct clk_vdd_class *vdd_class;
-	unsigned long fmax[MAX_VDD_LEVELS];
-	unsigned long rate;
-
-	struct list_head children;
-	struct list_head siblings;
-
-	unsigned count;
-	spinlock_t lock;
-	unsigned prepare_count;
-	struct mutex prepare_lock;
-};
-
-#define CLK_INIT(name) \
-	.lock = __SPIN_LOCK_UNLOCKED((name).lock), \
-	.prepare_lock = __MUTEX_INITIALIZER((name).prepare_lock), \
-	.children = LIST_HEAD_INIT((name).children), \
-	.siblings = LIST_HEAD_INIT((name).siblings)
 
 /**
  * struct clock_init_data - SoC specific clock initialization data
@@ -171,30 +49,20 @@
 extern struct clock_init_data msm8974_clock_init_data;
 extern struct clock_init_data msm8974_rumi_clock_init_data;
 
-void msm_clock_init(struct clock_init_data *data);
-int vote_vdd_level(struct clk_vdd_class *vdd_class, int level);
-int unvote_vdd_level(struct clk_vdd_class *vdd_class, int level);
+int msm_clock_init(struct clock_init_data *data);
 int find_vdd_level(struct clk *clk, unsigned long rate);
 
 #ifdef CONFIG_DEBUG_FS
-int clock_debug_init(struct clock_init_data *data);
-int clock_debug_add(struct clk *clock);
+int clock_debug_init(void);
+int clock_debug_register(struct clk_lookup *t, size_t s);
 void clock_debug_print_enabled(void);
 #else
-static inline int clock_debug_init(struct clock_init_data *data) { return 0; }
-static inline int clock_debug_add(struct clk *clock) { return 0; }
+static inline int clock_debug_init(void) { return 0; }
+static inline int clock_debug_register(struct clk_lookup *t, size_t s)
+{
+	return 0;
+}
 static inline void clock_debug_print_enabled(void) { return; }
 #endif
 
-extern struct clk dummy_clk;
-
-#define CLK_DUMMY(clk_name, clk_id, clk_dev, flags) { \
-	.con_id = clk_name, \
-	.dev_id = clk_dev, \
-	.clk = &dummy_clk, \
-	}
-
-#define CLK_LOOKUP(con, c, dev) { .con_id = con, .clk = &c, .dev_id = dev }
-
 #endif
-
diff --git a/arch/arm/mach-msm/devices-8064.c b/arch/arm/mach-msm/devices-8064.c
index 0f106f5..e66881b 100644
--- a/arch/arm/mach-msm/devices-8064.c
+++ b/arch/arm/mach-msm/devices-8064.c
@@ -26,6 +26,7 @@
 #include <mach/msm_sps.h>
 #include <mach/dma.h>
 #include <mach/msm_dsps.h>
+#include <mach/clk-provider.h>
 #include <sound/msm-dai-q6.h>
 #include <sound/apr_audio.h>
 #include <mach/msm_tsif.h>
diff --git a/arch/arm/mach-msm/devices-8960.c b/arch/arm/mach-msm/devices-8960.c
index b6926a2..64b901f 100644
--- a/arch/arm/mach-msm/devices-8960.c
+++ b/arch/arm/mach-msm/devices-8960.c
@@ -35,6 +35,7 @@
 #include <mach/msm_dcvs.h>
 #include <mach/msm_rtb.h>
 #include <mach/msm_cache_dump.h>
+#include <mach/clk-provider.h>
 #include <sound/msm-dai-q6.h>
 #include <sound/apr_audio.h>
 #include <mach/msm_tsif.h>
diff --git a/arch/arm/mach-msm/devices-msm7x27a.c b/arch/arm/mach-msm/devices-msm7x27a.c
index c877ba9..343ea76 100644
--- a/arch/arm/mach-msm/devices-msm7x27a.c
+++ b/arch/arm/mach-msm/devices-msm7x27a.c
@@ -30,6 +30,7 @@
 #include <asm/cacheflush.h>
 #include <mach/rpc_hsusb.h>
 #include <mach/socinfo.h>
+#include <mach/clk-provider.h>
 
 #include "devices.h"
 #include "devices-msm7x2xa.h"
diff --git a/arch/arm/mach-msm/etm.c b/arch/arm/mach-msm/etm.c
index 6cceff2..ae42733 100644
--- a/arch/arm/mach-msm/etm.c
+++ b/arch/arm/mach-msm/etm.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2011-2012, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -24,8 +24,7 @@
 #include <linux/pm_qos.h>
 
 #include <asm/atomic.h>
-
-#include "cp14.h"
+#include <asm/hardware/cp14.h>
 
 #define LOG_BUF_LEN			32768
 /* each slot is 4 bytes, 8kb total */
diff --git a/arch/arm/mach-msm/footswitch-8x60.c b/arch/arm/mach-msm/footswitch-8x60.c
index 84735aa..a7b26c1 100644
--- a/arch/arm/mach-msm/footswitch-8x60.c
+++ b/arch/arm/mach-msm/footswitch-8x60.c
@@ -24,7 +24,7 @@
 #include <mach/msm_iomap.h>
 #include <mach/msm_bus.h>
 #include <mach/scm-io.h>
-#include "clock.h"
+#include <mach/clk.h>
 #include "footswitch.h"
 
 #ifdef CONFIG_MSM_SECURE_IO
diff --git a/arch/arm/mach-msm/include/mach/clk-provider.h b/arch/arm/mach-msm/include/mach/clk-provider.h
new file mode 100644
index 0000000..0da0b33
--- /dev/null
+++ b/arch/arm/mach-msm/include/mach/clk-provider.h
@@ -0,0 +1,145 @@
+/*
+ * Copyright (C) 2007 Google, Inc.
+ * Copyright (c) 2007-2012, 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
+ * may be copied, distributed, and modified under those terms.
+ *
+ * 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 __MACH_CLK_PROVIDER_H
+#define __MACH_CLK_PROVIDER_H
+
+#include <linux/types.h>
+#include <linux/list.h>
+#include <linux/clkdev.h>
+#include <linux/spinlock.h>
+#include <mach/clk.h>
+
+/*
+ * Bit manipulation macros
+ */
+#define BM(msb, lsb)	(((((uint32_t)-1) << (31-msb)) >> (31-msb+lsb)) << lsb)
+#define BVAL(msb, lsb, val)	(((val) << lsb) & BM(msb, lsb))
+
+/*
+ * Halt/Status Checking Mode Macros
+ */
+#define HALT		0	/* Bit pol: 1 = halted */
+#define NOCHECK		1	/* No bit to check, do nothing */
+#define HALT_VOTED	2	/* Bit pol: 1 = halted; delay on disable */
+#define ENABLE		3	/* Bit pol: 1 = running */
+#define ENABLE_VOTED	4	/* Bit pol: 1 = running; delay on disable */
+#define DELAY		5	/* No bit to check, just delay */
+
+#define MAX_VDD_LEVELS			4
+
+/**
+ * struct clk_vdd_class - Voltage scaling class
+ * @class_name: name of the class
+ * @set_vdd: function to call when applying a new voltage setting
+ * @level_votes: array of votes for each level
+ * @cur_level: the currently set voltage level
+ * @lock: lock to protect this struct
+ */
+struct clk_vdd_class {
+	const char *class_name;
+	int (*set_vdd)(struct clk_vdd_class *v_class, int level);
+	int level_votes[MAX_VDD_LEVELS];
+	unsigned long cur_level;
+	spinlock_t lock;
+};
+
+#define DEFINE_VDD_CLASS(_name, _set_vdd) \
+	struct clk_vdd_class _name = { \
+		.class_name = #_name, \
+		.set_vdd = _set_vdd, \
+		.cur_level = ARRAY_SIZE(_name.level_votes), \
+		.lock = __SPIN_LOCK_UNLOCKED(lock) \
+	}
+
+enum handoff {
+	HANDOFF_ENABLED_CLK,
+	HANDOFF_DISABLED_CLK,
+	HANDOFF_UNKNOWN_RATE,
+};
+
+struct clk_ops {
+	int (*prepare)(struct clk *clk);
+	int (*enable)(struct clk *clk);
+	void (*disable)(struct clk *clk);
+	void (*unprepare)(struct clk *clk);
+	void (*enable_hwcg)(struct clk *clk);
+	void (*disable_hwcg)(struct clk *clk);
+	int (*in_hwcg_mode)(struct clk *clk);
+	enum handoff (*handoff)(struct clk *clk);
+	int (*reset)(struct clk *clk, enum clk_reset_action action);
+	int (*set_rate)(struct clk *clk, unsigned long rate);
+	int (*set_max_rate)(struct clk *clk, unsigned long rate);
+	int (*set_flags)(struct clk *clk, unsigned flags);
+	unsigned long (*get_rate)(struct clk *clk);
+	int (*list_rate)(struct clk *clk, unsigned n);
+	int (*is_enabled)(struct clk *clk);
+	long (*round_rate)(struct clk *clk, unsigned long rate);
+	int (*set_parent)(struct clk *clk, struct clk *parent);
+	struct clk *(*get_parent)(struct clk *clk);
+	bool (*is_local)(struct clk *clk);
+};
+
+/**
+ * struct clk
+ * @prepare_count: prepare refcount
+ * @prepare_lock: protects clk_prepare()/clk_unprepare() path and @prepare_count
+ * @count: enable refcount
+ * @lock: protects clk_enable()/clk_disable() path and @count
+ * @depends: non-direct parent of clock to enable when this clock is enabled
+ * @vdd_class: voltage scaling requirement class
+ * @fmax: maximum frequency in Hz supported at each voltage level
+ */
+struct clk {
+	uint32_t flags;
+	struct clk_ops *ops;
+	const char *dbg_name;
+	struct clk *depends;
+	struct clk_vdd_class *vdd_class;
+	unsigned long fmax[MAX_VDD_LEVELS];
+	unsigned long rate;
+
+	struct list_head children;
+	struct list_head siblings;
+
+	unsigned count;
+	spinlock_t lock;
+	unsigned prepare_count;
+	struct mutex prepare_lock;
+};
+
+#define CLK_INIT(name) \
+	.lock = __SPIN_LOCK_UNLOCKED((name).lock), \
+	.prepare_lock = __MUTEX_INITIALIZER((name).prepare_lock), \
+	.children = LIST_HEAD_INIT((name).children), \
+	.siblings = LIST_HEAD_INIT((name).siblings)
+
+int vote_vdd_level(struct clk_vdd_class *vdd_class, int level);
+int unvote_vdd_level(struct clk_vdd_class *vdd_class, int level);
+
+/* Register clocks with the MSM clock driver */
+int msm_clock_register(struct clk_lookup *table, size_t size);
+
+extern struct clk dummy_clk;
+
+#define CLK_DUMMY(clk_name, clk_id, clk_dev, flags) { \
+	.con_id = clk_name, \
+	.dev_id = clk_dev, \
+	.clk = &dummy_clk, \
+	}
+
+#define CLK_LOOKUP(con, c, dev) { .con_id = con, .clk = &c, .dev_id = dev }
+
+#endif
diff --git a/arch/arm/mach-msm/include/mach/clk.h b/arch/arm/mach-msm/include/mach/clk.h
index 8c0ebfa..d69b372 100644
--- a/arch/arm/mach-msm/include/mach/clk.h
+++ b/arch/arm/mach-msm/include/mach/clk.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2009, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2009, 2012 Code Aurora Forum. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -12,19 +12,24 @@
 #ifndef __MACH_CLK_H
 #define __MACH_CLK_H
 
-/* Magic rate value for use with PM QOS to request the board's maximum
- * supported AXI rate. PM QOS will only pass positive s32 rate values
- * through to the clock driver, so INT_MAX is used.
- */
-#define MSM_AXI_MAX_FREQ	LONG_MAX
+#define CLKFLAG_INVERT			0x00000001
+#define CLKFLAG_NOINVERT		0x00000002
+#define CLKFLAG_NONEST			0x00000004
+#define CLKFLAG_NORESET			0x00000008
+#define CLKFLAG_RETAIN			0x00000040
+#define CLKFLAG_NORETAIN		0x00000080
+#define CLKFLAG_SKIP_HANDOFF		0x00000100
+#define CLKFLAG_MIN			0x00000400
+#define CLKFLAG_MAX			0x00000800
+
+struct clk_lookup;
+struct clk;
 
 enum clk_reset_action {
 	CLK_RESET_DEASSERT	= 0,
 	CLK_RESET_ASSERT	= 1
 };
 
-struct clk;
-
 /* Rate is maximum clock rate in Hz */
 int clk_set_max_rate(struct clk *clk, unsigned long rate);
 
diff --git a/arch/arm/mach-msm/qdsp6v2/q6core.h b/arch/arm/mach-msm/include/mach/qdsp6v2/q6core.h
similarity index 81%
rename from arch/arm/mach-msm/qdsp6v2/q6core.h
rename to arch/arm/mach-msm/include/mach/qdsp6v2/q6core.h
index cb25d6b..ea345fb 100644
--- a/arch/arm/mach-msm/qdsp6v2/q6core.h
+++ b/arch/arm/mach-msm/include/mach/qdsp6v2/q6core.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2011-2012, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -45,8 +45,18 @@
 	uint32_t power_collapse;
 };
 
+#define ADSP_CMD_SET_DTS_MODEL_ID 0x00012917
+
+struct adsp_dts_modelid {
+	struct apr_hdr hdr;
+	uint32_t  model_ID_size;
+	uint8_t   model_ID[128];
+};
+
 int core_req_bus_bandwith(u16 bus_id, u32 ab_bps, u32 ib_bps);
 
 uint32_t core_get_adsp_version(void);
 
+uint32_t core_set_dts_model_id(uint32_t id_size, uint8_t *id);
+
 #endif /* __Q6CORE_H__ */
diff --git a/arch/arm/mach-msm/jtag.c b/arch/arm/mach-msm/jtag.c
index 4f14b19..24e1c41 100644
--- a/arch/arm/mach-msm/jtag.c
+++ b/arch/arm/mach-msm/jtag.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -20,11 +20,10 @@
 #include <linux/printk.h>
 #include <linux/ratelimit.h>
 #include <linux/coresight.h>
+#include <asm/hardware/cp14.h>
 #include <mach/scm.h>
 #include <mach/jtag.h>
 
-#include "cp14.h"
-
 /* DBGv7 with baseline CP14 registers implemented */
 #define ARM_DEBUG_ARCH_V7B	(0x3)
 /* DBGv7 with all CP14 registers implemented */
diff --git a/arch/arm/mach-msm/mdm.c b/arch/arm/mach-msm/mdm.c
index 4280fb4..02978cf 100644
--- a/arch/arm/mach-msm/mdm.c
+++ b/arch/arm/mach-msm/mdm.c
@@ -28,7 +28,6 @@
 #include <linux/debugfs.h>
 #include <linux/completion.h>
 #include <linux/workqueue.h>
-#include <linux/clk.h>
 #include <asm/mach-types.h>
 #include <asm/uaccess.h>
 #include <linux/mfd/pm8xxx/misc.h>
@@ -39,7 +38,6 @@
 #include <linux/msm_charm.h>
 #include "msm_watchdog.h"
 #include "devices.h"
-#include "clock.h"
 
 #define CHARM_MODEM_TIMEOUT	6000
 #define CHARM_HOLD_TIME		4000
diff --git a/arch/arm/mach-msm/mdm2.c b/arch/arm/mach-msm/mdm2.c
index 43c85bb..f548417 100644
--- a/arch/arm/mach-msm/mdm2.c
+++ b/arch/arm/mach-msm/mdm2.c
@@ -28,7 +28,6 @@
 #include <linux/debugfs.h>
 #include <linux/completion.h>
 #include <linux/workqueue.h>
-#include <linux/clk.h>
 #include <linux/mfd/pmic8058.h>
 #include <asm/mach-types.h>
 #include <asm/uaccess.h>
@@ -39,7 +38,6 @@
 #include <linux/msm_charm.h>
 #include "msm_watchdog.h"
 #include "devices.h"
-#include "clock.h"
 #include "mdm_private.h"
 #define MDM_PBLRDY_CNT		20
 
diff --git a/arch/arm/mach-msm/mpm.c b/arch/arm/mach-msm/mpm.c
index 1c39415..5127607 100644
--- a/arch/arm/mach-msm/mpm.c
+++ b/arch/arm/mach-msm/mpm.c
@@ -388,6 +388,7 @@
 {
 	unsigned long *apps_irq_bitmap;
 	int debug_mask;
+	int i = 0;
 
 	if (from_idle) {
 		apps_irq_bitmap = msm_mpm_enabled_apps_irqs;
@@ -400,15 +401,17 @@
 	}
 
 	if (debug_mask) {
-		static char buf[DIV_ROUND_UP(MSM_MPM_NR_APPS_IRQS, 32)*9+1];
+		i = find_first_bit(apps_irq_bitmap, MSM_MPM_NR_APPS_IRQS);
+		while (i < MSM_MPM_NR_APPS_IRQS) {
+			struct irq_desc *desc = i ?
+				irq_to_desc(i) : NULL;
+			pr_info("%s: cannot monitor irq=%d %s\n",
+			__func__, i, desc->name);
+			i = find_next_bit(apps_irq_bitmap,
+				MSM_MPM_NR_APPS_IRQS, i + 1);
+		}
 
-		bitmap_scnprintf(buf, sizeof(buf), apps_irq_bitmap,
-				MSM_MPM_NR_APPS_IRQS);
-		buf[sizeof(buf) - 1] = '\0';
-
-		pr_info("%s: cannot monitor %s", __func__, buf);
 	}
-
 	return (bool)__bitmap_empty(apps_irq_bitmap, MSM_MPM_NR_APPS_IRQS);
 }
 
diff --git a/arch/arm/mach-msm/ocmem_core.c b/arch/arm/mach-msm/ocmem_core.c
index 5a85eec..9a85a17 100644
--- a/arch/arm/mach-msm/ocmem_core.c
+++ b/arch/arm/mach-msm/ocmem_core.c
@@ -856,7 +856,7 @@
 /* Interfaces invoked from the scheduler */
 int ocmem_memory_off(int id, unsigned long offset, unsigned long len)
 {
-	return switch_power_state(id, offset, len, REGION_DEFAULT_OFF);
+	return switch_power_state(id, offset, len, REGION_DEFAULT_ON);
 }
 
 int ocmem_memory_on(int id, unsigned long offset, unsigned long len)
@@ -866,7 +866,7 @@
 
 int ocmem_memory_retain(int id, unsigned long offset, unsigned long len)
 {
-	return switch_power_state(id, offset, len, REGION_DEFAULT_RETENTION);
+	return switch_power_state(id, offset, len, REGION_DEFAULT_ON);
 }
 
 static int ocmem_power_show_sw_state(struct seq_file *f, void *dummy)
diff --git a/arch/arm/mach-msm/qdsp5/adsp_driver.c b/arch/arm/mach-msm/qdsp5/adsp_driver.c
index 9d261ae..6419bd0 100644
--- a/arch/arm/mach-msm/qdsp5/adsp_driver.c
+++ b/arch/arm/mach-msm/qdsp5/adsp_driver.c
@@ -139,7 +139,7 @@
 		pr_err("%s: could not get flags for the handle\n", __func__);
 		goto flag_error;
 	}
-	temp_ptr = ion_map_kernel(region->client, region->handle, ionflag);
+	temp_ptr = ion_map_kernel(region->client, region->handle);
 	if (IS_ERR_OR_NULL(temp_ptr)) {
 		pr_err("%s: could not get virtual address\n", __func__);
 		goto map_error;
@@ -267,7 +267,7 @@
 			module->name, vaddr, len);
 		return ret;
 	}
-	if ((region->ion_flag == CACHED) && region->handle) {
+	if ((region->ion_flag == ION_FLAG_CACHED) && region->handle) {
 		len = ((((len) + 31) & (~31)) + 32);
 		ret = msm_ion_do_cache_op(region->client, region->handle,
 				(void *)paddr, len, cmd);
diff --git a/arch/arm/mach-msm/qdsp5/audio_aac.c b/arch/arm/mach-msm/qdsp5/audio_aac.c
index ac7cca3..46a80d7 100644
--- a/arch/arm/mach-msm/qdsp5/audio_aac.c
+++ b/arch/arm/mach-msm/qdsp5/audio_aac.c
@@ -1716,7 +1716,7 @@
 
 	MM_DBG("allocating mem sz = %d\n", mem_sz);
 	handle = ion_alloc(client, mem_sz, SZ_4K,
-		ION_HEAP(ION_AUDIO_HEAP_ID));
+		ION_HEAP(ION_AUDIO_HEAP_ID), 0);
 	if (IS_ERR_OR_NULL(handle)) {
 		MM_ERR("Unable to create allocate O/P buffers\n");
 		rc = -ENOMEM;
@@ -1742,7 +1742,7 @@
 		goto output_buff_get_flags_error;
 	}
 
-	audio->map_v_write = ion_map_kernel(client, handle, ionflag);
+	audio->map_v_write = ion_map_kernel(client, handle);
 	if (IS_ERR(audio->map_v_write)) {
 		MM_ERR("could not map write buffers,freeing instance 0x%08x\n",
 				(int)audio);
@@ -1758,7 +1758,7 @@
 	mem_sz = (PCM_BUFSZ_MIN * PCM_BUF_MAX_COUNT);
 	MM_DBG("allocating mem sz = %d\n", mem_sz);
 	handle = ion_alloc(client, mem_sz,
-			SZ_4K, ION_HEAP(ION_AUDIO_HEAP_ID));
+			SZ_4K, ION_HEAP(ION_AUDIO_HEAP_ID), 0);
 	if (IS_ERR_OR_NULL(handle)) {
 		MM_ERR("Unable to create allocate I/P buffers\n");
 		rc = -ENOMEM;
@@ -1785,8 +1785,7 @@
 		goto input_buff_get_flags_error;
 	}
 
-	audio->map_v_read = ion_map_kernel(client,
-		handle, ionflag);
+	audio->map_v_read = ion_map_kernel(client, handle);
 	if (IS_ERR(audio->map_v_read)) {
 		MM_ERR("could not map read buffers, freeing instance \
 				0x%08x\n", (int)audio);
diff --git a/arch/arm/mach-msm/qdsp5/audio_aac_in.c b/arch/arm/mach-msm/qdsp5/audio_aac_in.c
index 2e64a09..c86c1dd 100644
--- a/arch/arm/mach-msm/qdsp5/audio_aac_in.c
+++ b/arch/arm/mach-msm/qdsp5/audio_aac_in.c
@@ -1370,7 +1370,7 @@
 
 	MM_DBG("allocating mem sz = %d\n", dma_size);
 	handle = ion_alloc(client, dma_size, SZ_4K,
-		ION_HEAP(ION_AUDIO_HEAP_ID));
+		ION_HEAP(ION_AUDIO_HEAP_ID), 0);
 	if (IS_ERR_OR_NULL(handle)) {
 		MM_ERR("Unable to create allocate O/P buffers\n");
 		rc = -ENOMEM;
@@ -1398,7 +1398,7 @@
 		goto output_buff_get_flags_error;
 	}
 
-	audio->map_v_read = ion_map_kernel(client, handle, ionflag);
+	audio->map_v_read = ion_map_kernel(client, handle);
 	if (IS_ERR(audio->map_v_read)) {
 		MM_ERR("could not map read buffers,freeing instance 0x%08x\n",
 				(int)audio);
@@ -1414,7 +1414,7 @@
 
 		MM_DBG("allocating BUFFER_SIZE  %d\n", BUFFER_SIZE);
 		handle = ion_alloc(client, BUFFER_SIZE,
-				SZ_4K, ION_HEAP(ION_AUDIO_HEAP_ID));
+				SZ_4K, ION_HEAP(ION_AUDIO_HEAP_ID), 0);
 		if (IS_ERR_OR_NULL(handle)) {
 			MM_ERR("Unable to create allocate I/P buffers\n");
 			rc = -ENOMEM;
@@ -1444,8 +1444,7 @@
 			goto input_buff_get_flags_error;
 		}
 
-		audio->map_v_write = ion_map_kernel(client,
-			handle, ionflag);
+		audio->map_v_write = ion_map_kernel(client, handle);
 		if (IS_ERR(audio->map_v_write)) {
 			MM_ERR("could not map write buffers\n");
 			rc = -ENOMEM;
diff --git a/arch/arm/mach-msm/qdsp5/audio_ac3.c b/arch/arm/mach-msm/qdsp5/audio_ac3.c
index 63904fb..e453ec5 100644
--- a/arch/arm/mach-msm/qdsp5/audio_ac3.c
+++ b/arch/arm/mach-msm/qdsp5/audio_ac3.c
@@ -1029,7 +1029,7 @@
 				handle = ion_alloc(audio->client,
 					(config.buffer_size *
 					config.buffer_count),
-					SZ_4K, ION_HEAP(ION_AUDIO_HEAP_ID));
+					SZ_4K, ION_HEAP(ION_AUDIO_HEAP_ID), 0);
 				if (IS_ERR_OR_NULL(handle)) {
 					MM_ERR("Unable to alloc I/P buffs\n");
 					audio->input_buff_handle = NULL;
@@ -1067,8 +1067,7 @@
 				}
 
 				audio->map_v_read = ion_map_kernel(
-					audio->client,
-					handle, ionflag);
+					audio->client, handle);
 				if (IS_ERR(audio->map_v_read)) {
 					MM_ERR("map of read buf failed\n");
 					ion_free(audio->client, handle);
@@ -1588,7 +1587,7 @@
 	audio->client = client;
 
 	handle = ion_alloc(client, DMASZ, SZ_4K,
-			ION_HEAP(ION_AUDIO_HEAP_ID));
+			ION_HEAP(ION_AUDIO_HEAP_ID), 0);
 	if (IS_ERR_OR_NULL(handle)) {
 		MM_ERR("Unable to create allocate O/P buffers\n");
 		rc = -ENOMEM;
@@ -1614,7 +1613,7 @@
 		goto output_buff_get_flags_error;
 	}
 
-	audio->map_v_write = ion_map_kernel(client, handle, ionflag);
+	audio->map_v_write = ion_map_kernel(client, handle);
 	if (IS_ERR(audio->map_v_write)) {
 		MM_ERR("could not map write buffers,freeing instance 0x%08x\n",
 				(int)audio);
diff --git a/arch/arm/mach-msm/qdsp5/audio_amrnb.c b/arch/arm/mach-msm/qdsp5/audio_amrnb.c
index 8aa102a..0792e3f 100644
--- a/arch/arm/mach-msm/qdsp5/audio_amrnb.c
+++ b/arch/arm/mach-msm/qdsp5/audio_amrnb.c
@@ -981,7 +981,7 @@
 				handle = ion_alloc(audio->client,
 					(config.buffer_size *
 					config.buffer_count),
-					SZ_4K, ION_HEAP(ION_AUDIO_HEAP_ID));
+					SZ_4K, ION_HEAP(ION_AUDIO_HEAP_ID), 0);
 				if (IS_ERR_OR_NULL(handle)) {
 					MM_ERR("Unable to alloc I/P buffs\n");
 					audio->input_buff_handle = NULL;
@@ -1018,8 +1018,7 @@
 					break;
 				}
 				audio->map_v_read = ion_map_kernel(
-					audio->client,
-					handle, ionflag);
+					audio->client, handle);
 			if (IS_ERR(audio->map_v_read)) {
 				MM_ERR("failed to map read buf\n");
 				ion_free(audio->client, handle);
@@ -1536,7 +1535,7 @@
 	audio->client = client;
 
 	handle = ion_alloc(client, mem_sz, SZ_4K,
-		ION_HEAP(ION_AUDIO_HEAP_ID));
+		ION_HEAP(ION_AUDIO_HEAP_ID), 0);
 	if (IS_ERR_OR_NULL(handle)) {
 		MM_ERR("Unable to create allocate O/P buffers\n");
 		rc = -ENOMEM;
@@ -1562,7 +1561,7 @@
 		goto output_buff_get_flags_error;
 	}
 
-	audio->map_v_write = ion_map_kernel(client, handle, ionflag);
+	audio->map_v_write = ion_map_kernel(client, handle);
 	if (IS_ERR(audio->map_v_write)) {
 		MM_ERR("could not map write buffers\n");
 		rc = -ENOMEM;
diff --git a/arch/arm/mach-msm/qdsp5/audio_amrnb_in.c b/arch/arm/mach-msm/qdsp5/audio_amrnb_in.c
index 4effc8e..0742686 100644
--- a/arch/arm/mach-msm/qdsp5/audio_amrnb_in.c
+++ b/arch/arm/mach-msm/qdsp5/audio_amrnb_in.c
@@ -1336,7 +1336,7 @@
 	if (audio->mode == MSM_AUD_ENC_MODE_NONTUNNEL) {
 		MM_DBG("allocating BUFFER_SIZE  %d\n", BUFFER_SIZE);
 		handle = ion_alloc(client, BUFFER_SIZE,
-				SZ_4K, ION_HEAP(ION_AUDIO_HEAP_ID));
+				SZ_4K, ION_HEAP(ION_AUDIO_HEAP_ID), 0);
 		if (IS_ERR_OR_NULL(handle)) {
 			MM_ERR("Unable to create allocate write buffers\n");
 			rc = -ENOMEM;
@@ -1366,8 +1366,7 @@
 			goto input_buff_get_flags_error;
 		}
 
-		audio->map_v_write = ion_map_kernel(client,
-			handle, ionflag);
+		audio->map_v_write = ion_map_kernel(client, handle);
 		if (IS_ERR(audio->map_v_write)) {
 			MM_ERR("could not map write buffers\n");
 			rc = -ENOMEM;
diff --git a/arch/arm/mach-msm/qdsp5/audio_amrwb.c b/arch/arm/mach-msm/qdsp5/audio_amrwb.c
index 83320f3..7d37cea 100644
--- a/arch/arm/mach-msm/qdsp5/audio_amrwb.c
+++ b/arch/arm/mach-msm/qdsp5/audio_amrwb.c
@@ -977,7 +977,7 @@
 				handle = ion_alloc(audio->client,
 					(config.buffer_size *
 					config.buffer_count),
-					SZ_4K, ION_HEAP(ION_AUDIO_HEAP_ID));
+					SZ_4K, ION_HEAP(ION_AUDIO_HEAP_ID), 0);
 				if (IS_ERR_OR_NULL(handle)) {
 					MM_ERR("Unable to alloc I/P buffs\n");
 					audio->input_buff_handle = NULL;
@@ -1014,8 +1014,7 @@
 					break;
 				}
 				audio->map_v_read = ion_map_kernel(
-					audio->client,
-					handle, ionflag);
+					audio->client, handle);
 			if (IS_ERR(audio->map_v_read)) {
 				MM_ERR("failed to map mem for read buf\n");
 				ion_free(audio->client, handle);
@@ -1600,7 +1599,7 @@
 	audio->client = client;
 
 	handle = ion_alloc(client, mem_sz, SZ_4K,
-		ION_HEAP(ION_AUDIO_HEAP_ID));
+		ION_HEAP(ION_AUDIO_HEAP_ID), 0);
 	if (IS_ERR_OR_NULL(handle)) {
 		MM_ERR("Unable to create allocate O/P buffers\n");
 		goto output_buff_alloc_error;
@@ -1625,7 +1624,7 @@
 		goto output_buff_get_flags_error;
 	}
 
-	audio->map_v_write = ion_map_kernel(client, handle, ionflag);
+	audio->map_v_write = ion_map_kernel(client, handle);
 	if (IS_ERR(audio->map_v_write)) {
 		MM_ERR("could not map write buffers\n");
 		rc = -ENOMEM;
diff --git a/arch/arm/mach-msm/qdsp5/audio_evrc.c b/arch/arm/mach-msm/qdsp5/audio_evrc.c
index c0486db..155b0e1 100644
--- a/arch/arm/mach-msm/qdsp5/audio_evrc.c
+++ b/arch/arm/mach-msm/qdsp5/audio_evrc.c
@@ -966,7 +966,7 @@
 				handle = ion_alloc(audio->client,
 					(config.buffer_size *
 					config.buffer_count),
-					SZ_4K, ION_HEAP(ION_AUDIO_HEAP_ID));
+					SZ_4K, ION_HEAP(ION_AUDIO_HEAP_ID), 0);
 				if (IS_ERR_OR_NULL(handle)) {
 					MM_ERR("Unable to alloc I/P buffs\n");
 					audio->input_buff_handle = NULL;
@@ -1003,8 +1003,7 @@
 					break;
 				}
 				audio->map_v_read = ion_map_kernel(
-					audio->client,
-					handle, ionflag);
+					audio->client, handle);
 				if (IS_ERR(audio->map_v_read)) {
 					MM_ERR("failed to map mem"
 							" for read buf\n");
@@ -1527,7 +1526,7 @@
 	audio->client = client;
 
 	handle = ion_alloc(client, mem_sz, SZ_4K,
-		ION_HEAP(ION_AUDIO_HEAP_ID));
+		ION_HEAP(ION_AUDIO_HEAP_ID), 0);
 	if (IS_ERR_OR_NULL(handle)) {
 		MM_ERR("Unable to create allocate O/P buffers\n");
 		rc = -ENOMEM;
@@ -1553,7 +1552,7 @@
 		goto output_buff_get_flags_error;
 	}
 
-	audio->map_v_write = ion_map_kernel(client, handle, ionflag);
+	audio->map_v_write = ion_map_kernel(client, handle);
 	if (IS_ERR(audio->map_v_write)) {
 		MM_ERR("could not map write buffers\n");
 		rc = -ENOMEM;
diff --git a/arch/arm/mach-msm/qdsp5/audio_evrc_in.c b/arch/arm/mach-msm/qdsp5/audio_evrc_in.c
index 9bf0e83..89ad974 100644
--- a/arch/arm/mach-msm/qdsp5/audio_evrc_in.c
+++ b/arch/arm/mach-msm/qdsp5/audio_evrc_in.c
@@ -1310,7 +1310,7 @@
 
 	MM_DBG("allocating mem sz = %d\n", dma_size);
 	handle = ion_alloc(client, dma_size, SZ_4K,
-		ION_HEAP(ION_AUDIO_HEAP_ID));
+		ION_HEAP(ION_AUDIO_HEAP_ID), 0);
 	if (IS_ERR_OR_NULL(handle)) {
 		MM_ERR("Unable to create allocate O/P buffers\n");
 		rc = -ENOMEM;
@@ -1338,7 +1338,7 @@
 		goto output_buff_get_flags_error;
 	}
 
-	audio->map_v_read = ion_map_kernel(client, handle, ionflag);
+	audio->map_v_read = ion_map_kernel(client, handle);
 	if (IS_ERR(audio->map_v_read)) {
 		MM_ERR("could not map read buffers,freeing instance 0x%08x\n",
 				(int)audio);
@@ -1353,7 +1353,7 @@
 	if (audio->mode == MSM_AUD_ENC_MODE_NONTUNNEL) {
 		MM_DBG("allocating BUFFER_SIZE  %d\n", BUFFER_SIZE);
 		handle = ion_alloc(client, BUFFER_SIZE,
-				SZ_4K, ION_HEAP(ION_AUDIO_HEAP_ID));
+				SZ_4K, ION_HEAP(ION_AUDIO_HEAP_ID), 0);
 		if (IS_ERR_OR_NULL(handle)) {
 			MM_ERR("Unable to create allocate I/P buffers\n");
 			rc = -ENOMEM;
@@ -1383,8 +1383,7 @@
 			goto input_buff_alloc_error;
 		}
 
-		audio->map_v_write = ion_map_kernel(client,
-			handle, ionflag);
+		audio->map_v_write = ion_map_kernel(client, handle);
 		if (IS_ERR(audio->map_v_write)) {
 			MM_ERR("could not map write buffers\n");
 			rc = -ENOMEM;
diff --git a/arch/arm/mach-msm/qdsp5/audio_lpa.c b/arch/arm/mach-msm/qdsp5/audio_lpa.c
index a067b83..8120d7b 100644
--- a/arch/arm/mach-msm/qdsp5/audio_lpa.c
+++ b/arch/arm/mach-msm/qdsp5/audio_lpa.c
@@ -741,7 +741,7 @@
 		pr_err("%s: could not get flags for the handle\n", __func__);
 		goto flag_error;
 	}
-	kvaddr = (unsigned long)ion_map_kernel(audio->client, handle, ionflag);
+	kvaddr = (unsigned long)ion_map_kernel(audio->client, handle);
 	if (IS_ERR_OR_NULL((void *)kvaddr)) {
 		pr_err("%s: could not get virtual address\n", __func__);
 		goto map_error;
diff --git a/arch/arm/mach-msm/qdsp5/audio_mp3.c b/arch/arm/mach-msm/qdsp5/audio_mp3.c
index cef3d99..b8c64be 100644
--- a/arch/arm/mach-msm/qdsp5/audio_mp3.c
+++ b/arch/arm/mach-msm/qdsp5/audio_mp3.c
@@ -1095,7 +1095,7 @@
 		goto flag_error;
 	}
 
-	temp_ptr = ion_map_kernel(audio->client, handle, ionflag);
+	temp_ptr = ion_map_kernel(audio->client, handle);
 	if (IS_ERR_OR_NULL(temp_ptr)) {
 		pr_err("%s: could not get virtual address\n", __func__);
 		goto map_error;
@@ -1525,7 +1525,7 @@
 				handle = ion_alloc(audio->client,
 					(config.buffer_size *
 					config.buffer_count),
-					SZ_4K, ION_HEAP(ION_AUDIO_HEAP_ID));
+					SZ_4K, ION_HEAP(ION_AUDIO_HEAP_ID), 0);
 				if (IS_ERR_OR_NULL(handle)) {
 					MM_ERR("Unable to alloc I/P buffs\n");
 					rc = -ENOMEM;
@@ -1558,8 +1558,7 @@
 				}
 
 				audio->map_v_read = ion_map_kernel(
-					audio->client,
-					handle, ionflag);
+					audio->client, handle);
 
 				if (IS_ERR(audio->map_v_read)) {
 					MM_ERR("map of read buf failed\n");
@@ -2254,7 +2253,7 @@
 		MM_DBG("memsz = %d\n", mem_sz);
 
 		handle = ion_alloc(client, mem_sz, SZ_4K,
-			ION_HEAP(ION_AUDIO_HEAP_ID));
+			ION_HEAP(ION_AUDIO_HEAP_ID), 0);
 		if (IS_ERR_OR_NULL(handle)) {
 			MM_ERR("Unable to create allocate O/P buffers\n");
 			rc = -ENOMEM;
@@ -2280,7 +2279,7 @@
 			goto output_buff_get_flags_error;
 		}
 
-		audio->map_v_write = ion_map_kernel(client, handle, ionflag);
+		audio->map_v_write = ion_map_kernel(client, handle);
 		if (IS_ERR(audio->map_v_write)) {
 			MM_ERR("could not map write buffers\n");
 			rc = -ENOMEM;
diff --git a/arch/arm/mach-msm/qdsp5/audio_pcm.c b/arch/arm/mach-msm/qdsp5/audio_pcm.c
index 340bcc6..3eb72c8 100644
--- a/arch/arm/mach-msm/qdsp5/audio_pcm.c
+++ b/arch/arm/mach-msm/qdsp5/audio_pcm.c
@@ -823,7 +823,7 @@
 		pr_err("%s: could not get flags for the handle\n", __func__);
 		goto flag_error;
 	}
-	kvaddr = (unsigned long)ion_map_kernel(audio->client, handle, ionflag);
+	kvaddr = (unsigned long)ion_map_kernel(audio->client, handle);
 	if (IS_ERR_OR_NULL((void *)kvaddr)) {
 		pr_err("%s: could not get virtual address\n", __func__);
 		goto map_error;
@@ -1576,7 +1576,7 @@
 		MM_DBG("memsz = %d\n", mem_sz);
 
 		handle = ion_alloc(client, mem_sz, SZ_4K,
-			ION_HEAP(ION_AUDIO_HEAP_ID));
+			ION_HEAP(ION_AUDIO_HEAP_ID), 0);
 		if (IS_ERR_OR_NULL(handle)) {
 			MM_ERR("Unable to create allocate O/P buffers\n");
 			rc = -ENOMEM;
@@ -1602,7 +1602,7 @@
 			goto output_buff_get_flags_error;
 		}
 
-		audio->map_v_write = ion_map_kernel(client, handle, ionflag);
+		audio->map_v_write = ion_map_kernel(client, handle);
 		if (IS_ERR(audio->map_v_write)) {
 			MM_ERR("could not map write buffers\n");
 			rc = -ENOMEM;
diff --git a/arch/arm/mach-msm/qdsp5/audio_pcm_in.c b/arch/arm/mach-msm/qdsp5/audio_pcm_in.c
index 2da1f19..68ffcfef 100644
--- a/arch/arm/mach-msm/qdsp5/audio_pcm_in.c
+++ b/arch/arm/mach-msm/qdsp5/audio_pcm_in.c
@@ -843,7 +843,7 @@
 
 	MM_DBG("allocating mem sz = %d\n", DMASZ);
 	handle = ion_alloc(client, DMASZ, SZ_4K,
-		ION_HEAP(ION_AUDIO_HEAP_ID));
+		ION_HEAP(ION_AUDIO_HEAP_ID), 0);
 	if (IS_ERR_OR_NULL(handle)) {
 		MM_ERR("Unable to create allocate O/P buffers\n");
 		rc = -ENOMEM;
@@ -871,7 +871,7 @@
 		goto output_buff_get_flags_error;
 	}
 
-	audio->data = ion_map_kernel(client, handle, ionflag);
+	audio->data = ion_map_kernel(client, handle);
 	if (IS_ERR(audio->data)) {
 		MM_ERR("could not map read buffers,freeing instance 0x%08x\n",
 				(int)audio);
diff --git a/arch/arm/mach-msm/qdsp5/audio_qcelp.c b/arch/arm/mach-msm/qdsp5/audio_qcelp.c
index 1a0c333..876c909 100644
--- a/arch/arm/mach-msm/qdsp5/audio_qcelp.c
+++ b/arch/arm/mach-msm/qdsp5/audio_qcelp.c
@@ -967,7 +967,7 @@
 				handle = ion_alloc(audio->client,
 					(config.buffer_size *
 					config.buffer_count),
-					SZ_4K, ION_HEAP(ION_AUDIO_HEAP_ID));
+					SZ_4K, ION_HEAP(ION_AUDIO_HEAP_ID), 0);
 				if (IS_ERR_OR_NULL(handle)) {
 					MM_ERR("Unable to alloc I/P buffs\n");
 					audio->input_buff_handle = NULL;
@@ -1004,8 +1004,7 @@
 					break;
 				}
 				audio->map_v_read = ion_map_kernel(
-					audio->client,
-					handle, ionflag);
+					audio->client, handle);
 				if (IS_ERR(audio->map_v_read)) {
 					MM_ERR("failed to map read buf\n");
 					ion_free(audio->client, handle);
@@ -1525,7 +1524,7 @@
 	audio->client = client;
 
 	handle = ion_alloc(client, mem_sz, SZ_4K,
-		ION_HEAP(ION_AUDIO_HEAP_ID));
+		ION_HEAP(ION_AUDIO_HEAP_ID), 0);
 	if (IS_ERR_OR_NULL(handle)) {
 		MM_ERR("Unable to create allocate O/P buffers\n");
 		rc = -ENOMEM;
@@ -1551,7 +1550,7 @@
 		goto output_buff_get_flags_error;
 	}
 
-	audio->map_v_write = ion_map_kernel(client, handle, ionflag);
+	audio->map_v_write = ion_map_kernel(client, handle);
 	if (IS_ERR(audio->map_v_write)) {
 		MM_ERR("could not map write buffers\n");
 		rc = -ENOMEM;
diff --git a/arch/arm/mach-msm/qdsp5/audio_qcelp_in.c b/arch/arm/mach-msm/qdsp5/audio_qcelp_in.c
index ee079bc..6ca3382 100644
--- a/arch/arm/mach-msm/qdsp5/audio_qcelp_in.c
+++ b/arch/arm/mach-msm/qdsp5/audio_qcelp_in.c
@@ -1312,7 +1312,7 @@
 
 	MM_DBG("allocating mem sz = %d\n", dma_size);
 	handle = ion_alloc(client, dma_size, SZ_4K,
-		ION_HEAP(ION_AUDIO_HEAP_ID));
+		ION_HEAP(ION_AUDIO_HEAP_ID), 0);
 	if (IS_ERR_OR_NULL(handle)) {
 		MM_ERR("Unable to create allocate O/P buffers\n");
 		rc = -ENOMEM;
@@ -1340,7 +1340,7 @@
 		goto output_buff_get_flags_error;
 	}
 
-	audio->map_v_read = ion_map_kernel(client, handle, ionflag);
+	audio->map_v_read = ion_map_kernel(client, handle);
 	if (IS_ERR(audio->map_v_read)) {
 		MM_ERR("could not map read buffers,freeing instance 0x%08x\n",
 				(int)audio);
@@ -1355,7 +1355,7 @@
 	if (audio->mode == MSM_AUD_ENC_MODE_NONTUNNEL) {
 		MM_DBG("allocating BUFFER_SIZE  %d\n", BUFFER_SIZE);
 		handle = ion_alloc(client, BUFFER_SIZE,
-				SZ_4K, ION_HEAP(ION_AUDIO_HEAP_ID));
+				SZ_4K, ION_HEAP(ION_AUDIO_HEAP_ID), 0);
 		if (IS_ERR_OR_NULL(handle)) {
 			MM_ERR("Unable to create allocate I/P buffers\n");
 			rc = -ENOMEM;
@@ -1385,8 +1385,7 @@
 			goto input_buff_get_flags_error;
 		}
 
-		audio->map_v_write = ion_map_kernel(client,
-			handle, ionflag);
+		audio->map_v_write = ion_map_kernel(client, handle);
 		if (IS_ERR(audio->map_v_write)) {
 			MM_ERR("could not map write buffers\n");
 			rc = -ENOMEM;
diff --git a/arch/arm/mach-msm/qdsp5/audio_wma.c b/arch/arm/mach-msm/qdsp5/audio_wma.c
index 0a77b58..6d520b4 100644
--- a/arch/arm/mach-msm/qdsp5/audio_wma.c
+++ b/arch/arm/mach-msm/qdsp5/audio_wma.c
@@ -1045,7 +1045,7 @@
 				handle = ion_alloc(audio->client,
 					(config.buffer_size *
 					config.buffer_count),
-					SZ_4K, ION_HEAP(ION_AUDIO_HEAP_ID));
+					SZ_4K, ION_HEAP(ION_AUDIO_HEAP_ID), 0);
 				if (IS_ERR_OR_NULL(handle)) {
 					MM_ERR("Unable to alloc I/P buffs\n");
 					audio->input_buff_handle = NULL;
@@ -1083,8 +1083,7 @@
 				}
 
 				audio->map_v_read = ion_map_kernel(
-					audio->client,
-					handle, ionflag);
+					audio->client, handle);
 				if (IS_ERR(audio->map_v_read)) {
 					MM_ERR("map of read buf failed\n");
 					ion_free(audio->client, handle);
@@ -1678,7 +1677,7 @@
 	audio->client = client;
 
 	handle = ion_alloc(client, mem_sz, SZ_4K,
-		ION_HEAP(ION_AUDIO_HEAP_ID));
+		ION_HEAP(ION_AUDIO_HEAP_ID), 0);
 	if (IS_ERR_OR_NULL(handle)) {
 		MM_ERR("Unable to create allocate O/P buffers\n");
 		rc = -ENOMEM;
@@ -1704,7 +1703,7 @@
 		goto output_buff_get_flags_error;
 	}
 
-	audio->map_v_write = ion_map_kernel(client, handle, ionflag);
+	audio->map_v_write = ion_map_kernel(client, handle);
 	if (IS_ERR(audio->map_v_write)) {
 		MM_ERR("could not map write buffers\n");
 		rc = -ENOMEM;
diff --git a/arch/arm/mach-msm/qdsp5/audio_wmapro.c b/arch/arm/mach-msm/qdsp5/audio_wmapro.c
index 82fc3f9..a08f3c9 100644
--- a/arch/arm/mach-msm/qdsp5/audio_wmapro.c
+++ b/arch/arm/mach-msm/qdsp5/audio_wmapro.c
@@ -1042,7 +1042,7 @@
 				handle = ion_alloc(audio->client,
 					(config.buffer_size *
 					config.buffer_count),
-					SZ_4K, ION_HEAP(ION_AUDIO_HEAP_ID));
+					SZ_4K, ION_HEAP(ION_AUDIO_HEAP_ID), 0);
 				if (IS_ERR_OR_NULL(handle)) {
 					MM_ERR("Unable to alloc I/P buffs\n");
 					audio->input_buff_handle = NULL;
@@ -1080,8 +1080,7 @@
 				}
 
 				audio->map_v_read = ion_map_kernel(
-					audio->client,
-					handle, ionflag);
+					audio->client, handle);
 				if (IS_ERR(audio->map_v_read)) {
 					MM_ERR("map of read buf failed\n");
 					ion_free(audio->client, handle);
@@ -1673,7 +1672,7 @@
 	audio->client = client;
 
 	handle = ion_alloc(client, mem_sz, SZ_4K,
-		ION_HEAP(ION_AUDIO_HEAP_ID));
+		ION_HEAP(ION_AUDIO_HEAP_ID), 0);
 	if (IS_ERR_OR_NULL(handle)) {
 		MM_ERR("Unable to create allocate O/P buffers\n");
 		rc = -ENOMEM;
@@ -1699,7 +1698,7 @@
 		goto output_buff_get_flags_error;
 	}
 
-	audio->map_v_write = ion_map_kernel(client, handle, ionflag);
+	audio->map_v_write = ion_map_kernel(client, handle);
 	if (IS_ERR(audio->map_v_write)) {
 		MM_ERR("could not map write buffers\n");
 		rc = -ENOMEM;
diff --git a/arch/arm/mach-msm/qdsp5v2/audio_amrnb_in.c b/arch/arm/mach-msm/qdsp5v2/audio_amrnb_in.c
index 2f03cd0..f1951f7 100644
--- a/arch/arm/mach-msm/qdsp5v2/audio_amrnb_in.c
+++ b/arch/arm/mach-msm/qdsp5v2/audio_amrnb_in.c
@@ -803,7 +803,7 @@
 	audio->client = client;
 
 	handle = ion_alloc(client, DMASZ, SZ_4K,
-		ION_HEAP(ION_AUDIO_HEAP_ID));
+		ION_HEAP(ION_AUDIO_HEAP_ID), 0);
 	if (IS_ERR_OR_NULL(handle)) {
 		MM_ERR("Unable to create allocate O/P buffers\n");
 		rc = -ENOMEM;
@@ -828,7 +828,7 @@
 		goto buff_get_flags_error;
 	}
 
-	audio->map_v_read = ion_map_kernel(client, handle, ionflag);
+	audio->map_v_read = ion_map_kernel(client, handle);
 	if (IS_ERR(audio->map_v_read)) {
 		MM_ERR("could not map write buffers\n");
 		rc = -ENOMEM;
diff --git a/arch/arm/mach-msm/qdsp5v2/audio_evrc_in.c b/arch/arm/mach-msm/qdsp5v2/audio_evrc_in.c
index 1180e8d..6e95dc5 100644
--- a/arch/arm/mach-msm/qdsp5v2/audio_evrc_in.c
+++ b/arch/arm/mach-msm/qdsp5v2/audio_evrc_in.c
@@ -1363,7 +1363,7 @@
 
 	MM_DBG("allocating mem sz = %d\n", DMASZ);
 	handle = ion_alloc(client, DMASZ, SZ_4K,
-		ION_HEAP(ION_AUDIO_HEAP_ID));
+		ION_HEAP(ION_AUDIO_HEAP_ID), 0);
 	if (IS_ERR_OR_NULL(handle)) {
 		MM_ERR("Unable to create allocate O/P buffers\n");
 		rc = -ENOMEM;
@@ -1391,7 +1391,7 @@
 		goto output_buff_get_flags_error;
 	}
 
-	audio->map_v_read = ion_map_kernel(client, handle, ionflag);
+	audio->map_v_read = ion_map_kernel(client, handle);
 	if (IS_ERR(audio->map_v_read)) {
 		MM_ERR("could not map read buffers,freeing instance 0x%08x\n",
 				(int)audio);
@@ -1458,7 +1458,7 @@
 
 	MM_DBG("allocating BUFFER_SIZE  %d\n", BUFFER_SIZE);
 	handle = ion_alloc(client, BUFFER_SIZE,
-			SZ_4K, ION_HEAP(ION_AUDIO_HEAP_ID));
+			SZ_4K, ION_HEAP(ION_AUDIO_HEAP_ID), 0);
 	if (IS_ERR_OR_NULL(handle)) {
 		MM_ERR("Unable to create allocate I/P buffers\n");
 		rc = -ENOMEM;
@@ -1488,8 +1488,7 @@
 		goto input_buff_alloc_error;
 	}
 
-	audio->map_v_write = ion_map_kernel(client,
-		handle, ionflag);
+	audio->map_v_write = ion_map_kernel(client, handle);
 	if (IS_ERR(audio->map_v_write)) {
 		MM_ERR("could not map write buffers\n");
 		rc = -ENOMEM;
diff --git a/arch/arm/mach-msm/qdsp5v2/audio_qcelp_in.c b/arch/arm/mach-msm/qdsp5v2/audio_qcelp_in.c
index 7fac2ea..8ad738e 100644
--- a/arch/arm/mach-msm/qdsp5v2/audio_qcelp_in.c
+++ b/arch/arm/mach-msm/qdsp5v2/audio_qcelp_in.c
@@ -1368,7 +1368,7 @@
 
 	MM_DBG("allocating mem sz = %d\n", DMASZ);
 	handle = ion_alloc(client, DMASZ, SZ_4K,
-		ION_HEAP(ION_AUDIO_HEAP_ID));
+		ION_HEAP(ION_AUDIO_HEAP_ID), 0);
 	if (IS_ERR_OR_NULL(handle)) {
 		MM_ERR("Unable to create allocate O/P buffers\n");
 		rc = -ENOMEM;
@@ -1396,7 +1396,7 @@
 		goto output_buff_get_flags_error;
 	}
 
-	audio->map_v_read = ion_map_kernel(client, handle, ionflag);
+	audio->map_v_read = ion_map_kernel(client, handle);
 	if (IS_ERR(audio->map_v_read)) {
 		MM_ERR("could not map read buffers,freeing instance 0x%08x\n",
 				(int)audio);
@@ -1465,7 +1465,7 @@
 
 	MM_DBG("allocating BUFFER_SIZE  %d\n", BUFFER_SIZE);
 	handle = ion_alloc(client, BUFFER_SIZE,
-			SZ_4K, ION_HEAP(ION_AUDIO_HEAP_ID));
+			SZ_4K, ION_HEAP(ION_AUDIO_HEAP_ID), 0);
 	if (IS_ERR_OR_NULL(handle)) {
 		MM_ERR("Unable to create allocate I/P buffers\n");
 		rc = -ENOMEM;
@@ -1495,8 +1495,7 @@
 		goto input_buff_alloc_error;
 	}
 
-	audio->map_v_write = ion_map_kernel(client,
-		handle, ionflag);
+	audio->map_v_write = ion_map_kernel(client, handle);
 	if (IS_ERR(audio->map_v_write)) {
 		MM_ERR("could not map write buffers\n");
 		rc = -ENOMEM;
diff --git a/arch/arm/mach-msm/qdsp5v2/audio_wma.c b/arch/arm/mach-msm/qdsp5v2/audio_wma.c
index 4ba5821..8562020 100644
--- a/arch/arm/mach-msm/qdsp5v2/audio_wma.c
+++ b/arch/arm/mach-msm/qdsp5v2/audio_wma.c
@@ -1061,7 +1061,7 @@
 				handle = ion_alloc(audio->client,
 					(config.buffer_size *
 					config.buffer_count),
-					SZ_4K, ION_HEAP(ION_AUDIO_HEAP_ID));
+					SZ_4K, ION_HEAP(ION_AUDIO_HEAP_ID), 0);
 				if (IS_ERR_OR_NULL(handle)) {
 					MM_ERR("Unable to alloc I/P buffs\n");
 					audio->input_buff_handle = NULL;
@@ -1099,8 +1099,7 @@
 				}
 
 				audio->map_v_read = ion_map_kernel(
-					audio->client,
-					handle, ionflag);
+					audio->client, handle);
 				if (IS_ERR(audio->map_v_read)) {
 					MM_ERR("map of read buf failed\n");
 					ion_free(audio->client, handle);
@@ -1696,7 +1695,7 @@
 	audio->client = client;
 
 	handle = ion_alloc(client, mem_sz, SZ_4K,
-		ION_HEAP(ION_AUDIO_HEAP_ID));
+		ION_HEAP(ION_AUDIO_HEAP_ID), 0);
 	if (IS_ERR_OR_NULL(handle)) {
 		MM_ERR("Unable to create allocate O/P buffers\n");
 		rc = -ENOMEM;
@@ -1722,7 +1721,7 @@
 		goto output_buff_get_flags_error;
 	}
 
-	audio->map_v_write = ion_map_kernel(client, handle, ionflag);
+	audio->map_v_write = ion_map_kernel(client, handle);
 	if (IS_ERR(audio->map_v_write)) {
 		MM_ERR("could not map write buffers\n");
 		rc = -ENOMEM;
diff --git a/arch/arm/mach-msm/qdsp6v2/adsprpc.c b/arch/arm/mach-msm/qdsp6v2/adsprpc.c
index 6e6f8e8..49008de 100644
--- a/arch/arm/mach-msm/qdsp6v2/adsprpc.c
+++ b/arch/arm/mach-msm/qdsp6v2/adsprpc.c
@@ -73,11 +73,10 @@
 	int err = 0;
 
 	buf->handle = ion_alloc(clnt, buf->size, SZ_4K,
-				ION_HEAP(ION_AUDIO_HEAP_ID));
+				ION_HEAP(ION_AUDIO_HEAP_ID), 0);
 	VERIFY(0 == IS_ERR_OR_NULL(buf->handle));
 	buf->virt = 0;
-	VERIFY(0 != (buf->virt = ion_map_kernel(clnt, buf->handle,
-						ION_SET_CACHE(CACHED))));
+	VERIFY(0 != (buf->virt = ion_map_kernel(clnt, buf->handle)));
 	VERIFY(0 == ion_phys(clnt, buf->handle, &buf->phys, &buf->size));
  bail:
 	if (err && !IS_ERR_OR_NULL(buf->handle))
diff --git a/arch/arm/mach-msm/qdsp6v2/audio_acdb.c b/arch/arm/mach-msm/qdsp6v2/audio_acdb.c
index 7298fa1..7272f97 100644
--- a/arch/arm/mach-msm/qdsp6v2/audio_acdb.c
+++ b/arch/arm/mach-msm/qdsp6v2/audio_acdb.c
@@ -662,7 +662,7 @@
 	}
 
 	kvptr = ion_map_kernel(acdb_data.ion_client,
-		acdb_data.ion_handle, 0);
+		acdb_data.ion_handle);
 	if (IS_ERR_OR_NULL(kvptr)) {
 		pr_err("%s: Could not get kernel virt addr!!!\n", __func__);
 		result = PTR_ERR(kvptr);
diff --git a/arch/arm/mach-msm/qdsp6v2/audio_lpa.c b/arch/arm/mach-msm/qdsp6v2/audio_lpa.c
index b5a382e..176f364 100644
--- a/arch/arm/mach-msm/qdsp6v2/audio_lpa.c
+++ b/arch/arm/mach-msm/qdsp6v2/audio_lpa.c
@@ -486,7 +486,7 @@
 		goto flag_error;
 	}
 
-	temp_ptr = ion_map_kernel(audio->client, handle, ionflag);
+	temp_ptr = ion_map_kernel(audio->client, handle);
 	if (IS_ERR_OR_NULL(temp_ptr)) {
 		pr_err("%s: could not get virtual address\n", __func__);
 		goto map_error;
diff --git a/arch/arm/mach-msm/qdsp6v2/audio_utils_aio.c b/arch/arm/mach-msm/qdsp6v2/audio_utils_aio.c
index 2e4b756..28bf5c6 100644
--- a/arch/arm/mach-msm/qdsp6v2/audio_utils_aio.c
+++ b/arch/arm/mach-msm/qdsp6v2/audio_utils_aio.c
@@ -676,7 +676,7 @@
 		goto flag_error;
 	}
 
-	temp_ptr = ion_map_kernel(audio->client, handle, ionflag);
+	temp_ptr = ion_map_kernel(audio->client, handle);
 	if (IS_ERR_OR_NULL(temp_ptr)) {
 		pr_err("%s: could not get virtual address\n", __func__);
 		goto map_error;
@@ -1057,8 +1057,14 @@
 	switch (cmd) {
 	case AUDIO_GET_STATS: {
 		struct msm_audio_stats stats;
+		uint64_t timestamp;
 		stats.byte_count = atomic_read(&audio->in_bytes);
 		stats.sample_count = atomic_read(&audio->in_samples);
+		timestamp = q6asm_get_session_time(audio->ac);
+		if (timestamp >= 0)
+			memcpy(&stats.unused[0], &timestamp, sizeof(timestamp));
+		else
+			pr_debug("Error while getting timestamp\n");
 		if (copy_to_user((void *)arg, &stats, sizeof(stats)))
 			rc = -EFAULT;
 		break;
diff --git a/arch/arm/mach-msm/qdsp6v2/lpa_if_hdmi.c b/arch/arm/mach-msm/qdsp6v2/lpa_if_hdmi.c
index c19fd85..63b3064 100644
--- a/arch/arm/mach-msm/qdsp6v2/lpa_if_hdmi.c
+++ b/arch/arm/mach-msm/qdsp6v2/lpa_if_hdmi.c
@@ -26,7 +26,7 @@
 #include <mach/msm_hdmi_audio.h>
 #include <mach/audio_dma_msm8k.h>
 #include <sound/dai.h>
-#include "q6core.h"
+#include <mach/qdsp6v2/q6core.h>
 
 #define DMA_ALLOC_BUF_SZ		(SZ_4K * 16)
 
diff --git a/arch/arm/mach-msm/qdsp6v2/q6core.c b/arch/arm/mach-msm/qdsp6v2/q6core.c
index d7de50e..9dd66e1 100644
--- a/arch/arm/mach-msm/qdsp6v2/q6core.c
+++ b/arch/arm/mach-msm/qdsp6v2/q6core.c
@@ -26,7 +26,7 @@
 #include <linux/delay.h>
 #include <mach/msm_smd.h>
 #include <mach/qdsp6v2/apr.h>
-#include "q6core.h"
+#include <mach/qdsp6v2/q6core.h>
 
 #define TIMEOUT_MS 1000
 
@@ -79,6 +79,10 @@
 			bus_bw_resp_received = 1;
 			wake_up(&bus_bw_req_wait);
 			break;
+		case ADSP_CMD_SET_DTS_MODEL_ID:
+			pr_debug("ADSP_CMD_SET_DTS_MODEL_ID status[0x%x]\n",
+					payload1[1]);
+			break;
 		default:
 			pr_err("Invalid cmd rsp[0x%x][0x%x]\n",
 					payload1[0], payload1[1]);
@@ -382,6 +386,35 @@
 	return count;
 }
 
+uint32_t core_set_dts_model_id(uint32_t id_size, uint8_t *id)
+{
+	struct adsp_dts_modelid payload;
+	int rc = 0;
+	pr_debug("core_set_dts_model_id(): Enter\n");
+	core_open();
+	if (core_handle_q) {
+		payload.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_EVENT,
+			APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
+		payload.hdr.pkt_size = APR_PKT_SIZE(APR_HDR_SIZE,
+					sizeof(uint32_t)+id_size);
+		payload.hdr.src_port = 0;
+		payload.hdr.dest_port = 0;
+		payload.hdr.token = 0;
+		payload.hdr.opcode = ADSP_CMD_SET_DTS_MODEL_ID;
+		payload.model_ID_size = id_size;
+		memcpy(payload.model_ID, id, id_size+1);
+		pr_debug("Send DTS sec opcode=%x modelID = %s, size=%d\n",
+			payload.hdr.opcode, (char *)payload.model_ID,
+			payload.model_ID_size);
+		rc = apr_send_pkt(core_handle_q, (uint32_t *)&payload);
+		if (rc < 0)
+			pr_err("%s: SET_DTS_DTS_MODEL_ID failed op[0x%x]rc[%d]\n",
+				__func__, payload.hdr.opcode, rc);
+	}
+	pr_debug("core_set_dts_model_id(): Exit\n");
+	return rc;
+}
+
 static const struct file_operations apr_debug_fops = {
 	.write = apr_debug_write,
 	.open = apr_debug_open,
diff --git a/arch/arm/mach-msm/qdsp6v2/q6voice.c b/arch/arm/mach-msm/qdsp6v2/q6voice.c
index 12a02c5..7464ed7 100644
--- a/arch/arm/mach-msm/qdsp6v2/q6voice.c
+++ b/arch/arm/mach-msm/qdsp6v2/q6voice.c
@@ -30,7 +30,7 @@
 #include <mach/qdsp6v2/rtac.h>
 #include <mach/qdsp6v2/audio_acdb.h>
 
-#include "q6core.h"
+#include <mach/qdsp6v2/q6core.h>
 
 
 #define TIMEOUT_MS 3000
diff --git a/arch/arm/mach-msm/smd_rpcrouter.c b/arch/arm/mach-msm/smd_rpcrouter.c
index 983d0c1..68c3dd3 100644
--- a/arch/arm/mach-msm/smd_rpcrouter.c
+++ b/arch/arm/mach-msm/smd_rpcrouter.c
@@ -2421,6 +2421,7 @@
 {
 	struct rpcrouter_xprt_info *xprt_info;
 	struct rpcrouter_xprt_work *xprt_work;
+	unsigned long flags;
 
 	/* Workqueue is created in init function which works for all existing
 	 * clients.  If this fails in the future, then it will need to be
@@ -2452,11 +2453,13 @@
 
 	xprt_info = xprt->priv;
 	if (xprt_info) {
+		spin_lock_irqsave(&xprt_info->lock, flags);
 		/* Check read_avail even for OPEN event to handle missed
 		   DATA events while processing the OPEN event*/
 		if (xprt->read_avail() >= xprt_info->need_len)
 			wake_lock(&xprt_info->wakelock);
 		wake_up(&xprt_info->read_wait);
+		spin_unlock_irqrestore(&xprt_info->lock, flags);
 	}
 }
 
diff --git a/arch/arm/mach-msm/wcnss-ssr-8974.c b/arch/arm/mach-msm/wcnss-ssr-8974.c
new file mode 100644
index 0000000..d8745fc
--- /dev/null
+++ b/arch/arm/mach-msm/wcnss-ssr-8974.c
@@ -0,0 +1,163 @@
+/* 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/kernel.h>
+#include <linux/interrupt.h>
+#include <linux/module.h>
+#include <linux/err.h>
+
+#include <mach/subsystem_restart.h>
+#include <mach/msm_smsm.h>
+
+#define MODULE_NAME			"wcnss_8974"
+#define MAX_SSR_REASON_LEN			0x51
+
+static int ss_restart_inprogress;
+static int wcnss_crash;
+static struct subsys_device *wcnss_ssr_dev;
+
+#define WCNSS_APSS_WDOG_BITE_RESET_RDY_IRQ		231
+
+static void log_wcnss_sfr(void)
+{
+	char *smem_reset_reason;
+	char buffer[MAX_SSR_REASON_LEN];
+	unsigned smem_reset_size;
+	unsigned size;
+
+	smem_reset_reason = smem_get_entry(SMEM_SSR_REASON_WCNSS0,
+			&smem_reset_size);
+
+	if (!smem_reset_reason || !smem_reset_size) {
+		pr_err("%s: wcnss subsystem failure reason: %s\n",
+				__func__, "(unknown, smem_get_entry failed)");
+	} else if (!smem_reset_reason[0]) {
+		pr_err("%s: wcnss subsystem failure reason: %s\n",
+				__func__, "(unknown, init string found)");
+	} else {
+		size = smem_reset_size < MAX_SSR_REASON_LEN ? smem_reset_size :
+			(MAX_SSR_REASON_LEN - 1);
+		memcpy(buffer, smem_reset_reason, size);
+		buffer[size] = '\0';
+		pr_err("%s: wcnss subsystem failure reason: %s\n",
+				__func__, buffer);
+		memset(smem_reset_reason, 0, smem_reset_size);
+		wmb();
+	}
+}
+
+static void restart_wcnss(void)
+{
+	log_wcnss_sfr();
+	subsystem_restart("wcnss");
+}
+
+static void smsm_state_cb_hdlr(void *data, uint32_t old_state,
+					uint32_t new_state)
+{
+	wcnss_crash = true;
+
+	pr_err("%s: smsm state changed\n", MODULE_NAME);
+
+	if (!(new_state & SMSM_RESET))
+		return;
+
+	if (ss_restart_inprogress) {
+		pr_err("%s: Ignoring smsm reset req, restart in progress\n",
+						MODULE_NAME);
+		return;
+	}
+
+	ss_restart_inprogress = true;
+	restart_wcnss();
+}
+
+
+static irqreturn_t wcnss_wdog_bite_irq_hdlr(int irq, void *dev_id)
+{
+	wcnss_crash = true;
+
+	if (ss_restart_inprogress) {
+		pr_err("%s: Ignoring wcnss bite irq, restart in progress\n",
+						MODULE_NAME);
+		return IRQ_HANDLED;
+	}
+
+	ss_restart_inprogress = true;
+	restart_wcnss();
+
+	return IRQ_HANDLED;
+}
+
+
+static int wcnss_shutdown(const struct subsys_desc *subsys)
+{
+	return 0;
+}
+
+static int wcnss_powerup(const struct subsys_desc *subsys)
+{
+	return 0;
+}
+
+/* wcnss crash handler */
+static void wcnss_crash_shutdown(const struct subsys_desc *subsys)
+{
+	pr_err("%s: crash shutdown : %d\n", MODULE_NAME, wcnss_crash);
+	if (wcnss_crash != true)
+		smsm_change_state(SMSM_APPS_STATE, SMSM_RESET, SMSM_RESET);
+}
+
+static int wcnss_ramdump(int enable,
+				const struct subsys_desc *crashed_subsys)
+{
+	return 0;
+}
+
+static struct subsys_desc wcnss_ssr = {
+	.name = "wcnss",
+	.shutdown = wcnss_shutdown,
+	.powerup = wcnss_powerup,
+	.ramdump = wcnss_ramdump,
+	.crash_shutdown = wcnss_crash_shutdown
+};
+
+static int __init wcnss_ssr_init(void)
+{
+	int ret;
+
+	ret = smsm_state_cb_register(SMSM_WCNSS_STATE, SMSM_RESET,
+					smsm_state_cb_hdlr, 0);
+	if (ret < 0) {
+		pr_err("%s: Unable to register smsm callback for wcnss Reset! %d\n",
+				MODULE_NAME, ret);
+		goto out;
+	}
+	ret = request_irq(WCNSS_APSS_WDOG_BITE_RESET_RDY_IRQ,
+			wcnss_wdog_bite_irq_hdlr, IRQF_TRIGGER_HIGH,
+				"wcnss_wdog", NULL);
+
+	if (ret < 0) {
+		pr_err("%s: Unable to register for wcnss bite interrupt (%d)\n",
+				MODULE_NAME, ret);
+		goto out;
+	}
+	wcnss_ssr_dev = subsys_register(&wcnss_ssr);
+	if (IS_ERR(wcnss_ssr_dev))
+		return PTR_ERR(wcnss_ssr_dev);
+
+	pr_info("%s: module initialized\n", MODULE_NAME);
+out:
+	return ret;
+}
+
+arch_initcall(wcnss_ssr_init);
diff --git a/drivers/coresight/Makefile b/drivers/coresight/Makefile
index a2815de..033e5a0 100644
--- a/drivers/coresight/Makefile
+++ b/drivers/coresight/Makefile
@@ -1,3 +1,3 @@
 obj-$(CONFIG_CONTROL_TRACE) += control_trace.o
 obj-$(CONFIG_OF) += of_coresight.o
-obj-$(CONFIG_MSM_QDSS) += coresight.o coresight-csr.o coresight-tmc.o coresight-tpiu.o coresight-etb.o coresight-funnel.o coresight-replicator.o coresight-stm.o coresight-etm.o
+obj-$(CONFIG_MSM_QDSS) += coresight.o coresight-csr.o coresight-tmc.o coresight-tpiu.o coresight-etb.o coresight-funnel.o coresight-replicator.o coresight-stm.o coresight-etm.o coresight-etm-cp14.o
diff --git a/drivers/coresight/coresight-etm-cp14.c b/drivers/coresight/coresight-etm-cp14.c
new file mode 100644
index 0000000..9a6c13a
--- /dev/null
+++ b/drivers/coresight/coresight-etm-cp14.c
@@ -0,0 +1,510 @@
+/* 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/kernel.h>
+#include <linux/types.h>
+#include <asm/hardware/cp14.h>
+
+static unsigned int etm_read_reg(uint32_t reg)
+{
+	switch (reg) {
+	case 0x0:
+		return etm_read(ETMCR);
+	case 0x1:
+		return etm_read(ETMCCR);
+	case 0x2:
+		return etm_read(ETMTRIGGER);
+	case 0x4:
+		return etm_read(ETMSR);
+	case 0x5:
+		return etm_read(ETMSCR);
+	case 0x6:
+		return etm_read(ETMTSSCR);
+	case 0x8:
+		return etm_read(ETMTEEVR);
+	case 0x9:
+		return etm_read(ETMTECR1);
+	case 0xB:
+		return etm_read(ETMFFLR);
+	case 0x10:
+		return etm_read(ETMACVR0);
+	case 0x11:
+		return etm_read(ETMACVR1);
+	case 0x12:
+		return etm_read(ETMACVR2);
+	case 0x13:
+		return etm_read(ETMACVR3);
+	case 0x14:
+		return etm_read(ETMACVR4);
+	case 0x15:
+		return etm_read(ETMACVR5);
+	case 0x16:
+		return etm_read(ETMACVR6);
+	case 0x17:
+		return etm_read(ETMACVR7);
+	case 0x18:
+		return etm_read(ETMACVR8);
+	case 0x19:
+		return etm_read(ETMACVR9);
+	case 0x1A:
+		return etm_read(ETMACVR10);
+	case 0x1B:
+		return etm_read(ETMACVR11);
+	case 0x1C:
+		return etm_read(ETMACVR12);
+	case 0x1D:
+		return etm_read(ETMACVR13);
+	case 0x1E:
+		return etm_read(ETMACVR14);
+	case 0x1F:
+		return etm_read(ETMACVR15);
+	case 0x20:
+		return etm_read(ETMACTR0);
+	case 0x21:
+		return etm_read(ETMACTR1);
+	case 0x22:
+		return etm_read(ETMACTR2);
+	case 0x23:
+		return etm_read(ETMACTR3);
+	case 0x24:
+		return etm_read(ETMACTR4);
+	case 0x25:
+		return etm_read(ETMACTR5);
+	case 0x26:
+		return etm_read(ETMACTR6);
+	case 0x27:
+		return etm_read(ETMACTR7);
+	case 0x28:
+		return etm_read(ETMACTR8);
+	case 0x29:
+		return etm_read(ETMACTR9);
+	case 0x2A:
+		return etm_read(ETMACTR10);
+	case 0x2B:
+		return etm_read(ETMACTR11);
+	case 0x2C:
+		return etm_read(ETMACTR12);
+	case 0x2D:
+		return etm_read(ETMACTR13);
+	case 0x2E:
+		return etm_read(ETMACTR14);
+	case 0x2F:
+		return etm_read(ETMACTR15);
+	case 0x50:
+		return etm_read(ETMCNTRLDVR0);
+	case 0x51:
+		return etm_read(ETMCNTRLDVR1);
+	case 0x52:
+		return etm_read(ETMCNTRLDVR2);
+	case 0x53:
+		return etm_read(ETMCNTRLDVR3);
+	case 0x54:
+		return etm_read(ETMCNTENR0);
+	case 0x55:
+		return etm_read(ETMCNTENR1);
+	case 0x56:
+		return etm_read(ETMCNTENR2);
+	case 0x57:
+		return etm_read(ETMCNTENR3);
+	case 0x58:
+		return etm_read(ETMCNTRLDEVR0);
+	case 0x59:
+		return etm_read(ETMCNTRLDEVR1);
+	case 0x5A:
+		return etm_read(ETMCNTRLDEVR2);
+	case 0x5B:
+		return etm_read(ETMCNTRLDEVR3);
+	case 0x5C:
+		return etm_read(ETMCNTVR0);
+	case 0x5D:
+		return etm_read(ETMCNTVR1);
+	case 0x5E:
+		return etm_read(ETMCNTVR2);
+	case 0x5F:
+		return etm_read(ETMCNTVR3);
+	case 0x60:
+		return etm_read(ETMSQ12EVR);
+	case 0x61:
+		return etm_read(ETMSQ21EVR);
+	case 0x62:
+		return etm_read(ETMSQ23EVR);
+	case 0x63:
+		return etm_read(ETMSQ31EVR);
+	case 0x64:
+		return etm_read(ETMSQ32EVR);
+	case 0x65:
+		return etm_read(ETMSQ13EVR);
+	case 0x67:
+		return etm_read(ETMSQR);
+	case 0x68:
+		return etm_read(ETMEXTOUTEVR0);
+	case 0x69:
+		return etm_read(ETMEXTOUTEVR1);
+	case 0x6A:
+		return etm_read(ETMEXTOUTEVR2);
+	case 0x6B:
+		return etm_read(ETMEXTOUTEVR3);
+	case 0x6C:
+		return etm_read(ETMCIDCVR0);
+	case 0x6D:
+		return etm_read(ETMCIDCVR1);
+	case 0x6E:
+		return etm_read(ETMCIDCVR2);
+	case 0x6F:
+		return etm_read(ETMCIDCMR);
+	case 0x70:
+		return etm_read(ETMIMPSPEC0);
+	case 0x71:
+		return etm_read(ETMIMPSPEC1);
+	case 0x72:
+		return etm_read(ETMIMPSPEC2);
+	case 0x73:
+		return etm_read(ETMIMPSPEC3);
+	case 0x74:
+		return etm_read(ETMIMPSPEC4);
+	case 0x75:
+		return etm_read(ETMIMPSPEC5);
+	case 0x76:
+		return etm_read(ETMIMPSPEC6);
+	case 0x77:
+		return etm_read(ETMIMPSPEC7);
+	case 0x78:
+		return etm_read(ETMSYNCFR);
+	case 0x79:
+		return etm_read(ETMIDR);
+	case 0x7A:
+		return etm_read(ETMCCER);
+	case 0x7B:
+		return etm_read(ETMEXTINSELR);
+	case 0x7C:
+		return etm_read(ETMTESSEICR);
+	case 0x7D:
+		return etm_read(ETMEIBCR);
+	case 0x7E:
+		return etm_read(ETMTSEVR);
+	case 0x7F:
+		return etm_read(ETMAUXCR);
+	case 0x80:
+		return etm_read(ETMTRACEIDR);
+	case 0x90:
+		return etm_read(ETMVMIDCVR);
+	case 0xC1:
+		return etm_read(ETMOSLSR);
+	case 0xC2:
+		return etm_read(ETMOSSRR);
+	case 0xC4:
+		return etm_read(ETMPDCR);
+	case 0xC5:
+		return etm_read(ETMPDSR);
+	default:
+		WARN(1, "invalid CP14 access to ETM reg: %lx",
+							(unsigned long)reg);
+		return 0;
+	}
+}
+
+static void etm_write_reg(uint32_t val, uint32_t reg)
+{
+	switch (reg) {
+	case 0x0:
+		etm_write(val, ETMCR);
+		return;
+	case 0x2:
+		etm_write(val, ETMTRIGGER);
+		return;
+	case 0x4:
+		etm_write(val, ETMSR);
+		return;
+	case 0x6:
+		etm_write(val, ETMTSSCR);
+		return;
+	case 0x8:
+		etm_write(val, ETMTEEVR);
+		return;
+	case 0x9:
+		etm_write(val, ETMTECR1);
+		return;
+	case 0xB:
+		etm_write(val, ETMFFLR);
+		return;
+	case 0x10:
+		etm_write(val, ETMACVR0);
+		return;
+	case 0x11:
+		etm_write(val, ETMACVR1);
+		return;
+	case 0x12:
+		etm_write(val, ETMACVR2);
+		return;
+	case 0x13:
+		etm_write(val, ETMACVR3);
+		return;
+	case 0x14:
+		etm_write(val, ETMACVR4);
+		return;
+	case 0x15:
+		etm_write(val, ETMACVR5);
+		return;
+	case 0x16:
+		etm_write(val, ETMACVR6);
+		return;
+	case 0x17:
+		etm_write(val, ETMACVR7);
+		return;
+	case 0x18:
+		etm_write(val, ETMACVR8);
+		return;
+	case 0x19:
+		etm_write(val, ETMACVR9);
+		return;
+	case 0x1A:
+		etm_write(val, ETMACVR10);
+		return;
+	case 0x1B:
+		etm_write(val, ETMACVR11);
+		return;
+	case 0x1C:
+		etm_write(val, ETMACVR12);
+		return;
+	case 0x1D:
+		etm_write(val, ETMACVR13);
+		return;
+	case 0x1E:
+		etm_write(val, ETMACVR14);
+		return;
+	case 0x1F:
+		etm_write(val, ETMACVR15);
+		return;
+	case 0x20:
+		etm_write(val, ETMACTR0);
+		return;
+	case 0x21:
+		etm_write(val, ETMACTR1);
+		return;
+	case 0x22:
+		etm_write(val, ETMACTR2);
+		return;
+	case 0x23:
+		etm_write(val, ETMACTR3);
+		return;
+	case 0x24:
+		etm_write(val, ETMACTR4);
+		return;
+	case 0x25:
+		etm_write(val, ETMACTR5);
+		return;
+	case 0x26:
+		etm_write(val, ETMACTR6);
+		return;
+	case 0x27:
+		etm_write(val, ETMACTR7);
+		return;
+	case 0x28:
+		etm_write(val, ETMACTR8);
+		return;
+	case 0x29:
+		etm_write(val, ETMACTR9);
+		return;
+	case 0x2A:
+		etm_write(val, ETMACTR10);
+		return;
+	case 0x2B:
+		etm_write(val, ETMACTR11);
+		return;
+	case 0x2C:
+		etm_write(val, ETMACTR12);
+		return;
+	case 0x2D:
+		etm_write(val, ETMACTR13);
+		return;
+	case 0x2E:
+		etm_write(val, ETMACTR14);
+		return;
+	case 0x2F:
+		etm_write(val, ETMACTR15);
+		return;
+	case 0x50:
+		etm_write(val, ETMCNTRLDVR0);
+		return;
+	case 0x51:
+		etm_write(val, ETMCNTRLDVR1);
+		return;
+	case 0x52:
+		etm_write(val, ETMCNTRLDVR2);
+		return;
+	case 0x53:
+		etm_write(val, ETMCNTRLDVR3);
+		return;
+	case 0x54:
+		etm_write(val, ETMCNTENR0);
+		return;
+	case 0x55:
+		etm_write(val, ETMCNTENR1);
+		return;
+	case 0x56:
+		etm_write(val, ETMCNTENR2);
+		return;
+	case 0x57:
+		etm_write(val, ETMCNTENR3);
+		return;
+	case 0x58:
+		etm_write(val, ETMCNTRLDEVR0);
+		return;
+	case 0x59:
+		etm_write(val, ETMCNTRLDEVR1);
+		return;
+	case 0x5A:
+		etm_write(val, ETMCNTRLDEVR2);
+		return;
+	case 0x5B:
+		etm_write(val, ETMCNTRLDEVR3);
+		return;
+	case 0x5C:
+		etm_write(val, ETMCNTVR0);
+		return;
+	case 0x5D:
+		etm_write(val, ETMCNTVR1);
+		return;
+	case 0x5E:
+		etm_write(val, ETMCNTVR2);
+		return;
+	case 0x5F:
+		etm_write(val, ETMCNTVR3);
+		return;
+	case 0x60:
+		etm_write(val, ETMSQ12EVR);
+		return;
+	case 0x61:
+		etm_write(val, ETMSQ21EVR);
+		return;
+	case 0x62:
+		etm_write(val, ETMSQ23EVR);
+		return;
+	case 0x63:
+		etm_write(val, ETMSQ31EVR);
+		return;
+	case 0x64:
+		etm_write(val, ETMSQ32EVR);
+		return;
+	case 0x65:
+		etm_write(val, ETMSQ13EVR);
+		return;
+	case 0x67:
+		etm_write(val, ETMSQR);
+		return;
+	case 0x68:
+		etm_write(val, ETMEXTOUTEVR0);
+		return;
+	case 0x69:
+		etm_write(val, ETMEXTOUTEVR1);
+		return;
+	case 0x6A:
+		etm_write(val, ETMEXTOUTEVR2);
+		return;
+	case 0x6B:
+		etm_write(val, ETMEXTOUTEVR3);
+		return;
+	case 0x6C:
+		etm_write(val, ETMCIDCVR0);
+		return;
+	case 0x6D:
+		etm_write(val, ETMCIDCVR1);
+		return;
+	case 0x6E:
+		etm_write(val, ETMCIDCVR2);
+		return;
+	case 0x6F:
+		etm_write(val, ETMCIDCMR);
+		return;
+	case 0x70:
+		etm_write(val, ETMIMPSPEC0);
+		return;
+	case 0x71:
+		etm_write(val, ETMIMPSPEC1);
+		return;
+	case 0x72:
+		etm_write(val, ETMIMPSPEC2);
+		return;
+	case 0x73:
+		etm_write(val, ETMIMPSPEC3);
+		return;
+	case 0x74:
+		etm_write(val, ETMIMPSPEC4);
+		return;
+	case 0x75:
+		etm_write(val, ETMIMPSPEC5);
+		return;
+	case 0x76:
+		etm_write(val, ETMIMPSPEC6);
+		return;
+	case 0x77:
+		etm_write(val, ETMIMPSPEC7);
+		return;
+	case 0x78:
+		etm_write(val, ETMSYNCFR);
+		return;
+	case 0x7B:
+		etm_write(val, ETMEXTINSELR);
+		return;
+	case 0x7C:
+		etm_write(val, ETMTESSEICR);
+		return;
+	case 0x7D:
+		etm_write(val, ETMEIBCR);
+		return;
+	case 0x7E:
+		etm_write(val, ETMTSEVR);
+		return;
+	case 0x7F:
+		etm_write(val, ETMAUXCR);
+		return;
+	case 0x80:
+		etm_write(val, ETMTRACEIDR);
+		return;
+	case 0x90:
+		etm_write(val, ETMVMIDCVR);
+		return;
+	case 0xC0:
+		etm_write(val, ETMOSLAR);
+		return;
+	case 0xC2:
+		etm_write(val, ETMOSSRR);
+		return;
+	case 0xC4:
+		etm_write(val, ETMPDCR);
+		return;
+	case 0xC5:
+		etm_write(val, ETMPDSR);
+		return;
+	default:
+		WARN(1, "invalid CP14 access to ETM reg: %lx",
+							(unsigned long)reg);
+		return;
+	}
+}
+
+static inline uint32_t offset_to_reg_num(uint32_t off)
+{
+	return off >> 2;
+}
+
+unsigned int etm_readl_cp14(uint32_t off)
+{
+	uint32_t reg = offset_to_reg_num(off);
+	return etm_read_reg(reg);
+}
+
+void etm_writel_cp14(uint32_t val, uint32_t off)
+{
+	uint32_t reg = offset_to_reg_num(off);
+	etm_write_reg(val, reg);
+}
diff --git a/drivers/coresight/coresight-etm.c b/drivers/coresight/coresight-etm.c
index f4c4d08..ce4d7d1 100644
--- a/drivers/coresight/coresight-etm.c
+++ b/drivers/coresight/coresight-etm.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2011-2012, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -35,20 +35,45 @@
 
 #include "coresight-priv.h"
 
-#define etm_writel(drvdata, val, off)	\
+#define etm_writel_mm(drvdata, val, off)  \
 			__raw_writel((val), drvdata->base + off)
-#define etm_readl(drvdata, off)		\
+#define etm_readl_mm(drvdata, off)        \
 			__raw_readl(drvdata->base + off)
 
+#define etm_writel(drvdata, val, off)					\
+({									\
+	if (cpu_is_krait_v3())						\
+		etm_writel_cp14(val, off);				\
+	else								\
+		etm_writel_mm(drvdata, val, off);			\
+})
+#define etm_readl(drvdata, off)						\
+({									\
+	uint32_t val;							\
+	if (cpu_is_krait_v3())						\
+		val = etm_readl_cp14(off);				\
+	else								\
+		val = etm_readl_mm(drvdata, off);			\
+	val;								\
+})
+
 #define ETM_LOCK(drvdata)						\
 do {									\
+	/* recommended by spec to ensure ETM writes are committed prior
+	 * to resuming execution
+	 */								\
 	mb();								\
-	etm_writel(drvdata, 0x0, CORESIGHT_LAR);			\
+	isb();								\
+	etm_writel_mm(drvdata, 0x0, CORESIGHT_LAR);			\
 } while (0)
 #define ETM_UNLOCK(drvdata)						\
 do {									\
-	etm_writel(drvdata, CORESIGHT_UNLOCK, CORESIGHT_LAR);		\
+	etm_writel_mm(drvdata, CORESIGHT_UNLOCK, CORESIGHT_LAR);	\
+	/* ensure unlock and any pending writes are committed prior to
+	 * programming ETM registers
+	 */								\
 	mb();								\
+	isb();								\
 } while (0)
 
 /*
@@ -214,22 +239,28 @@
  * clock vote in the driver and the save-restore code uses 1. above
  * for its vote
  */
-static void etm_set_pwrdwn(struct etm_drvdata *drvdata)
+static void etm_set_pwrup(struct etm_drvdata *drvdata)
 {
-	uint32_t etmcr;
+	uint32_t etmpdcr;
 
-	etmcr = etm_readl(drvdata, ETMCR);
-	etmcr |= BIT(0);
-	etm_writel(drvdata, etmcr, ETMCR);
+	etmpdcr = etm_readl_mm(drvdata, ETMPDCR);
+	etmpdcr |= BIT(3);
+	etm_writel_mm(drvdata, etmpdcr, ETMPDCR);
+	/* ensure pwrup completes before subsequent cp14 accesses */
+	mb();
+	isb();
 }
 
-static void etm_clr_pwrdwn(struct etm_drvdata *drvdata)
+static void etm_clr_pwrup(struct etm_drvdata *drvdata)
 {
-	uint32_t etmcr;
+	uint32_t etmpdcr;
 
-	etmcr = etm_readl(drvdata, ETMCR);
-	etmcr &= ~BIT(0);
-	etm_writel(drvdata, etmcr, ETMCR);
+	/* ensure pending cp14 accesses complete before clearing pwrup */
+	mb();
+	isb();
+	etmpdcr = etm_readl_mm(drvdata, ETMPDCR);
+	etmpdcr &= ~BIT(3);
+	etm_writel_mm(drvdata, etmpdcr, ETMPDCR);
 }
 
 static void etm_set_prog(struct etm_drvdata *drvdata)
@@ -240,6 +271,10 @@
 	etmcr = etm_readl(drvdata, ETMCR);
 	etmcr |= BIT(10);
 	etm_writel(drvdata, etmcr, ETMCR);
+	/* recommended by spec for cp14 accesses to ensure etmcr write is
+	 * complete before polling etmsr
+	 */
+	isb();
 	for (count = TIMEOUT_US; BVAL(etm_readl(drvdata, ETMSR), 1) != 1
 				&& count > 0; count--)
 		udelay(1);
@@ -255,6 +290,10 @@
 	etmcr = etm_readl(drvdata, ETMCR);
 	etmcr &= ~BIT(10);
 	etm_writel(drvdata, etmcr, ETMCR);
+	/* recommended by spec for cp14 accesses to ensure etmcr write is
+	 * complete before polling etmsr
+	 */
+	isb();
 	for (count = TIMEOUT_US; BVAL(etm_readl(drvdata, ETMSR), 1) != 0
 				&& count > 0; count--)
 		udelay(1);
@@ -269,7 +308,7 @@
 
 	ETM_UNLOCK(drvdata);
 	/* Vote for ETM power/clock enable */
-	etm_clr_pwrdwn(drvdata);
+	etm_set_pwrup(drvdata);
 	etm_set_prog(drvdata);
 
 	etm_writel(drvdata, drvdata->ctrl | BIT(10), ETMCR);
@@ -352,7 +391,7 @@
 	etm_writel(drvdata, 0x6F | BIT(14), ETMTEEVR);
 
 	/* Vote for ETM power/clock disable */
-	etm_set_pwrdwn(drvdata);
+	etm_clr_pwrup(drvdata);
 	ETM_LOCK(drvdata);
 
 	dev_dbg(drvdata->dev, "cpu: %d disable smp call done\n", drvdata->cpu);
@@ -1416,17 +1455,24 @@
 	return true;
 }
 
-static void __devinit etm_init_arch_data(struct etm_drvdata *drvdata)
+static void __devinit etm_prepare_arch(struct etm_drvdata *drvdata)
+{
+	/* Unlock OS lock first to allow memory mapped reads and writes. This
+	 * is required for Krait pass1
+	 * */
+	etm_os_unlock(NULL);
+	smp_call_function(etm_os_unlock, NULL, 1);
+}
+
+static void __devinit etm_init_arch_data(void *info)
 {
 	uint32_t etmidr;
 	uint32_t etmccr;
+	struct etm_drvdata *drvdata = info;
 
-	/* Unlock OS lock first to allow memory mapped reads and writes */
-	etm_os_unlock(NULL);
-	smp_call_function(etm_os_unlock, NULL, 1);
 	ETM_UNLOCK(drvdata);
 	/* Vote for ETM power/clock enable */
-	etm_clr_pwrdwn(drvdata);
+	etm_set_pwrup(drvdata);
 	/* Set prog bit. It will be set from reset but this is included to
 	 * ensure it is set
 	 */
@@ -1444,7 +1490,7 @@
 	drvdata->nr_ctxid_cmp = BMVAL(etmccr, 24, 25);
 
 	/* Vote for ETM power/clock disable */
-	etm_set_pwrdwn(drvdata);
+	etm_clr_pwrup(drvdata);
 	ETM_LOCK(drvdata);
 }
 
@@ -1518,12 +1564,6 @@
 	struct msm_client_dump dump;
 	struct coresight_desc *desc;
 
-	/* Fail probe for Krait pass3 until supported */
-	if (cpu_is_krait_v3()) {
-		dev_info(dev, "ETM: failing probe for Krait pass3\n");
-		return -EINVAL;
-	}
-
 	if (pdev->dev.of_node) {
 		pdata = of_get_coresight_platform_data(dev, pdev->dev.of_node);
 		if (IS_ERR(pdata))
@@ -1569,7 +1609,9 @@
 	 * ETMs copy it over from ETM0.
 	 */
 	if (drvdata->cpu == 0) {
-		etm_init_arch_data(drvdata);
+		etm_prepare_arch(drvdata);
+		smp_call_function_single(drvdata->cpu, etm_init_arch_data,
+					 drvdata, 1);
 		etm0drvdata = drvdata;
 	} else {
 		etm_copy_arch_data(drvdata);
diff --git a/drivers/coresight/coresight-priv.h b/drivers/coresight/coresight-priv.h
index 2b00242..0cf2b3d 100644
--- a/drivers/coresight/coresight-priv.h
+++ b/drivers/coresight/coresight-priv.h
@@ -39,9 +39,13 @@
 #ifdef CONFIG_MSM_QDSS
 extern void msm_qdss_csr_enable_bam_to_usb(void);
 extern void msm_qdss_csr_disable_bam_to_usb(void);
+extern unsigned int etm_readl_cp14(uint32_t off);
+extern void etm_writel_cp14(uint32_t val, uint32_t off);
 #else
 static inline void msm_qdss_csr_enable_bam_to_usb(void) {}
 static inline void msm_qdss_csr_disable_bam_to_usb(void) {}
+static inline unsigned int etm_readl_cp14(uint32_t off) { return 0; }
+static inline void etm_writel_cp14(uint32_t val, uint32_t off) {}
 #endif
 
 #endif
diff --git a/drivers/gpio/gpio-msm-common.c b/drivers/gpio/gpio-msm-common.c
index 46f6460..800c376 100644
--- a/drivers/gpio/gpio-msm-common.c
+++ b/drivers/gpio/gpio-msm-common.c
@@ -300,9 +300,11 @@
 
 	spin_lock_irqsave(&tlmm_lock, irq_flags);
 	__set_bit(gpio, msm_gpio.enabled_irqs);
-	__msm_gpio_set_intr_status(gpio);
-	__msm_gpio_set_intr_cfg_enable(gpio, 1);
-	mb();
+	if (!__msm_gpio_get_intr_cfg_enable(gpio)) {
+		__msm_gpio_set_intr_status(gpio);
+		__msm_gpio_set_intr_cfg_enable(gpio, 1);
+		mb();
+	}
 	spin_unlock_irqrestore(&tlmm_lock, irq_flags);
 
 	if (msm_gpio_irq_extn.irq_mask)
diff --git a/drivers/gpio/gpio-msm-common.h b/drivers/gpio/gpio-msm-common.h
index c9ea3da..b1590ef 100644
--- a/drivers/gpio/gpio-msm-common.h
+++ b/drivers/gpio/gpio-msm-common.h
@@ -21,6 +21,7 @@
 unsigned __msm_gpio_get_intr_status(unsigned gpio);
 void __msm_gpio_set_intr_status(unsigned gpio);
 unsigned __msm_gpio_get_intr_config(unsigned gpio);
+unsigned __msm_gpio_get_intr_cfg_enable(unsigned gpio);
 void __msm_gpio_set_intr_cfg_enable(unsigned gpio, unsigned val);
 void __msm_gpio_set_intr_cfg_type(unsigned gpio, unsigned type);
 void __gpio_tlmm_config(unsigned config);
diff --git a/drivers/gpio/gpio-msm-v2.c b/drivers/gpio/gpio-msm-v2.c
index 943a4a2..592391e 100644
--- a/drivers/gpio/gpio-msm-v2.c
+++ b/drivers/gpio/gpio-msm-v2.c
@@ -155,6 +155,11 @@
 	}
 }
 
+unsigned  __msm_gpio_get_intr_cfg_enable(unsigned gpio)
+{
+	return __msm_gpio_get_intr_config(gpio) & INTR_ENABLE;
+}
+
 void __msm_gpio_set_intr_cfg_type(unsigned gpio, unsigned type)
 {
 	unsigned cfg;
diff --git a/drivers/gpio/gpio-msm-v3.c b/drivers/gpio/gpio-msm-v3.c
index 26716a0..1da276f 100644
--- a/drivers/gpio/gpio-msm-v3.c
+++ b/drivers/gpio/gpio-msm-v3.c
@@ -163,6 +163,11 @@
 	__raw_writel(cfg, GPIO_INTR_CFG(gpio));
 }
 
+unsigned  __msm_gpio_get_intr_cfg_enable(unsigned gpio)
+{
+	return __msm_gpio_get_intr_config(gpio) & INTR_ENABLE;
+}
+
 void __msm_gpio_set_intr_cfg_type(unsigned gpio, unsigned type)
 {
 	unsigned cfg;
diff --git a/drivers/gpu/ion/ion.c b/drivers/gpu/ion/ion.c
index 7f760ed..b23181f 100644
--- a/drivers/gpu/ion/ion.c
+++ b/drivers/gpu/ion/ion.c
@@ -107,24 +107,6 @@
 
 static void ion_iommu_release(struct kref *kref);
 
-static int ion_validate_buffer_flags(struct ion_buffer *buffer,
-					unsigned long flags)
-{
-	if (buffer->kmap_cnt || buffer->dmap_cnt || buffer->umap_cnt ||
-		buffer->iommu_map_cnt) {
-		if (buffer->flags != flags) {
-			pr_err("%s: buffer was already mapped with flags %lx,"
-				" cannot map with flags %lx\n", __func__,
-				buffer->flags, flags);
-			return 1;
-		}
-
-	} else {
-		buffer->flags = flags;
-	}
-	return 0;
-}
-
 /* this function should only be called while dev->lock is held */
 static void ion_buffer_add(struct ion_device *dev,
 			   struct ion_buffer *buffer)
@@ -232,6 +214,7 @@
 
 	buffer->dev = dev;
 	buffer->size = len;
+	buffer->flags = flags;
 
 	table = buffer->heap->ops->map_dma(buffer->heap, buffer);
 	if (IS_ERR_OR_NULL(table)) {
@@ -412,7 +395,8 @@
 }
 
 struct ion_handle *ion_alloc(struct ion_client *client, size_t len,
-			     size_t align, unsigned int flags)
+			     size_t align, unsigned int heap_mask,
+			     unsigned int flags)
 {
 	struct rb_node *n;
 	struct ion_handle *handle;
@@ -443,7 +427,7 @@
 		if (!((1 << heap->type) & client->heap_mask))
 			continue;
 		/* if the caller didn't specify this heap type */
-		if (!((1 << heap->id) & flags))
+		if (!((1 << heap->id) & heap_mask))
 			continue;
 		/* Do not allow un-secure heap if secure is specified */
 		if (secure_allocation && (heap->type != ION_HEAP_TYPE_CP))
@@ -773,8 +757,7 @@
 }
 EXPORT_SYMBOL(ion_unmap_iommu);
 
-void *ion_map_kernel(struct ion_client *client, struct ion_handle *handle,
-			unsigned long flags)
+void *ion_map_kernel(struct ion_client *client, struct ion_handle *handle)
 {
 	struct ion_buffer *buffer;
 	void *vaddr;
@@ -796,11 +779,6 @@
 		return ERR_PTR(-ENODEV);
 	}
 
-	if (ion_validate_buffer_flags(buffer, flags)) {
-		mutex_unlock(&client->lock);
-		return ERR_PTR(-EEXIST);
-	}
-
 	mutex_lock(&buffer->lock);
 	vaddr = ion_handle_kmap_get(handle);
 	mutex_unlock(&buffer->lock);
@@ -1228,36 +1206,6 @@
 	.kunmap = ion_dma_buf_kunmap,
 };
 
-static int ion_share_set_flags(struct ion_client *client,
-				struct ion_handle *handle,
-				unsigned long flags)
-{
-	struct ion_buffer *buffer;
-	bool valid_handle;
-	unsigned long ion_flags = ION_SET_CACHE(CACHED);
-	if (flags & O_DSYNC)
-		ion_flags = ION_SET_CACHE(UNCACHED);
-
-	mutex_lock(&client->lock);
-	valid_handle = ion_handle_validate(client, handle);
-	mutex_unlock(&client->lock);
-	if (!valid_handle) {
-		WARN(1, "%s: invalid handle passed to set_flags.\n", __func__);
-		return -EINVAL;
-	}
-
-	buffer = handle->buffer;
-
-	mutex_lock(&buffer->lock);
-	if (ion_validate_buffer_flags(buffer, ion_flags)) {
-		mutex_unlock(&buffer->lock);
-		return -EEXIST;
-	}
-	mutex_unlock(&buffer->lock);
-	return 0;
-}
-
-
 int ion_share_dma_buf(struct ion_client *client, struct ion_handle *handle)
 {
 	struct ion_buffer *buffer;
@@ -1337,7 +1285,7 @@
 		if (copy_from_user(&data, (void __user *)arg, sizeof(data)))
 			return -EFAULT;
 		data.handle = ion_alloc(client, data.len, data.align,
-					     data.flags);
+					     data.heap_mask, data.flags);
 
 		if (IS_ERR(data.handle))
 			return PTR_ERR(data.handle);
@@ -1368,14 +1316,9 @@
 	case ION_IOC_SHARE:
 	{
 		struct ion_fd_data data;
-		int ret;
 		if (copy_from_user(&data, (void __user *)arg, sizeof(data)))
 			return -EFAULT;
 
-		ret = ion_share_set_flags(client, data.handle, filp->f_flags);
-		if (ret)
-			return ret;
-
 		data.fd = ion_share_dma_buf(client, data.handle);
 		if (copy_to_user((void __user *)arg, &data, sizeof(data)))
 			return -EFAULT;
diff --git a/drivers/gpu/msm/adreno_drawctxt.c b/drivers/gpu/msm/adreno_drawctxt.c
index 70ad81c..7cbc7a8 100644
--- a/drivers/gpu/msm/adreno_drawctxt.c
+++ b/drivers/gpu/msm/adreno_drawctxt.c
@@ -226,7 +226,8 @@
 		adreno_drawctxt_switch(adreno_dev, NULL, 0);
 	}
 
-	adreno_idle(device);
+	if (device->state != KGSL_STATE_HUNG)
+		adreno_idle(device);
 
 	kgsl_sharedmem_free(&drawctxt->gpustate);
 	kgsl_sharedmem_free(&drawctxt->context_gmem_shadow.gmemshadow);
diff --git a/drivers/media/dvb/mpq/demux/mpq_dmx_plugin_common.c b/drivers/media/dvb/mpq/demux/mpq_dmx_plugin_common.c
index 836ca65..7435ab2 100644
--- a/drivers/media/dvb/mpq/demux/mpq_dmx_plugin_common.c
+++ b/drivers/media/dvb/mpq/demux/mpq_dmx_plugin_common.c
@@ -932,7 +932,8 @@
 		ion_alloc(mpq_demux->ion_client,
 				  actual_buffer_size,
 				  SZ_4K,
-				  (ION_HEAP(ION_CP_MM_HEAP_ID) | CACHED));
+				  ION_HEAP(ION_CP_MM_HEAP_ID),
+				  ION_FLAG_CACHED);
 
 	if (IS_ERR_OR_NULL(feed_data->payload_buff_handle)) {
 		ret = PTR_ERR(feed_data->payload_buff_handle);
@@ -948,8 +949,7 @@
 
 	payload_buffer =
 		ion_map_kernel(mpq_demux->ion_client,
-					   feed_data->payload_buff_handle,
-					   0);
+					   feed_data->payload_buff_handle);
 
 	if (IS_ERR_OR_NULL(payload_buffer)) {
 		ret = PTR_ERR(payload_buffer);
diff --git a/drivers/media/dvb/mpq/video/mpq_dvb_video.c b/drivers/media/dvb/mpq/video/mpq_dvb_video.c
index 4b3fb0c..bd8c4a4 100644
--- a/drivers/media/dvb/mpq/video/mpq_dvb_video.c
+++ b/drivers/media/dvb/mpq/video/mpq_dvb_video.c
@@ -572,7 +572,7 @@
 		ion_flag = vidc_get_fd_info(client_ctx, BUFFER_TYPE_OUTPUT,
 				pmem_fd, kernel_vaddr, buffer_index,
 				&buff_handle);
-		if (ion_flag == CACHED && buff_handle) {
+		if (ion_flag == ION_FLAG_CACHED && buff_handle) {
 			msm_ion_do_cache_op(
 				client_ctx->user_ion_client,
 				buff_handle,
@@ -1133,8 +1133,7 @@
 		}
 		vcd_h264_mv_buffer->kernel_virtual_addr =
 			(u8 *) ion_map_kernel(client_ctx->user_ion_client,
-					client_ctx->h264_mv_ion_handle,
-					ionflag);
+					client_ctx->h264_mv_ion_handle);
 		if (!vcd_h264_mv_buffer->kernel_virtual_addr) {
 			DBG("%s(): get_ION_kernel virtual addr failed\n",
 				 __func__);
@@ -1146,7 +1145,7 @@
 				VIDEO_DOMAIN, VIDEO_MAIN_POOL,
 				SZ_4K, 0, (unsigned long *)&iova,
 				(unsigned long *)&buffer_size,
-				UNCACHED, 0);
+				0, 0);
 		if (rc) {
 			DBG("%s():get_ION_kernel physical addr fail\n",
 						 __func__);
@@ -1503,7 +1502,7 @@
 						kernel_vaddr,
 						buffer_index,
 						&buff_handle);
-			if (ion_flag == CACHED && buff_handle) {
+			if (ion_flag == ION_FLAG_CACHED && buff_handle) {
 				msm_ion_do_cache_op(
 				client_ctx->user_ion_client,
 				buff_handle,
diff --git a/drivers/media/video/msm/gemini/msm_gemini_platform.c b/drivers/media/video/msm/gemini/msm_gemini_platform.c
index 28d2439..111402b 100644
--- a/drivers/media/video/msm/gemini/msm_gemini_platform.c
+++ b/drivers/media/video/msm/gemini/msm_gemini_platform.c
@@ -52,7 +52,7 @@
 		return 0;
 
 	rc = ion_map_iommu(gemini_client, *ionhandle, CAMERA_DOMAIN, GEN_POOL,
-			SZ_4K, 0, &paddr, (unsigned long *)&size, UNCACHED, 0);
+			SZ_4K, 0, &paddr, (unsigned long *)&size, 0, 0);
 #elif CONFIG_ANDROID_PMEM
 	unsigned long kvstart;
 	rc = get_pmem_file(fd, &paddr, &kvstart, &size, file_p);
diff --git a/drivers/media/video/msm/io/msm_io_7x27a_v4l2.c b/drivers/media/video/msm/io/msm_io_7x27a_v4l2.c
index d508c1d..9e7ede4 100644
--- a/drivers/media/video/msm/io/msm_io_7x27a_v4l2.c
+++ b/drivers/media/video/msm/io/msm_io_7x27a_v4l2.c
@@ -145,13 +145,10 @@
 	case S_PREVIEW:
 		break;
 	case S_VIDEO:
-		update_axi_qos(MSM_AXI_QOS_RECORDING);
 		break;
 	case S_CAPTURE:
-		update_axi_qos(MSM_AXI_QOS_SNAPSHOT);
 		break;
 	case S_DEFAULT:
-		update_axi_qos(PM_QOS_DEFAULT_VALUE);
 		break;
 	case S_EXIT:
 		axi_free(AXI_FLOW_VIEWFINDER_HI);
diff --git a/drivers/media/video/msm/jpeg_10/msm_jpeg_platform.c b/drivers/media/video/msm/jpeg_10/msm_jpeg_platform.c
index 0370f63..06135ec 100644
--- a/drivers/media/video/msm/jpeg_10/msm_jpeg_platform.c
+++ b/drivers/media/video/msm/jpeg_10/msm_jpeg_platform.c
@@ -50,7 +50,7 @@
 		return 0;
 
 	rc = ion_map_iommu(pgmn_dev->jpeg_client, *ionhandle, domain_num, 0,
-		SZ_4K, 0, &paddr, (unsigned long *)&size, UNCACHED,
+		SZ_4K, 0, &paddr, (unsigned long *)&size, 0,
 0); JPEG_DBG("%s:%d] addr 0x%x size %ld", __func__, __LINE__,
 							(uint32_t)paddr, size);
 
diff --git a/drivers/media/video/msm/mercury/msm_mercury_platform.c b/drivers/media/video/msm/mercury/msm_mercury_platform.c
index e90c63c..3dc7f4b 100644
--- a/drivers/media/video/msm/mercury/msm_mercury_platform.c
+++ b/drivers/media/video/msm/mercury/msm_mercury_platform.c
@@ -58,7 +58,7 @@
 
 	rc = ion_map_iommu(mercury_client, *ionhandle, CAMERA_DOMAIN,
 		GEN_POOL, SZ_4K, 0, &paddr,
-		(unsigned long *)&size, UNCACHED, 0);
+		(unsigned long *)&size, 0, 0);
 #elif CONFIG_ANDROID_PMEM
 	unsigned long kvstart;
 	rc = get_pmem_file(fd, &paddr, &kvstart, &size, file_p);
diff --git a/drivers/media/video/msm/msm_mctl.c b/drivers/media/video/msm/msm_mctl.c
index 482e569..3b678c4 100644
--- a/drivers/media/video/msm/msm_mctl.c
+++ b/drivers/media/video/msm/msm_mctl.c
@@ -267,6 +267,11 @@
 			core, ioctl, VIDIOC_MSM_SENSOR_CFG, argp);
 			break;
 
+	case MSM_CAM_IOCTL_OEM:
+	 rc = v4l2_subdev_call(p_mctl->sensor_sdev,
+		 core, ioctl, VIDIOC_MSM_SENSOR_CFG, argp);
+		 break;
+
 	case MSM_CAM_IOCTL_SENSOR_V4l2_S_CTRL: {
 			struct v4l2_control v4l2_ctrl;
 			CDBG("subdev call\n");
diff --git a/drivers/media/video/msm/msm_mctl_buf.c b/drivers/media/video/msm/msm_mctl_buf.c
index 953f042..3083bb2 100644
--- a/drivers/media/video/msm/msm_mctl_buf.c
+++ b/drivers/media/video/msm/msm_mctl_buf.c
@@ -898,7 +898,7 @@
 			meta_frame->map[i].handle);
 		if (ion_map_iommu(client, meta_frame->map[i].handle,
 				domain_num, 0, SZ_4K,
-				0, &paddr, &len, UNCACHED, 0) < 0) {
+				0, &paddr, &len, 0, 0) < 0) {
 			pr_err("%s: cannot map address plane %d", __func__, i);
 			ion_free(client, meta_frame->map[i].handle);
 			/* Roll back previous plane mappings, if any */
diff --git a/drivers/media/video/msm/msm_mem.c b/drivers/media/video/msm/msm_mem.c
index 5136d9d..1875df2 100644
--- a/drivers/media/video/msm/msm_mem.c
+++ b/drivers/media/video/msm/msm_mem.c
@@ -136,7 +136,7 @@
 	if (IS_ERR_OR_NULL(region->handle))
 		goto out1;
 	if (ion_map_iommu(client, region->handle, domain_num, 0,
-				  SZ_4K, 0, &paddr, &len, UNCACHED, 0) < 0)
+				  SZ_4K, 0, &paddr, &len, 0, 0) < 0)
 		goto out2;
 #elif CONFIG_ANDROID_PMEM
 	rc = get_pmem_file(info->fd, &paddr, &kvstart, &len, &file);
diff --git a/drivers/media/video/msm/sensors/imx091.h b/drivers/media/video/msm/sensors/imx091.h
index 3618b4c..411b90c 100644
--- a/drivers/media/video/msm/sensors/imx091.h
+++ b/drivers/media/video/msm/sensors/imx091.h
@@ -82,6 +82,7 @@
 	.sensor_power_up = msm_sensor_bayer_power_up,
 	.sensor_power_down = msm_sensor_bayer_power_down,
 	.sensor_get_csi_params = msm_sensor_bayer_get_csi_params,
+	.sensor_read_eeprom = msm_sensor_bayer_eeprom_read,
 };
 
 static struct msm_sensor_ctrl_t imx091_s_ctrl = {
diff --git a/drivers/media/video/msm/sensors/msm_sensor_bayer.c b/drivers/media/video/msm/sensors/msm_sensor_bayer.c
index c867867..31313d2 100644
--- a/drivers/media/video/msm/sensors/msm_sensor_bayer.c
+++ b/drivers/media/video/msm/sensors/msm_sensor_bayer.c
@@ -332,7 +332,7 @@
 	}
 	case CFG_GET_EEPROM_DATA: {
 		if (copy_to_user((void *)cdata.cfg.eeprom_data.eeprom_data,
-			&s_ctrl->eeprom_data, s_ctrl->eeprom_data.length)) {
+			&s_ctrl->eeprom_data.data, s_ctrl->eeprom_data.length)){
 			pr_err("%s:%d failed\n", __func__, __LINE__);
 			rc = -EFAULT;
 		}
@@ -658,7 +658,7 @@
 	return rc;
 }
 
-static int32_t msm_sensor_bayer_eeprom_read(struct msm_sensor_ctrl_t *s_ctrl)
+int32_t msm_sensor_bayer_eeprom_read(struct msm_sensor_ctrl_t *s_ctrl)
 {
 	uint32_t reg_addr = 0;
 	uint8_t *data = s_ctrl->eeprom_data.data;
@@ -749,7 +749,10 @@
 	msm_sensor_register(&s_ctrl->sensor_v4l2_subdev);
 	s_ctrl->sensor_v4l2_subdev.entity.revision =
 		s_ctrl->sensor_v4l2_subdev.devnode->num;
-	msm_sensor_bayer_eeprom_read(s_ctrl);
+	if (s_ctrl->func_tbl->sensor_read_eeprom != NULL)
+		s_ctrl->func_tbl->sensor_read_eeprom(s_ctrl);
+	else
+		msm_sensor_bayer_eeprom_read(s_ctrl);
 	goto power_down;
 probe_fail:
 	pr_err("%s %s_i2c_probe failed\n", __func__, client->name);
diff --git a/drivers/media/video/msm/sensors/msm_sensor_bayer.h b/drivers/media/video/msm/sensors/msm_sensor_bayer.h
index d12244b..34e654b 100644
--- a/drivers/media/video/msm/sensors/msm_sensor_bayer.h
+++ b/drivers/media/video/msm/sensors/msm_sensor_bayer.h
@@ -65,6 +65,8 @@
 int32_t msm_sensor_bayer_get_csi_params(struct msm_sensor_ctrl_t *s_ctrl,
 		struct csi_lane_params_t *sensor_output_info);
 
+int32_t msm_sensor_bayer_eeprom_read(struct msm_sensor_ctrl_t *s_ctrl);
+
 #define VIDIOC_MSM_SENSOR_CFG \
 	_IOWR('V', BASE_VIDIOC_PRIVATE + 4, void __user *)
 
diff --git a/drivers/media/video/msm/sensors/msm_sensor_common.h b/drivers/media/video/msm/sensors/msm_sensor_common.h
index 79fe52e..1f34a0f 100644
--- a/drivers/media/video/msm/sensors/msm_sensor_common.h
+++ b/drivers/media/video/msm/sensors/msm_sensor_common.h
@@ -156,6 +156,7 @@
 	void (*sensor_adjust_frame_lines) (struct msm_sensor_ctrl_t *s_ctrl);
 	int32_t (*sensor_get_csi_params)(struct msm_sensor_ctrl_t *,
 		struct csi_lane_params_t *);
+	int32_t (*sensor_read_eeprom)(struct msm_sensor_ctrl_t *);
 };
 
 struct msm_sensor_csi_info {
diff --git a/drivers/media/video/msm/sensors/s5k3l1yx.c b/drivers/media/video/msm/sensors/s5k3l1yx.c
index 6a2372e..0bd625c 100644
--- a/drivers/media/video/msm/sensors/s5k3l1yx.c
+++ b/drivers/media/video/msm/sensors/s5k3l1yx.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -442,6 +442,43 @@
 	{0x0B00, 0x00},
 };
 
+static struct msm_camera_i2c_reg_conf s5k3l1yx_19mhz_prev_settings[] = {
+	{0x0501, 0x00}, /* compression_algorithim_L(1d) */
+	{0x0112, 0x0A}, /* CCP_data_format_H */
+	{0x0113, 0x0A}, /* CCP_data_format_L raw8=0808 ,DCPM10 -->8= 0A08 */
+	{0x0306, 0x00}, /* pll_multiplier */
+	{0x0307, 0xCE}, /* pll_multiplier */
+	{0x0202, 0x06}, /* coarse_integration_time */
+	{0x0203, 0x00}, /* coarse_integration_time */
+	{0x0340, 0x09}, /* frame_length_lines */
+	{0x0341, 0x6C}, /* frame_length_lines */
+	{0x0342, 0x11}, /* line_length_pck */
+	{0x0343, 0x80}, /* line_length_pck */
+	{0x0344, 0x00}, /* x_addr_start */
+	{0x0345, 0x18}, /* x_addr_start */
+	{0x0346, 0x00}, /* y_addr_start */
+	{0x0347, 0x00}, /* y_addr_start */
+	{0x0348, 0x0F}, /* x_addr_end */
+	{0x0349, 0x97}, /* x_addr_end */
+	{0x034A, 0x0B}, /* y_addr_end */
+	{0x034B, 0xC7}, /* y_addr_end */
+	{0x034C, 0x07}, /* x_output_size */
+	{0x034D, 0xC0}, /* x_output_size */
+	{0x034E, 0x05}, /* y_output_size */
+	{0x034F, 0xE4}, /* y_output_size */
+	{0x0380, 0x00}, /* x_even_inc */
+	{0x0381, 0x01}, /* x_even_inc */
+	{0x0382, 0x00}, /* x_odd_inc */
+	{0x0383, 0x03}, /* x_odd_inc */
+	{0x0384, 0x00}, /* y_even_inc */
+	{0x0385, 0x01}, /* y_even_inc */
+	{0x0386, 0x00}, /* y_odd_inc */
+	{0x0387, 0x03}, /* y_odd_inc */
+	{0x0900, 0x01}, /* binning_mode */
+	{0x0901, 0x22}, /* binning_type */
+	{0x0902, 0x01}, /* binning_weighting */
+};
+
 static struct v4l2_subdev_info s5k3l1yx_subdev_info[] = {
 	{
 	.code   = V4L2_MBUS_FMT_SBGGR10_1X10,
@@ -471,6 +508,8 @@
 					MSM_CAMERA_I2C_BYTE_DATA},
 	{&s5k3l1yx_dpcm_settings[0],
 	ARRAY_SIZE(s5k3l1yx_dpcm_settings), 0, MSM_CAMERA_I2C_BYTE_DATA},
+	{&s5k3l1yx_19mhz_prev_settings[0],
+	ARRAY_SIZE(s5k3l1yx_19mhz_prev_settings), 0, MSM_CAMERA_I2C_BYTE_DATA},
 };
 
 static struct msm_sensor_output_info_t s5k3l1yx_dimensions[] = {
@@ -534,6 +573,16 @@
 		.op_pixel_clk = 320000000,
 		.binning_factor = 1,
 	},
+	/* 30 fps preview with 19.2 input clock*/
+	{
+		.x_output = 1984,
+		.y_output = 1508,
+		.line_length_pclk = 4480,
+		.frame_length_lines = 2412,
+		.vt_pixel_clk = 330000000,
+		.op_pixel_clk = 264000000,
+		.binning_factor = 1,
+	},
 };
 
 static struct msm_sensor_output_reg_addr_t s5k3l1yx_reg_addr = {
diff --git a/drivers/media/video/msm/vfe/msm_vfe_stats_buf.c b/drivers/media/video/msm/vfe/msm_vfe_stats_buf.c
index a813e09..36f8b11 100644
--- a/drivers/media/video/msm/vfe/msm_vfe_stats_buf.c
+++ b/drivers/media/video/msm/vfe/msm_vfe_stats_buf.c
@@ -221,7 +221,7 @@
 	}
 	if (ion_map_iommu(client, stats_buf->handle,
 			domain_num, 0, SZ_4K,
-			0, &paddr, &len, UNCACHED, 0) < 0) {
+			0, &paddr, &len, 0, 0) < 0) {
 		rc = -EINVAL;
 		pr_err("%s: cannot map address", __func__);
 		goto out2;
diff --git a/drivers/media/video/msm_vidc/msm_smem.c b/drivers/media/video/msm_vidc/msm_smem.c
index 156a721..3dd2193 100644
--- a/drivers/media/video/msm_vidc/msm_smem.c
+++ b/drivers/media/video/msm_vidc/msm_smem.c
@@ -24,7 +24,7 @@
 static int get_device_address(struct ion_client *clnt,
 		struct ion_handle *hndl, int domain_num, int partition_num,
 		unsigned long align, unsigned long *iova,
-		unsigned long *buffer_size,	unsigned long flags)
+		unsigned long *buffer_size)
 {
 	int rc;
 	if (!iova || !buffer_size || !hndl || !clnt) {
@@ -37,7 +37,7 @@
 	dprintk(VIDC_DBG, "domain: %d, partition: %d\n",
 		domain_num, partition_num);
 	rc = ion_map_iommu(clnt, hndl, domain_num, partition_num, align,
-			0, iova, buffer_size, UNCACHED, 0);
+			0, iova, buffer_size, 0, 0);
 	if (rc)
 		dprintk(VIDC_ERR,
 		"ion_map_iommu failed(%d).domain: %d,partition: %d\n",
@@ -57,7 +57,6 @@
 			struct msm_smem *mem)
 {
 	struct ion_handle *hndl;
-	unsigned long ionflag;
 	unsigned long iova = 0;
 	unsigned long buffer_size = 0;
 	int rc = 0;
@@ -68,16 +67,11 @@
 		rc = -ENOMEM;
 		goto fail_import_fd;
 	}
-	rc = ion_handle_get_flags(client->clnt, hndl, &ionflag);
-	if (rc) {
-		dprintk(VIDC_ERR, "Failed to get ion flags: %d", rc);
-		goto fail_map;
-	}
 	mem->kvaddr = NULL;
 	mem->domain = domain;
 	mem->partition_num = partition;
 	rc = get_device_address(client->clnt, hndl, mem->domain,
-		mem->partition_num, 4096, &iova, &buffer_size, ionflag);
+		mem->partition_num, 4096, &iova, &buffer_size);
 	if (rc) {
 		dprintk(VIDC_ERR, "Failed to get device address: %d\n", rc);
 		goto fail_device_address;
@@ -92,7 +86,6 @@
 	return rc;
 fail_device_address:
 	ion_unmap_kernel(client->clnt, hndl);
-fail_map:
 	ion_free(client->clnt, hndl);
 fail_import_fd:
 	return rc;
@@ -106,19 +99,20 @@
 	unsigned long iova = 0;
 	unsigned long buffer_size = 0;
 	unsigned long ionflags = 0;
+	unsigned long heap_mask = 0;
 	int rc = 0;
 	if (flags == SMEM_CACHED)
-		ionflags |= ION_SET_CACHE(CACHED);
+		ionflags = ION_SET_CACHED(ionflags);
 	else
-		ionflags |= ION_SET_CACHE(UNCACHED);
+		ionflags = ION_SET_UNCACHED(ionflags);
 
-	ionflags = ionflags | ION_HEAP(ION_CP_MM_HEAP_ID);
+	heap_mask = ION_HEAP(ION_CP_MM_HEAP_ID);
 	if (align < 4096)
 		align = 4096;
 	size = (size + 4095) & (~4095);
 	dprintk(VIDC_DBG, "domain: %d, partition: %d\n",
 		domain, partition);
-	hndl = ion_alloc(client->clnt, size, align, ionflags);
+	hndl = ion_alloc(client->clnt, size, align, heap_mask, ionflags);
 	if (IS_ERR_OR_NULL(hndl)) {
 		dprintk(VIDC_ERR,
 		"Failed to allocate shared memory = %p, %d, %d, 0x%lx\n",
@@ -131,7 +125,7 @@
 	mem->domain = domain;
 	mem->partition_num = partition;
 	if (map_kernel) {
-		mem->kvaddr = ion_map_kernel(client->clnt, hndl, 0);
+		mem->kvaddr = ion_map_kernel(client->clnt, hndl);
 		if (!mem->kvaddr) {
 			dprintk(VIDC_ERR,
 				"Failed to map shared mem in kernel\n");
@@ -142,7 +136,7 @@
 		mem->kvaddr = NULL;
 
 	rc = get_device_address(client->clnt, hndl, mem->domain,
-		mem->partition_num, align, &iova, &buffer_size, UNCACHED);
+		mem->partition_num, align, &iova, &buffer_size);
 	if (rc) {
 		dprintk(VIDC_ERR, "Failed to get device address: %d\n",
 			rc);
diff --git a/drivers/media/video/msm_vidc/msm_v4l2_vidc.c b/drivers/media/video/msm_vidc/msm_v4l2_vidc.c
index 7fa4f26..fda03de 100644
--- a/drivers/media/video/msm_vidc/msm_v4l2_vidc.c
+++ b/drivers/media/video/msm_vidc/msm_v4l2_vidc.c
@@ -583,7 +583,7 @@
 				buffer_info.m.planes[0].reserved[0],
 				buffer_info.m.planes[0].reserved[1],
 				buffer_info.m.planes[0].length);
-			rc = msm_vidc_release_buf(&v4l2_inst->vidc_inst,
+			rc = msm_vidc_release_buf(v4l2_inst->vidc_inst,
 				&buffer_info);
 			if (rc)
 				dprintk(VIDC_ERR,
diff --git a/drivers/media/video/msm_vidc/msm_vdec.c b/drivers/media/video/msm_vidc/msm_vdec.c
index ead118d..d843d87 100644
--- a/drivers/media/video/msm_vidc/msm_vdec.c
+++ b/drivers/media/video/msm_vidc/msm_vdec.c
@@ -281,7 +281,7 @@
 int msm_vdec_streamon(struct msm_vidc_inst *inst, enum v4l2_buf_type i)
 {
 	int rc = 0;
-	struct vb2_queue *q;
+	struct buf_queue *q;
 	q = msm_comm_get_vb2q(inst, i);
 	if (!q) {
 		dprintk(VIDC_ERR,
@@ -289,7 +289,9 @@
 		return -EINVAL;
 	}
 	dprintk(VIDC_DBG, "Calling streamon\n");
-	rc = vb2_streamon(q, i);
+	mutex_lock(&q->lock);
+	rc = vb2_streamon(&q->vb2_bufq, i);
+	mutex_unlock(&q->lock);
 	if (rc)
 		dprintk(VIDC_ERR, "streamon failed on port: %d\n", i);
 	return rc;
@@ -298,7 +300,7 @@
 int msm_vdec_streamoff(struct msm_vidc_inst *inst, enum v4l2_buf_type i)
 {
 	int rc = 0;
-	struct vb2_queue *q;
+	struct buf_queue *q;
 
 	q = msm_comm_get_vb2q(inst, i);
 	if (!q) {
@@ -307,7 +309,9 @@
 		return -EINVAL;
 	}
 	dprintk(VIDC_DBG, "Calling streamoff\n");
-	rc = vb2_streamoff(q, i);
+	mutex_lock(&q->lock);
+	rc = vb2_streamoff(&q->vb2_bufq, i);
+	mutex_unlock(&q->lock);
 	if (rc)
 		dprintk(VIDC_ERR, "streamoff failed on port: %d\n", i);
 	return rc;
@@ -403,7 +407,7 @@
 
 int msm_vdec_qbuf(struct msm_vidc_inst *inst, struct v4l2_buffer *b)
 {
-	struct vb2_queue *q = NULL;
+	struct buf_queue *q = NULL;
 	int rc = 0;
 	q = msm_comm_get_vb2q(inst, b->type);
 	if (!q) {
@@ -411,14 +415,16 @@
 			, b->type);
 		return -EINVAL;
 	}
-	rc = vb2_qbuf(q, b);
+	mutex_lock(&q->lock);
+	rc = vb2_qbuf(&q->vb2_bufq, b);
+	mutex_unlock(&q->lock);
 	if (rc)
 		dprintk(VIDC_ERR, "Failed to qbuf, %d\n", rc);
 	return rc;
 }
 int msm_vdec_dqbuf(struct msm_vidc_inst *inst, struct v4l2_buffer *b)
 {
-	struct vb2_queue *q = NULL;
+	struct buf_queue *q = NULL;
 	int rc = 0;
 	q = msm_comm_get_vb2q(inst, b->type);
 	if (!q) {
@@ -426,7 +432,9 @@
 			, b->type);
 		return -EINVAL;
 	}
-	rc = vb2_dqbuf(q, b, true);
+	mutex_lock(&q->lock);
+	rc = vb2_dqbuf(&q->vb2_bufq, b, true);
+	mutex_unlock(&q->lock);
 	if (rc)
 		dprintk(VIDC_WARN, "Failed to dqbuf, %d\n", rc);
 	return rc;
@@ -434,7 +442,7 @@
 
 int msm_vdec_reqbufs(struct msm_vidc_inst *inst, struct v4l2_requestbuffers *b)
 {
-	struct vb2_queue *q = NULL;
+	struct buf_queue *q = NULL;
 	int rc = 0;
 	if (!inst || !b) {
 		dprintk(VIDC_ERR,
@@ -448,7 +456,9 @@
 		return -EINVAL;
 	}
 
-	rc = vb2_reqbufs(q, b);
+	mutex_lock(&q->lock);
+	rc = vb2_reqbufs(&q->vb2_bufq, b);
+	mutex_unlock(&q->lock);
 	if (rc)
 		dprintk(VIDC_ERR, "Failed to get reqbufs, %d\n", rc);
 	return rc;
@@ -770,11 +780,11 @@
 		"Streamon called on: %d capability\n", q->type);
 	switch (q->type) {
 	case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
-		if (inst->vb2_bufq[CAPTURE_PORT].streaming)
+		if (inst->bufq[CAPTURE_PORT].vb2_bufq.streaming)
 			rc = start_streaming(inst);
 		break;
 	case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
-		if (inst->vb2_bufq[OUTPUT_PORT].streaming)
+		if (inst->bufq[OUTPUT_PORT].vb2_bufq.streaming)
 			rc = start_streaming(inst);
 		break;
 	default:
@@ -797,11 +807,11 @@
 	dprintk(VIDC_DBG, "Streamoff called on: %d capability\n", q->type);
 	switch (q->type) {
 	case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
-		if (!inst->vb2_bufq[CAPTURE_PORT].streaming)
+		if (!inst->bufq[CAPTURE_PORT].vb2_bufq.streaming)
 			rc = stop_streaming(inst);
 		break;
 	case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
-		if (!inst->vb2_bufq[OUTPUT_PORT].streaming)
+		if (!inst->bufq[OUTPUT_PORT].vb2_bufq.streaming)
 			rc = stop_streaming(inst);
 		break;
 	default:
diff --git a/drivers/media/video/msm_vidc/msm_venc.c b/drivers/media/video/msm_vidc/msm_venc.c
index c137c08..948676a 100644
--- a/drivers/media/video/msm_vidc/msm_venc.c
+++ b/drivers/media/video/msm_vidc/msm_venc.c
@@ -444,6 +444,17 @@
 		(1 << L_MODE)
 		),
 	},
+	{
+		.id = V4L2_CID_QCOM_VIDEO_SYNC_FRAME_SEQ_HDR,
+		.name = "CodecConfig with sync frame",
+		.type = V4L2_CTRL_TYPE_BOOLEAN,
+		.minimum = 0,
+		.maximum = 1,
+		.default_value = 1,
+		.step = 1,
+		.menu_skip_mask = 0,
+		.qmenu = NULL,
+	},
 };
 
 #define NUM_CTRLS ARRAY_SIZE(msm_venc_ctrls)
@@ -625,7 +636,6 @@
 			sizes[i] = inst->fmts[OUTPUT_PORT]->get_frame_size(
 					i, inst->prop.height, inst->prop.width);
 		}
-
 		break;
 	default:
 		dprintk(VIDC_ERR, "Invalid q type = %d\n", q->type);
@@ -641,6 +651,7 @@
 	unsigned long flags;
 	struct vb2_buf_entry *temp;
 	struct list_head *ptr, *next;
+
 	rc = msm_comm_try_get_bufreqs(inst);
 	if (rc) {
 		dprintk(VIDC_ERR,
@@ -700,11 +711,11 @@
 	dprintk(VIDC_DBG, "Streamon called on: %d capability\n", q->type);
 	switch (q->type) {
 	case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
-		if (inst->vb2_bufq[CAPTURE_PORT].streaming)
+		if (inst->bufq[CAPTURE_PORT].vb2_bufq.streaming)
 			rc = start_streaming(inst);
 		break;
 	case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
-		if (inst->vb2_bufq[OUTPUT_PORT].streaming)
+		if (inst->bufq[OUTPUT_PORT].vb2_bufq.streaming)
 			rc = start_streaming(inst);
 		break;
 	default:
@@ -785,6 +796,7 @@
 	struct hal_intra_refresh intra_refresh;
 	struct hal_multi_slice_control multi_slice_control;
 	struct hal_h264_db_control h264_db_control;
+	struct hal_enable enable;
 	u32 property_id = 0;
 	u32 property_val = 0;
 	void *pdata;
@@ -1204,6 +1216,12 @@
 		h264_db_control.slice_beta_offset = control.value;
 		pdata = &h264_db_control;
 		break;
+	case V4L2_CID_QCOM_VIDEO_SYNC_FRAME_SEQ_HDR:
+		property_id =
+			HAL_PARAM_VENC_SYNC_FRAME_SEQUENCE_HEADER;
+		enable.enable = control.value;
+		pdata = &enable;
+		break;
 	default:
 		break;
 	}
@@ -1419,7 +1437,7 @@
 
 int msm_venc_reqbufs(struct msm_vidc_inst *inst, struct v4l2_requestbuffers *b)
 {
-	struct vb2_queue *q = NULL;
+	struct buf_queue *q = NULL;
 	int rc = 0;
 	if (!inst || !b) {
 		dprintk(VIDC_ERR,
@@ -1433,7 +1451,9 @@
 		return -EINVAL;
 	}
 
-	rc = vb2_reqbufs(q, b);
+	mutex_lock(&q->lock);
+	rc = vb2_reqbufs(&q->vb2_bufq, b);
+	mutex_unlock(&q->lock);
 	if (rc)
 		dprintk(VIDC_ERR, "Failed to get reqbufs, %d\n", rc);
 	return rc;
@@ -1479,7 +1499,7 @@
 
 int msm_venc_qbuf(struct msm_vidc_inst *inst, struct v4l2_buffer *b)
 {
-	struct vb2_queue *q = NULL;
+	struct buf_queue *q = NULL;
 	int rc = 0;
 	q = msm_comm_get_vb2q(inst, b->type);
 	if (!q) {
@@ -1487,7 +1507,9 @@
 			"Failed to find buffer queue for type = %d\n", b->type);
 		return -EINVAL;
 	}
-	rc = vb2_qbuf(q, b);
+	mutex_lock(&q->lock);
+	rc = vb2_qbuf(&q->vb2_bufq, b);
+	mutex_unlock(&q->lock);
 	if (rc)
 		dprintk(VIDC_ERR, "Failed to qbuf, %d\n", rc);
 	return rc;
@@ -1495,7 +1517,7 @@
 
 int msm_venc_dqbuf(struct msm_vidc_inst *inst, struct v4l2_buffer *b)
 {
-	struct vb2_queue *q = NULL;
+	struct buf_queue *q = NULL;
 	int rc = 0;
 	q = msm_comm_get_vb2q(inst, b->type);
 	if (!q) {
@@ -1503,7 +1525,9 @@
 			"Failed to find buffer queue for type = %d\n", b->type);
 		return -EINVAL;
 	}
-	rc = vb2_dqbuf(q, b, true);
+	mutex_lock(&q->lock);
+	rc = vb2_dqbuf(&q->vb2_bufq, b, true);
+	mutex_unlock(&q->lock);
 	if (rc)
 		dprintk(VIDC_DBG, "Failed to dqbuf, %d\n", rc);
 	return rc;
@@ -1512,7 +1536,7 @@
 int msm_venc_streamon(struct msm_vidc_inst *inst, enum v4l2_buf_type i)
 {
 	int rc = 0;
-	struct vb2_queue *q;
+	struct buf_queue *q;
 	q = msm_comm_get_vb2q(inst, i);
 	if (!q) {
 		dprintk(VIDC_ERR,
@@ -1520,7 +1544,9 @@
 		return -EINVAL;
 	}
 	dprintk(VIDC_DBG, "Calling streamon\n");
-	rc = vb2_streamon(q, i);
+	mutex_lock(&q->lock);
+	rc = vb2_streamon(&q->vb2_bufq, i);
+	mutex_unlock(&q->lock);
 	if (rc)
 		dprintk(VIDC_ERR, "streamon failed on port: %d\n", i);
 	return rc;
@@ -1529,7 +1555,7 @@
 int msm_venc_streamoff(struct msm_vidc_inst *inst, enum v4l2_buf_type i)
 {
 	int rc = 0;
-	struct vb2_queue *q;
+	struct buf_queue *q;
 	q = msm_comm_get_vb2q(inst, i);
 	if (!q) {
 		dprintk(VIDC_ERR,
@@ -1537,7 +1563,9 @@
 		return -EINVAL;
 	}
 	dprintk(VIDC_DBG, "Calling streamoff on port: %d\n", i);
-	rc = vb2_streamoff(q, i);
+	mutex_lock(&q->lock);
+	rc = vb2_streamoff(&q->vb2_bufq, i);
+	mutex_unlock(&q->lock);
 	if (rc)
 		dprintk(VIDC_ERR, "streamoff failed on port: %d\n", i);
 	return rc;
diff --git a/drivers/media/video/msm_vidc/msm_vidc.c b/drivers/media/video/msm_vidc/msm_vidc.c
index ec9dac8..8ff7714 100644
--- a/drivers/media/video/msm_vidc/msm_vidc.c
+++ b/drivers/media/video/msm_vidc/msm_vidc.c
@@ -27,8 +27,8 @@
 static int get_poll_flags(void *instance)
 {
 	struct msm_vidc_inst *inst = instance;
-	struct vb2_queue *outq = &inst->vb2_bufq[OUTPUT_PORT];
-	struct vb2_queue *capq = &inst->vb2_bufq[CAPTURE_PORT];
+	struct vb2_queue *outq = &inst->bufq[OUTPUT_PORT].vb2_bufq;
+	struct vb2_queue *capq = &inst->bufq[CAPTURE_PORT].vb2_bufq;
 	struct vb2_buffer *out_vb = NULL;
 	struct vb2_buffer *cap_vb = NULL;
 	unsigned long flags;
@@ -62,8 +62,8 @@
 		struct poll_table_struct *wait)
 {
 	struct msm_vidc_inst *inst = instance;
-	struct vb2_queue *outq = &inst->vb2_bufq[OUTPUT_PORT];
-	struct vb2_queue *capq = &inst->vb2_bufq[CAPTURE_PORT];
+	struct vb2_queue *outq = &inst->bufq[OUTPUT_PORT].vb2_bufq;
+	struct vb2_queue *capq = &inst->bufq[CAPTURE_PORT].vb2_bufq;
 
 	poll_wait(filp, &inst->event_handler.wait, wait);
 	poll_wait(filp, &capq->done_wq, wait);
@@ -306,9 +306,9 @@
 {
 	struct vb2_queue *q = NULL;
 	if (type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
-		q = &inst->vb2_bufq[CAPTURE_PORT];
+		q = &inst->bufq[CAPTURE_PORT].vb2_bufq;
 	} else if (type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
-		q = &inst->vb2_bufq[OUTPUT_PORT];
+		q = &inst->bufq[OUTPUT_PORT].vb2_bufq;
 	} else {
 		dprintk(VIDC_ERR, "buf_type = %d not recognised\n", type);
 		return -EINVAL;
@@ -404,6 +404,8 @@
 	}
 
 	mutex_init(&inst->sync_lock);
+	mutex_init(&inst->bufq[CAPTURE_PORT].lock);
+	mutex_init(&inst->bufq[OUTPUT_PORT].lock);
 	spin_lock_init(&inst->lock);
 	inst->session_type = session_type;
 	INIT_LIST_HEAD(&inst->pendingq);
@@ -489,8 +491,10 @@
 				buf = list_entry(ptr, struct internal_buf,
 						list);
 				list_del(&buf->list);
+				spin_unlock_irqrestore(&inst->lock, flags);
 				msm_smem_free(inst->mem_client, buf->handle);
 				kfree(buf);
+				spin_lock_irqsave(&inst->lock, flags);
 			}
 		}
 		if (!list_empty(&inst->persistbufs)) {
@@ -498,12 +502,17 @@
 				buf = list_entry(ptr, struct internal_buf,
 						list);
 				list_del(&buf->list);
+				spin_unlock_irqrestore(&inst->lock, flags);
 				msm_smem_free(inst->mem_client, buf->handle);
 				kfree(buf);
+				spin_lock_irqsave(&inst->lock, flags);
 			}
 		}
-		if (inst->extradata_handle)
+		if (inst->extradata_handle) {
+			spin_unlock_irqrestore(&inst->lock, flags);
 			msm_smem_free(inst->mem_client, inst->extradata_handle);
+			spin_lock_irqsave(&inst->lock, flags);
+		}
 		spin_unlock_irqrestore(&inst->lock, flags);
 		msm_smem_delete_client(inst->mem_client);
 		debugfs_remove_recursive(inst->debugfs_root);
diff --git a/drivers/media/video/msm_vidc/msm_vidc_common.c b/drivers/media/video/msm_vidc/msm_vidc_common.c
index 2aed0b7..1cad40f 100644
--- a/drivers/media/video/msm_vidc/msm_vidc_common.c
+++ b/drivers/media/video/msm_vidc/msm_vidc_common.c
@@ -258,13 +258,13 @@
 	return &fmt[i];
 }
 
-struct vb2_queue *msm_comm_get_vb2q(
+struct buf_queue *msm_comm_get_vb2q(
 		struct msm_vidc_inst *inst,	enum v4l2_buf_type type)
 {
 	if (type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
-		return &inst->vb2_bufq[CAPTURE_PORT];
+		return &inst->bufq[CAPTURE_PORT];
 	if (type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)
-		return &inst->vb2_bufq[OUTPUT_PORT];
+		return &inst->bufq[OUTPUT_PORT];
 	return NULL;
 }
 
@@ -527,21 +527,25 @@
 	}
 }
 
-static struct vb2_buffer *get_vb_from_device_addr(struct vb2_queue *q,
+static struct vb2_buffer *get_vb_from_device_addr(struct buf_queue *bufq,
 		u32 dev_addr)
 {
 	struct vb2_buffer *vb = NULL;
+	struct vb2_queue *q = NULL;
 	int found = 0;
-	if (!q) {
+	if (!bufq) {
 		dprintk(VIDC_ERR, "Invalid parameter\n");
 		return NULL;
 	}
+	q = &bufq->vb2_bufq;
+	mutex_lock(&bufq->lock);
 	list_for_each_entry(vb, &q->queued_list, queued_entry) {
 		if (vb->v4l2_planes[0].m.userptr == dev_addr) {
 			found = 1;
 			break;
 		}
 	}
+	mutex_unlock(&bufq->lock);
 	if (!found) {
 		dprintk(VIDC_ERR,
 			"Failed to find the buffer in queued list: %d, %d\n",
@@ -563,7 +567,9 @@
 	vb = response->clnt_data;
 	inst = (struct msm_vidc_inst *)response->session_id;
 	if (vb) {
+		mutex_lock(&inst->bufq[OUTPUT_PORT].lock);
 		vb2_buffer_done(vb, VB2_BUF_STATE_DONE);
+		mutex_unlock(&inst->bufq[OUTPUT_PORT].lock);
 		wake_up(&inst->kernel_event_queue);
 	}
 }
@@ -580,7 +586,7 @@
 	}
 	inst = (struct msm_vidc_inst *)response->session_id;
 	fill_buf_done = (struct vidc_hal_fbd *)&response->output_done;
-	vb = get_vb_from_device_addr(&inst->vb2_bufq[CAPTURE_PORT],
+	vb = get_vb_from_device_addr(&inst->bufq[CAPTURE_PORT],
 		(u32)fill_buf_done->packet_buffer1);
 	if (vb) {
 		vb->v4l2_planes[0].bytesused = fill_buf_done->filled_len1;
@@ -600,10 +606,8 @@
 			vb->v4l2_buf.flags |= V4L2_BUF_FLAG_EOS;
 		if (fill_buf_done->flags1 & HAL_BUFFERFLAG_CODECCONFIG)
 			vb->v4l2_buf.flags &= ~V4L2_QCOM_BUF_FLAG_CODECCONFIG;
-
-		if (!inst->fbd_count)
-			vb->v4l2_buf.flags = V4L2_BUF_FLAG_KEYFRAME;
-		++inst->fbd_count;
+		if (fill_buf_done->flags1 & HAL_BUFFERFLAG_SYNCFRAME)
+			vb->v4l2_buf.flags |= V4L2_BUF_FLAG_KEYFRAME;
 
 		switch (fill_buf_done->picture_type) {
 		case HAL_PICTURE_IDR:
@@ -628,7 +632,9 @@
 		dprintk(VIDC_DBG, "Filled length = %d; flags %x\n",
 				vb->v4l2_planes[0].bytesused,
 				vb->v4l2_buf.flags);
+		mutex_lock(&inst->bufq[CAPTURE_PORT].lock);
 		vb2_buffer_done(vb, VB2_BUF_STATE_DONE);
+		mutex_unlock(&inst->bufq[CAPTURE_PORT].lock);
 		wake_up(&inst->kernel_event_queue);
 	} else {
 		/*
@@ -645,18 +651,19 @@
 		 */
 		if (fill_buf_done->flags1 & HAL_BUFFERFLAG_EOS
 			&& fill_buf_done->filled_len1 == 0) {
-			struct vb2_queue *q = &inst->vb2_bufq[CAPTURE_PORT];
+			struct buf_queue *q = &inst->bufq[CAPTURE_PORT];
 
-			if (!list_empty(&q->queued_list)) {
-				vb = list_first_entry(&q->queued_list,
+			if (!list_empty(&q->vb2_bufq.queued_list)) {
+				vb = list_first_entry(&q->vb2_bufq.queued_list,
 					struct vb2_buffer, queued_entry);
 				vb->v4l2_planes[0].bytesused = 0;
 				vb->v4l2_buf.flags |= V4L2_BUF_FLAG_EOS;
+				mutex_lock(&q->lock);
 				vb2_buffer_done(vb, VB2_BUF_STATE_DONE);
+				mutex_unlock(&q->lock);
 			}
 
 		}
-
 	}
 }
 
@@ -672,7 +679,7 @@
 	}
 	inst = (struct msm_vidc_inst *)response->session_id;
 	fill_buf_done = (struct vidc_hal_fbd *)&response->output_done;
-	vb = get_vb_from_device_addr(&inst->vb2_bufq[CAPTURE_PORT],
+	vb = get_vb_from_device_addr(&inst->bufq[CAPTURE_PORT],
 		(u32)fill_buf_done->packet_buffer1);
 	if (vb)
 		vb->v4l2_planes[0].bytesused = fill_buf_done->filled_len1;
@@ -682,7 +689,9 @@
 	dprintk(VIDC_DBG, "Filled length = %d; flags %x\n",
 				vb->v4l2_planes[0].bytesused,
 				vb->v4l2_buf.flags);
+	mutex_lock(&inst->bufq[CAPTURE_PORT].lock);
 	vb2_buffer_done(vb, VB2_BUF_STATE_DONE);
+	mutex_unlock(&inst->bufq[CAPTURE_PORT].lock);
 }
 
 void handle_cmd_response(enum command_response cmd, void *data)
@@ -1203,7 +1212,6 @@
 		goto exit;
 	}
 	inst->ftb_count = 0;
-	inst->fbd_count = 0;
 	change_inst_state(inst, MSM_VIDC_OPEN);
 exit:
 	return rc;
@@ -1586,9 +1594,16 @@
 			buffer_info.align_device_addr = handle->device_addr;
 			rc = vidc_hal_session_release_buffers(
 				(void *) inst->session,	&buffer_info);
+			if (rc)
+				dprintk(VIDC_WARN,
+					"Failed to release scratch buffer: 0x%x, %d",
+					buffer_info.align_device_addr,
+					buffer_info.buffer_size);
 			list_del(&buf->list);
+			spin_unlock_irqrestore(&inst->lock, flags);
 			msm_smem_free(inst->mem_client, buf->handle);
 			kfree(buf);
+			spin_lock_irqsave(&inst->lock, flags);
 		}
 	}
 	spin_unlock_irqrestore(&inst->lock, flags);
@@ -1617,11 +1632,14 @@
 				(void *) inst->session,	&buffer_info);
 			if (rc)
 				dprintk(VIDC_WARN,
-					"Failed in %s for buffer %ld\n",
-					__func__, handle->device_addr);
+					"Failed to release persist buffer 0x%x, %d\n",
+					buffer_info.align_device_addr,
+					buffer_info.buffer_size);
 			list_del(&buf->list);
+			spin_unlock_irqrestore(&inst->lock, flags);
 			msm_smem_free(inst->mem_client, buf->handle);
 			kfree(buf);
+			spin_lock_irqsave(&inst->lock, flags);
 		}
 	}
 	spin_unlock_irqrestore(&inst->lock, flags);
@@ -1633,7 +1651,6 @@
 	int rc = 0;
 	struct msm_smem *handle;
 	struct internal_buf *binfo;
-	struct list_head *ptr, *next;
 	struct vidc_buffer_addr_info buffer_info;
 	unsigned long flags;
 	struct hal_buffer_requirements *scratch_buf =
@@ -1643,28 +1660,9 @@
 		"scratch: num = %d, size = %d\n",
 		scratch_buf->buffer_count_actual,
 		scratch_buf->buffer_size);
-	spin_lock_irqsave(&inst->lock, flags);
-	if (!list_empty(&inst->internalbufs)) {
-		list_for_each_safe(ptr, next, &inst->internalbufs) {
-			binfo = list_entry(ptr, struct internal_buf,
-					list);
-			handle = binfo->handle;
-			buffer_info.buffer_size = handle->size;
-			buffer_info.buffer_type = HAL_BUFFER_INTERNAL_SCRATCH;
-			buffer_info.num_buffers = 1;
-			buffer_info.align_device_addr = handle->device_addr;
-			rc = vidc_hal_session_release_buffers(
-				(void *) inst->session, &buffer_info);
-			if (rc)
-				dprintk(VIDC_WARN,
-					"Failed in release %s for buffer %ld\n",
-					__func__, handle->device_addr);
-			list_del(&binfo->list);
-			msm_smem_free(inst->mem_client, binfo->handle);
-			kfree(binfo);
-		}
-	}
-	spin_unlock_irqrestore(&inst->lock, flags);
+	if (msm_comm_release_scratch_buffers(inst))
+		dprintk(VIDC_WARN, "Failed to release scratch buffers\n");
+
 	if (scratch_buf->buffer_size) {
 		for (i = 0; i < scratch_buf->buffer_count_actual;
 				i++) {
diff --git a/drivers/media/video/msm_vidc/msm_vidc_common.h b/drivers/media/video/msm_vidc/msm_vidc_common.h
index 1301e5c..0708724 100644
--- a/drivers/media/video/msm_vidc/msm_vidc_common.h
+++ b/drivers/media/video/msm_vidc/msm_vidc_common.h
@@ -23,7 +23,7 @@
 	const struct msm_vidc_format fmt[], int size, int index, int fmt_type);
 const struct msm_vidc_format *msm_comm_get_pixel_fmt_fourcc(
 	const struct msm_vidc_format fmt[], int size, int fourcc, int fmt_type);
-struct vb2_queue *msm_comm_get_vb2q(
+struct buf_queue *msm_comm_get_vb2q(
 		struct msm_vidc_inst *inst, enum v4l2_buf_type type);
 int msm_comm_try_state(struct msm_vidc_inst *inst, int state);
 int msm_comm_try_get_bufreqs(struct msm_vidc_inst *inst);
diff --git a/drivers/media/video/msm_vidc/msm_vidc_internal.h b/drivers/media/video/msm_vidc/msm_vidc_internal.h
index 1f2eff8..1ea92fc 100644
--- a/drivers/media/video/msm_vidc/msm_vidc_internal.h
+++ b/drivers/media/video/msm_vidc/msm_vidc_internal.h
@@ -188,6 +188,11 @@
 	u32 bitrate;
 };
 
+struct buf_queue {
+	struct vb2_queue vb2_bufq;
+	struct mutex lock;
+};
+
 struct msm_vidc_core {
 	struct list_head list;
 	struct mutex sync_lock;
@@ -216,7 +221,7 @@
 	struct session_prop prop;
 	int state;
 	const struct msm_vidc_format *fmts[MAX_PORT_NUM];
-	struct vb2_queue vb2_bufq[MAX_PORT_NUM];
+	struct buf_queue bufq[MAX_PORT_NUM];
 	spinlock_t lock;
 	struct list_head pendingq;
 	struct list_head internalbufs;
@@ -233,7 +238,6 @@
 	u32 reconfig_height;
 	struct dentry *debugfs_root;
 	u32 ftb_count;
-	u32 fbd_count;
 	struct vb2_buffer *vb2_seq_hdr;
 	void *priv;
 };
diff --git a/drivers/media/video/msm_vidc/vidc_hal.c b/drivers/media/video/msm_vidc/vidc_hal.c
index 0639dea..f0d0e73 100644
--- a/drivers/media/video/msm_vidc/vidc_hal.c
+++ b/drivers/media/video/msm_vidc/vidc_hal.c
@@ -177,7 +177,7 @@
 		new_write_idx -= queue->qhdr_q_size;
 		memcpy(write_ptr, packet, (packet_size_in_words -
 			new_write_idx) << 2);
-		memcpy((void *)queue->qhdr_start_addr,
+		memcpy((void *)qinfo->q_array.align_virtual_addr,
 			packet + ((packet_size_in_words - new_write_idx) << 2),
 			new_write_idx  << 2);
 	}
@@ -285,8 +285,9 @@
 		memcpy(packet, read_ptr,
 			(packet_size_in_words - new_read_idx) << 2);
 		memcpy(packet + ((packet_size_in_words -
-				new_read_idx) << 2),
-			(u8 *)queue->qhdr_start_addr, new_read_idx << 2);
+			new_read_idx) << 2),
+			(u8 *)qinfo->q_array.align_virtual_addr,
+			new_read_idx << 2);
 	}
 
 	queue->qhdr_read_idx = new_read_idx;
@@ -1169,6 +1170,16 @@
 		pkt->size += sizeof(u32) * 2;
 		break;
 	}
+	case HAL_PARAM_VENC_SYNC_FRAME_SEQUENCE_HEADER:
+	{
+		struct hfi_enable *hfi;
+		pkt->rg_property_data[0] =
+			HFI_PROPERTY_PARAM_VENC_SYNC_FRAME_SEQUENCE_HEADER;
+		hfi = (struct hfi_enable *) &pkt->rg_property_data[1];
+		hfi->enable = ((struct hfi_enable *) pdata)->enable;
+		pkt->size += sizeof(u32) * 2;
+		break;
+	}
 	case HAL_CONFIG_VENC_REQUEST_IFRAME:
 		pkt->rg_property_data[0] =
 			HFI_PROPERTY_CONFIG_VENC_REQUEST_SYNC_FRAME;
diff --git a/drivers/media/video/msm_vidc/vidc_hal_api.h b/drivers/media/video/msm_vidc/vidc_hal_api.h
index c77ae12..659cf7e 100644
--- a/drivers/media/video/msm_vidc/vidc_hal_api.h
+++ b/drivers/media/video/msm_vidc/vidc_hal_api.h
@@ -137,6 +137,7 @@
 	HAL_PARAM_VENC_MULTI_SLICE_INFO,
 	HAL_CONFIG_VENC_TIMESTAMP_SCALE,
 	HAL_PARAM_VENC_LOW_LATENCY,
+	HAL_PARAM_VENC_SYNC_FRAME_SEQUENCE_HEADER,
 };
 
 enum hal_domain {
diff --git a/drivers/media/video/msm_wfd/enc-mfc-subdev.c b/drivers/media/video/msm_wfd/enc-mfc-subdev.c
index 5997345..bc2d2ce 100644
--- a/drivers/media/video/msm_wfd/enc-mfc-subdev.c
+++ b/drivers/media/video/msm_wfd/enc-mfc-subdev.c
@@ -1932,7 +1932,7 @@
 	struct vcd_property_enc_recon_buffer *ctrl = NULL;
 	unsigned long phy_addr;
 	int i = 0;
-	int flags = 0;
+	int heap_mask = 0;
 	u32 len;
 	control.width = inst->width;
 	control.height = inst->height;
@@ -1945,8 +1945,8 @@
 		WFD_MSG_ERR("Failed to get recon buf size\n");
 		goto err;
 	}
-	flags = ION_HEAP(ION_CP_MM_HEAP_ID);
-	flags |= inst->secure ? ION_SECURE : ION_HEAP(ION_IOMMU_HEAP_ID);
+	heap_mask = ION_HEAP(ION_CP_MM_HEAP_ID);
+	heap_mask |= inst->secure ? ION_SECURE : ION_HEAP(ION_IOMMU_HEAP_ID);
 
 	if (vcd_get_ion_status()) {
 		for (i = 0; i < 4; ++i) {
@@ -1957,11 +1957,11 @@
 			ctrl->user_virtual_addr = (void *)i;
 			client_ctx->recon_buffer_ion_handle[i]
 				= ion_alloc(client_ctx->user_ion_client,
-			control.size, SZ_8K, flags);
+			control.size, SZ_8K, heap_mask, 0);
 
 			ctrl->kernel_virtual_addr = ion_map_kernel(
 				client_ctx->user_ion_client,
-				client_ctx->recon_buffer_ion_handle[i],	0);
+				client_ctx->recon_buffer_ion_handle[i]);
 
 			if (IS_ERR_OR_NULL(ctrl->kernel_virtual_addr)) {
 				WFD_MSG_ERR("ion map kernel failed\n");
diff --git a/drivers/media/video/msm_wfd/enc-venus-subdev.c b/drivers/media/video/msm_wfd/enc-venus-subdev.c
index 04e42f5..89ad6c7 100644
--- a/drivers/media/video/msm_wfd/enc-venus-subdev.c
+++ b/drivers/media/video/msm_wfd/enc-venus-subdev.c
@@ -617,7 +617,7 @@
 	}
 
 	mregion->kvaddr = ion_map_kernel(venc_ion_client,
-				mregion->ion_handle, flags);
+				mregion->ion_handle);
 
 	if (IS_ERR_OR_NULL(mregion->kvaddr)) {
 		WFD_MSG_ERR("Failed to map buffer into kernel\n");
diff --git a/drivers/media/video/msm_wfd/wfd-ioctl.c b/drivers/media/video/msm_wfd/wfd-ioctl.c
index 23af7e9..04b787a 100644
--- a/drivers/media/video/msm_wfd/wfd-ioctl.c
+++ b/drivers/media/video/msm_wfd/wfd-ioctl.c
@@ -160,7 +160,7 @@
 	alloc_regions |= secure ? ION_SECURE :
 				ION_HEAP(ION_IOMMU_HEAP_ID);
 	handle = ion_alloc(client,
-			mregion->size, SZ_4K, alloc_regions);
+			mregion->size, SZ_4K, alloc_regions, 0);
 
 	if (IS_ERR_OR_NULL(handle)) {
 		WFD_MSG_ERR("Failed to allocate input buffer\n");
@@ -168,7 +168,7 @@
 		goto alloc_fail;
 	}
 
-	kvaddr = ion_map_kernel(client, handle, secure ? UNCACHED : CACHED);
+	kvaddr = ion_map_kernel(client, handle);
 
 	if (IS_ERR_OR_NULL(kvaddr)) {
 		WFD_MSG_ERR("Failed to get virtual addr\n");
@@ -1596,12 +1596,21 @@
 	kfree(wfd_dev);
 	return 0;
 }
+
+static const struct of_device_id msm_wfd_dt_match[] = {
+	{.compatible = "qcom,msm-wfd"},
+	{}
+};
+
+MODULE_DEVICE_TABLE(of, msm_vidc_dt_match);
+
 static struct platform_driver wfd_driver = {
 	.probe =  __wfd_probe,
 	.remove = __wfd_remove,
 	.driver = {
 		.name = "msm_wfd",
 		.owner = THIS_MODULE,
+		.of_match_table = msm_wfd_dt_match,
 	}
 };
 
diff --git a/drivers/media/video/v4l2-ctrls.c b/drivers/media/video/v4l2-ctrls.c
index 7da4657..47b36ae 100644
--- a/drivers/media/video/v4l2-ctrls.c
+++ b/drivers/media/video/v4l2-ctrls.c
@@ -577,6 +577,8 @@
 	case V4L2_CID_MPEG_VIDEO_MPEG4_LEVEL:			return "MPEG4 Level";
 	case V4L2_CID_MPEG_VIDEO_MPEG4_PROFILE:			return "MPEG4 Profile";
 	case V4L2_CID_MPEG_VIDEO_MPEG4_QPEL:			return "Quarter Pixel Search Enable";
+	case V4L2_CID_QCOM_VIDEO_SYNC_FRAME_SEQ_HDR:
+		return "CodecConfig with sync frame";
 	case V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MAX_BYTES:		return "Maximum Bytes in a Slice";
 	case V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MAX_MB:		return "Number of MBs in a Slice";
 	case V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MODE:		return "Slice Partitioning Method";
@@ -795,6 +797,11 @@
 		*type = V4L2_CTRL_TYPE_INTEGER64;
 		*flags |= V4L2_CTRL_FLAG_READ_ONLY | V4L2_CTRL_FLAG_VOLATILE;
 		break;
+	case V4L2_CID_QCOM_VIDEO_SYNC_FRAME_SEQ_HDR:
+		*type = V4L2_CTRL_TYPE_BOOLEAN;
+		*min = 0;
+		*max = *step = 1;
+		break;
 	default:
 		*type = V4L2_CTRL_TYPE_INTEGER;
 		break;
diff --git a/drivers/media/video/vcap_vp.c b/drivers/media/video/vcap_vp.c
index 4c3ff16..aa39aad 100644
--- a/drivers/media/video/vcap_vp.c
+++ b/drivers/media/video/vcap_vp.c
@@ -464,7 +464,7 @@
 	}
 
 	handle = ion_alloc(dev->ion_client, size, SZ_4K,
-			ION_HEAP(ION_CP_MM_HEAP_ID));
+			ION_HEAP(ION_CP_MM_HEAP_ID), 0);
 	if (IS_ERR_OR_NULL(handle)) {
 		pr_err("%s: ion_alloc failed\n", __func__);
 		return -ENOMEM;
@@ -483,7 +483,7 @@
 		return rc;
 	}
 
-	vaddr = ion_map_kernel(dev->ion_client, handle, ionflag);
+	vaddr = ion_map_kernel(dev->ion_client, handle);
 	if (IS_ERR(vaddr)) {
 		pr_err("%s: Map motion buffer failed\n", __func__);
 		ion_free(dev->ion_client, handle);
@@ -535,7 +535,7 @@
 		tot_size = frame_size / 2 * 3;
 
 	handle = ion_alloc(dev->ion_client, tot_size, SZ_4K,
-			ION_HEAP(ION_CP_MM_HEAP_ID));
+			ION_HEAP(ION_CP_MM_HEAP_ID), 0);
 	if (IS_ERR_OR_NULL(handle)) {
 		pr_err("%s: ion_alloc failed\n", __func__);
 		return -ENOMEM;
@@ -665,7 +665,7 @@
 
 	dprintk(2, "%s: Start VP dummy event\n", __func__);
 	handle = ion_alloc(dev->ion_client, 0x1200, SZ_4K,
-			ION_HEAP(ION_CP_MM_HEAP_ID));
+			ION_HEAP(ION_CP_MM_HEAP_ID), 0);
 	if (IS_ERR_OR_NULL(handle)) {
 		pr_err("%s: ion_alloc failed\n", __func__);
 		return -ENOMEM;
diff --git a/drivers/media/video/videobuf2-core.c b/drivers/media/video/videobuf2-core.c
index a7d13a8..668cc73 100644
--- a/drivers/media/video/videobuf2-core.c
+++ b/drivers/media/video/videobuf2-core.c
@@ -1330,14 +1330,11 @@
 		return -EINVAL;
 	}
 
-	mutex_lock(&q->q_lock);
 	ret = __vb2_get_done_vb(q, &vb, nonblocking);
 	if (ret < 0) {
 		dprintk(1, "dqbuf: error getting next done buffer\n");
-		mutex_unlock(&q->q_lock);
 		return ret;
 	}
-	mutex_unlock(&q->q_lock);
 	ret = call_qop(q, buf_finish, vb);
 	if (ret) {
 		dprintk(1, "dqbuf: buffer finish failed\n");
@@ -1449,17 +1446,14 @@
 	/*
 	 * Let driver notice that streaming state has been enabled.
 	 */
-	mutex_lock(&q->q_lock);
 	ret = call_qop(q, start_streaming, q, atomic_read(&q->queued_count));
 	if (ret) {
 		dprintk(1, "streamon: driver refused to start streaming\n");
 		__vb2_queue_cancel(q);
-		mutex_unlock(&q->q_lock);
 		return ret;
 	}
 
 	q->streaming = 1;
-	mutex_unlock(&q->q_lock);
 	dprintk(3, "Streamon successful\n");
 	return 0;
 }
@@ -1733,7 +1727,6 @@
 	INIT_LIST_HEAD(&q->queued_list);
 	INIT_LIST_HEAD(&q->done_list);
 	spin_lock_init(&q->done_lock);
-	mutex_init(&q->q_lock);
 	init_waitqueue_head(&q->done_wq);
 
 	if (q->buf_struct_size == 0)
diff --git a/drivers/media/video/videobuf2-msm-mem.c b/drivers/media/video/videobuf2-msm-mem.c
index c1a392e2..97bc7c3 100644
--- a/drivers/media/video/videobuf2-msm-mem.c
+++ b/drivers/media/video/videobuf2-msm-mem.c
@@ -56,7 +56,7 @@
 		goto client_failed;
 	}
 	mem->ion_handle = ion_alloc(mem->client, mem->size, SZ_4K,
-		(0x1 << ION_CP_MM_HEAP_ID | 0x1 << ION_IOMMU_HEAP_ID));
+		(0x1 << ION_CP_MM_HEAP_ID | 0x1 << ION_IOMMU_HEAP_ID), 0);
 	if (IS_ERR((void *)mem->ion_handle)) {
 		pr_err("%s Could not allocate\n", __func__);
 		goto alloc_failed;
@@ -64,7 +64,7 @@
 	rc = ion_map_iommu(mem->client, mem->ion_handle,
 			-1, 0, SZ_4K, 0,
 			(unsigned long *)&phyaddr,
-			(unsigned long *)&len, UNCACHED, 0);
+			(unsigned long *)&len, 0, 0);
 	if (rc < 0) {
 		pr_err("%s Could not get physical address\n", __func__);
 		goto phys_failed;
@@ -192,7 +192,7 @@
 		return PTR_ERR(mem->ion_handle);
 	}
 	rc = ion_map_iommu(client, mem->ion_handle, domain_num, 0,
-		SZ_4K, 0, (unsigned long *)&mem->phyaddr, &len, UNCACHED, 0);
+		SZ_4K, 0, (unsigned long *)&mem->phyaddr, &len, 0, 0);
 	if (rc < 0)
 		ion_free(client, mem->ion_handle);
 #elif CONFIG_ANDROID_PMEM
diff --git a/drivers/misc/qseecom.c b/drivers/misc/qseecom.c
index d6d209b..4840e64 100644
--- a/drivers/misc/qseecom.c
+++ b/drivers/misc/qseecom.c
@@ -254,7 +254,6 @@
 				struct qseecom_register_listener_req *listener)
 {
 	int ret = 0;
-	unsigned int flags = 0;
 	struct qseecom_register_listener_ireq req;
 	struct qseecom_command_scm_resp resp;
 	ion_phys_addr_t pa;
@@ -271,8 +270,7 @@
 	ret = ion_phys(qseecom.ion_clnt, svc->ihandle, &pa, &svc->sb_length);
 
 	/* Populate the structure for sending scm call to load image */
-	svc->sb_virt = (char *) ion_map_kernel(qseecom.ion_clnt,
-							svc->ihandle, flags);
+	svc->sb_virt = (char *) ion_map_kernel(qseecom.ion_clnt, svc->ihandle);
 	svc->sb_phys = pa;
 
 	if (qseecom.qseos_version == QSEOS_VERSION_14) {
@@ -494,7 +492,6 @@
 {
 	ion_phys_addr_t pa;
 	int32_t ret;
-	unsigned int flags = 0;
 	struct qseecom_set_sb_mem_param_req req;
 	uint32_t len;
 
@@ -513,8 +510,7 @@
 	ret = ion_phys(qseecom.ion_clnt, data->client.ihandle, &pa, &len);
 	/* Populate the structure for sending scm call to load image */
 	data->client.sb_virt = (char *) ion_map_kernel(qseecom.ion_clnt,
-							data->client.ihandle,
-							flags);
+							data->client.ihandle);
 	data->client.sb_phys = pa;
 	data->client.sb_length = req.sb_len;
 	data->client.user_virt_sb_base = req.virt_sb_base;
diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
index 478cfac..9b316bb 100644
--- a/drivers/mmc/core/core.c
+++ b/drivers/mmc/core/core.c
@@ -28,6 +28,7 @@
 #include <linux/random.h>
 #include <linux/wakelock.h>
 #include <linux/pm.h>
+#include <linux/slab.h>
 
 #include <linux/mmc/card.h>
 #include <linux/mmc/host.h>
@@ -43,6 +44,12 @@
 #include "sd_ops.h"
 #include "sdio_ops.h"
 
+/*
+ * Background operations can take a long time, depending on the housekeeping
+ * operations the card has to perform.
+ */
+#define MMC_BKOPS_MAX_TIMEOUT	(4 * 60 * 1000) /* max time to wait in ms */
+
 static struct workqueue_struct *workqueue;
 
 /*
@@ -272,6 +279,70 @@
 	host->ops->request(host, mrq);
 }
 
+/**
+ *	mmc_start_bkops - start BKOPS for supported cards
+ *	@card: MMC card to start BKOPS
+ *	@form_exception: A flag to indicate if this function was
+ *			 called due to an exception raised by the card
+ *
+ *	Start background operations whenever requested.
+ *	When the urgent BKOPS bit is set in a R1 command response
+ *	then background operations should be started immediately.
+*/
+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 || mmc_card_doing_bkops(card))
+		return;
+
+	err = mmc_read_bkops_status(card);
+	if (err) {
+		pr_err("%s: Failed to read bkops status: %d\n",
+		       mmc_hostname(card->host), err);
+		return;
+	}
+
+	if (!card->ext_csd.raw_bkops_status)
+		return;
+
+	if (card->ext_csd.raw_bkops_status < EXT_CSD_BKOPS_LEVEL_2 &&
+	    from_exception)
+		return;
+
+	mmc_claim_host(card->host);
+	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;
+	}
+
+	err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
+			EXT_CSD_BKOPS_START, 1, timeout, use_busy_signal);
+	if (err) {
+		pr_warn("%s: Error %d starting bkops\n",
+			mmc_hostname(card->host), err);
+		goto out;
+	}
+
+	/*
+	 * 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);
+out:
+	mmc_release_host(card->host);
+}
+EXPORT_SYMBOL(mmc_start_bkops);
+
 static void mmc_wait_done(struct mmc_request *mrq)
 {
 	complete(&mrq->completion);
@@ -381,6 +452,14 @@
 	if (host->areq) {
 		mmc_wait_for_req_done(host, host->areq->mrq);
 		err = host->areq->err_check(host->card, host->areq);
+		/*
+		 * Check BKOPS urgency for each R1 response
+		 */
+		if (host->card && mmc_card_mmc(host->card) &&
+		    ((mmc_resp_type(host->areq->mrq->cmd) == MMC_RSP_R1) ||
+		     (mmc_resp_type(host->areq->mrq->cmd) == MMC_RSP_R1B)) &&
+		    (host->areq->mrq->cmd->resp[0] & R1_EXCEPTION_EVENT))
+			mmc_start_bkops(host->card, true);
 	}
 
 	if (!err && areq)
@@ -425,7 +504,7 @@
  *	@card: the MMC card associated with the HPI transfer
  *
  *	Issued High Priority Interrupt, and check for card status
- *	util out-of prg-state.
+ *	until out-of prg-state.
  */
 int mmc_interrupt_hpi(struct mmc_card *card)
 {
@@ -507,6 +586,64 @@
 EXPORT_SYMBOL(mmc_wait_for_cmd);
 
 /**
+ *	mmc_stop_bkops - stop ongoing BKOPS
+ *	@card: MMC card to check BKOPS
+ *
+ *	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.
+ */
+int mmc_stop_bkops(struct mmc_card *card)
+{
+	int err = 0;
+
+	BUG_ON(!card);
+	err = mmc_interrupt_hpi(card);
+
+	/*
+	 * If err is EINVAL, we can't issue an HPI.
+	 * It should complete the BKOPS.
+	 */
+	if (!err || (err == -EINVAL)) {
+		mmc_card_clr_doing_bkops(card);
+		err = 0;
+	}
+
+	return err;
+}
+EXPORT_SYMBOL(mmc_stop_bkops);
+
+int mmc_read_bkops_status(struct mmc_card *card)
+{
+	int err;
+	u8 *ext_csd;
+
+	/*
+	 * In future work, we should consider storing the entire ext_csd.
+	 */
+	ext_csd = kmalloc(512, GFP_KERNEL);
+	if (!ext_csd) {
+		pr_err("%s: could not allocate buffer to receive the ext_csd.\n",
+		       mmc_hostname(card->host));
+		return -ENOMEM;
+	}
+
+	mmc_claim_host(card->host);
+	err = mmc_send_ext_csd(card, ext_csd);
+	mmc_release_host(card->host);
+	if (err)
+		goto out;
+
+	card->ext_csd.raw_bkops_status = ext_csd[EXT_CSD_BKOPS_STATUS];
+	card->ext_csd.raw_exception_status = ext_csd[EXT_CSD_EXP_EVENTS_STATUS];
+out:
+	kfree(ext_csd);
+	return err;
+}
+EXPORT_SYMBOL(mmc_read_bkops_status);
+
+/**
  *	mmc_set_data_timeout - set the timeout for a data command
  *	@data: data phase for command
  *	@card: the MMC card associated with the data transfer
@@ -2370,8 +2507,14 @@
 				err = -EBUSY;
 
 		if (!err) {
-			if (host->bus_ops->suspend)
+			if (host->bus_ops->suspend) {
+				if (mmc_card_doing_bkops(host->card)) {
+					err = mmc_stop_bkops(host->card);
+					if (err)
+						goto stop_bkops_err;
+				}
 				err = host->bus_ops->suspend(host);
+			}
 			if (!(host->card && mmc_card_sdio(host->card)))
 				mmc_release_host(host);
 
@@ -2401,6 +2544,10 @@
 
 out:
 	return err;
+stop_bkops_err:
+	if (!(host->card && mmc_card_sdio(host->card)))
+		mmc_release_host(host);
+	return err;
 }
 
 EXPORT_SYMBOL(mmc_suspend_host);
@@ -2463,11 +2610,21 @@
 	struct mmc_host *host = container_of(
 		notify_block, struct mmc_host, pm_notify);
 	unsigned long flags;
-
+	int err = 0;
 
 	switch (mode) {
 	case PM_HIBERNATION_PREPARE:
 	case PM_SUSPEND_PREPARE:
+		if (host->card && mmc_card_mmc(host->card) &&
+		    mmc_card_doing_bkops(host->card)) {
+			err = mmc_stop_bkops(host->card);
+			if (err) {
+				pr_err("%s: didn't stop bkops\n",
+					mmc_hostname(host));
+				return err;
+			}
+			mmc_card_clr_doing_bkops(host->card);
+		}
 
 		spin_lock_irqsave(&host->lock, flags);
 		if (mmc_bus_needs_resume(host)) {
diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c
index f87b8cc..6343760 100644
--- a/drivers/mmc/core/mmc.c
+++ b/drivers/mmc/core/mmc.c
@@ -463,6 +463,17 @@
 	}
 
 	if (card->ext_csd.rev >= 5) {
+		/* check whether the eMMC card supports BKOPS */
+		if (ext_csd[EXT_CSD_BKOPS_SUPPORT] & 0x1) {
+			card->ext_csd.bkops = 1;
+			card->ext_csd.bkops_en = ext_csd[EXT_CSD_BKOPS_EN];
+			card->ext_csd.raw_bkops_status =
+				ext_csd[EXT_CSD_BKOPS_STATUS];
+			if (!card->ext_csd.bkops_en)
+				pr_info("%s: BKOPS_EN bit is not set\n",
+					mmc_hostname(card->host));
+		}
+
 		/* check whether the eMMC card supports HPI */
 		if (ext_csd[EXT_CSD_HPI_FEATURES] & 0x1) {
 			card->ext_csd.hpi = 1;
diff --git a/drivers/mmc/core/mmc_ops.c b/drivers/mmc/core/mmc_ops.c
index e18d922..4f46ed1 100644
--- a/drivers/mmc/core/mmc_ops.c
+++ b/drivers/mmc/core/mmc_ops.c
@@ -368,18 +368,19 @@
 }
 
 /**
- *	mmc_switch - modify EXT_CSD register
+ *	__mmc_switch - modify EXT_CSD register
  *	@card: the MMC card associated with the data transfer
  *	@set: cmd set values
  *	@index: EXT_CSD register index
  *	@value: value to program into EXT_CSD register
  *	@timeout_ms: timeout (ms) for operation performed by register write,
  *                   timeout of zero implies maximum possible timeout
+ *	@use_busy_signal: use the busy signal as response type
  *
  *	Modifies the EXT_CSD register for selected card.
  */
-int mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value,
-	       unsigned int timeout_ms)
+int __mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value,
+	       unsigned int timeout_ms, bool use_busy_signal)
 {
 	int err;
 	struct mmc_command cmd = {0};
@@ -393,13 +394,23 @@
 		  (index << 16) |
 		  (value << 8) |
 		  set;
-	cmd.flags = MMC_RSP_SPI_R1B | MMC_RSP_R1B | MMC_CMD_AC;
+	cmd.flags = MMC_CMD_AC;
+	if (use_busy_signal)
+		cmd.flags |= MMC_RSP_SPI_R1B | MMC_RSP_R1B;
+	else
+		cmd.flags |= MMC_RSP_SPI_R1 | MMC_RSP_R1;
+
+
 	cmd.cmd_timeout_ms = timeout_ms;
 
 	err = mmc_wait_for_cmd(card->host, &cmd, MMC_CMD_RETRIES);
 	if (err)
 		return err;
 
+	/* No need to check card status in case of unblocking command */
+	if (!use_busy_signal)
+		return 0;
+
 	/* Must check status to be sure of no errors */
 	do {
 		err = mmc_send_status(card, &status);
@@ -424,6 +435,13 @@
 
 	return 0;
 }
+EXPORT_SYMBOL_GPL(__mmc_switch);
+
+int mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value,
+		unsigned int timeout_ms)
+{
+	return __mmc_switch(card, set, index, value, timeout_ms, true);
+}
 EXPORT_SYMBOL_GPL(mmc_switch);
 
 int mmc_send_status(struct mmc_card *card, u32 *status)
diff --git a/drivers/power/Kconfig b/drivers/power/Kconfig
index 2542845..c474e36 100644
--- a/drivers/power/Kconfig
+++ b/drivers/power/Kconfig
@@ -395,6 +395,16 @@
 	help
 	  Say Y here to enable support for pm8921 chip charger subdevice
 
+config QPNP_CHARGER
+	tristate "QPNP Charger driver"
+	depends on SPMI
+	depends on OF_SPMI
+	help
+	  Say Y here to enable the switch mode battery charger
+	  and boost device which supports USB detection and charging. The driver
+	  also offers relevant information to userspace via the power supply
+	  framework.
+
 config PM8XXX_CCADC
 	tristate "PM8XXX battery current adc driver"
 	depends on MFD_PM8921_CORE
diff --git a/drivers/power/Makefile b/drivers/power/Makefile
index 9dc1960..3521cfd 100644
--- a/drivers/power/Makefile
+++ b/drivers/power/Makefile
@@ -57,6 +57,7 @@
 obj-$(CONFIG_PM8921_BMS)	+= pm8921-bms.o
 obj-$(CONFIG_QPNP_BMS)		+= qpnp-bms.o
 obj-$(CONFIG_PM8921_CHARGER)	+= pm8921-charger.o
+obj-$(CONFIG_QPNP_CHARGER)	+= qpnp-charger.o
 obj-$(CONFIG_LTC4088_CHARGER)	+= ltc4088-charger.o
 obj-$(CONFIG_CHARGER_SMB347)	+= smb347-charger.o
 obj-$(CONFIG_BATTERY_BCL)	+= battery_current_limit.o
diff --git a/drivers/power/pm8921-bms.c b/drivers/power/pm8921-bms.c
index b3d31d5..c63c99f 100644
--- a/drivers/power/pm8921-bms.c
+++ b/drivers/power/pm8921-bms.c
@@ -3248,7 +3248,10 @@
 	check_initial_ocv(chip);
 
 	/* start periodic hkadc calibration */
-	schedule_delayed_work(&chip->calib_hkadc_delayed_work, 0);
+	calib_hkadc(chip);
+	schedule_delayed_work(&chip->calib_hkadc_delayed_work,
+			round_jiffies_relative(msecs_to_jiffies
+			(HKADC_CALIB_DELAY_MS)));
 
 	/* enable the vbatt reading interrupts for scheduling hkadc calib */
 	pm8921_bms_enable_irq(chip, PM8921_BMS_GOOD_OCV);
diff --git a/drivers/power/qpnp-charger.c b/drivers/power/qpnp-charger.c
new file mode 100644
index 0000000..dda8976
--- /dev/null
+++ b/drivers/power/qpnp-charger.c
@@ -0,0 +1,1259 @@
+/* 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.
+ *
+ */
+#define pr_fmt(fmt)	"%s: " fmt, __func__
+
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/err.h>
+#include <linux/spmi.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/radix-tree.h>
+#include <linux/interrupt.h>
+#include <linux/qpnp/qpnp-adc.h>
+#include <linux/power_supply.h>
+#include <linux/bitops.h>
+
+/* Interrupt offsets */
+#define INT_RT_STS(base)			(base + 0x10)
+#define INT_SET_TYPE(base)			(base + 0x11)
+#define INT_POLARITY_HIGH(base)			(base + 0x12)
+#define INT_POLARITY_LOW(base)			(base + 0x13)
+#define INT_LATCHED_CLR(base)			(base + 0x14)
+#define INT_EN_SET(base)			(base + 0x15)
+#define INT_EN_CLR(base)			(base + 0x16)
+#define INT_LATCHED_STS(base)			(base + 0x18)
+#define INT_PENDING_STS(base)			(base + 0x19)
+#define INT_MID_SEL(base)			(base + 0x1A)
+#define INT_PRIORITY(base)			(base + 0x1B)
+
+/* Peripheral register offsets */
+#define CHGR_CHG_OPTION				0x08
+#define CHGR_ATC_STATUS				0x0A
+#define CHGR_VBAT_STATUS			0x0B
+#define CHGR_IBAT_BMS				0x0C
+#define CHGR_IBAT_STS				0x0D
+#define CHGR_VDD_MAX				0x40
+#define CHGR_VDD_SAFE				0x41
+#define CHGR_VDD_MAX_STEP			0x42
+#define CHGR_IBAT_MAX				0x44
+#define CHGR_IBAT_SAFE				0x45
+#define CHGR_VIN_MIN				0x47
+#define CHGR_VIN_MIN_STEP			0x48
+#define CHGR_CHG_CTRL				0x49
+#define CHGR_CHG_FAILED				0x4A
+#define CHGR_ATC_CTRL				0x4B
+#define CHGR_ATC_FAILED				0x4C
+#define CHGR_VBAT_TRKL				0x50
+#define CHGR_VBAT_WEAK				0x52
+#define CHGR_IBAT_ATC_A				0x54
+#define CHGR_IBAT_ATC_B				0x55
+#define CHGR_IBAT_TERM_CHGR			0x5B
+#define CHGR_IBAT_TERM_BMS			0x5C
+#define CHGR_VBAT_DET				0x5D
+#define CHGR_TTRKL_MAX				0x5F
+#define CHGR_TTRKL_MAX_EN			0x60
+#define CHGR_TCHG_MAX				0x61
+#define CHGR_CHG_WDOG_TIME			0x62
+#define CHGR_CHG_WDOG_DLY			0x63
+#define CHGR_CHG_WDOG_PET			0x64
+#define CHGR_CHG_WDOG_EN			0x65
+#define CHGR_USB_IUSB_MAX			0x44
+#define CHGR_USB_ENUM_T_STOP			0x4E
+#define CHGR_CHG_TEMP_THRESH			0x66
+#define CHGR_BAT_IF_PRES_STATUS			0x08
+#define CHGR_BAT_TEMP_STATUS			0x09
+#define CHGR_BAT_IF_VCP				0x42
+#define CHGR_BAT_IF_BATFET_CTRL1		0x90
+#define CHGR_MISC_BOOT_DONE			0x42
+#define MISC_REVISION2				0x01
+
+/* SMBB peripheral subtype values */
+#define REG_OFFSET_PERP_SUBTYPE			0x05
+#define SMBB_CHGR_SUBTYPE			0x01
+#define SMBB_BUCK_SUBTYPE			0x02
+#define SMBB_BAT_IF_SUBTYPE			0x03
+#define SMBB_USB_CHGPTH_SUBTYPE			0x04
+#define SMBB_DC_CHGPTH_SUBTYPE			0x05
+#define SMBB_BOOST_SUBTYPE			0x06
+#define SMBB_MISC_SUBTYPE			0x07
+
+#define QPNP_CHARGER_DEV_NAME	"qcom,qpnp-charger"
+
+/* Interrupt definitions */
+/* smbb_chg_interrupts */
+#define CHG_DONE_IRQ			BIT(7)
+#define CHG_FAILED_IRQ			BIT(6)
+#define FAST_CHG_ON_IRQ			BIT(5)
+#define TRKL_CHG_ON_IRQ			BIT(4)
+#define STATE_CHANGE_ON_IR		BIT(3)
+#define CHGWDDOG_IRQ			BIT(2)
+#define VBAT_DET_HI_IRQ			BIT(1)
+#define VBAT_DET_LOW_IRQ		BIT(0)
+
+/* smbb_buck_interrupts */
+#define VDD_LOOP_IRQ			BIT(6)
+#define IBAT_LOOP_IRQ			BIT(5)
+#define ICHG_LOOP_IRQ			BIT(4)
+#define VCHG_LOOP_IRQ			BIT(3)
+#define OVERTEMP_IRQ			BIT(2)
+#define VREF_OV_IRQ			BIT(1)
+#define VBAT_OV_IRQ			BIT(0)
+
+/* smbb_bat_if_interrupts */
+#define PSI_IRQ				BIT(4)
+#define VCP_ON_IRQ			BIT(3)
+#define BAT_FET_ON_IRQ			BIT(2)
+#define BAT_TEMP_OK_IRQ			BIT(1)
+#define BATT_PRES_IRQ			BIT(0)
+
+/* smbb_usb_interrupts */
+#define CHG_GONE_IRQ			BIT(2)
+#define USBIN_VALID_IRQ			BIT(1)
+#define COARSE_DET_USB_IRQ		BIT(0)
+
+/* smbb_dc_interrupts */
+#define DCIN_VALID_IRQ			BIT(1)
+#define COARSE_DET_DC_IRQ		BIT(0)
+
+/* smbb_boost_interrupts */
+#define LIMIT_ERROR_IRQ			BIT(1)
+#define BOOST_PWR_OK_IRQ		BIT(0)
+
+/* smbb_misc_interrupts */
+#define TFTWDOG_IRQ			BIT(0)
+
+/**
+ * struct qpnp_chg_chip - device information
+ * @dev:			device pointer to access the parent
+ * @spmi:			spmi pointer to access spmi information
+ * @chgr_base:			charger peripheral base address
+ * @buck_base:			buck  peripheral base address
+ * @bat_if_base:		battery interface  peripheral base address
+ * @usb_chgpth_base:		USB charge path peripheral base address
+ * @dc_chgpth_base:		DC charge path peripheral base address
+ * @boost_base:			boost peripheral base address
+ * @misc_base:			misc peripheral base address
+ * @freq_base:			freq peripheral base address
+ * @chg_done:			indicates that charging is completed
+ * @usb_present:		present status of usb
+ * @dc_present:			present status of dc
+ * @max_voltage_mv:		the max volts the batt should be charged up to
+ * @min_voltage_mv:		the min battery voltage before turning the FETon
+ * @term_current:		the charging based term current
+ * @revision:			PMIC revision
+ * @dc_psy			power supply to export information to userspace
+ * @usb_psy			power supply to export information to userspace
+ * @bms_psy			power supply to export information to userspace
+ * @batt_psy:			power supply to export information to userspace
+ *
+ */
+struct qpnp_chg_chip {
+	struct device			*dev;
+	struct spmi_device		*spmi;
+	u16				chgr_base;
+	u16				buck_base;
+	u16				bat_if_base;
+	u16				usb_chgpth_base;
+	u16				dc_chgpth_base;
+	u16				boost_base;
+	u16				misc_base;
+	u16				freq_base;
+	unsigned int			usbin_valid_irq;
+	unsigned int			chg_done_irq;
+	unsigned int			chg_failed_irq;
+	bool				chg_done;
+	bool				usb_present;
+	bool				dc_present;
+	unsigned int			max_bat_chg_current;
+	unsigned int			safe_voltage_mv;
+	unsigned int			max_voltage_mv;
+	unsigned int			min_voltage_mv;
+	unsigned int			term_current;
+	unsigned int			revision;
+	struct power_supply		dc_psy;
+	struct power_supply		*usb_psy;
+	struct power_supply		*bms_psy;
+	struct power_supply		batt_psy;
+};
+
+static struct qpnp_chg_chip *the_chip;
+static int charging_disabled;
+
+static struct of_device_id qpnp_charger_match_table[] = {
+	{ .compatible = QPNP_CHARGER_DEV_NAME, },
+	{}
+};
+
+static int
+qpnp_chg_read(struct qpnp_chg_chip *chip, u8 *val,
+			u16 base, int count)
+{
+	int rc;
+	struct spmi_device *spmi = chip->spmi;
+
+	rc = spmi_ext_register_readl(spmi->ctrl, spmi->sid, base, val,
+					count);
+	if (rc) {
+		pr_err("SPMI read failed base=0x%02x sid=0x%02x rc=%d\n", base,
+				spmi->sid, rc);
+		return rc;
+	}
+	return 0;
+}
+
+static int
+qpnp_chg_write(struct qpnp_chg_chip *chip, u8 *val,
+			u16 base, int count)
+{
+	int rc;
+	struct spmi_device *spmi = chip->spmi;
+
+	rc = spmi_ext_register_writel(spmi->ctrl, spmi->sid, base, val,
+					count);
+	if (rc) {
+		pr_err("write failed base=0x%02x sid=0x%02x rc=%d\n",
+			base, spmi->sid, rc);
+		return rc;
+	}
+
+	return 0;
+}
+
+static int
+qpnp_chg_masked_write(struct qpnp_chg_chip *chip, u16 base,
+						u8 mask, u8 val, int count)
+{
+	int rc;
+	u8 reg;
+
+	rc = qpnp_chg_read(chip, &reg, base, count);
+	if (rc) {
+		pr_err("spmi read failed: addr=%03X, rc=%d\n", base, rc);
+		return rc;
+	}
+	pr_debug("addr = 0x%x read 0x%x\n", base, reg);
+
+	reg &= ~mask;
+	reg |= val & mask;
+
+	pr_debug("Writing 0x%x\n", reg);
+
+	rc = qpnp_chg_write(chip, &reg, base, count);
+	if (rc) {
+		pr_err("spmi write failed: addr=%03X, rc=%d\n", base, rc);
+		return rc;
+	}
+
+	return 0;
+}
+
+static int
+qpnp_chg_is_usb_chg_plugged_in(struct qpnp_chg_chip *chip)
+{
+	u8 usbin_valid_rt_sts;
+	int rc;
+
+	rc = qpnp_chg_read(chip, &usbin_valid_rt_sts,
+				 INT_RT_STS(chip->usb_chgpth_base), 1);
+
+	if (rc) {
+		pr_err("spmi read failed: addr=%03X, rc=%d\n",
+				INT_RT_STS(chip->usb_chgpth_base), rc);
+		return rc;
+	}
+	pr_debug("chgr usb sts 0x%x\n", usbin_valid_rt_sts);
+
+	return (usbin_valid_rt_sts & USBIN_VALID_IRQ) ? 1 : 0;
+}
+
+static int
+qpnp_chg_is_dc_chg_plugged_in(struct qpnp_chg_chip *chip)
+{
+	u8 dcin_valid_rt_sts;
+	int rc;
+
+	rc = qpnp_chg_read(chip, &dcin_valid_rt_sts,
+				 INT_RT_STS(chip->dc_chgpth_base), 1);
+	if (rc) {
+		pr_err("spmi read failed: addr=%03X, rc=%d\n",
+				INT_RT_STS(chip->dc_chgpth_base), rc);
+		return rc;
+	}
+
+	return (dcin_valid_rt_sts & DCIN_VALID_IRQ) ? 1 : 0;
+}
+
+#define VCP_IUSBMAX_SETTING_MA			2000
+#define QPNP_CHG_IUSB_MAX_MIN_100		100
+#define QPNP_CHG_IUSB_MAX_MIN_150		150
+#define QPNP_CHG_IUSB_MAX_MIN_MA		200
+#define QPNP_CHG_IUSB_MAX_MAX_MA		2500
+#define QPNP_CHG_IUSB_MAX_STEP_MA		100
+static int
+qpnp_chg_iusbmax_set(struct qpnp_chg_chip *chip, int mA)
+{
+	u8 usb_reg = 0;
+
+	if (mA == QPNP_CHG_IUSB_MAX_MIN_100) {
+		usb_reg = 0x00;
+		pr_debug("current=%d setting %02x\n", mA, usb_reg);
+		return qpnp_chg_write(chip, &usb_reg,
+		chip->usb_chgpth_base + CHGR_USB_IUSB_MAX, 1);
+	} else if (mA == QPNP_CHG_IUSB_MAX_MIN_150) {
+		usb_reg = 0x01;
+		pr_debug("current=%d setting %02x\n", mA, usb_reg);
+		return qpnp_chg_write(chip, &usb_reg,
+		chip->usb_chgpth_base + CHGR_USB_IUSB_MAX, 1);
+	}
+
+	if (mA < QPNP_CHG_IUSB_MAX_MIN_MA
+			|| mA > QPNP_CHG_IUSB_MAX_MAX_MA) {
+		pr_err("bad mA=%d asked to set\n", mA);
+		return -EINVAL;
+	}
+
+	/* Hack for VCP issue make sure IUSBMAX setting
+	 * is at least 2 A to not brown out device */
+	mA = VCP_IUSBMAX_SETTING_MA;
+
+	usb_reg = mA / QPNP_CHG_IUSB_MAX_STEP_MA;
+
+	pr_debug("current=%d setting 0x%x\n", mA, usb_reg);
+	return qpnp_chg_write(chip, &usb_reg,
+		chip->usb_chgpth_base + CHGR_USB_IUSB_MAX, 1);
+	pr_debug("done\n");
+	return 0;
+}
+
+#define ENUM_T_STOP_BIT		BIT(0)
+static irqreturn_t
+qpnp_chg_usb_usbin_valid_irq_handler(int irq, void *_chip)
+{
+	struct qpnp_chg_chip *chip = _chip;
+	int usb_present;
+
+	usb_present = qpnp_chg_is_usb_chg_plugged_in(chip);
+	pr_debug("usbin-valid triggered: %d\n", usb_present);
+
+	if (chip->usb_present ^ usb_present) {
+		chip->usb_present = usb_present;
+		power_supply_set_present(chip->usb_psy,
+			chip->usb_present);
+	} else if (!(chip->usb_present && usb_present)) {
+			qpnp_chg_masked_write(chip,
+				chip->usb_chgpth_base + CHGR_USB_ENUM_T_STOP,
+				ENUM_T_STOP_BIT,
+				ENUM_T_STOP_BIT, 1);
+	}
+
+	return IRQ_HANDLED;
+}
+
+#define CHGR_CHG_FAILED_BIT	BIT(7)
+static irqreturn_t
+qpnp_chg_chgr_chg_failed_irq_handler(int irq, void *_chip)
+{
+	struct qpnp_chg_chip *chip = _chip;
+	int rc, usb_present;
+
+	rc = qpnp_chg_masked_write(chip,
+		chip->usb_chgpth_base + CHGR_CHG_FAILED,
+		CHGR_CHG_FAILED_BIT,
+		CHGR_CHG_FAILED_BIT, 1);
+	if (rc)
+		pr_err("Failed to write chg_fail clear bit!\n");
+
+	/* Hack: recheck usbin_valid status after chg_fail triggered */
+	usb_present = qpnp_chg_is_usb_chg_plugged_in(chip);
+	pr_debug("usb_status: %d\n", usb_present);
+	if (usb_present)
+		qpnp_chg_usb_usbin_valid_irq_handler(chip->usbin_valid_irq,
+			_chip);
+
+
+	return IRQ_HANDLED;
+}
+
+static irqreturn_t
+qpnp_chg_chgr_chg_done_irq_handler(int irq, void *_chip)
+{
+	struct qpnp_chg_chip *chip = _chip;
+
+	pr_debug("CHG_DONE IRQ triggered\n");
+	chip->chg_done = true;
+
+	return IRQ_HANDLED;
+}
+
+static enum power_supply_property pm_power_props_mains[] = {
+	POWER_SUPPLY_PROP_PRESENT,
+	POWER_SUPPLY_PROP_ONLINE,
+};
+
+static enum power_supply_property msm_batt_power_props[] = {
+	POWER_SUPPLY_PROP_STATUS,
+	POWER_SUPPLY_PROP_CHARGE_TYPE,
+	POWER_SUPPLY_PROP_HEALTH,
+	POWER_SUPPLY_PROP_PRESENT,
+	POWER_SUPPLY_PROP_TECHNOLOGY,
+	POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN,
+	POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN,
+	POWER_SUPPLY_PROP_VOLTAGE_NOW,
+	POWER_SUPPLY_PROP_CAPACITY,
+	POWER_SUPPLY_PROP_CURRENT_NOW,
+	POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN,
+	POWER_SUPPLY_PROP_TEMP,
+};
+
+static char *pm_power_supplied_to[] = {
+	"battery",
+};
+
+#define USB_WALL_THRESHOLD_MA	500
+static int
+qpnp_power_get_property_mains(struct power_supply *psy,
+				  enum power_supply_property psp,
+				  union power_supply_propval *val)
+{
+	struct qpnp_chg_chip *chip = container_of(psy, struct qpnp_chg_chip,
+								dc_psy);
+
+	switch (psp) {
+	case POWER_SUPPLY_PROP_PRESENT:
+	case POWER_SUPPLY_PROP_ONLINE:
+		val->intval = 0;
+		if (charging_disabled)
+			return 0;
+
+		val->intval = qpnp_chg_is_dc_chg_plugged_in(chip);
+		break;
+	default:
+		return -EINVAL;
+	}
+	return 0;
+}
+
+static int
+get_prop_battery_voltage_now(struct qpnp_chg_chip *chip)
+{
+	int rc = 0;
+	struct qpnp_vadc_result results;
+
+	if (chip->revision > 0) {
+		rc = qpnp_vadc_read(VBAT_SNS, &results);
+		if (rc) {
+			pr_err("Unable to read vbat rc=%d\n", rc);
+			return 0;
+		}
+		return results.physical;
+	} else {
+		pr_err("vbat reading not supported for 1.0 rc=%d\n", rc);
+		return 0;
+	}
+}
+
+#define BATT_PRES_BIT BIT(7)
+static int
+get_prop_batt_present(struct qpnp_chg_chip *chip)
+{
+	u8 batt_present;
+	int rc;
+
+	rc = qpnp_chg_read(chip, &batt_present,
+				chip->bat_if_base + CHGR_BAT_IF_PRES_STATUS, 1);
+	if (rc) {
+		pr_err("Couldn't read battery status read failed rc=%d\n", rc);
+		return 0;
+	};
+	return (batt_present & BATT_PRES_BIT) ? 1 : 0;
+}
+
+#define BATT_TEMP_HOT	BIT(6)
+#define BATT_TEMP_OK	BIT(7)
+static int
+get_prop_batt_health(struct qpnp_chg_chip *chip)
+{
+	u8 batt_health;
+	int rc;
+
+	rc = qpnp_chg_read(chip, &batt_health,
+				chip->bat_if_base + CHGR_BAT_TEMP_STATUS, 1);
+	if (rc) {
+		pr_err("Couldn't read battery health read failed rc=%d\n", rc);
+		return POWER_SUPPLY_HEALTH_UNKNOWN;
+	};
+
+	if (BATT_TEMP_OK & batt_health)
+		return POWER_SUPPLY_HEALTH_GOOD;
+	if (BATT_TEMP_HOT & batt_health)
+		return POWER_SUPPLY_HEALTH_OVERHEAT;
+	else
+		return POWER_SUPPLY_HEALTH_COLD;
+}
+
+static int
+get_prop_charge_type(struct qpnp_chg_chip *chip)
+{
+	int rc;
+	u8 chgr_sts;
+
+	if (!get_prop_batt_present(chip))
+		return POWER_SUPPLY_CHARGE_TYPE_NONE;
+
+	rc = qpnp_chg_read(chip, &chgr_sts,
+				INT_RT_STS(chip->chgr_base), 1);
+	if (rc) {
+		pr_err("failed to read interrupt sts %d\n", rc);
+		return POWER_SUPPLY_CHARGE_TYPE_NONE;
+	}
+
+	if (chgr_sts & TRKL_CHG_ON_IRQ)
+		return POWER_SUPPLY_CHARGE_TYPE_TRICKLE;
+	if (chgr_sts & FAST_CHG_ON_IRQ)
+		return POWER_SUPPLY_CHARGE_TYPE_FAST;
+
+	return POWER_SUPPLY_CHARGE_TYPE_NONE;
+}
+
+static int
+get_prop_batt_status(struct qpnp_chg_chip *chip)
+{
+	int rc;
+	u8 chgr_sts;
+
+	rc = qpnp_chg_read(chip, &chgr_sts,
+				INT_RT_STS(chip->chgr_base), 1);
+	if (rc) {
+		pr_err("failed to read interrupt sts %d\n", rc);
+		return POWER_SUPPLY_STATUS_DISCHARGING;
+	}
+
+	pr_debug("chgr sts 0x%x\n", chgr_sts);
+	if (chgr_sts & CHG_DONE_IRQ || chip->chg_done)
+		return POWER_SUPPLY_STATUS_FULL;
+	else
+		chip->chg_done = false;
+
+	if (chgr_sts & TRKL_CHG_ON_IRQ)
+		return POWER_SUPPLY_STATUS_CHARGING;
+	if (chgr_sts & FAST_CHG_ON_IRQ)
+		return POWER_SUPPLY_STATUS_CHARGING;
+
+	return POWER_SUPPLY_STATUS_DISCHARGING;
+}
+
+static int
+get_prop_current_now(struct qpnp_chg_chip *chip)
+{
+	union power_supply_propval ret = {0,};
+
+	if (chip->bms_psy) {
+		chip->bms_psy->get_property(chip->bms_psy,
+			  POWER_SUPPLY_PROP_CURRENT_NOW, &ret);
+		return ret.intval;
+	} else {
+		pr_debug("No BMS supply registered return 0\n");
+	}
+
+	return 0;
+}
+
+static int
+get_prop_full_design(struct qpnp_chg_chip *chip)
+{
+	union power_supply_propval ret = {0,};
+
+	if (chip->bms_psy) {
+		chip->bms_psy->get_property(chip->bms_psy,
+			  POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN, &ret);
+		return ret.intval;
+	} else {
+		pr_debug("No BMS supply registered return 0\n");
+	}
+
+	return 0;
+}
+
+#define DEFAULT_CAPACITY	50
+static int
+get_prop_capacity(struct qpnp_chg_chip *chip)
+{
+	union power_supply_propval ret = {0,};
+
+	if (chip->bms_psy) {
+		chip->bms_psy->get_property(chip->bms_psy,
+			  POWER_SUPPLY_PROP_CAPACITY, &ret);
+		return ret.intval;
+	} else {
+		pr_debug("No BMS supply registered return 50\n");
+	}
+
+	/* return default capacity to avoid userspace
+	 * from shutting down unecessarily */
+	return DEFAULT_CAPACITY;
+}
+
+#define DEFAULT_TEMP		25
+#define MAX_TOLERABLE_BATT_TEMP_DDC	680
+static int
+get_prop_batt_temp(struct qpnp_chg_chip *chip)
+{
+	int rc = 0;
+	struct qpnp_vadc_result results;
+
+	if (chip->revision > 0) {
+		rc = qpnp_vadc_read(LR_MUX1_BATT_THERM, &results);
+		if (rc) {
+			pr_debug("Unable to read batt temperature rc=%d\n", rc);
+			return 0;
+		}
+		pr_debug("get_bat_temp %d %lld\n",
+			results.adc_code, results.physical);
+		return (int)results.physical;
+	} else {
+		pr_debug("batt temp not supported for PMIC 1.0 rc=%d\n", rc);
+	}
+
+	/* return default temperature to avoid userspace
+	 * from shutting down unecessarily */
+	return DEFAULT_TEMP;
+}
+
+static void
+qpnp_batt_external_power_changed(struct power_supply *psy)
+{
+	struct qpnp_chg_chip *chip = container_of(psy, struct qpnp_chg_chip,
+								batt_psy);
+	union power_supply_propval ret = {0,};
+
+	if (!chip->bms_psy)
+		chip->bms_psy = power_supply_get_by_name("bms");
+
+	chip->usb_psy->get_property(chip->usb_psy,
+			  POWER_SUPPLY_PROP_ONLINE, &ret);
+
+	if (ret.intval && qpnp_chg_is_usb_chg_plugged_in(chip)) {
+		chip->usb_psy->get_property(chip->usb_psy,
+			  POWER_SUPPLY_PROP_CURRENT_MAX, &ret);
+		qpnp_chg_iusbmax_set(chip, ret.intval / 1000);
+	} else {
+		qpnp_chg_iusbmax_set(chip, QPNP_CHG_IUSB_MAX_MIN_MA);
+	}
+
+	pr_debug("end of power supply changed\n");
+	power_supply_changed(&chip->batt_psy);
+}
+
+static int
+qpnp_batt_power_get_property(struct power_supply *psy,
+				       enum power_supply_property psp,
+				       union power_supply_propval *val)
+{
+	struct qpnp_chg_chip *chip = container_of(psy, struct qpnp_chg_chip,
+								batt_psy);
+
+	switch (psp) {
+	case POWER_SUPPLY_PROP_STATUS:
+		val->intval = get_prop_batt_status(chip);
+		break;
+	case POWER_SUPPLY_PROP_CHARGE_TYPE:
+		val->intval = get_prop_charge_type(chip);
+		break;
+	case POWER_SUPPLY_PROP_HEALTH:
+		val->intval = get_prop_batt_health(chip);
+		break;
+	case POWER_SUPPLY_PROP_PRESENT:
+		val->intval = get_prop_batt_present(chip);
+		break;
+	case POWER_SUPPLY_PROP_TECHNOLOGY:
+		val->intval = POWER_SUPPLY_TECHNOLOGY_LION;
+		break;
+	case POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN:
+		val->intval = chip->max_voltage_mv * 1000;
+		break;
+	case POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN:
+		val->intval = chip->min_voltage_mv * 1000;
+		break;
+	case POWER_SUPPLY_PROP_VOLTAGE_NOW:
+		val->intval = get_prop_battery_voltage_now(chip);
+		break;
+	case POWER_SUPPLY_PROP_TEMP:
+		val->intval = get_prop_batt_temp(chip);
+		break;
+	case POWER_SUPPLY_PROP_CAPACITY:
+		val->intval = get_prop_capacity(chip);
+		break;
+	case POWER_SUPPLY_PROP_CURRENT_NOW:
+		val->intval = get_prop_current_now(chip);
+		break;
+	case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN:
+		val->intval = get_prop_full_design(chip);
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+#define CHGR_BOOT_DONE	BIT(7)
+#define CHGR_CHG_EN	BIT(7)
+#define CHGR_ON_BAT_FORCE_BIT	BIT(0)
+#define CHGR_BAT_IF_CONST_RDS_EN	BIT(7)
+#define CHGR_BAT_IF_VCP_EN	BIT(0)
+static int
+qpnp_chg_charge_dis(struct qpnp_chg_chip *chip, int disable)
+{
+	/* 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,
+			CHGR_ON_BAT_FORCE_BIT,
+			disable ? CHGR_ON_BAT_FORCE_BIT : 0, 1);
+}
+
+static int
+qpnp_chg_charge_en(struct qpnp_chg_chip *chip, int enable)
+{
+	return qpnp_chg_masked_write(chip, chip->chgr_base + CHGR_CHG_CTRL,
+			CHGR_CHG_EN,
+			enable ? CHGR_CHG_EN : 0, 1);
+}
+
+static int
+qpnp_chg_set_disable_status_param(const char *val, struct kernel_param *kp)
+{
+	int ret;
+	struct qpnp_chg_chip *chip = the_chip;
+
+	ret = param_set_int(val, kp);
+	if (ret) {
+		pr_err("error setting value %d\n", ret);
+		return ret;
+	}
+	pr_info("factory set disable param to %d\n", charging_disabled);
+	if (chip)
+		qpnp_chg_charge_dis(chip, charging_disabled);
+	return 0;
+}
+module_param_call(disabled, qpnp_chg_set_disable_status_param, param_get_uint,
+					&charging_disabled, 0644);
+
+#define QPNP_CHG_VINMIN_MIN_MV		3400
+#define QPNP_CHG_VINMIN_HIGH_MIN_MV	5600
+#define QPNP_CHG_VINMIN_HIGH_MIN_VAL	0x2B
+#define QPNP_CHG_VINMIN_MAX_MV		9600
+#define QPNP_CHG_VINMIN_STEP_MV		50
+#define QPNP_CHG_VINMIN_STEP_HIGH_MV	200
+#define QPNP_CHG_VINMIN_MASK		0x1F
+static int
+qpnp_chg_vinmin_set(struct qpnp_chg_chip *chip, int voltage)
+{
+	u8 temp;
+
+	if (voltage < QPNP_CHG_VINMIN_MIN_MV
+			|| voltage > QPNP_CHG_VINMIN_MAX_MV) {
+		pr_err("bad mV=%d asked to set\n", voltage);
+		return -EINVAL;
+	}
+	if (voltage >= QPNP_CHG_VINMIN_HIGH_MIN_MV) {
+		temp = QPNP_CHG_VINMIN_HIGH_MIN_VAL;
+		temp += (voltage - QPNP_CHG_VINMIN_MIN_MV)
+			/ QPNP_CHG_VINMIN_STEP_HIGH_MV;
+	} else {
+		temp = (voltage - QPNP_CHG_VINMIN_MIN_MV)
+			/ QPNP_CHG_VINMIN_STEP_MV;
+	}
+
+	pr_debug("voltage=%d setting %02x\n", voltage, temp);
+	return qpnp_chg_masked_write(chip,
+			chip->chgr_base + CHGR_VIN_MIN,
+			QPNP_CHG_VINMIN_MASK, temp, 1);
+}
+
+
+#define QPNP_CHG_ITERM_MIN_MA		100
+#define QPNP_CHG_ITERM_MAX_MA		250
+#define QPNP_CHG_ITERM_STEP_MA		50
+#define QPNP_CHG_ITERM_MASK			0x03
+static int
+qpnp_chg_ibatterm_set(struct qpnp_chg_chip *chip, int term_current)
+{
+	u8 temp;
+
+	if (term_current < QPNP_CHG_ITERM_MIN_MA
+			|| term_current > QPNP_CHG_ITERM_MAX_MA) {
+		pr_err("bad mA=%d asked to set\n", term_current);
+		return -EINVAL;
+	}
+
+	temp = (term_current - QPNP_CHG_ITERM_MIN_MA)
+				/ QPNP_CHG_ITERM_STEP_MA;
+	return qpnp_chg_masked_write(chip,
+			chip->chgr_base + CHGR_IBAT_TERM_CHGR,
+			QPNP_CHG_ITERM_MASK, temp, 1);
+}
+
+#define QPNP_CHG_IBATMAX_MIN	100
+#define QPNP_CHG_IBATMAX_MAX	3250
+#define QPNP_CHG_I_STEP_MA		50
+#define QPNP_CHG_I_MIN_MA		100
+#define QPNP_CHG_I_MASK			0x3F
+static int
+qpnp_chg_ibatmax_set(struct qpnp_chg_chip *chip, int chg_current)
+{
+	u8 temp;
+
+	if (chg_current < QPNP_CHG_IBATMAX_MIN
+			|| chg_current > QPNP_CHG_IBATMAX_MAX) {
+		pr_err("bad mA=%d asked to set\n", chg_current);
+		return -EINVAL;
+	}
+	temp = (chg_current - QPNP_CHG_I_MIN_MA) / QPNP_CHG_I_STEP_MA;
+	return qpnp_chg_masked_write(chip, chip->chgr_base + CHGR_IBAT_MAX,
+			QPNP_CHG_I_MASK, temp, 1);
+}
+
+
+#define QPNP_CHG_V_MIN_MV	3240
+#define QPNP_CHG_V_MAX_MV	4500
+#define QPNP_CHG_V_STEP_MV	10
+static int
+qpnp_chg_vddsafe_set(struct qpnp_chg_chip *chip, int voltage)
+{
+	u8 temp;
+
+	if (voltage < QPNP_CHG_V_MIN_MV
+			|| voltage > QPNP_CHG_V_MAX_MV) {
+		pr_err("bad mV=%d asked to set\n", voltage);
+		return -EINVAL;
+	}
+	temp = (voltage - QPNP_CHG_V_MIN_MV) / QPNP_CHG_V_STEP_MV;
+	pr_debug("voltage=%d setting %02x\n", voltage, temp);
+	return qpnp_chg_write(chip, &temp,
+		chip->chgr_base + CHGR_VDD_SAFE, 1);
+}
+
+#define QPNP_CHG_VDDMAX_MIN	3400
+static int
+qpnp_chg_vddmax_set(struct qpnp_chg_chip *chip, int voltage)
+{
+	u8 temp = 0;
+
+	if (voltage < QPNP_CHG_VDDMAX_MIN
+			|| voltage > QPNP_CHG_V_MAX_MV) {
+		pr_err("bad mV=%d asked to set\n", voltage);
+		return -EINVAL;
+	}
+
+	temp = (voltage - QPNP_CHG_V_MIN_MV) / QPNP_CHG_V_STEP_MV;
+
+	pr_debug("voltage=%d setting %02x\n", voltage, temp);
+	return qpnp_chg_write(chip, &temp,
+		chip->chgr_base + CHGR_VDD_MAX, 1);
+}
+
+#define WDOG_EN_BIT	BIT(7)
+static int
+qpnp_chg_hwinit(struct qpnp_chg_chip *chip, u8 subtype,
+				struct spmi_resource *spmi_resource)
+{
+	int rc = 0;
+	u8 reg;
+
+	switch (subtype) {
+	case SMBB_CHGR_SUBTYPE:
+		chip->chg_done_irq = spmi_get_irq_byname(chip->spmi,
+						spmi_resource, "chg-done");
+		if (chip->chg_done_irq < 0) {
+			pr_err("Unable to get chg_done irq\n");
+			return -ENXIO;
+		}
+
+		chip->chg_failed_irq = spmi_get_irq_byname(chip->spmi,
+						spmi_resource, "chg-failed");
+		if (chip->chg_failed_irq < 0) {
+			pr_err("Unable to get chg_failed irq\n");
+			return -ENXIO;
+		}
+		rc |= devm_request_irq(chip->dev, chip->chg_done_irq,
+				qpnp_chg_chgr_chg_done_irq_handler,
+				IRQF_TRIGGER_RISING, "chg_done", chip);
+		if (rc < 0) {
+			pr_err("Can't request %d chg_done for chg: %d\n",
+						chip->chg_done_irq, rc);
+			return -ENXIO;
+		}
+		rc |= devm_request_irq(chip->dev, chip->chg_failed_irq,
+				qpnp_chg_chgr_chg_failed_irq_handler,
+				IRQF_TRIGGER_RISING, "chg_failed", chip);
+		if (rc < 0) {
+			pr_err("Can't request %d chg_failed chg: %d\n",
+						chip->chg_failed_irq, rc);
+			return -ENXIO;
+		}
+
+		rc = qpnp_chg_vinmin_set(chip, chip->min_voltage_mv);
+		if (rc) {
+			pr_debug("failed setting  min_voltage rc=%d\n", rc);
+			return rc;
+		}
+		rc = qpnp_chg_vddmax_set(chip, chip->max_voltage_mv);
+		if (rc) {
+			pr_debug("failed setting max_voltage rc=%d\n", rc);
+			return rc;
+		}
+		rc = qpnp_chg_vddsafe_set(chip, chip->safe_voltage_mv);
+		if (rc) {
+			pr_debug("failed setting safe_voltage rc=%d\n", rc);
+			return rc;
+		}
+		rc = qpnp_chg_ibatmax_set(chip, chip->max_bat_chg_current);
+		if (rc) {
+			pr_debug("failed setting ibatmax rc=%d\n", rc);
+			return rc;
+		}
+		rc = qpnp_chg_ibatterm_set(chip, chip->term_current);
+		if (rc) {
+			pr_debug("failed setting ibatterm rc=%d\n", rc);
+			return rc;
+		}
+		/* HACK: Disable wdog */
+		rc = qpnp_chg_masked_write(chip, chip->chgr_base + 0x62,
+			0xFF, 0xA0, 1);
+
+		/* HACK: use analog EOC */
+		rc = qpnp_chg_masked_write(chip, chip->chgr_base +
+			CHGR_IBAT_TERM_CHGR,
+			0x80, 0x80, 1);
+
+		enable_irq_wake(chip->chg_done_irq);
+		break;
+	case SMBB_BUCK_SUBTYPE:
+		break;
+	case SMBB_BAT_IF_SUBTYPE:
+		/* HACK: Unlock secure access to override temp comparator */
+		rc = qpnp_chg_masked_write(chip,
+				chip->bat_if_base + 0xD0,
+				0xA5, 0xA5, 1);
+		pr_debug("override hot cold\n");
+		rc = qpnp_chg_masked_write(chip,
+				chip->bat_if_base + 0xE5,
+				0xFF, 0x28, 1);
+		break;
+	case SMBB_USB_CHGPTH_SUBTYPE:
+		chip->usbin_valid_irq = spmi_get_irq_byname(chip->spmi,
+						spmi_resource, "usbin-valid");
+		if (chip->usbin_valid_irq < 0) {
+			pr_err("Unable to get usbin irq\n");
+			return -ENXIO;
+		}
+		rc = devm_request_irq(chip->dev, chip->usbin_valid_irq,
+				qpnp_chg_usb_usbin_valid_irq_handler,
+				IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
+				"chg_usbin_valid", chip);
+		if (rc < 0) {
+			pr_err("Can't request %d usbinvalid  for chg: %d\n",
+						chip->usbin_valid_irq, rc);
+			return -ENXIO;
+		}
+
+		enable_irq_wake(chip->usbin_valid_irq);
+		chip->usb_present = qpnp_chg_is_usb_chg_plugged_in(chip);
+		if (chip->usb_present) {
+			rc = qpnp_chg_masked_write(chip,
+				chip->usb_chgpth_base + CHGR_USB_ENUM_T_STOP,
+				ENUM_T_STOP_BIT,
+				ENUM_T_STOP_BIT, 1);
+			if (rc) {
+				pr_err("failed to write enum stop rc=%d\n", rc);
+				return -ENXIO;
+			}
+		}
+		break;
+	case SMBB_DC_CHGPTH_SUBTYPE:
+		break;
+	case SMBB_BOOST_SUBTYPE:
+		break;
+	case SMBB_MISC_SUBTYPE:
+		pr_debug("Setting BOOT_DONE\n");
+		rc = qpnp_chg_masked_write(chip,
+			chip->misc_base + CHGR_MISC_BOOT_DONE,
+			CHGR_BOOT_DONE, CHGR_BOOT_DONE, 1);
+		rc = qpnp_chg_read(chip, &reg,
+				 chip->misc_base + MISC_REVISION2, 1);
+		if (rc) {
+			pr_err("failed to read revision register rc=%d\n", rc);
+			return rc;
+		}
+
+		chip->revision = reg;
+		break;
+	default:
+		pr_err("Invalid peripheral subtype\n");
+	}
+	return rc;
+}
+
+static int __devinit
+qpnp_charger_probe(struct spmi_device *spmi)
+{
+	u8 subtype;
+	struct qpnp_chg_chip	*chip;
+	struct resource *resource;
+	struct spmi_resource *spmi_resource;
+	int rc = 0;
+
+	chip = kzalloc(sizeof *chip, GFP_KERNEL);
+	if (chip == NULL) {
+		pr_err("kzalloc() failed.\n");
+		return -ENOMEM;
+	}
+
+	rc = qpnp_vadc_is_ready();
+	if (rc)
+		goto fail_chg_enable;
+
+	chip->dev = &(spmi->dev);
+	chip->spmi = spmi;
+
+	chip->usb_psy = power_supply_get_by_name("usb");
+	if (!chip->usb_psy) {
+		pr_err("usb supply not found deferring probe\n");
+		rc = -EPROBE_DEFER;
+		goto fail_chg_enable;
+	}
+
+	/* Get the vddmax property */
+	rc = of_property_read_u32(spmi->dev.of_node, "qcom,chg-vddmax-mv",
+						&chip->max_voltage_mv);
+	if (rc && rc != -EINVAL) {
+		pr_err("Error reading vddmax property %d\n", rc);
+		goto fail_chg_enable;
+	}
+
+	/* Get the vinmin property */
+	rc = of_property_read_u32(spmi->dev.of_node, "qcom,chg-vinmin-mv",
+						&chip->min_voltage_mv);
+	if (rc && rc != -EINVAL) {
+		pr_err("Error reading vddmax property %d\n", rc);
+		goto fail_chg_enable;
+	}
+
+	/* Get the vddmax property */
+	rc = of_property_read_u32(spmi->dev.of_node, "qcom,chg-vddsafe-mv",
+						&chip->safe_voltage_mv);
+	if (rc && rc != -EINVAL) {
+		pr_err("Error reading vddsave property %d\n", rc);
+		goto fail_chg_enable;
+	}
+
+	/* Get the ibatterm property */
+	rc = of_property_read_u32(spmi->dev.of_node,
+				"qcom,chg-ibatterm-ma",
+				&chip->term_current);
+	if (rc && rc != -EINVAL) {
+		pr_err("Error reading ibatterm property %d\n", rc);
+		goto fail_chg_enable;
+	}
+
+	/* Get the ibatmax property */
+	rc = of_property_read_u32(spmi->dev.of_node, "qcom,chg-ibatmax-ma",
+						&chip->max_bat_chg_current);
+	if (rc && rc != -EINVAL) {
+		pr_err("Error reading ibatmax property %d\n", rc);
+		goto fail_chg_enable;
+	}
+
+	spmi_for_each_container_dev(spmi_resource, spmi) {
+		if (!spmi_resource) {
+			pr_err("qpnp_chg: spmi resource absent\n");
+			rc = -ENXIO;
+			goto fail_chg_enable;
+		}
+
+		resource = spmi_get_resource(spmi, spmi_resource,
+						IORESOURCE_MEM, 0);
+		if (!(resource && resource->start)) {
+			pr_err("node %s IO resource absent!\n",
+				spmi->dev.of_node->full_name);
+			rc = -ENXIO;
+			goto fail_chg_enable;
+		}
+
+		rc = qpnp_chg_read(chip, &subtype,
+				resource->start + REG_OFFSET_PERP_SUBTYPE, 1);
+		if (rc) {
+			pr_err("Peripheral subtype read failed rc=%d\n", rc);
+			goto fail_chg_enable;
+		}
+
+		switch (subtype) {
+		case SMBB_CHGR_SUBTYPE:
+			chip->chgr_base = resource->start;
+			rc = qpnp_chg_hwinit(chip, subtype, spmi_resource);
+			if (rc) {
+				pr_err("Failed to init subtype 0x%x rc=%d\n",
+						subtype, rc);
+				goto fail_chg_enable;
+			}
+			break;
+		case SMBB_BUCK_SUBTYPE:
+			chip->buck_base = resource->start;
+			rc = qpnp_chg_hwinit(chip, subtype, spmi_resource);
+			if (rc) {
+				pr_err("Failed to init subtype 0x%x rc=%d\n",
+						subtype, rc);
+				goto fail_chg_enable;
+			}
+			break;
+		case SMBB_BAT_IF_SUBTYPE:
+			chip->bat_if_base = resource->start;
+			rc = qpnp_chg_hwinit(chip, subtype, spmi_resource);
+			if (rc) {
+				pr_err("Failed to init subtype 0x%x rc=%d\n",
+						subtype, rc);
+				goto fail_chg_enable;
+			}
+			break;
+		case SMBB_USB_CHGPTH_SUBTYPE:
+			chip->usb_chgpth_base = resource->start;
+			rc = qpnp_chg_hwinit(chip, subtype, spmi_resource);
+			if (rc) {
+				pr_err("Failed to init subtype 0x%x rc=%d\n",
+						subtype, rc);
+				goto fail_chg_enable;
+			}
+			break;
+		case SMBB_DC_CHGPTH_SUBTYPE:
+			chip->dc_chgpth_base = resource->start;
+			rc = qpnp_chg_hwinit(chip, subtype, spmi_resource);
+			if (rc) {
+				pr_err("Failed to init subtype 0x%x rc=%d\n",
+						subtype, rc);
+				goto fail_chg_enable;
+			}
+			break;
+		case SMBB_BOOST_SUBTYPE:
+			chip->boost_base = resource->start;
+			rc = qpnp_chg_hwinit(chip, subtype, spmi_resource);
+			if (rc) {
+				pr_err("Failed to init subtype 0x%x rc=%d\n",
+						subtype, rc);
+				goto fail_chg_enable;
+			}
+			break;
+		case SMBB_MISC_SUBTYPE:
+			chip->misc_base = resource->start;
+			rc = qpnp_chg_hwinit(chip, subtype, spmi_resource);
+			if (rc) {
+				pr_err("Failed to init subtype=0x%x rc=%d\n",
+						subtype, rc);
+				goto fail_chg_enable;
+			}
+			break;
+		default:
+			pr_err("Invalid peripheral subtype=0x%x\n", subtype);
+			rc = -EINVAL;
+			goto fail_chg_enable;
+		}
+	}
+	dev_set_drvdata(&spmi->dev, chip);
+	device_init_wakeup(&spmi->dev, 1);
+
+	chip->dc_psy.name = "qpnp-dc";
+	chip->dc_psy.type = POWER_SUPPLY_TYPE_MAINS;
+	chip->dc_psy.supplied_to = pm_power_supplied_to;
+	chip->dc_psy.num_supplicants = ARRAY_SIZE(pm_power_supplied_to);
+	chip->dc_psy.properties = pm_power_props_mains;
+	chip->dc_psy.num_properties = ARRAY_SIZE(pm_power_props_mains);
+	chip->dc_psy.get_property = qpnp_power_get_property_mains;
+
+	chip->batt_psy.name = "battery";
+	chip->batt_psy.type = POWER_SUPPLY_TYPE_BATTERY;
+	chip->batt_psy.properties = msm_batt_power_props;
+	chip->batt_psy.num_properties = ARRAY_SIZE(msm_batt_power_props);
+	chip->batt_psy.get_property = qpnp_batt_power_get_property;
+	chip->batt_psy.external_power_changed =
+				qpnp_batt_external_power_changed;
+
+	rc = power_supply_register(chip->dev, &chip->dc_psy);
+	if (rc < 0) {
+		pr_err("power_supply_register usb failed rc = %d\n", rc);
+		goto fail_chg_enable;
+	}
+
+	rc = power_supply_register(chip->dev, &chip->batt_psy);
+	if (rc < 0) {
+		pr_err("power_supply_register batt failed rc = %d\n", rc);
+		goto unregister_dc;
+	}
+
+	power_supply_set_present(chip->usb_psy,
+			qpnp_chg_is_usb_chg_plugged_in(chip));
+
+	qpnp_chg_charge_en(chip, 1);
+	the_chip = chip;
+	pr_info("Probe success !\n");
+	return 0;
+
+unregister_dc:
+	power_supply_unregister(&chip->dc_psy);
+fail_chg_enable:
+	kfree(chip);
+	dev_set_drvdata(&spmi->dev, NULL);
+	return rc;
+}
+
+static int __devexit
+qpnp_charger_remove(struct spmi_device *spmi)
+{
+	struct qpnp_chg_chip *chip = dev_get_drvdata(&spmi->dev);
+
+	dev_set_drvdata(&spmi->dev, NULL);
+	kfree(chip);
+
+	return 0;
+}
+
+static struct spmi_driver qpnp_charger_driver = {
+	.probe		= qpnp_charger_probe,
+	.remove		= __devexit_p(qpnp_charger_remove),
+	.driver		= {
+		.name	= QPNP_CHARGER_DEV_NAME,
+		.owner  = THIS_MODULE,
+		.of_match_table = qpnp_charger_match_table,
+	},
+};
+
+/**
+ * qpnp_chg_init() - register spmi driver for qpnp-chg
+ */
+int __init
+qpnp_chg_init(void)
+{
+	return spmi_driver_register(&qpnp_charger_driver);
+}
+module_init(qpnp_chg_init);
+
+static void __exit
+qpnp_chg_exit(void)
+{
+	spmi_driver_unregister(&qpnp_charger_driver);
+}
+module_exit(qpnp_chg_exit);
+
+
+MODULE_DESCRIPTION("QPNP charger driver");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:" QPNP_CHARGER_DEV_NAME);
diff --git a/drivers/usb/gadget/android.c b/drivers/usb/gadget/android.c
index 46f21a7..0fbe397 100644
--- a/drivers/usb/gadget/android.c
+++ b/drivers/usb/gadget/android.c
@@ -2131,7 +2131,6 @@
 	gadget->ep0->driver_data = cdev;
 
 	list_for_each_entry(conf, &dev->configs, list_item)
-		if (&conf->usb_config == cdev->config)
 			list_for_each_entry(f,
 					    &conf->enabled_functions,
 					    enabled_list)
diff --git a/drivers/usb/gadget/f_adb.c b/drivers/usb/gadget/f_adb.c
index 9778673..045fc6c 100644
--- a/drivers/usb/gadget/f_adb.c
+++ b/drivers/usb/gadget/f_adb.c
@@ -301,7 +301,7 @@
 requeue_req:
 	/* queue a request */
 	req = dev->rx_req;
-	req->length = count;
+	req->length = ADB_BULK_BUFFER_SIZE;
 	dev->rx_done = 0;
 	ret = usb_ep_queue(dev->ep_out, req, GFP_ATOMIC);
 	if (ret < 0) {
diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
index 8d967cd..adbf217 100644
--- a/drivers/usb/host/ehci-hcd.c
+++ b/drivers/usb/host/ehci-hcd.c
@@ -94,7 +94,7 @@
  */
 #define	EHCI_TUNE_FLS		1	/* (medium) 512-frame schedule */
 
-#define EHCI_IAA_MSECS		10		/* arbitrary */
+#define EHCI_IAA_MSECS		100		/* arbitrary */
 #define EHCI_IO_JIFFIES		(HZ/10)		/* io watchdog > irq_thresh */
 #define EHCI_ASYNC_JIFFIES	(HZ/20)		/* async idle timeout */
 #define EHCI_SHRINK_JIFFIES	(DIV_ROUND_UP(HZ, 200) + 1)
diff --git a/drivers/video/msm/mdp4_overlay.c b/drivers/video/msm/mdp4_overlay.c
index 18cf817..a5307e6 100644
--- a/drivers/video/msm/mdp4_overlay.c
+++ b/drivers/video/msm/mdp4_overlay.c
@@ -735,37 +735,53 @@
 	*luma_off = 0;
 	*chroma_off = 0;
 
-	if (pipe->src_x && (pipe->frame_format ==
+	if ((pipe->src_x || pipe->src_y) && (pipe->frame_format ==
 		MDP4_FRAME_FORMAT_LINEAR)) {
-		src_xy = (pipe->src_y << 16) | pipe->src_x;
-		src_xy &= 0xffff0000;
+		src_xy = 0;
 		outpdw(vg_base + 0x0004, src_xy);	/* MDP_RGB_SRC_XY */
 
 		switch (pipe->src_format) {
 		case MDP_Y_CR_CB_H2V2:
 		case MDP_Y_CR_CB_GH2V2:
 		case MDP_Y_CB_CR_H2V2:
-				*luma_off = pipe->src_x;
-				*chroma_off = pipe->src_x/2;
+			*luma_off = pipe->src_x +
+				(pipe->src_y * pipe->srcp0_ystride);
+			*chroma_off = pipe->src_x / 2 +
+				((pipe->src_y / 2) * pipe->srcp1_ystride);
 			break;
 
 		case MDP_Y_CBCR_H2V2_TILE:
 		case MDP_Y_CRCB_H2V2_TILE:
 		case MDP_Y_CBCR_H2V2:
 		case MDP_Y_CRCB_H2V2:
+			*luma_off = pipe->src_x +
+				(pipe->src_y * pipe->srcp0_ystride);
+			*chroma_off = pipe->src_x +
+				((pipe->src_y / 2) * pipe->srcp1_ystride);
+			break;
+
 		case MDP_Y_CRCB_H1V1:
 		case MDP_Y_CBCR_H1V1:
+			*luma_off = pipe->src_x +
+				(pipe->src_y * pipe->srcp0_ystride);
+			*chroma_off = pipe->src_x +
+				((pipe->src_y * 2) * pipe->srcp1_ystride);
+			break;
+
 		case MDP_Y_CRCB_H2V1:
 		case MDP_Y_CBCR_H2V1:
 		case MDP_Y_CRCB_H1V2:
-			*luma_off = pipe->src_x;
-			*chroma_off = pipe->src_x;
+			*luma_off = pipe->src_x +
+				(pipe->src_y * pipe->srcp0_ystride);
+			*chroma_off = pipe->src_x +
+				(pipe->src_y * pipe->srcp1_ystride);
 			break;
 
 		case MDP_YCRYCB_H2V1:
 			if (pipe->src_x & 0x1)
 				pipe->src_x += 1;
-			*luma_off += pipe->src_x * 2;
+			*luma_off += pipe->src_x * 2 +
+				((pipe->src_y * 2) * pipe->srcp0_ystride);
 			break;
 
 		case MDP_ARGB_8888:
@@ -778,7 +794,8 @@
 		case MDP_RGB_888:
 		case MDP_YCBCR_H1V1:
 		case MDP_YCRCB_H1V1:
-			*luma_off = pipe->src_x * pipe->bpp;
+			*luma_off = (pipe->src_x * pipe->bpp) +
+					(pipe->src_y * pipe->srcp0_ystride);
 			break;
 
 		default:
diff --git a/drivers/video/msm/mdp4_util.c b/drivers/video/msm/mdp4_util.c
index b35acfb..80ef22a 100644
--- a/drivers/video/msm/mdp4_util.c
+++ b/drivers/video/msm/mdp4_util.c
@@ -2309,7 +2309,7 @@
 		pr_info("%s:%d ion based allocation mfd->mem_hid 0x%x\n",
 			__func__, __LINE__, mfd->mem_hid);
 		buf->ihdl = ion_alloc(mfd->iclient, buffer_size, SZ_4K,
-			mfd->mem_hid);
+			mfd->mem_hid, 0);
 		if (!IS_ERR_OR_NULL(buf->ihdl)) {
 			if (mdp_iommu_split_domain) {
 				if (ion_map_iommu(mfd->iclient, buf->ihdl,
diff --git a/drivers/video/msm/mdss/mdss.h b/drivers/video/msm/mdss/mdss.h
index 6f42565..4008893 100644
--- a/drivers/video/msm/mdss/mdss.h
+++ b/drivers/video/msm/mdss/mdss.h
@@ -15,6 +15,7 @@
 #define MDSS_H
 
 #include <linux/msm_ion.h>
+#include <linux/earlysuspend.h>
 #include <linux/msm_mdp.h>
 #include <linux/spinlock.h>
 #include <linux/types.h>
@@ -53,6 +54,7 @@
 	u32 irq_buzy;
 
 	u32 mdp_irq_mask;
+	u32 mdp_hist_irq_mask;
 
 	u32 suspend;
 	u32 timeout;
@@ -74,6 +76,8 @@
 	struct ion_client *iclient;
 	int iommu_domain;
 	int iommu_attached;
+
+	struct early_suspend early_suspend;
 };
 extern struct mdss_data_type *mdss_res;
 
diff --git a/drivers/video/msm/mdss/mdss_fb.c b/drivers/video/msm/mdss/mdss_fb.c
index 3bef9b3..7400a7b 100644
--- a/drivers/video/msm/mdss/mdss_fb.c
+++ b/drivers/video/msm/mdss/mdss_fb.c
@@ -316,6 +316,9 @@
 					mfd->op_enable);
 		if (ret)
 			pr_warn("can't turn on display!\n");
+
+		if (mfd->vsync_pending)
+			mdss_mdp_overlay_vsync_ctrl(mfd, mfd->vsync_pending);
 	}
 
 	return ret;
@@ -598,14 +601,14 @@
 		if (iclient) {
 			mfd->ihdl = ion_alloc(iclient, size, SZ_4K,
 					 ION_HEAP(ION_CP_MM_HEAP_ID) |
-					 ION_HEAP(ION_SF_HEAP_ID));
+					 ION_HEAP(ION_SF_HEAP_ID), 0);
 			if (IS_ERR_OR_NULL(mfd->ihdl)) {
 				pr_err("unable to alloc fbmem from ion (%p)\n",
 					mfd->ihdl);
 				return -ENOMEM;
 			}
 
-			virt = ion_map_kernel(iclient, mfd->ihdl, 0);
+			virt = ion_map_kernel(iclient, mfd->ihdl);
 			ion_phys(iclient, mfd->ihdl, &phys, &size);
 
 			if (is_mdss_iommu_attached()) {
@@ -1148,6 +1151,46 @@
 		ret = mdss_mdp_pa_config(&mdp_pp.data.pa_cfg_data,
 				&copyback);
 		break;
+
+	case mdp_op_pcc_cfg:
+		ret = mdss_mdp_pcc_config(&mdp_pp.data.pcc_cfg_data,
+			   &copyback);
+		break;
+
+	case mdp_op_lut_cfg:
+		switch (mdp_pp.data.lut_cfg_data.lut_type) {
+		case mdp_lut_igc:
+			ret = mdss_mdp_igc_lut_config(
+					(struct mdp_igc_lut_data *)
+					&mdp_pp.data.lut_cfg_data.data,
+					&copyback);
+			break;
+
+		case mdp_lut_pgc:
+			ret = mdss_mdp_argc_config(
+				&mdp_pp.data.lut_cfg_data.data.pgc_lut_data,
+				&copyback);
+			break;
+
+		case mdp_lut_hist:
+			ret = mdss_mdp_hist_lut_config(
+				(struct mdp_hist_lut_data *)
+				&mdp_pp.data.lut_cfg_data.data, &copyback);
+			break;
+
+		default:
+			ret = -ENOTSUPP;
+			break;
+		}
+		break;
+	case mdp_op_dither_cfg:
+		ret = mdss_mdp_dither_config(&mdp_pp.data.dither_cfg_data,
+				&copyback);
+		break;
+	case mdp_op_gamut_cfg:
+		ret = mdss_mdp_gamut_config(&mdp_pp.data.gamut_cfg_data,
+				&copyback);
+		break;
 	default:
 		pr_err("Unsupported request to MDP_PP IOCTL.\n");
 		ret = -EINVAL;
@@ -1163,6 +1206,9 @@
 {
 	struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
 	void __user *argp = (void __user *)arg;
+	struct mdp_histogram_data hist;
+	struct mdp_histogram_start_req hist_req;
+	u32 block, hist_data_addr = 0;
 	struct mdp_page_protection fb_page_protection;
 	int ret = -ENOSYS;
 
@@ -1175,6 +1221,43 @@
 		ret = mdss_fb_set_lut(info, argp);
 		break;
 
+	case MSMFB_HISTOGRAM:
+		if (!mfd->panel_power_on)
+			return -EPERM;
+
+		ret = copy_from_user(&hist, argp, sizeof(hist));
+		if (ret)
+			return ret;
+
+		ret = mdss_mdp_hist_collect(info, &hist, &hist_data_addr);
+		if ((ret == 0) && hist_data_addr) {
+			ret = copy_to_user(hist.c0, (u32 *)hist_data_addr,
+				sizeof(u32) * hist.bin_cnt);
+			if (ret == 0)
+				ret = copy_to_user(argp, &hist,
+						   sizeof(hist));
+		}
+		break;
+
+	case MSMFB_HISTOGRAM_START:
+		if (!mfd->panel_power_on)
+			return -EPERM;
+
+		ret = copy_from_user(&hist_req, argp, sizeof(hist_req));
+		if (ret)
+			return ret;
+
+		ret = mdss_mdp_histogram_start(&hist_req);
+		break;
+
+	case MSMFB_HISTOGRAM_STOP:
+		ret = copy_from_user(&block, argp, sizeof(int));
+		if (ret)
+			return ret;
+
+		ret = mdss_mdp_histogram_stop(block);
+		break;
+
 	case MSMFB_GET_PAGE_PROTECTION:
 		fb_page_protection.page_protection =
 			mfd->mdp_fb_page_protection;
diff --git a/drivers/video/msm/mdss/mdss_fb.h b/drivers/video/msm/mdss/mdss_fb.h
index a10e5e4..80ebc4f 100644
--- a/drivers/video/msm/mdss/mdss_fb.h
+++ b/drivers/video/msm/mdss/mdss_fb.h
@@ -56,6 +56,7 @@
 	int op_enable;
 	u32 fb_imgType;
 	u32 dst_format;
+	int vsync_pending;
 
 	int hw_refresh;
 
diff --git a/drivers/video/msm/mdss/mdss_mdp.c b/drivers/video/msm/mdss/mdss_mdp.c
index 63df84c..4f641cc 100644
--- a/drivers/video/msm/mdss/mdss_mdp.c
+++ b/drivers/video/msm/mdss/mdss_mdp.c
@@ -128,6 +128,8 @@
 static DEFINE_SPINLOCK(mdss_lock);
 struct mdss_hw *mdss_irq_handlers[MDSS_MAX_HW_BLK];
 
+static int mdss_mdp_register_early_suspend(struct mdss_data_type *mdata);
+
 static inline int mdss_irq_dispatch(u32 hw_ndx, int irq, void *ptr)
 {
 	struct mdss_hw *hw;
@@ -216,8 +218,9 @@
 
 	spin_lock_irqsave(&mdss_lock, irq_flags);
 	if (!(mdss_res->irq_mask & ndx_bit)) {
-		pr_warn("MDSS HW ndx=%d is NOT set, mask=%x\n",
-			hw->hw_ndx, mdss_res->mdp_irq_mask);
+		pr_warn("MDSS HW ndx=%d is NOT set, mask=%x, hist mask=%x\n",
+			hw->hw_ndx, mdss_res->mdp_irq_mask,
+			mdss_res->mdp_hist_irq_mask);
 	} else {
 		mdss_irq_handlers[hw->hw_ndx] = NULL;
 		mdss_res->irq_mask &= ~ndx_bit;
@@ -244,8 +247,9 @@
 
 	spin_lock(&mdss_lock);
 	if (!(mdss_res->irq_mask & ndx_bit)) {
-		pr_warn("MDSS HW ndx=%d is NOT set, mask=%x\n",
-			hw->hw_ndx, mdss_res->mdp_irq_mask);
+		pr_warn("MDSS HW ndx=%d is NOT set, mask=%x, hist mask=%x\n",
+			hw->hw_ndx, mdss_res->mdp_irq_mask,
+			mdss_res->mdp_hist_irq_mask);
 	} else {
 		mdss_irq_handlers[hw->hw_ndx] = NULL;
 		mdss_res->irq_mask &= ~ndx_bit;
@@ -357,6 +361,29 @@
 
 	return ret;
 }
+int mdss_mdp_hist_irq_enable(u32 irq)
+{
+	unsigned long irq_flags;
+	int ret = 0;
+
+	spin_lock_irqsave(&mdp_lock, irq_flags);
+	if (mdss_res->mdp_hist_irq_mask & irq) {
+		pr_warn("MDSS MDP Hist IRQ-0x%x is already set, mask=%x\n",
+				irq, mdss_res->mdp_hist_irq_mask);
+		ret = -EBUSY;
+	} else {
+		pr_debug("MDP IRQ mask old=%x new=%x\n",
+				mdss_res->mdp_hist_irq_mask, irq);
+		mdss_res->mdp_hist_irq_mask |= irq;
+		MDSS_MDP_REG_WRITE(MDSS_MDP_REG_HIST_INTR_CLEAR, irq);
+		MDSS_MDP_REG_WRITE(MDSS_MDP_REG_HIST_INTR_EN,
+				mdss_res->mdp_hist_irq_mask);
+		mdss_enable_irq(&mdss_mdp_hw);
+	}
+	spin_unlock_irqrestore(&mdp_lock, irq_flags);
+
+	return ret;
+}
 
 void mdss_mdp_irq_disable(u32 intr_type, u32 intf_num)
 {
@@ -374,7 +401,27 @@
 
 		MDSS_MDP_REG_WRITE(MDSS_MDP_REG_INTR_EN,
 				mdss_res->mdp_irq_mask);
-		if (mdss_res->mdp_irq_mask == 0)
+		if ((mdss_res->mdp_irq_mask == 0) &&
+			(mdss_res->mdp_hist_irq_mask == 0))
+			mdss_disable_irq(&mdss_mdp_hw);
+	}
+	spin_unlock_irqrestore(&mdp_lock, irq_flags);
+}
+
+void mdss_mdp_hist_irq_disable(u32 irq)
+{
+	unsigned long irq_flags;
+
+	spin_lock_irqsave(&mdp_lock, irq_flags);
+	if (!(mdss_res->mdp_hist_irq_mask & irq)) {
+		pr_warn("MDSS MDP IRQ-%x is NOT set, mask=%x\n",
+				irq, mdss_res->mdp_hist_irq_mask);
+	} else {
+		mdss_res->mdp_hist_irq_mask &= ~irq;
+		MDSS_MDP_REG_WRITE(MDSS_MDP_REG_HIST_INTR_EN,
+				mdss_res->mdp_hist_irq_mask);
+		if ((mdss_res->mdp_irq_mask == 0) &&
+			(mdss_res->mdp_hist_irq_mask == 0))
 			mdss_disable_irq(&mdss_mdp_hw);
 	}
 	spin_unlock_irqrestore(&mdp_lock, irq_flags);
@@ -394,7 +441,8 @@
 		mdss_res->mdp_irq_mask &= ~irq;
 		MDSS_MDP_REG_WRITE(MDSS_MDP_REG_INTR_EN,
 				mdss_res->mdp_irq_mask);
-		if (mdss_res->mdp_irq_mask == 0)
+		if ((mdss_res->mdp_irq_mask == 0) &&
+			(mdss_res->mdp_hist_irq_mask == 0))
 			mdss_disable_irq_nosync(&mdss_mdp_hw);
 	}
 	spin_unlock(&mdp_lock);
@@ -852,6 +900,16 @@
 		goto probe_done;
 	}
 	rc = mdss_mdp_bus_scale_register(mdata);
+	if (rc) {
+		pr_err("unable to register bus scaling\n");
+		goto probe_done;
+	}
+
+	rc = mdss_mdp_register_early_suspend(mdata);
+	if (rc) {
+		pr_err("unable to register early suspend\n");
+		goto probe_done;
+	}
 probe_done:
 	if (IS_ERR_VALUE(rc)) {
 		mdss_res = NULL;
@@ -861,88 +919,154 @@
 	return rc;
 }
 
-void mdss_mdp_footswitch_ctrl(int on)
+static void mdss_mdp_footswitch_ctrl(struct mdss_data_type *mdata, int on)
 {
 	mutex_lock(&mdp_suspend_mutex);
-	if (!mdss_res->suspend || mdss_res->eintf_ena || !mdss_res->fs) {
+	if (!mdata->suspend || mdata->eintf_ena || !mdata->fs) {
 		mutex_unlock(&mdp_suspend_mutex);
 		return;
 	}
 
-	if (on && !mdss_res->fs_ena) {
+	if (on && !mdata->fs_ena) {
 		pr_debug("Enable MDP FS\n");
-		regulator_enable(mdss_res->fs);
+		regulator_enable(mdata->fs);
 		mdss_iommu_attach();
-		mdss_res->fs_ena = true;
-	} else if (!on && mdss_res->fs_ena) {
+		mdata->fs_ena = true;
+	} else if (!on && mdata->fs_ena) {
 		pr_debug("Disable MDP FS\n");
 		mdss_iommu_dettach();
-		regulator_disable(mdss_res->fs);
-		mdss_res->fs_ena = false;
+		regulator_disable(mdata->fs);
+		mdata->fs_ena = false;
 	}
 	mutex_unlock(&mdp_suspend_mutex);
 }
 
-#ifdef CONFIG_PM
-static void mdss_mdp_suspend_sub(void)
-{
-	cancel_delayed_work(&mdss_res->clk_ctrl_worker);
-
-	flush_workqueue(mdss_res->clk_ctrl_wq);
-
-	mdss_mdp_clk_ctrl(MDP_BLOCK_MASTER_OFF, false);
-
-	mutex_lock(&mdp_suspend_mutex);
-	mdss_res->suspend = true;
-	mutex_unlock(&mdp_suspend_mutex);
-}
-
-static int mdss_mdp_suspend(struct platform_device *pdev, pm_message_t state)
+static inline int mdss_mdp_suspend_sub(struct mdss_data_type *mdata)
 {
 	int ret;
-	pr_debug("display suspend");
 
 	ret = mdss_fb_suspend_all();
 	if (IS_ERR_VALUE(ret)) {
 		pr_err("Unable to suspend all fb panels (%d)\n", ret);
 		return ret;
 	}
-	mdss_mdp_suspend_sub();
-	if (mdss_res->clk_ena) {
+
+	cancel_delayed_work(&mdata->clk_ctrl_worker);
+
+	flush_workqueue(mdata->clk_ctrl_wq);
+
+	mdss_mdp_clk_ctrl(MDP_BLOCK_MASTER_OFF, false);
+
+	mutex_lock(&mdp_suspend_mutex);
+	mdata->suspend = true;
+	mutex_unlock(&mdp_suspend_mutex);
+
+	if (mdata->clk_ena) {
 		pr_err("MDP suspend failed\n");
 		return -EBUSY;
 	}
-	mdss_mdp_footswitch_ctrl(false);
+	mdss_mdp_footswitch_ctrl(mdata, false);
+
+	pr_debug("suspend done\n");
 
 	return 0;
 }
 
-static int mdss_mdp_resume(struct platform_device *pdev)
+static inline int mdss_mdp_resume_sub(struct mdss_data_type *mdata)
 {
-	struct mdss_data_type *mdata = platform_get_drvdata(pdev);
 	int ret = 0;
 
-	if (!mdata)
-		return -ENODEV;
-
-	pr_debug("resume display");
-
-	mdss_mdp_footswitch_ctrl(true);
+	mdss_mdp_footswitch_ctrl(mdata, true);
 	mutex_lock(&mdp_suspend_mutex);
-	mdss_res->suspend = false;
+	mdata->suspend = false;
 	mutex_unlock(&mdp_suspend_mutex);
 	mdss_hw_init(mdata);
 	ret = mdss_fb_resume_all();
 	if (IS_ERR_VALUE(ret))
 		pr_err("Unable to resume all fb panels (%d)\n", ret);
 
+	pr_debug("resume done\n");
+
 	return ret;
 }
+
+#if defined(CONFIG_PM) && !defined(CONFIG_HAS_EARLYSUSPEND)
+static int mdss_mdp_suspend(struct platform_device *pdev, pm_message_t state)
+{
+	struct mdss_data_type *mdata = platform_get_drvdata(pdev);
+
+	if (!mdata)
+		return -ENODEV;
+
+	pr_debug("display suspend\n");
+
+	return mdss_mdp_suspend_sub(mdata);
+}
+
+static int mdss_mdp_resume(struct platform_device *pdev)
+{
+	struct mdss_data_type *mdata = platform_get_drvdata(pdev);
+
+	if (!mdata)
+		return -ENODEV;
+
+	pr_debug("display resume\n");
+
+	return mdss_mdp_resume_sub(mdata);
+}
 #else
 #define mdss_mdp_suspend NULL
 #define mdss_mdp_resume NULL
 #endif
 
+#ifdef CONFIG_HAS_EARLYSUSPEND
+static void mdss_mdp_early_suspend(struct early_suspend *h)
+{
+	struct mdss_data_type *mdata;
+	mdata = container_of(h, struct mdss_data_type, early_suspend);
+
+	pr_debug("display early suspend\n");
+
+	mdss_mdp_suspend_sub(mdata);
+}
+
+static void mdss_mdp_late_resume(struct early_suspend *h)
+{
+	struct mdss_data_type *mdata;
+	mdata = container_of(h, struct mdss_data_type, early_suspend);
+
+	pr_debug("display early resume\n");
+
+	mdss_mdp_resume_sub(mdata);
+}
+
+static int mdss_mdp_register_early_suspend(struct mdss_data_type *mdata)
+{
+	mdata->early_suspend.suspend = mdss_mdp_early_suspend;
+	mdata->early_suspend.resume = mdss_mdp_late_resume;
+	mdata->early_suspend.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN;
+	register_early_suspend(&mdata->early_suspend);
+
+	return 0;
+}
+
+static int mdss_mdp_remove_early_suspend(struct mdss_data_type *mdata)
+{
+	unregister_early_suspend(&mdata->early_suspend);
+
+	return 0;
+}
+#else
+static int mdss_mdp_register_early_suspend(struct mdss_data_type *mdata)
+{
+	return 0;
+}
+static int mdss_mdp_remove_early_suspend(struct mdss_data_type *mdata)
+{
+	return 0;
+}
+#endif
+
 static int mdss_mdp_remove(struct platform_device *pdev)
 {
 	struct mdss_data_type *mdata = platform_get_drvdata(pdev);
@@ -951,6 +1075,7 @@
 	pm_runtime_disable(&pdev->dev);
 	mdss_mdp_pp_term(&pdev->dev);
 	mdss_mdp_bus_scale_unregister(mdata);
+	mdss_mdp_remove_early_suspend(mdata);
 	return 0;
 }
 
diff --git a/drivers/video/msm/mdss/mdss_mdp.h b/drivers/video/msm/mdss/mdss_mdp.h
index 610c132..2493570 100644
--- a/drivers/video/msm/mdss/mdss_mdp.h
+++ b/drivers/video/msm/mdss/mdss_mdp.h
@@ -242,6 +242,7 @@
 
 	struct mdss_mdp_data buffers[2];
 	struct list_head list;
+	struct mdp_overlay_pp_params pp_cfg;
 };
 
 struct mdss_mdp_writeback_arg {
@@ -250,6 +251,7 @@
 	void *priv_data;
 };
 
+#define is_vig_pipe(_pipe_id_) ((_pipe_id_) <= MDSS_MDP_SSPP_VIG2)
 static inline void mdss_mdp_ctl_write(struct mdss_mdp_ctl *ctl,
 				      u32 reg, u32 val)
 {
@@ -266,6 +268,8 @@
 irqreturn_t mdss_mdp_isr(int irq, void *ptr);
 int mdss_mdp_irq_enable(u32 intr_type, u32 intf_num);
 void mdss_mdp_irq_disable(u32 intr_type, u32 intf_num);
+int mdss_mdp_hist_irq_enable(u32 irq);
+void mdss_mdp_hist_irq_disable(u32 irq);
 void mdss_mdp_irq_disable_nosync(u32 intr_type, u32 intf_num);
 int mdss_mdp_set_intr_callback(u32 intr_type, u32 intf_num,
 			       void (*fnc_ptr)(void *), void *arg);
@@ -275,10 +279,10 @@
 unsigned long mdss_mdp_get_clk_rate(u32 clk_idx);
 int mdss_mdp_vsync_clk_enable(int enable);
 void mdss_mdp_clk_ctrl(int enable, int isr);
-void mdss_mdp_footswitch_ctrl(int on);
 
 int mdss_mdp_overlay_init(struct msm_fb_data_type *mfd);
 int mdss_mdp_overlay_release_all(struct msm_fb_data_type *mfd);
+int mdss_mdp_overlay_vsync_ctrl(struct msm_fb_data_type *mfd, int en);
 int mdss_mdp_video_start(struct mdss_mdp_ctl *ctl);
 int mdss_mdp_writeback_start(struct mdss_mdp_ctl *ctl);
 
@@ -295,7 +299,24 @@
 int mdss_mdp_display_commit(struct mdss_mdp_ctl *ctl, void *arg);
 
 int mdss_mdp_csc_setup(u32 block, u32 blk_idx, u32 tbl_idx, u32 csc_type);
+int mdss_mdp_csc_setup_data(u32 block, u32 blk_idx, u32 tbl_idx,
+				   struct mdp_csc_cfg *data);
+
 int mdss_mdp_pp_setup(struct mdss_mdp_ctl *ctl);
+int mdss_mdp_pcc_config(struct mdp_pcc_cfg_data *cfg_ptr, u32 *copyback);
+
+int mdss_mdp_igc_lut_config(struct mdp_igc_lut_data *config, u32 *copyback);
+int mdss_mdp_argc_config(struct mdp_pgc_lut_data *config, u32 *copyback);
+int mdss_mdp_hist_lut_config(struct mdp_hist_lut_data *config, u32 *copyback);
+int mdss_mdp_dither_config(struct mdp_dither_cfg_data *config, u32 *copyback);
+int mdss_mdp_gamut_config(struct mdp_gamut_cfg_data *config, u32 *copyback);
+
+int mdss_mdp_histogram_start(struct mdp_histogram_start_req *req);
+int mdss_mdp_histogram_stop(u32 block);
+int mdss_mdp_hist_collect(struct fb_info *info,
+		   struct mdp_histogram_data *hist, u32 *hist_data_addr);
+void mdss_mdp_hist_intr_done(u32 isr);
+
 
 struct mdss_mdp_pipe *mdss_mdp_pipe_alloc_pnum(u32 pnum);
 struct mdss_mdp_pipe *mdss_mdp_pipe_alloc_locked(u32 type);
diff --git a/drivers/video/msm/mdss/mdss_mdp_hwio.h b/drivers/video/msm/mdss/mdss_mdp_hwio.h
index 0139afd..651d595 100644
--- a/drivers/video/msm/mdss/mdss_mdp_hwio.h
+++ b/drivers/video/msm/mdss/mdss_mdp_hwio.h
@@ -74,6 +74,11 @@
 	MDSS_MDP_IRQ_INTF_VSYNC = 25,
 };
 
+#define MDSS_MDP_REG_IGC_VIG_BASE			0x300
+#define MDSS_MDP_REG_IGC_RGB_BASE			0x310
+#define MDSS_MDP_REG_IGC_DMA_BASE			0x320
+#define MDSS_MDP_REG_IGC_DSPP_BASE			0x400
+
 enum mdss_mdp_ctl_index {
 	MDSS_MDP_CTL0,
 	MDSS_MDP_CTL1,
@@ -189,6 +194,9 @@
 #define MDSS_MDP_REG_VIG_CSC_0_BASE			0x280
 #define MDSS_MDP_REG_VIG_CSC_1_BASE			0x320
 
+#define MDSS_MDP_REG_VIG_HIST_CTL_BASE			0x2C4
+#define MDSS_MDP_REG_VIG_HIST_LUT_BASE			0x2F0
+
 #define MDSS_MDP_SCALE_FILTER_NEAREST		0x0
 #define MDSS_MDP_SCALE_FILTER_BIL		0x1
 #define MDSS_MDP_SCALE_FILTER_PCMN		0x2
@@ -260,6 +268,8 @@
 #define MDSS_MDP_REG_LM_CURSOR_BLEND_TRANSP_HIGH0	0x108
 #define MDSS_MDP_REG_LM_CURSOR_BLEND_TRANSP_HIGH1	0x10C
 
+#define MDSS_MDP_REG_LM_GC_LUT_BASE	0x110
+
 #define MDSS_MDP_LM_BORDER_COLOR		(1 << 24)
 #define MDSS_MDP_LM_CURSOR_OUT			(1 << 25)
 #define MDSS_MDP_BLEND_FG_ALPHA_FG_CONST	(0 << 0)
@@ -323,7 +333,12 @@
 
 #define MDSS_MDP_REG_DSPP_OFFSET(pipe)	(0x4600 + ((pipe) * 0x400))
 #define MDSS_MDP_REG_DSPP_OP_MODE			0x000
+#define MDSS_MDP_REG_DSPP_PCC_BASE			0x030
+#define MDSS_MDP_REG_DSPP_DITHER_DEPTH			0x150
+#define MDSS_MDP_REG_DSPP_HIST_CTL_BASE			0x210
+#define MDSS_MDP_REG_DSPP_HIST_LUT_BASE			0x230
 #define MDSS_MDP_REG_DSPP_PA_BASE			0x238
+#define MDSS_MDP_REG_DSPP_GAMUT_BASE			0x2DC
 
 enum mdss_mpd_intf_index {
 	MDSS_MDP_NO_INTF,
diff --git a/drivers/video/msm/mdss/mdss_mdp_intf_video.c b/drivers/video/msm/mdss/mdss_mdp_intf_video.c
index fed7d21..3c7c362 100644
--- a/drivers/video/msm/mdss/mdss_mdp_intf_video.c
+++ b/drivers/video/msm/mdss/mdss_mdp_intf_video.c
@@ -183,7 +183,7 @@
 	if (mutex_lock_interruptible(&ctx->vsync_lock))
 		return -EINTR;
 
-	if (!ctx->timegen_en) {
+	if (vsync_handler && !ctx->timegen_en) {
 		ctx->vsync_time = ktime_get();
 		schedule_work(&ctx->vsync_work);
 	}
@@ -213,6 +213,9 @@
 		return -ENODEV;
 	}
 
+	if (ctx->vsync_handler)
+		mdss_mdp_video_set_vsync_handler(ctl, NULL);
+
 	if (ctx->timegen_en) {
 		off = MDSS_MDP_REG_INTF_OFFSET(ctl->intf_num);
 		MDSS_MDP_REG_WRITE(off + MDSS_MDP_REG_INTF_TIMING_ENGINE_EN, 0);
diff --git a/drivers/video/msm/mdss/mdss_mdp_overlay.c b/drivers/video/msm/mdss/mdss_mdp_overlay.c
index e8e8163..91f94ea 100644
--- a/drivers/video/msm/mdss/mdss_mdp_overlay.c
+++ b/drivers/video/msm/mdss/mdss_mdp_overlay.c
@@ -316,7 +316,17 @@
 
 	pipe->req_data = *req;
 
+	if (pipe->flags & MDP_OVERLAY_PP_CFG_EN) {
+		if (pipe->num <= MDSS_MDP_SSPP_VIG2)
+			memcpy(&pipe->pp_cfg, &req->overlay_pp_cfg,
+					sizeof(struct mdp_overlay_pp_params));
+		else
+			pr_debug("%s: RGB Pipes don't support CSC/QSEED\n",
+								__func__);
+	}
+
 	pipe->params_changed++;
+	pipe->play_cnt = 0;
 
 	req->id = pipe->ndx;
 
@@ -765,7 +775,7 @@
 	pr_debug("sent vsync on ctl=%d ts=%llu\n", ctl->num, ktime_to_ns(t));
 }
 
-static int mdss_mdp_overlay_vsync_ctrl(struct msm_fb_data_type *mfd, int en)
+int mdss_mdp_overlay_vsync_ctrl(struct msm_fb_data_type *mfd, int en)
 {
 	struct mdss_mdp_ctl *ctl = mfd->ctl;
 	int rc;
@@ -777,6 +787,11 @@
 
 	pr_debug("vsync en=%d\n", en);
 
+	if (!ctl->power_on) {
+		mfd->vsync_pending = en;
+		return 0;
+	}
+
 	mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_ON, false);
 	if (en)
 		rc = ctl->set_vsync_handler(ctl, mdss_mdp_overlay_handle_vsync);
diff --git a/drivers/video/msm/mdss/mdss_mdp_pipe.c b/drivers/video/msm/mdss/mdss_mdp_pipe.c
index c936b7d..c90ce8c 100644
--- a/drivers/video/msm/mdss/mdss_mdp_pipe.c
+++ b/drivers/video/msm/mdss/mdss_mdp_pipe.c
@@ -560,16 +560,32 @@
 
 	pr_debug("pnum=%x\n", pipe->num);
 
-	if (pipe->src_fmt->is_yuv)
-		opmode |= (0 << 19) |	/* DST_DATA=RGB */
-			  (1 << 18) |	/* SRC_DATA=YCBCR */
-			  (1 << 17);	/* CSC_1_EN */
-
-	/* only need to program once */
-	if (pipe->play_cnt == 0) {
-		mdss_mdp_csc_setup(MDSS_MDP_BLOCK_SSPP, pipe->num, 1,
-				   MDSS_MDP_CSC_YUV2RGB);
+	/* CSC Post Processing enabled? */
+	if (pipe->flags & MDP_OVERLAY_PP_CFG_EN) {
+		if (pipe->pp_cfg.config_ops & MDP_OVERLAY_PP_CSC_CFG) {
+			if (pipe->pp_cfg.csc_cfg.flags & MDP_CSC_FLAG_ENABLE)
+				opmode |= 1 << 17;	/* CSC_1_EN */
+			if (pipe->pp_cfg.csc_cfg.flags & MDP_CSC_FLAG_YUV_IN)
+				opmode |= 1 << 18;	/* SRC_DATA=YCBCR */
+			if (pipe->pp_cfg.csc_cfg.flags & MDP_CSC_FLAG_YUV_OUT)
+				opmode |= 1 << 19;	/* DST_DATA=YCBCR */
+			/* only need to program once */
+			if (pipe->play_cnt == 0)
+				mdss_mdp_csc_setup_data(MDSS_MDP_BLOCK_SSPP,
+				  pipe->num, 1, &pipe->pp_cfg.csc_cfg);
+		}
+	} else {
+		if (pipe->src_fmt->is_yuv)
+			opmode |= (0 << 19) |	/* DST_DATA=RGB */
+				  (1 << 18) |	/* SRC_DATA=YCBCR */
+				  (1 << 17);	/* CSC_1_EN */
+		/* only need to program once */
+		if (pipe->play_cnt == 0) {
+			mdss_mdp_csc_setup(MDSS_MDP_BLOCK_SSPP, pipe->num, 1,
+					   MDSS_MDP_CSC_YUV2RGB);
+		}
 	}
+
 	mdss_mdp_pipe_write(pipe, MDSS_MDP_REG_VIG_OP_MODE, opmode);
 
 	return 0;
diff --git a/drivers/video/msm/mdss/mdss_mdp_pp.c b/drivers/video/msm/mdss/mdss_mdp_pp.c
index 7ab3b01..6e04124 100644
--- a/drivers/video/msm/mdss/mdss_mdp_pp.c
+++ b/drivers/video/msm/mdss/mdss_mdp_pp.c
@@ -15,6 +15,9 @@
 
 #include "mdss_fb.h"
 #include "mdss_mdp.h"
+#include <linux/uaccess.h>
+#include <linux/spinlock.h>
+#include <linux/delay.h>
 
 struct mdp_csc_cfg mdp_csc_convert[MDSS_MDP_MAX_CSC] = {
 	[MDSS_MDP_CSC_RGB2RGB] = {
@@ -74,26 +77,118 @@
 
 #define MDSS_BLOCK_DISP_NUM	(MDP_BLOCK_MAX - MDP_LOGICAL_BLOCK_DISP_0)
 
+#define IGC_LUT_ENTRIES	256
+#define GC_LUT_SEGMENTS	16
+#define ENHIST_LUT_ENTRIES 256
+#define HIST_V_SIZE	256
+
+#define HIST_WAIT_TIMEOUT	1000
+/* hist collect state */
+enum {
+	HIST_UNKNOWN,
+	HIST_IDLE,
+	HIST_RESET,
+	HIST_START,
+	HIST_READY,
+};
+
+struct pp_hist_col_info {
+	u32 col_state;
+	u32 col_en;
+	u32 read_request;
+	u32 hist_cnt_read;
+	u32 hist_cnt_sent;
+	u32 frame_cnt;
+	struct completion comp;
+	u32 data[HIST_V_SIZE];
+};
+
+static u32 dither_matrix[16] = {
+	15, 7, 13, 5, 3, 11, 1, 9, 12, 4, 14, 6, 0, 8, 2, 10};
+static u32 dither_depth_map[9] = {
+	0, 0, 0, 0, 0, 1, 2, 3, 3};
+
+#define GAMUT_T0_SIZE	125
+#define GAMUT_T1_SIZE	100
+#define GAMUT_T2_SIZE	80
+#define GAMUT_T3_SIZE	100
+#define GAMUT_T4_SIZE	100
+#define GAMUT_T5_SIZE	80
+#define GAMUT_T6_SIZE	64
+#define GAMUT_T7_SIZE	80
+#define GAMUT_TOTAL_TABLE_SIZE (GAMUT_T0_SIZE + GAMUT_T1_SIZE + \
+	GAMUT_T2_SIZE + GAMUT_T3_SIZE + GAMUT_T4_SIZE + \
+	GAMUT_T5_SIZE + GAMUT_T6_SIZE + GAMUT_T7_SIZE)
+
 struct pp_sts_type {
 	u32 pa_sts;
+	u32 pcc_sts;
+	u32 igc_sts;
+	u32 igc_tbl_idx;
+	u32 argc_sts;
+	u32 enhist_sts;
+	u32 dither_sts;
+	u32 gamut_sts;
 };
 
 #define PP_FLAGS_DIRTY_PA	0x1
+#define PP_FLAGS_DIRTY_PCC	0x2
+#define PP_FLAGS_DIRTY_IGC	0x4
+#define PP_FLAGS_DIRTY_ARGC	0x8
+#define PP_FLAGS_DIRTY_ENHIST	0x10
+#define PP_FLAGS_DIRTY_DITHER	0x20
+#define PP_FLAGS_DIRTY_GAMUT	0x40
+#define PP_FLAGS_DIRTY_HIST_COL	0x80
 
 #define PP_STS_ENABLE	0x1
+#define PP_STS_GAMUT_FIRST	0x2
 
 struct mdss_pp_res_type {
 	/* logical info */
 	u32 pp_disp_flags[MDSS_BLOCK_DISP_NUM];
+	u32 igc_lut_c0c1[MDSS_BLOCK_DISP_NUM][IGC_LUT_ENTRIES];
+	u32 igc_lut_c2[MDSS_BLOCK_DISP_NUM][IGC_LUT_ENTRIES];
+	struct mdp_ar_gc_lut_data
+		gc_lut_r[MDSS_BLOCK_DISP_NUM][GC_LUT_SEGMENTS];
+	struct mdp_ar_gc_lut_data
+		gc_lut_g[MDSS_BLOCK_DISP_NUM][GC_LUT_SEGMENTS];
+	struct mdp_ar_gc_lut_data
+		gc_lut_b[MDSS_BLOCK_DISP_NUM][GC_LUT_SEGMENTS];
+	u32 enhist_lut[MDSS_BLOCK_DISP_NUM][ENHIST_LUT_ENTRIES];
 	struct mdp_pa_cfg_data pa_disp_cfg[MDSS_BLOCK_DISP_NUM];
+	struct mdp_pcc_cfg_data pcc_disp_cfg[MDSS_BLOCK_DISP_NUM];
+	struct mdp_igc_lut_data igc_disp_cfg[MDSS_BLOCK_DISP_NUM];
+	struct mdp_pgc_lut_data pgc_disp_cfg[MDSS_BLOCK_DISP_NUM];
+	struct mdp_hist_lut_data enhist_disp_cfg[MDSS_BLOCK_DISP_NUM];
+	struct mdp_dither_cfg_data dither_disp_cfg[MDSS_BLOCK_DISP_NUM];
+	struct mdp_gamut_cfg_data gamut_disp_cfg[MDSS_BLOCK_DISP_NUM];
+	uint16_t gamut_tbl[MDSS_BLOCK_DISP_NUM][GAMUT_TOTAL_TABLE_SIZE];
+	struct pp_hist_col_info
+		*hist_col[MDSS_BLOCK_DISP_NUM][MDSS_MDP_MAX_DSPP];
+	u32 hist_data[MDSS_BLOCK_DISP_NUM][HIST_V_SIZE];
 	/* physical info */
 	struct pp_sts_type pp_dspp_sts[MDSS_MDP_MAX_DSPP];
+	struct pp_hist_col_info dspp_hist[MDSS_MDP_MAX_DSPP];
 };
 
 static DEFINE_MUTEX(mdss_pp_mutex);
+static DEFINE_SPINLOCK(mdss_hist_lock);
+static DEFINE_MUTEX(mdss_mdp_hist_mutex);
 static struct mdss_pp_res_type *mdss_pp_res;
 
-static int mdss_mdp_csc_setup_data(u32 block, u32 blk_idx, u32 tbl_idx,
+
+static void pp_hist_read(u32 v_base, struct pp_hist_col_info *hist_info);
+
+static void pp_update_pcc_regs(u32 offset,
+				struct mdp_pcc_cfg_data *cfg_ptr);
+static void pp_update_igc_lut(struct mdp_igc_lut_data *cfg,
+				u32 offset, u32 blk_idx);
+static void pp_update_gc_one_lut(u32 offset,
+		struct mdp_ar_gc_lut_data *lut_data);
+static void pp_update_argc_lut(u32 offset,
+		struct mdp_pgc_lut_data *config);
+
+int mdss_mdp_csc_setup_data(u32 block, u32 blk_idx, u32 tbl_idx,
 				   struct mdp_csc_cfg *data)
 {
 	int i, ret = 0;
@@ -181,19 +276,123 @@
 	data = &mdp_csc_convert[csc_type];
 	return mdss_mdp_csc_setup_data(block, blk_idx, tbl_idx, data);
 }
-
-static int pp_dspp_setup(u32 disp_num, struct mdss_mdp_ctl *ctl,
+static int pp_mixer_setup(u32 disp_num, struct mdss_mdp_ctl *ctl,
 		struct mdss_mdp_mixer *mixer)
 {
-	u32 flags, base, offset, dspp_num, opmode = 0;
-	struct mdp_pa_cfg_data *pa_config;
+	u32 flags, offset, dspp_num, opmode = 0;
+	struct mdp_pgc_lut_data *pgc_config;
 	struct pp_sts_type *pp_sts;
-
 	dspp_num = mixer->num;
 	/* no corresponding dspp */
 	if ((mixer->type != MDSS_MDP_MIXER_TYPE_INTF) ||
 		(dspp_num >= MDSS_MDP_MAX_DSPP))
 		return 0;
+	if (disp_num < MDSS_BLOCK_DISP_NUM)
+		flags = mdss_pp_res->pp_disp_flags[disp_num];
+	else
+		flags = 0;
+
+	pp_sts = &mdss_pp_res->pp_dspp_sts[dspp_num];
+	/* GC_LUT is in layer mixer */
+	if (flags & PP_FLAGS_DIRTY_ARGC) {
+		pgc_config = &mdss_pp_res->pgc_disp_cfg[disp_num];
+		if (pgc_config->flags & MDP_PP_OPS_WRITE) {
+			offset = MDSS_MDP_REG_LM_OFFSET(disp_num) +
+				MDSS_MDP_REG_LM_GC_LUT_BASE;
+			pp_update_argc_lut(offset, pgc_config);
+		}
+		if (pgc_config->flags & MDP_PP_OPS_DISABLE)
+			pp_sts->argc_sts &= ~PP_STS_ENABLE;
+		else if (pgc_config->flags & MDP_PP_OPS_ENABLE)
+			pp_sts->argc_sts |= PP_STS_ENABLE;
+		ctl->flush_bits |= BIT(6) << dspp_num; /* LAYER_MIXER */
+	}
+	/* update LM opmode if LM needs flush */
+	if ((pp_sts->argc_sts & PP_STS_ENABLE) &&
+		(ctl->flush_bits & (BIT(6) << dspp_num))) {
+		offset = MDSS_MDP_REG_LM_OFFSET(dspp_num) +
+			MDSS_MDP_REG_LM_OP_MODE;
+		opmode = MDSS_MDP_REG_READ(offset);
+		opmode |= (1 << 0); /* GC_LUT_EN */
+		MDSS_MDP_REG_WRITE(offset, opmode);
+	}
+	return 0;
+}
+static void pp_gamut_config(struct mdp_gamut_cfg_data *gamut_cfg,
+							u32 base,
+							u32 *gamut_sts)
+{
+	u32 offset;
+	int i, j;
+	if (gamut_cfg->flags & MDP_PP_OPS_WRITE) {
+		offset = base + MDSS_MDP_REG_DSPP_GAMUT_BASE;
+		for (i = 0; i < MDP_GAMUT_TABLE_NUM; i++) {
+			for (j = 0; j < gamut_cfg->tbl_size[i]; j++)
+				MDSS_MDP_REG_WRITE(offset,
+					(u32)gamut_cfg->r_tbl[i][j]);
+			offset += 4;
+		}
+		for (i = 0; i < MDP_GAMUT_TABLE_NUM; i++) {
+			for (j = 0; j < gamut_cfg->tbl_size[i]; j++)
+				MDSS_MDP_REG_WRITE(offset,
+					(u32)gamut_cfg->g_tbl[i][j]);
+			offset += 4;
+		}
+		for (i = 0; i < MDP_GAMUT_TABLE_NUM; i++) {
+			for (j = 0; j < gamut_cfg->tbl_size[i]; j++)
+				MDSS_MDP_REG_WRITE(offset,
+					(u32)gamut_cfg->b_tbl[i][j]);
+			offset += 4;
+		}
+		if (gamut_cfg->gamut_first)
+			*gamut_sts |= PP_STS_GAMUT_FIRST;
+	}
+
+	if (gamut_cfg->flags & MDP_PP_OPS_DISABLE)
+		*gamut_sts &= ~PP_STS_ENABLE;
+	else if (gamut_cfg->flags & MDP_PP_OPS_ENABLE)
+		*gamut_sts |= PP_STS_ENABLE;
+}
+static int pp_dspp_setup(u32 disp_num, struct mdss_mdp_ctl *ctl,
+		struct mdss_mdp_mixer *mixer)
+{
+	u32 flags, base, offset, dspp_num, opmode = 0;
+	struct mdp_pa_cfg_data *pa_config;
+	struct mdp_pcc_cfg_data *pcc_config;
+	struct mdp_igc_lut_data *igc_config;
+	struct mdp_hist_lut_data *enhist_cfg;
+	struct mdp_dither_cfg_data *dither_cfg;
+	struct pp_hist_col_info *hist_info;
+	struct pp_sts_type *pp_sts;
+	u32 data, tbl_idx, col_state;
+	int i;
+	dspp_num = mixer->num;
+	/* no corresponding dspp */
+	if ((mixer->type != MDSS_MDP_MIXER_TYPE_INTF) ||
+		(dspp_num >= MDSS_MDP_MAX_DSPP))
+		return 0;
+	base = MDSS_MDP_REG_DSPP_OFFSET(dspp_num);
+	hist_info = &mdss_pp_res->dspp_hist[dspp_num];
+	if (hist_info->col_en) {
+		/* HIST_EN & AUTO_CLEAR */
+		opmode |= (1 << 16) | (1 << 17);
+		mutex_lock(&mdss_mdp_hist_mutex);
+		if (hist_info->col_state == HIST_READY)
+			pp_hist_read(base + MDSS_MDP_REG_DSPP_HIST_CTL_BASE +
+				0x1C, hist_info);
+		spin_lock(&mdss_hist_lock);
+		col_state = hist_info->col_state;
+		if ((col_state == HIST_IDLE) ||
+			(col_state == HIST_READY) ||
+			(col_state == HIST_START)) {
+			/* Kick off collection */
+			MDSS_MDP_REG_WRITE(base +
+				MDSS_MDP_REG_DSPP_HIST_CTL_BASE, 1);
+			hist_info->col_state = HIST_START;
+		}
+		spin_unlock(&mdss_hist_lock);
+		mutex_unlock(&mdss_mdp_hist_mutex);
+	}
 
 	if (disp_num < MDSS_BLOCK_DISP_NUM)
 		flags = mdss_pp_res->pp_disp_flags[disp_num];
@@ -201,10 +400,9 @@
 		flags = 0;
 
 	/* nothing to update */
-	if (!flags)
+	if ((!flags) && (!(hist_info->col_en)))
 		return 0;
 	pp_sts = &mdss_pp_res->pp_dspp_sts[dspp_num];
-	base = MDSS_MDP_REG_DSPP_OFFSET(dspp_num);
 	if (flags & PP_FLAGS_DIRTY_PA) {
 		pa_config = &mdss_pp_res->pa_disp_cfg[disp_num];
 		if (pa_config->flags & MDP_PP_OPS_WRITE) {
@@ -224,10 +422,108 @@
 	}
 	if (pp_sts->pa_sts & PP_STS_ENABLE)
 		opmode |= (1 << 20); /* PA_EN */
+	if (flags & PP_FLAGS_DIRTY_PCC) {
+		pcc_config = &mdss_pp_res->pcc_disp_cfg[disp_num];
+		if (pcc_config->ops & MDP_PP_OPS_WRITE) {
+			offset = base + MDSS_MDP_REG_DSPP_PCC_BASE;
+			pp_update_pcc_regs(offset, pcc_config);
+		}
+		if (pcc_config->ops & MDP_PP_OPS_DISABLE)
+			pp_sts->pcc_sts &= ~PP_STS_ENABLE;
+		else if (pcc_config->ops & MDP_PP_OPS_ENABLE)
+			pp_sts->pcc_sts |= PP_STS_ENABLE;
+	}
+	if (pp_sts->pcc_sts & PP_STS_ENABLE)
+		opmode |= (1 << 4); /* PCC_EN */
+
+	if (flags & PP_FLAGS_DIRTY_IGC) {
+		igc_config = &mdss_pp_res->igc_disp_cfg[disp_num];
+		if (igc_config->ops & MDP_PP_OPS_WRITE) {
+			offset = MDSS_MDP_REG_IGC_DSPP_BASE;
+			pp_update_igc_lut(igc_config, offset, dspp_num);
+		}
+		if (igc_config->ops & MDP_PP_IGC_FLAG_ROM0) {
+			pp_sts->pcc_sts |= PP_STS_ENABLE;
+			tbl_idx = 1;
+		} else if (igc_config->ops & MDP_PP_IGC_FLAG_ROM1) {
+			pp_sts->pcc_sts |= PP_STS_ENABLE;
+			tbl_idx = 2;
+		} else {
+			tbl_idx = 0;
+		}
+		pp_sts->igc_tbl_idx = tbl_idx;
+		if (igc_config->ops & MDP_PP_OPS_DISABLE)
+			pp_sts->igc_sts &= ~PP_STS_ENABLE;
+		else if (igc_config->ops & MDP_PP_OPS_ENABLE)
+			pp_sts->igc_sts |= PP_STS_ENABLE;
+	}
+	if (pp_sts->igc_sts & PP_STS_ENABLE) {
+		opmode |= (1 << 0) | /* IGC_LUT_EN */
+			      (pp_sts->igc_tbl_idx << 1);
+	}
+	if (flags & PP_FLAGS_DIRTY_ENHIST) {
+		enhist_cfg = &mdss_pp_res->enhist_disp_cfg[disp_num];
+		if (enhist_cfg->ops & MDP_PP_OPS_WRITE) {
+			offset = base + MDSS_MDP_REG_DSPP_HIST_LUT_BASE;
+			for (i = 0; i < ENHIST_LUT_ENTRIES; i++)
+				MDSS_MDP_REG_WRITE(offset, enhist_cfg->data[i]);
+			/* swap */
+			MDSS_MDP_REG_WRITE(offset + 4, 1);
+		}
+		if (enhist_cfg->ops & MDP_PP_OPS_DISABLE)
+			pp_sts->enhist_sts &= ~PP_STS_ENABLE;
+		else if (enhist_cfg->ops & MDP_PP_OPS_ENABLE)
+			pp_sts->enhist_sts |= PP_STS_ENABLE;
+	}
+	if (pp_sts->enhist_sts & PP_STS_ENABLE) {
+		opmode |= (1 << 19) | /* HIST_LUT_EN */
+				  (1 << 20); /* PA_EN */
+		if (!(pp_sts->pa_sts & PP_STS_ENABLE)) {
+			/* Program default value */
+			offset = base + MDSS_MDP_REG_DSPP_PA_BASE;
+			MDSS_MDP_REG_WRITE(offset, 0);
+			MDSS_MDP_REG_WRITE(offset + 4, 0);
+			MDSS_MDP_REG_WRITE(offset + 8, 0);
+			MDSS_MDP_REG_WRITE(offset + 12, 0);
+		}
+	}
+	if (flags & PP_FLAGS_DIRTY_DITHER) {
+		dither_cfg = &mdss_pp_res->dither_disp_cfg[disp_num];
+		if (dither_cfg->flags & MDP_PP_OPS_WRITE) {
+			offset = base + MDSS_MDP_REG_DSPP_DITHER_DEPTH;
+			MDSS_MDP_REG_WRITE(offset,
+			  dither_depth_map[dither_cfg->g_y_depth] |
+			  (dither_depth_map[dither_cfg->b_cb_depth] << 2) |
+			  (dither_depth_map[dither_cfg->r_cr_depth] << 4));
+			offset += 0x14;
+			for (i = 0; i << 16; i += 4) {
+				data = dither_matrix[i] |
+					(dither_matrix[i + 1] << 4) |
+					(dither_matrix[i + 2] << 8) |
+					(dither_matrix[i + 3] << 12);
+				MDSS_MDP_REG_WRITE(offset, data);
+				offset += 4;
+			}
+		}
+		if (dither_cfg->flags & MDP_PP_OPS_DISABLE)
+			pp_sts->dither_sts &= ~PP_STS_ENABLE;
+		else if (dither_cfg->flags & MDP_PP_OPS_ENABLE)
+			pp_sts->dither_sts |= PP_STS_ENABLE;
+	}
+	if (pp_sts->dither_sts & PP_STS_ENABLE)
+		opmode |= (1 << 8); /* DITHER_EN */
+	if (flags & PP_FLAGS_DIRTY_GAMUT)
+		pp_gamut_config(&mdss_pp_res->gamut_disp_cfg[disp_num],
+					base, &pp_sts->gamut_sts);
+	if (pp_sts->gamut_sts & PP_STS_ENABLE) {
+		opmode |= (1 << 23); /* GAMUT_EN */
+		if (pp_sts->gamut_sts & PP_STS_GAMUT_FIRST)
+			opmode |= (1 << 24); /* GAMUT_ORDER */
+	}
+
 	MDSS_MDP_REG_WRITE(base + MDSS_MDP_REG_DSPP_OP_MODE, opmode);
 	ctl->flush_bits |= BIT(13 + dspp_num); /* DSPP */
 	return 0;
-
 }
 int mdss_mdp_pp_setup(struct mdss_mdp_ctl *ctl)
 {
@@ -239,10 +535,14 @@
 	disp_num = ctl->mfd->index;
 
 	mutex_lock(&mdss_pp_mutex);
-	if (ctl->mixer_left)
+	if (ctl->mixer_left) {
+		pp_mixer_setup(disp_num, ctl, ctl->mixer_left);
 		pp_dspp_setup(disp_num, ctl, ctl->mixer_left);
-	if (ctl->mixer_right)
+	}
+	if (ctl->mixer_right) {
+		pp_mixer_setup(disp_num, ctl, ctl->mixer_right);
 		pp_dspp_setup(disp_num, ctl, ctl->mixer_right);
+	}
 	/* clear dirty flag */
 	if (disp_num < MDSS_BLOCK_DISP_NUM)
 		mdss_pp_res->pp_disp_flags[disp_num] = 0;
@@ -275,12 +575,31 @@
 		mutex_unlock(&mdss_pp_mutex);
 	}
 }
+static int pp_get_dspp_num(u32 disp_num, u32 *dspp_num)
+{
+	int i;
+	u32 mixer_cnt;
+	u32 mixer_id[MDSS_MDP_MAX_LAYERMIXER];
+	mixer_cnt = mdss_mdp_get_ctl_mixers(disp_num, mixer_id);
+
+	if (!mixer_cnt)
+		return -EPERM;
+
+	/* only read the first mixer */
+	for (i = 0; i < mixer_cnt; i++) {
+		if (mixer_id[i] < MDSS_MDP_MAX_DSPP)
+			break;
+	}
+	if (i >= mixer_cnt)
+		return -EPERM;
+	*dspp_num = mixer_id[i];
+	return 0;
+}
 
 int mdss_mdp_pa_config(struct mdp_pa_cfg_data *config, u32 *copyback)
 {
-	int i, ret = 0;
-	u32 pa_offset, disp_num, mixer_cnt;
-	u32 mixer_id[MDSS_MDP_MAX_LAYERMIXER];
+	int ret = 0;
+	u32 pa_offset, disp_num, dspp_num = 0;
 
 	if ((config->block < MDP_LOGICAL_BLOCK_DISP_0) ||
 		(config->block >= MDP_BLOCK_MAX))
@@ -290,24 +609,15 @@
 	disp_num = config->block - MDP_LOGICAL_BLOCK_DISP_0;
 
 	if (config->flags & MDP_PP_OPS_READ) {
-		mixer_cnt = mdss_mdp_get_ctl_mixers(disp_num, mixer_id);
-		if (!mixer_cnt) {
-			ret = -EPERM;
-			goto pa_config_exit;
-		}
-		/* only read the first mixer */
-		for (i = 0; i < mixer_cnt; i++) {
-			if (mixer_id[i] < MDSS_MDP_MAX_DSPP)
-				break;
-		}
-		if (i >= mixer_cnt) {
-			ret = -EPERM;
+		ret = pp_get_dspp_num(disp_num, &dspp_num);
+		if (ret) {
+			pr_err("%s, no dspp connects to disp %d",
+				__func__, disp_num);
 			goto pa_config_exit;
 		}
 		mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_ON, false);
-		pa_offset = MDSS_MDP_REG_DSPP_OFFSET(mixer_id[i]) +
+		pa_offset = MDSS_MDP_REG_DSPP_OFFSET(dspp_num) +
 			  MDSS_MDP_REG_DSPP_PA_BASE;
-
 		config->hue_adj = MDSS_MDP_REG_READ(pa_offset);
 		pa_offset += 4;
 		config->sat_adj = MDSS_MDP_REG_READ(pa_offset);
@@ -326,3 +636,910 @@
 	mutex_unlock(&mdss_pp_mutex);
 	return ret;
 }
+
+static void pp_read_pcc_regs(u32 offset,
+				struct mdp_pcc_cfg_data *cfg_ptr)
+{
+	cfg_ptr->r.c = MDSS_MDP_REG_READ(offset);
+	cfg_ptr->g.c = MDSS_MDP_REG_READ(offset + 4);
+	cfg_ptr->b.c = MDSS_MDP_REG_READ(offset + 8);
+	offset += 0x10;
+
+	cfg_ptr->r.r = MDSS_MDP_REG_READ(offset);
+	cfg_ptr->g.r = MDSS_MDP_REG_READ(offset + 4);
+	cfg_ptr->b.r = MDSS_MDP_REG_READ(offset + 8);
+	offset += 0x10;
+
+	cfg_ptr->r.g = MDSS_MDP_REG_READ(offset);
+	cfg_ptr->g.g = MDSS_MDP_REG_READ(offset + 4);
+	cfg_ptr->b.g = MDSS_MDP_REG_READ(offset + 8);
+	offset += 0x10;
+
+	cfg_ptr->r.b = MDSS_MDP_REG_READ(offset);
+	cfg_ptr->g.b = MDSS_MDP_REG_READ(offset + 4);
+	cfg_ptr->b.b = MDSS_MDP_REG_READ(offset + 8);
+	offset += 0x10;
+
+	cfg_ptr->r.rr = MDSS_MDP_REG_READ(offset);
+	cfg_ptr->g.rr = MDSS_MDP_REG_READ(offset + 4);
+	cfg_ptr->b.rr = MDSS_MDP_REG_READ(offset + 8);
+	offset += 0x10;
+
+	cfg_ptr->r.rg = MDSS_MDP_REG_READ(offset);
+	cfg_ptr->g.rg = MDSS_MDP_REG_READ(offset + 4);
+	cfg_ptr->b.rg = MDSS_MDP_REG_READ(offset + 8);
+	offset += 0x10;
+
+	cfg_ptr->r.rb = MDSS_MDP_REG_READ(offset);
+	cfg_ptr->g.rb = MDSS_MDP_REG_READ(offset + 4);
+	cfg_ptr->b.rb = MDSS_MDP_REG_READ(offset + 8);
+	offset += 0x10;
+
+	cfg_ptr->r.gg = MDSS_MDP_REG_READ(offset);
+	cfg_ptr->g.gg = MDSS_MDP_REG_READ(offset + 4);
+	cfg_ptr->b.gg = MDSS_MDP_REG_READ(offset + 8);
+	offset += 0x10;
+
+	cfg_ptr->r.gb = MDSS_MDP_REG_READ(offset);
+	cfg_ptr->g.gb = MDSS_MDP_REG_READ(offset + 4);
+	cfg_ptr->b.gb = MDSS_MDP_REG_READ(offset + 8);
+	offset += 0x10;
+
+	cfg_ptr->r.bb = MDSS_MDP_REG_READ(offset);
+	cfg_ptr->g.bb = MDSS_MDP_REG_READ(offset + 4);
+	cfg_ptr->b.bb = MDSS_MDP_REG_READ(offset + 8);
+	offset += 0x10;
+
+	cfg_ptr->r.rgb_0 = MDSS_MDP_REG_READ(offset);
+	cfg_ptr->g.rgb_0 = MDSS_MDP_REG_READ(offset + 4);
+	cfg_ptr->b.rgb_0 = MDSS_MDP_REG_READ(offset + 8);
+	offset += 0x10;
+
+	cfg_ptr->r.rgb_1 = MDSS_MDP_REG_READ(offset);
+	cfg_ptr->g.rgb_1 = MDSS_MDP_REG_READ(offset + 4);
+	cfg_ptr->b.rgb_1 = MDSS_MDP_REG_READ(offset + 8);
+}
+
+static void pp_update_pcc_regs(u32 offset,
+				struct mdp_pcc_cfg_data *cfg_ptr)
+{
+	MDSS_MDP_REG_WRITE(offset, cfg_ptr->r.c);
+	MDSS_MDP_REG_WRITE(offset + 4, cfg_ptr->g.c);
+	MDSS_MDP_REG_WRITE(offset + 8, cfg_ptr->b.c);
+	offset += 0x10;
+
+	MDSS_MDP_REG_WRITE(offset, cfg_ptr->r.r);
+	MDSS_MDP_REG_WRITE(offset + 4, cfg_ptr->g.r);
+	MDSS_MDP_REG_WRITE(offset + 8, cfg_ptr->b.r);
+	offset += 0x10;
+
+	MDSS_MDP_REG_WRITE(offset, cfg_ptr->r.g);
+	MDSS_MDP_REG_WRITE(offset + 4, cfg_ptr->g.g);
+	MDSS_MDP_REG_WRITE(offset + 8, cfg_ptr->b.g);
+	offset += 0x10;
+
+	MDSS_MDP_REG_WRITE(offset, cfg_ptr->r.b);
+	MDSS_MDP_REG_WRITE(offset + 4, cfg_ptr->g.b);
+	MDSS_MDP_REG_WRITE(offset + 8, cfg_ptr->b.b);
+	offset += 0x10;
+
+	MDSS_MDP_REG_WRITE(offset, cfg_ptr->r.rr);
+	MDSS_MDP_REG_WRITE(offset + 4, cfg_ptr->g.rr);
+	MDSS_MDP_REG_WRITE(offset + 8, cfg_ptr->b.rr);
+	offset += 0x10;
+
+	MDSS_MDP_REG_WRITE(offset, cfg_ptr->r.rg);
+	MDSS_MDP_REG_WRITE(offset + 4, cfg_ptr->g.rg);
+	MDSS_MDP_REG_WRITE(offset + 8, cfg_ptr->b.rg);
+	offset += 0x10;
+
+	MDSS_MDP_REG_WRITE(offset, cfg_ptr->r.rb);
+	MDSS_MDP_REG_WRITE(offset + 4, cfg_ptr->g.rb);
+	MDSS_MDP_REG_WRITE(offset + 8, cfg_ptr->b.rb);
+	offset += 0x10;
+
+	MDSS_MDP_REG_WRITE(offset, cfg_ptr->r.gg);
+	MDSS_MDP_REG_WRITE(offset + 4, cfg_ptr->g.gg);
+	MDSS_MDP_REG_WRITE(offset + 8, cfg_ptr->b.gg);
+	offset += 0x10;
+
+	MDSS_MDP_REG_WRITE(offset, cfg_ptr->r.gb);
+	MDSS_MDP_REG_WRITE(offset + 4, cfg_ptr->g.gb);
+	MDSS_MDP_REG_WRITE(offset + 8, cfg_ptr->b.gb);
+	offset += 0x10;
+
+	MDSS_MDP_REG_WRITE(offset, cfg_ptr->r.bb);
+	MDSS_MDP_REG_WRITE(offset + 4, cfg_ptr->g.bb);
+	MDSS_MDP_REG_WRITE(offset + 8, cfg_ptr->b.bb);
+	offset += 0x10;
+
+	MDSS_MDP_REG_WRITE(offset, cfg_ptr->r.rgb_0);
+	MDSS_MDP_REG_WRITE(offset + 4, cfg_ptr->g.rgb_0);
+	MDSS_MDP_REG_WRITE(offset + 8, cfg_ptr->b.rgb_0);
+	offset += 0x10;
+
+	MDSS_MDP_REG_WRITE(offset, cfg_ptr->r.rgb_1);
+	MDSS_MDP_REG_WRITE(offset + 4, cfg_ptr->g.rgb_1);
+	MDSS_MDP_REG_WRITE(offset + 8, cfg_ptr->b.rgb_1);
+}
+
+int mdss_mdp_pcc_config(struct mdp_pcc_cfg_data *config, u32 *copyback)
+{
+	int ret = 0;
+	u32 base, disp_num, dspp_num = 0;
+
+	if ((config->block < MDP_LOGICAL_BLOCK_DISP_0) ||
+		(config->block >= MDP_BLOCK_MAX))
+		return -EINVAL;
+
+	mutex_lock(&mdss_pp_mutex);
+	disp_num = config->block - MDP_LOGICAL_BLOCK_DISP_0;
+
+	if (config->ops & MDP_PP_OPS_READ) {
+		ret = pp_get_dspp_num(disp_num, &dspp_num);
+		if (ret) {
+			pr_err("%s, no dspp connects to disp %d",
+				__func__, disp_num);
+			goto pcc_config_exit;
+		}
+
+		mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_ON, false);
+
+		base = MDSS_MDP_REG_DSPP_OFFSET(dspp_num) +
+			  MDSS_MDP_REG_DSPP_PCC_BASE;
+		pp_read_pcc_regs(base, config);
+		*copyback = 1;
+		mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_OFF, false);
+	} else {
+		mdss_pp_res->pcc_disp_cfg[disp_num] = *config;
+		mdss_pp_res->pp_disp_flags[disp_num] |= PP_FLAGS_DIRTY_PCC;
+	}
+
+pcc_config_exit:
+	mutex_unlock(&mdss_pp_mutex);
+	return ret;
+
+}
+
+static void pp_read_igc_lut(struct mdp_igc_lut_data *cfg,
+				u32 offset, u32 blk_idx)
+{
+	int i;
+	u32 data;
+
+	/* INDEX_UPDATE & VALUE_UPDATEN */
+	data = (3 << 24) | (((~(1 << blk_idx)) & 0x7) << 28);
+	MDSS_MDP_REG_WRITE(offset, data);
+
+	for (i = 0; i < cfg->len; i++)
+		cfg->c0_c1_data[i] = MDSS_MDP_REG_READ(offset) & 0xFFF;
+
+	offset += 0x4;
+	MDSS_MDP_REG_WRITE(offset, data);
+	for (i = 0; i < cfg->len; i++)
+		cfg->c0_c1_data[i] |= (MDSS_MDP_REG_READ(offset) & 0xFFF) << 16;
+
+	offset += 0x4;
+	MDSS_MDP_REG_WRITE(offset, data);
+	for (i = 0; i < cfg->len; i++)
+		cfg->c2_data[i] = MDSS_MDP_REG_READ(offset) & 0xFFF;
+}
+
+static void pp_update_igc_lut(struct mdp_igc_lut_data *cfg,
+				u32 offset, u32 blk_idx)
+{
+	int i;
+	u32 data;
+	/* INDEX_UPDATE */
+	data = (1 << 25) | (((~(1 << blk_idx)) & 0x7) << 28);
+	MDSS_MDP_REG_WRITE(offset, (cfg->c0_c1_data[0] & 0xFFF) | data);
+
+	/* disable index update */
+	data &= ~(1 << 25);
+	for (i = 1; i < cfg->len; i++)
+		MDSS_MDP_REG_WRITE(offset, (cfg->c0_c1_data[i] & 0xFFF) | data);
+
+	offset += 0x4;
+	data |= (1 << 25);
+	MDSS_MDP_REG_WRITE(offset, ((cfg->c0_c1_data[0] >> 16) & 0xFFF) | data);
+	data &= ~(1 << 25);
+	for (i = 1; i < cfg->len; i++)
+		MDSS_MDP_REG_WRITE(offset,
+		((cfg->c0_c1_data[i] >> 16) & 0xFFF) | data);
+
+	offset += 0x4;
+	data |= (1 << 25);
+	MDSS_MDP_REG_WRITE(offset, (cfg->c2_data[0] & 0xFFF) | data);
+	data &= ~(1 << 25);
+	for (i = 1; i < cfg->len; i++)
+		MDSS_MDP_REG_WRITE(offset, (cfg->c2_data[i] & 0xFFF) | data);
+}
+
+int mdss_mdp_igc_lut_config(struct mdp_igc_lut_data *config, u32 *copyback)
+{
+	int ret = 0;
+	u32 tbl_idx, igc_offset, disp_num, dspp_num = 0;
+	struct mdp_igc_lut_data local_cfg;
+
+	if ((config->block < MDP_LOGICAL_BLOCK_DISP_0) ||
+		(config->block >= MDP_BLOCK_MAX))
+		return -EINVAL;
+
+	mutex_lock(&mdss_pp_mutex);
+	disp_num = config->block - MDP_LOGICAL_BLOCK_DISP_0;
+
+	if (config->ops & MDP_PP_OPS_READ) {
+		ret = pp_get_dspp_num(disp_num, &dspp_num);
+		if (ret) {
+			pr_err("%s, no dspp connects to disp %d",
+				__func__, disp_num);
+			goto igc_config_exit;
+		}
+		mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_ON, false);
+		if (config->ops & MDP_PP_IGC_FLAG_ROM0)
+			tbl_idx = 1;
+		else if (config->ops & MDP_PP_IGC_FLAG_ROM1)
+			tbl_idx = 2;
+		else
+			tbl_idx = 0;
+		igc_offset = MDSS_MDP_REG_IGC_DSPP_BASE + (0x10 * tbl_idx);
+		local_cfg = *config;
+		local_cfg.c0_c1_data =
+			&mdss_pp_res->igc_lut_c0c1[disp_num][0];
+		local_cfg.c2_data =
+			&mdss_pp_res->igc_lut_c2[disp_num][0];
+		pp_read_igc_lut(&local_cfg, igc_offset, dspp_num);
+		if (copy_to_user(config->c0_c1_data, local_cfg.c2_data,
+			config->len * sizeof(u32))) {
+			ret = -EFAULT;
+			goto igc_config_exit;
+		}
+		if (copy_to_user(config->c2_data, local_cfg.c0_c1_data,
+			config->len * sizeof(u32))) {
+			ret = -EFAULT;
+			goto igc_config_exit;
+		}
+		*copyback = 1;
+		mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_OFF, false);
+	} else {
+		if (copy_from_user(&mdss_pp_res->igc_lut_c0c1[disp_num][0],
+			config->c0_c1_data, config->len * sizeof(u32))) {
+			ret = -EFAULT;
+			goto igc_config_exit;
+		}
+		if (copy_from_user(&mdss_pp_res->igc_lut_c2[disp_num][0],
+			config->c2_data, config->len * sizeof(u32))) {
+			ret = -EFAULT;
+			goto igc_config_exit;
+		}
+		mdss_pp_res->igc_disp_cfg[disp_num] = *config;
+		mdss_pp_res->igc_disp_cfg[disp_num].c0_c1_data =
+			&mdss_pp_res->igc_lut_c0c1[disp_num][0];
+		mdss_pp_res->igc_disp_cfg[disp_num].c2_data =
+			&mdss_pp_res->igc_lut_c2[disp_num][0];
+		mdss_pp_res->pp_disp_flags[disp_num] |= PP_FLAGS_DIRTY_IGC;
+	}
+
+igc_config_exit:
+	mutex_unlock(&mdss_pp_mutex);
+	return ret;
+}
+static void pp_update_gc_one_lut(u32 offset,
+		struct mdp_ar_gc_lut_data *lut_data)
+{
+	int i, start_idx;
+
+	start_idx = (MDSS_MDP_REG_READ(offset) >> 16) & 0xF;
+	for (i = start_idx; i < GC_LUT_SEGMENTS; i++)
+		MDSS_MDP_REG_WRITE(offset, lut_data[i].x_start);
+	for (i = 0; i < start_idx; i++)
+		MDSS_MDP_REG_WRITE(offset, lut_data[i].x_start);
+	offset += 4;
+	start_idx = (MDSS_MDP_REG_READ(offset) >> 16) & 0xF;
+	for (i = start_idx; i < GC_LUT_SEGMENTS; i++)
+		MDSS_MDP_REG_WRITE(offset, lut_data[i].slope);
+	for (i = 0; i < start_idx; i++)
+		MDSS_MDP_REG_WRITE(offset, lut_data[i].slope);
+	offset += 4;
+	start_idx = (MDSS_MDP_REG_READ(offset) >> 16) & 0xF;
+	for (i = start_idx; i < GC_LUT_SEGMENTS; i++)
+		MDSS_MDP_REG_WRITE(offset, lut_data[i].offset);
+	for (i = 0; i < start_idx; i++)
+		MDSS_MDP_REG_WRITE(offset, lut_data[i].offset);
+}
+static void pp_update_argc_lut(u32 offset, struct mdp_pgc_lut_data *config)
+{
+	pp_update_gc_one_lut(offset, config->r_data);
+	offset += 0x10;
+	pp_update_gc_one_lut(offset, config->g_data);
+	offset += 0x10;
+	pp_update_gc_one_lut(offset, config->b_data);
+}
+static void pp_read_gc_one_lut(u32 offset,
+		struct mdp_ar_gc_lut_data *gc_data)
+{
+	int i, start_idx, data;
+	data = MDSS_MDP_REG_READ(offset);
+	start_idx = (data >> 16) & 0xF;
+	gc_data[start_idx].x_start = data & 0xFFF;
+
+	for (i = start_idx + 1; i < GC_LUT_SEGMENTS; i++) {
+		data = MDSS_MDP_REG_READ(offset);
+		gc_data[i].x_start = data & 0xFFF;
+	}
+	for (i = 0; i < start_idx; i++) {
+		data = MDSS_MDP_REG_READ(offset);
+		gc_data[i].x_start = data & 0xFFF;
+	}
+
+	offset += 4;
+	data = MDSS_MDP_REG_READ(offset);
+	start_idx = (data >> 16) & 0xF;
+	gc_data[start_idx].slope = data & 0x7FFF;
+	for (i = start_idx + 1; i < GC_LUT_SEGMENTS; i++) {
+		data = MDSS_MDP_REG_READ(offset);
+		gc_data[i].slope = data & 0x7FFF;
+	}
+	for (i = 0; i < start_idx; i++) {
+		data = MDSS_MDP_REG_READ(offset);
+		gc_data[i].slope = data & 0x7FFF;
+	}
+	offset += 4;
+	data = MDSS_MDP_REG_READ(offset);
+	start_idx = (data >> 16) & 0xF;
+	gc_data[start_idx].offset = data & 0x7FFF;
+	for (i = start_idx + 1; i < GC_LUT_SEGMENTS; i++) {
+		data = MDSS_MDP_REG_READ(offset);
+		gc_data[i].offset = data & 0x7FFF;
+	}
+	for (i = 0; i < start_idx; i++) {
+		data = MDSS_MDP_REG_READ(offset);
+		gc_data[i].offset = data & 0x7FFF;
+	}
+}
+
+static int pp_read_argc_lut(struct mdp_pgc_lut_data *config, u32 offset)
+{
+	int ret = 0;
+	pp_read_gc_one_lut(offset, config->r_data);
+	offset += 0x10;
+	pp_read_gc_one_lut(offset, config->g_data);
+	offset += 0x10;
+	pp_read_gc_one_lut(offset, config->b_data);
+	return ret;
+}
+int mdss_mdp_argc_config(struct mdp_pgc_lut_data *config, u32 *copyback)
+{
+	int ret = 0;
+	u32 argc_offset, disp_num, dspp_num = 0;
+	struct mdp_pgc_lut_data local_cfg;
+	u32 tbl_size;
+
+	if ((config->block < MDP_LOGICAL_BLOCK_DISP_0) ||
+		(config->block >= MDP_BLOCK_MAX))
+		return -EINVAL;
+
+	mutex_lock(&mdss_pp_mutex);
+	disp_num = config->block - MDP_LOGICAL_BLOCK_DISP_0;
+
+	tbl_size = GC_LUT_SEGMENTS * sizeof(struct mdp_ar_gc_lut_data);
+	if (config->flags & MDP_PP_OPS_READ) {
+		ret = pp_get_dspp_num(disp_num, &dspp_num);
+		if (ret) {
+			pr_err("%s, no dspp connects to disp %d",
+				__func__, disp_num);
+			goto argc_config_exit;
+		}
+		mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_ON, false);
+
+		argc_offset = MDSS_MDP_REG_LM_OFFSET(dspp_num) +
+				MDSS_MDP_REG_LM_GC_LUT_BASE;
+		mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_ON, false);
+		local_cfg = *config;
+		local_cfg.r_data =
+			&mdss_pp_res->gc_lut_r[disp_num][0];
+		local_cfg.g_data =
+			&mdss_pp_res->gc_lut_g[disp_num][0];
+		local_cfg.b_data =
+			&mdss_pp_res->gc_lut_b[disp_num][0];
+		pp_read_argc_lut(&local_cfg, argc_offset);
+		if (copy_to_user(config->r_data,
+			&mdss_pp_res->gc_lut_r[disp_num][0], tbl_size)) {
+			ret = -EFAULT;
+			goto argc_config_exit;
+		}
+		if (copy_to_user(config->g_data,
+			&mdss_pp_res->gc_lut_g[disp_num][0], tbl_size)) {
+			ret = -EFAULT;
+			goto argc_config_exit;
+		}
+		if (copy_to_user(config->b_data,
+			&mdss_pp_res->gc_lut_b[disp_num][0], tbl_size)) {
+			ret = -EFAULT;
+			goto argc_config_exit;
+		}
+		*copyback = 1;
+		mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_OFF, false);
+	} else {
+		if (copy_from_user(&mdss_pp_res->gc_lut_r[disp_num][0],
+			config->r_data, tbl_size)) {
+			ret = -EFAULT;
+			goto argc_config_exit;
+		}
+		if (copy_from_user(&mdss_pp_res->gc_lut_g[disp_num][0],
+			config->g_data, tbl_size)) {
+			ret = -EFAULT;
+			goto argc_config_exit;
+		}
+		if (copy_from_user(&mdss_pp_res->gc_lut_b[disp_num][0],
+			config->b_data, tbl_size)) {
+			ret = -EFAULT;
+			goto argc_config_exit;
+		}
+		mdss_pp_res->pgc_disp_cfg[disp_num] = *config;
+		mdss_pp_res->pgc_disp_cfg[disp_num].r_data =
+			&mdss_pp_res->gc_lut_r[disp_num][0];
+		mdss_pp_res->pgc_disp_cfg[disp_num].g_data =
+			&mdss_pp_res->gc_lut_g[disp_num][0];
+		mdss_pp_res->pgc_disp_cfg[disp_num].b_data =
+			&mdss_pp_res->gc_lut_b[disp_num][0];
+		mdss_pp_res->pp_disp_flags[disp_num] |= PP_FLAGS_DIRTY_ARGC;
+	}
+argc_config_exit:
+	mutex_unlock(&mdss_pp_mutex);
+	return ret;
+}
+int mdss_mdp_hist_lut_config(struct mdp_hist_lut_data *config, u32 *copyback)
+{
+	int i, ret = 0;
+	u32 hist_offset, disp_num, dspp_num = 0;
+
+	if ((config->block < MDP_LOGICAL_BLOCK_DISP_0) ||
+		(config->block >= MDP_BLOCK_MAX))
+		return -EINVAL;
+
+	mutex_lock(&mdss_pp_mutex);
+	disp_num = config->block - MDP_LOGICAL_BLOCK_DISP_0;
+
+	if (config->ops & MDP_PP_OPS_READ) {
+		ret = pp_get_dspp_num(disp_num, &dspp_num);
+		if (ret) {
+			pr_err("%s, no dspp connects to disp %d",
+				__func__, disp_num);
+			goto enhist_config_exit;
+		}
+		mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_ON, false);
+
+		hist_offset = MDSS_MDP_REG_DSPP_OFFSET(dspp_num) +
+			  MDSS_MDP_REG_DSPP_HIST_LUT_BASE;
+		for (i = 0; i < ENHIST_LUT_ENTRIES; i++)
+			mdss_pp_res->enhist_lut[disp_num][i] =
+				MDSS_MDP_REG_READ(hist_offset);
+		if (copy_to_user(config->data,
+			&mdss_pp_res->enhist_lut[disp_num][0],
+			ENHIST_LUT_ENTRIES * sizeof(u32))) {
+			ret = -EFAULT;
+			goto enhist_config_exit;
+		}
+		*copyback = 1;
+		mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_OFF, false);
+	} else {
+		if (copy_from_user(&mdss_pp_res->enhist_lut[disp_num][0],
+			config->data, ENHIST_LUT_ENTRIES * sizeof(u32))) {
+			ret = -EFAULT;
+			goto enhist_config_exit;
+		}
+		mdss_pp_res->enhist_disp_cfg[disp_num] = *config;
+		mdss_pp_res->enhist_disp_cfg[disp_num].data =
+			&mdss_pp_res->enhist_lut[disp_num][0];
+		mdss_pp_res->pp_disp_flags[disp_num] |= PP_FLAGS_DIRTY_ENHIST;
+	}
+enhist_config_exit:
+	mutex_unlock(&mdss_pp_mutex);
+	return ret;
+}
+
+int mdss_mdp_dither_config(struct mdp_dither_cfg_data *config, u32 *copyback)
+{
+	u32 disp_num;
+	if ((config->block < MDP_LOGICAL_BLOCK_DISP_0) ||
+		(config->block >= MDP_BLOCK_MAX))
+		return -EINVAL;
+	if (config->flags & MDP_PP_OPS_READ)
+		return -ENOTSUPP;
+
+	mutex_lock(&mdss_pp_mutex);
+	disp_num = config->block - MDP_LOGICAL_BLOCK_DISP_0;
+	mdss_pp_res->dither_disp_cfg[disp_num] = *config;
+	mdss_pp_res->pp_disp_flags[disp_num] |= PP_FLAGS_DIRTY_DITHER;
+	mutex_unlock(&mdss_pp_mutex);
+	return 0;
+}
+
+int mdss_mdp_gamut_config(struct mdp_gamut_cfg_data *config, u32 *copyback)
+{
+	int i, j, size_total = 0, ret = 0;
+	u32 offset, disp_num, dspp_num = 0;
+	uint16_t *tbl_off;
+	struct mdp_gamut_cfg_data local_cfg;
+
+	if ((config->block < MDP_LOGICAL_BLOCK_DISP_0) ||
+		(config->block >= MDP_BLOCK_MAX))
+		return -EINVAL;
+	for (i = 0; i < MDP_GAMUT_TABLE_NUM; i++)
+		size_total += config->tbl_size[i];
+	if (size_total != GAMUT_TOTAL_TABLE_SIZE)
+		return -EINVAL;
+
+	mutex_lock(&mdss_pp_mutex);
+	disp_num = config->block - MDP_LOGICAL_BLOCK_DISP_0;
+
+	if (config->flags & MDP_PP_OPS_READ) {
+		ret = pp_get_dspp_num(disp_num, &dspp_num);
+		if (ret) {
+			pr_err("%s, no dspp connects to disp %d",
+				__func__, disp_num);
+			goto gamut_config_exit;
+		}
+		mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_ON, false);
+
+		offset = MDSS_MDP_REG_DSPP_OFFSET(dspp_num) +
+			  MDSS_MDP_REG_DSPP_GAMUT_BASE;
+		for (i = 0; i < MDP_GAMUT_TABLE_NUM; i++) {
+			for (j = 0; j < config->tbl_size[i]; j++)
+				config->r_tbl[i][j] =
+					(u16)MDSS_MDP_REG_READ(offset);
+			offset += 4;
+		}
+		for (i = 0; i < MDP_GAMUT_TABLE_NUM; i++) {
+			for (j = 0; j < config->tbl_size[i]; j++)
+				config->g_tbl[i][j] =
+					(u16)MDSS_MDP_REG_READ(offset);
+			offset += 4;
+		}
+		for (i = 0; i < MDP_GAMUT_TABLE_NUM; i++) {
+			for (j = 0; j < config->tbl_size[i]; j++)
+				config->b_tbl[i][j] =
+					(u16)MDSS_MDP_REG_READ(offset);
+			offset += 4;
+		}
+		*copyback = 1;
+		mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_OFF, false);
+	} else {
+		local_cfg = *config;
+		tbl_off = mdss_pp_res->gamut_tbl[disp_num];
+		for (i = 0; i < MDP_GAMUT_TABLE_NUM; i++) {
+			local_cfg.r_tbl[i] = tbl_off;
+			if (copy_from_user(tbl_off, config->r_tbl[i],
+				config->tbl_size[i] * sizeof(uint16_t))) {
+				ret = -EFAULT;
+				goto gamut_config_exit;
+			}
+			tbl_off += local_cfg.tbl_size[i];
+		}
+		for (i = 0; i < MDP_GAMUT_TABLE_NUM; i++) {
+			local_cfg.g_tbl[i] = tbl_off;
+			if (copy_from_user(tbl_off, config->g_tbl[i],
+				config->tbl_size[i] * sizeof(uint16_t))) {
+				ret = -EFAULT;
+				goto gamut_config_exit;
+			}
+			tbl_off += local_cfg.tbl_size[i];
+		}
+		for (i = 0; i < MDP_GAMUT_TABLE_NUM; i++) {
+			local_cfg.b_tbl[i] = tbl_off;
+			if (copy_from_user(tbl_off, config->b_tbl[i],
+				config->tbl_size[i] * sizeof(uint16_t))) {
+				ret = -EFAULT;
+				goto gamut_config_exit;
+			}
+			tbl_off += local_cfg.tbl_size[i];
+		}
+		mdss_pp_res->gamut_disp_cfg[disp_num] = local_cfg;
+		mdss_pp_res->pp_disp_flags[disp_num] |= PP_FLAGS_DIRTY_GAMUT;
+	}
+gamut_config_exit:
+	mutex_unlock(&mdss_pp_mutex);
+	return ret;
+}
+static void pp_hist_read(u32 v_base, struct pp_hist_col_info *hist_info)
+{
+	int i, i_start;
+	u32 data;
+	data = MDSS_MDP_REG_READ(v_base);
+	i_start = data >> 24;
+	hist_info->data[i_start] = data & 0xFFFFFF;
+	for (i = i_start + 1; i < HIST_V_SIZE; i++)
+		hist_info->data[i] = MDSS_MDP_REG_READ(v_base) & 0xFFFFFF;
+	for (i = 0; i < i_start - 1; i++)
+		hist_info->data[i] = MDSS_MDP_REG_READ(v_base) & 0xFFFFFF;
+	hist_info->hist_cnt_read++;
+}
+
+int mdss_mdp_histogram_start(struct mdp_histogram_start_req *req)
+{
+	u32 ctl_base, done_shift_bit;
+	struct pp_hist_col_info *hist_info;
+	int i, ret = 0;
+	u32 disp_num, dspp_num = 0;
+	u32 mixer_cnt, mixer_id[MDSS_MDP_MAX_LAYERMIXER];
+
+	if ((req->block < MDP_LOGICAL_BLOCK_DISP_0) ||
+		(req->block >= MDP_BLOCK_MAX))
+		return -EINVAL;
+
+	mutex_lock(&mdss_mdp_hist_mutex);
+	disp_num = req->block - MDP_LOGICAL_BLOCK_DISP_0;
+	mixer_cnt = mdss_mdp_get_ctl_mixers(disp_num, mixer_id);
+
+	if (!mixer_cnt) {
+		pr_err("%s, no dspp connects to disp %d",
+			__func__, disp_num);
+		ret = -EPERM;
+		goto hist_start_exit;
+	}
+	if (mixer_cnt >= MDSS_MDP_MAX_DSPP) {
+		pr_err("%s, Too many dspp connects to disp %d",
+			__func__, mixer_cnt);
+		ret = -EPERM;
+		goto hist_start_exit;
+	}
+	mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_ON, false);
+	for (i = 0; i < mixer_cnt; i++) {
+		dspp_num = mixer_id[i];
+		hist_info = &mdss_pp_res->dspp_hist[dspp_num];
+		done_shift_bit = (dspp_num * 4) + 12;
+		/* check if it is idle */
+		if (hist_info->col_en) {
+			mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_OFF, false);
+			pr_info("%s Hist collection has already been enabled %d",
+				__func__, dspp_num);
+			goto hist_start_exit;
+		}
+		spin_lock(&mdss_hist_lock);
+		hist_info->frame_cnt = req->frame_cnt;
+		init_completion(&hist_info->comp);
+		hist_info->hist_cnt_read = 0;
+		hist_info->hist_cnt_sent = 0;
+		hist_info->read_request = false;
+		hist_info->col_state = HIST_RESET;
+		hist_info->col_en = true;
+		spin_unlock(&mdss_hist_lock);
+		mdss_pp_res->hist_col[disp_num][i] =
+			&mdss_pp_res->dspp_hist[dspp_num];
+		mdss_mdp_hist_irq_enable(3 << done_shift_bit);
+		ctl_base = MDSS_MDP_REG_DSPP_OFFSET(dspp_num) +
+			  MDSS_MDP_REG_DSPP_HIST_CTL_BASE;
+		MDSS_MDP_REG_WRITE(ctl_base + 8, req->frame_cnt);
+		/* Kick out reset start */
+		MDSS_MDP_REG_WRITE(ctl_base + 4, 1);
+	}
+	for (i = mixer_cnt; i < MDSS_MDP_MAX_DSPP; i++)
+		mdss_pp_res->hist_col[disp_num][i] = 0;
+	mdss_pp_res->pp_disp_flags[disp_num] |= PP_FLAGS_DIRTY_HIST_COL;
+	mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_OFF, false);
+hist_start_exit:
+	mutex_unlock(&mdss_mdp_hist_mutex);
+	return ret;
+}
+
+int mdss_mdp_histogram_stop(u32 block)
+{
+	int i, ret = 0;
+	u32 dspp_num, disp_num, ctl_base, done_bit;
+	struct pp_hist_col_info *hist_info;
+	u32 mixer_cnt, mixer_id[MDSS_MDP_MAX_LAYERMIXER];
+
+	if ((block < MDP_LOGICAL_BLOCK_DISP_0) ||
+		(block >= MDP_BLOCK_MAX))
+		return -EINVAL;
+
+	mutex_lock(&mdss_mdp_hist_mutex);
+	disp_num = block - MDP_LOGICAL_BLOCK_DISP_0;
+	mixer_cnt = mdss_mdp_get_ctl_mixers(disp_num, mixer_id);
+
+	if (!mixer_cnt) {
+		pr_err("%s, no dspp connects to disp %d",
+			__func__, disp_num);
+		ret = -EPERM;
+		goto hist_stop_exit;
+	}
+	if (mixer_cnt >= MDSS_MDP_MAX_DSPP) {
+		pr_err("%s, Too many dspp connects to disp %d",
+			__func__, mixer_cnt);
+		ret = -EPERM;
+		goto hist_stop_exit;
+	}
+	mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_ON, false);
+	for (i = 0; i < mixer_cnt; i++) {
+		dspp_num = mixer_id[i];
+		hist_info = &mdss_pp_res->dspp_hist[dspp_num];
+		done_bit = 3 << ((dspp_num * 4) + 12);
+		ctl_base = MDSS_MDP_REG_DSPP_OFFSET(dspp_num) +
+			  MDSS_MDP_REG_DSPP_HIST_CTL_BASE;
+		if (hist_info->col_en == false) {
+			mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_OFF, false);
+			goto hist_stop_exit;
+		}
+		complete_all(&hist_info->comp);
+		spin_lock(&mdss_hist_lock);
+		hist_info->col_en = false;
+		hist_info->col_state = HIST_UNKNOWN;
+		spin_unlock(&mdss_hist_lock);
+		mdss_mdp_hist_irq_disable(done_bit);
+		MDSS_MDP_REG_WRITE(ctl_base, (1 << 1));/* cancel */
+	}
+	for (i = 0; i < MDSS_MDP_MAX_DSPP; i++)
+		mdss_pp_res->hist_col[disp_num][i] = 0;
+	mdss_pp_res->pp_disp_flags[disp_num] |= PP_FLAGS_DIRTY_HIST_COL;
+	mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_OFF, false);
+hist_stop_exit:
+	mutex_unlock(&mdss_mdp_hist_mutex);
+	return ret;
+}
+
+int mdss_mdp_hist_collect(struct fb_info *info,
+		  struct mdp_histogram_data *hist, u32 *hist_data_addr)
+{
+	int i, j, wait_ret, ret = 0;
+	u32 timeout, v_base;
+	struct pp_hist_col_info *hist_info;
+	u32 dspp_num, disp_num, ctl_base;
+	u32 mixer_cnt, mixer_id[MDSS_MDP_MAX_LAYERMIXER];
+
+	if ((hist->block < MDP_LOGICAL_BLOCK_DISP_0) ||
+		(hist->block >= MDP_BLOCK_MAX))
+		return -EINVAL;
+
+	mutex_lock(&mdss_mdp_hist_mutex);
+	disp_num = hist->block - MDP_LOGICAL_BLOCK_DISP_0;
+	mixer_cnt = mdss_mdp_get_ctl_mixers(disp_num, mixer_id);
+
+	if (!mixer_cnt) {
+		pr_err("%s, no dspp connects to disp %d",
+			__func__, disp_num);
+		ret = -EPERM;
+		goto hist_collect_exit;
+	}
+	if (mixer_cnt >= MDSS_MDP_MAX_DSPP) {
+		pr_err("%s, Too many dspp connects to disp %d",
+			__func__, mixer_cnt);
+		ret = -EPERM;
+		goto hist_collect_exit;
+	}
+	hist_info = &mdss_pp_res->dspp_hist[0];
+	for (i = 0; i < mixer_cnt; i++) {
+		dspp_num = mixer_id[i];
+		hist_info = &mdss_pp_res->dspp_hist[dspp_num];
+		ctl_base = MDSS_MDP_REG_DSPP_OFFSET(dspp_num) +
+			  MDSS_MDP_REG_DSPP_HIST_CTL_BASE;
+		if ((hist_info->col_en == 0) ||
+			(hist_info->col_state == HIST_UNKNOWN)) {
+			ret = -EINVAL;
+			goto hist_collect_exit;
+		}
+		spin_lock(&mdss_hist_lock);
+		if ((hist_info->col_state == HIST_READY) ||
+			(hist_info->hist_cnt_read == 0)) {
+			/* wait for hist done if cache has no data */
+			if ((hist_info->col_state != HIST_READY) &&
+				(hist_info->hist_cnt_read == 0)) {
+				hist_info->read_request = true;
+				spin_unlock(&mdss_hist_lock);
+				timeout = HIST_WAIT_TIMEOUT *
+					hist_info->frame_cnt;
+				mutex_unlock(&mdss_mdp_hist_mutex);
+				wait_ret = wait_for_completion_killable_timeout(
+					&(hist_info->comp), timeout);
+
+				mutex_lock(&mdss_mdp_hist_mutex);
+				hist_info->read_request = false;
+				if (wait_ret == 0) {
+					ret = -ETIMEDOUT;
+					pr_debug("%s: bin collection timedout",
+						__func__);
+					goto hist_collect_exit;
+				} else if (wait_ret < 0) {
+					ret = -EINTR;
+					pr_debug("%s: bin collection interrupted",
+						__func__);
+					goto hist_collect_exit;
+				}
+				if (hist_info->col_state != HIST_READY) {
+					ret = -EBUSY;
+					pr_err("%s: collection state is not ready: %d",
+						__func__, hist_info->col_state);
+					goto hist_collect_exit;
+				}
+			} else {
+				spin_unlock(&mdss_hist_lock);
+			}
+			if (hist_info->col_state == HIST_READY) {
+				v_base = ctl_base + 0x1C;
+				mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_ON, false);
+				pp_hist_read(v_base, hist_info);
+				mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_OFF, false);
+				spin_lock(&mdss_hist_lock);
+				hist_info->col_state = HIST_IDLE;
+				spin_unlock(&mdss_hist_lock);
+			}
+		} else {
+			spin_unlock(&mdss_hist_lock);
+		}
+		hist_info->hist_cnt_sent = hist_info->hist_cnt_read;
+	}
+	if (mixer_cnt > 1) {
+		memset(&mdss_pp_res->hist_data[disp_num][0],
+			0, HIST_V_SIZE * sizeof(u32));
+		for (i = 0; i < mixer_cnt; i++) {
+			dspp_num = mixer_id[i];
+			hist_info = &mdss_pp_res->dspp_hist[dspp_num];
+			for (j = 0; j < HIST_V_SIZE; j++)
+				mdss_pp_res->hist_data[disp_num][i] +=
+					hist_info->data[i];
+		}
+		*hist_data_addr = (u32)&mdss_pp_res->hist_data[disp_num][0];
+	} else {
+		*hist_data_addr = (u32)hist_info->data;
+	}
+
+hist_collect_exit:
+	mutex_unlock(&mdss_mdp_hist_mutex);
+	return ret;
+}
+void mdss_mdp_hist_intr_done(u32 isr)
+{
+	u32 isr_blk, blk_idx;
+	struct pp_hist_col_info *hist_info;
+	isr &= 0x333333;
+	while (isr != 0) {
+		if (isr & 0xFFF000) {
+			if (isr & 0x3000) {
+				blk_idx = 0;
+				isr_blk = (isr >> 12) & 0x3;
+				isr &= ~0x3000;
+			} else if (isr & 0x30000) {
+				blk_idx = 1;
+				isr_blk = (isr >> 16) & 0x3;
+				isr &= ~0x30000;
+			} else {
+				blk_idx = 2;
+				isr_blk = (isr >> 20) & 0x3;
+				isr &= ~0x300000;
+			}
+			hist_info = &mdss_pp_res->dspp_hist[blk_idx];
+		} else {
+			if (isr & 0x3) {
+				blk_idx = 0;
+				isr_blk = isr & 0x3;
+				isr &= ~0x3;
+			} else if (isr & 0x30) {
+				blk_idx = 1;
+				isr_blk = (isr >> 4) & 0x3;
+				isr &= ~0x30;
+			} else {
+				blk_idx = 2;
+				isr_blk = (isr >> 8) & 0x3;
+				isr &= ~0x300;
+			}
+			/* SSPP block, not support yet*/
+			continue;
+		}
+		/* Histogram Done Interrupt */
+		if ((isr_blk & 0x1) &&
+			(hist_info->col_en)) {
+			spin_lock(&mdss_hist_lock);
+			hist_info->col_state = HIST_READY;
+			spin_unlock(&mdss_hist_lock);
+			if (hist_info->read_request)
+				complete(&hist_info->comp);
+		}
+		/* Histogram Reset Done Interrupt */
+		if ((isr_blk & 0x2) &&
+			(hist_info->col_en)) {
+				spin_lock(&mdss_hist_lock);
+				hist_info->col_state = HIST_IDLE;
+				spin_unlock(&mdss_hist_lock);
+		}
+	};
+}
diff --git a/drivers/video/msm/mdss/mdss_mdp_util.c b/drivers/video/msm/mdss/mdss_mdp_util.c
index 57e8441..aa65018 100644
--- a/drivers/video/msm/mdss/mdss_mdp_util.c
+++ b/drivers/video/msm/mdss/mdss_mdp_util.c
@@ -112,22 +112,22 @@
 
 irqreturn_t mdss_mdp_isr(int irq, void *ptr)
 {
-	u32 isr, mask;
+	u32 isr, mask, hist_isr, hist_mask;
 
 
 	isr = MDSS_MDP_REG_READ(MDSS_MDP_REG_INTR_STATUS);
 
-	pr_debug("isr=%x\n", isr);
-
 	if (isr == 0)
-		goto done;
+		goto mdp_isr_done;
+
+	pr_debug("isr=%x\n", isr);
 
 	mask = MDSS_MDP_REG_READ(MDSS_MDP_REG_INTR_EN);
 	MDSS_MDP_REG_WRITE(MDSS_MDP_REG_INTR_CLEAR, isr);
 
 	isr &= mask;
 	if (isr == 0)
-		goto done;
+		goto mdp_isr_done;
 
 	if (isr & MDSS_MDP_INTR_PING_PONG_0_DONE)
 		mdss_mdp_intr_done(MDP_INTR_PING_PONG_0);
@@ -159,7 +159,17 @@
 	if (isr & MDSS_MDP_INTR_WB_2_DONE)
 		mdss_mdp_intr_done(MDP_INTR_WB_2);
 
-done:
+mdp_isr_done:
+	hist_isr = MDSS_MDP_REG_READ(MDSS_MDP_REG_HIST_INTR_STATUS);
+	if (hist_isr == 0)
+		goto hist_isr_done;
+	hist_mask = MDSS_MDP_REG_READ(MDSS_MDP_REG_HIST_INTR_EN);
+	MDSS_MDP_REG_WRITE(MDSS_MDP_REG_HIST_INTR_CLEAR, hist_isr);
+	hist_isr &= hist_mask;
+	if (hist_isr == 0)
+		goto hist_isr_done;
+	mdss_mdp_hist_intr_done(hist_isr);
+hist_isr_done:
 	return IRQ_HANDLED;
 }
 
diff --git a/drivers/video/msm/mdss/mdss_mdp_wb.c b/drivers/video/msm/mdss/mdss_mdp_wb.c
index b0a67938..b18efbe 100644
--- a/drivers/video/msm/mdss/mdss_mdp_wb.c
+++ b/drivers/video/msm/mdss/mdss_mdp_wb.c
@@ -86,13 +86,13 @@
 
 
 		ihdl = ion_alloc(iclient, img_size, SZ_4K,
-				 ION_HEAP(ION_SF_HEAP_ID));
+				 ION_HEAP(ION_SF_HEAP_ID), 0);
 		if (IS_ERR_OR_NULL(ihdl)) {
 			pr_err("unable to alloc fbmem from ion (%p)\n", ihdl);
 			return NULL;
 		}
 
-		videomemory = ion_map_kernel(iclient, ihdl, 0);
+		videomemory = ion_map_kernel(iclient, ihdl);
 		ion_phys(iclient, ihdl, &mdss_wb_mem, &img_size);
 
 		if (is_mdss_iommu_attached()) {
diff --git a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_helper.c b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_helper.c
index d4601f2..1782fd2 100644
--- a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_helper.c
+++ b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_helper.c
@@ -278,7 +278,8 @@
 				memset(frame[i].vcd_frm.virtual + luma_size,
 					 0x80808080,
 					frame[i].vcd_frm.alloc_len - luma_size);
-				if (frame[i].vcd_frm.ion_flag == CACHED) {
+				if (frame[i].vcd_frm.ion_flag
+					== ION_FLAG_CACHED) {
 					msm_ion_do_cache_op(
 					ddl_context->video_ion_client,
 					frame[i].vcd_frm.buff_ion_handle,
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 596c86f..931c1c8 100644
--- a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_properties.c
+++ b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_properties.c
@@ -1859,6 +1859,7 @@
 	struct vcd_buffer_requirement *input_buf_req;
 	struct vcd_buffer_requirement *output_buf_req;
 	u32  min_dpb, y_cb_cr_size;
+	u32  frame_height_actual = 0;
 
 	if (!decoder->codec.codec)
 		return false;
@@ -1882,6 +1883,7 @@
 		if ((decoder->buf_format.buffer_format ==
 			VCD_BUFFER_FORMAT_TILE_4x2) &&
 			(frame_size->height < MDP_MIN_TILE_HEIGHT)) {
+			frame_height_actual = frame_size->height;
 			frame_size->height = MDP_MIN_TILE_HEIGHT;
 			ddl_calculate_stride(frame_size,
 				!decoder->progressive_only);
@@ -1920,6 +1922,10 @@
 	input_buf_req->sz = (1024 * 1024 * 2);
 	input_buf_req->align = DDL_LINEAR_BUFFER_ALIGN_BYTES;
 	decoder->min_input_buf_req = *input_buf_req;
+	if (frame_height_actual) {
+		frame_size->height = frame_height_actual;
+		ddl_calculate_stride(frame_size, !decoder->progressive_only);
+	}
 	return true;
 }
 
diff --git a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_utils.c b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_utils.c
index 5897a33..31f60e5 100644
--- a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_utils.c
+++ b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_utils.c
@@ -45,7 +45,6 @@
 	unsigned long iova = 0;
 	unsigned long buffer_size = 0;
 	unsigned long *kernel_vaddr = NULL;
-	unsigned long ionflag = 0;
 	unsigned long flags = 0;
 	int ret = 0;
 	ion_phys_addr_t phyaddr = 0;
@@ -71,20 +70,15 @@
 		alloc_size = (alloc_size+4095) & ~4095;
 		addr->alloc_handle = ion_alloc(
 		ddl_context->video_ion_client, alloc_size, SZ_4K,
-			res_trk_get_mem_type());
+			res_trk_get_mem_type(), 0);
 		if (IS_ERR_OR_NULL(addr->alloc_handle)) {
 			DDL_MSG_ERROR("%s() :DDL ION alloc failed\n",
 						 __func__);
 			goto bail_out;
 		}
-		if (res_trk_check_for_sec_session() ||
-			addr->mem_type == DDL_FW_MEM)
-			ionflag = UNCACHED;
-		else
-			ionflag = CACHED;
 		kernel_vaddr = (unsigned long *) ion_map_kernel(
 					ddl_context->video_ion_client,
-					addr->alloc_handle, ionflag);
+					addr->alloc_handle);
 		if (IS_ERR_OR_NULL(kernel_vaddr)) {
 				DDL_MSG_ERROR("%s() :DDL ION map failed\n",
 							 __func__);
@@ -111,7 +105,7 @@
 					0,
 					&iova,
 					&buffer_size,
-					UNCACHED, 0);
+					0, 0);
 			if (ret || !iova) {
 				DDL_MSG_ERROR(
 				"%s():DDL ION ion map iommu failed, ret = %d iova = 0x%lx\n",
diff --git a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_vidc.c b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_vidc.c
index 978d1de..4687915 100644
--- a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_vidc.c
+++ b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_vidc.c
@@ -15,6 +15,7 @@
 #include "vcd_ddl_metadata.h"
 #include "vcd_ddl_shared_mem.h"
 #include "vcd_core.h"
+#include "vcd_res_tracker_api.h"
 
 #if defined(PIX_CACHE_DISABLE)
 #define DDL_PIX_CACHE_ENABLE  false
@@ -108,7 +109,8 @@
 		dec_pix_cache = VIDC_1080P_DECODE_PCACHE_DISABLE;
 	const enum vidc_1080p_encode_p_cache_enable
 		enc_pix_cache = VIDC_1080P_ENCODE_PCACHE_ENABLE;
-	u32 pix_cache_ctrl, ctxt_mem_offset, ctxt_mem_size;
+	u32 pix_cache_ctrl, ctxt_mem_offset, ctxt_mem_size, arg1 = 0;
+	u8 *hw_ctxt = NULL;
 
 	if (ddl->decoding) {
 		ddl_set_core_start_time(__func__, DEC_OP_TIME);
@@ -116,6 +118,8 @@
 		pix_cache_ctrl = (u32)dec_pix_cache;
 		ctxt_mem_offset = DDL_ADDR_OFFSET(ddl_context->dram_base_a,
 		ddl->codec_data.decoder.hw_bufs.context) >> 11;
+		hw_ctxt =
+		ddl->codec_data.decoder.hw_bufs.context.virtual_base_addr;
 		ctxt_mem_size =
 			ddl->codec_data.decoder.hw_bufs.context.buffer_size;
 	} else {
@@ -123,9 +127,15 @@
 		pix_cache_ctrl = (u32)enc_pix_cache;
 		ctxt_mem_offset = DDL_ADDR_OFFSET(ddl_context->dram_base_a,
 			ddl->codec_data.encoder.hw_bufs.context) >> 11;
+		hw_ctxt =
+		ddl->codec_data.encoder.hw_bufs.context.virtual_base_addr;
 		ctxt_mem_size =
 			ddl->codec_data.encoder.hw_bufs.context.buffer_size;
 	}
+	if (!res_trk_check_for_sec_session() && hw_ctxt) {
+		memset(hw_ctxt, 0, ctxt_mem_size);
+		arg1 = 1 << 29;
+	}
 	switch (*vcd_codec) {
 	default:
 	case VCD_CODEC_MPEG4:
@@ -184,8 +194,9 @@
 	DDL_MSG_LOW("ddl_state_transition: %s ~~> DDL_CLIENT_WAIT_FOR_CHDONE",
 	ddl_get_state_string(ddl->client_state));
 	ddl->client_state = DDL_CLIENT_WAIT_FOR_CHDONE;
+	arg1 |= (u32)codec;
 	vidc_1080p_set_host2risc_cmd(VIDC_1080P_HOST2RISC_CMD_OPEN_CH,
-		(u32)codec, pix_cache_ctrl, ctxt_mem_offset,
+		arg1, pix_cache_ctrl, ctxt_mem_offset,
 		ctxt_mem_size);
 }
 
diff --git a/drivers/video/msm/vidc/1080p/resource_tracker/vcd_res_tracker.c b/drivers/video/msm/vidc/1080p/resource_tracker/vcd_res_tracker.c
index 3ac396c..f68802e 100644
--- a/drivers/video/msm/vidc/1080p/resource_tracker/vcd_res_tracker.c
+++ b/drivers/video/msm/vidc/1080p/resource_tracker/vcd_res_tracker.c
@@ -69,7 +69,7 @@
 	if (res_trk_get_enable_ion() && addr->alloc_handle) {
 		kernel_vaddr = (unsigned long *) ion_map_kernel(
 					ddl_context->video_ion_client,
-					addr->alloc_handle, UNCACHED);
+					addr->alloc_handle);
 		if (IS_ERR_OR_NULL(kernel_vaddr)) {
 			DDL_MSG_ERROR("%s():DDL ION client map failed\n",
 						 __func__);
@@ -84,7 +84,7 @@
 				0,
 				&iova,
 				&buffer_size,
-				UNCACHED, 0);
+				0, 0);
 		if (ret || !iova) {
 			DDL_MSG_ERROR(
 			"%s():DDL ION client iommu map failed, ret = %d iova = 0x%lx\n",
@@ -209,7 +209,7 @@
 			addr->alloc_handle = ion_alloc(
 					ddl_context->video_ion_client,
 					 alloc_size, SZ_4K,
-					res_trk_get_mem_type());
+					res_trk_get_mem_type(), 0);
 			if (IS_ERR_OR_NULL(addr->alloc_handle)) {
 				DDL_MSG_ERROR("%s() :DDL ION alloc failed\n",
 						__func__);
diff --git a/drivers/video/msm/vidc/720p/ddl/vcd_ddl_utils.c b/drivers/video/msm/vidc/720p/ddl/vcd_ddl_utils.c
index 21f01d1..3b40640 100644
--- a/drivers/video/msm/vidc/720p/ddl/vcd_ddl_utils.c
+++ b/drivers/video/msm/vidc/720p/ddl/vcd_ddl_utils.c
@@ -124,7 +124,7 @@
 					ddl_context->video_ion_client,
 					alloc_size,
 					SZ_4K,
-					buff_addr->mem_type);
+					buff_addr->mem_type, 0);
 		if (!buff_addr->alloc_handle) {
 			ERR("\n%s(): DDL ION alloc failed\n",
 					__func__);
@@ -142,8 +142,7 @@
 		buff_addr->physical_base_addr = (u32 *)phyaddr;
 		kernel_vaddr = (unsigned long *) ion_map_kernel(
 					ddl_context->video_ion_client,
-					buff_addr->alloc_handle,
-					UNCACHED);
+					buff_addr->alloc_handle);
 		if (IS_ERR_OR_NULL(kernel_vaddr)) {
 			ERR("\n%s(): DDL ION map failed\n", __func__);
 			goto unmap_ion_buffer;
diff --git a/drivers/video/msm/vidc/common/dec/vdec.c b/drivers/video/msm/vidc/common/dec/vdec.c
index 68bcd5c..59e19b7 100644
--- a/drivers/video/msm/vidc/common/dec/vdec.c
+++ b/drivers/video/msm/vidc/common/dec/vdec.c
@@ -347,7 +347,7 @@
 		ion_flag = vidc_get_fd_info(client_ctx, BUFFER_TYPE_OUTPUT,
 				pmem_fd, kernel_vaddr, buffer_index,
 				&buff_handle);
-		if (ion_flag == CACHED && buff_handle) {
+		if (ion_flag == ION_FLAG_CACHED && buff_handle) {
 			DBG("%s: Cache invalidate: vaddr (%p), "\
 				"size %u\n", __func__,
 				(void *)kernel_vaddr,
@@ -908,8 +908,7 @@
 		}
 		vcd_h264_mv_buffer->kernel_virtual_addr = (u8 *) ion_map_kernel(
 			client_ctx->user_ion_client,
-			client_ctx->h264_mv_ion_handle,
-			ionflag);
+			client_ctx->h264_mv_ion_handle);
 		if (!vcd_h264_mv_buffer->kernel_virtual_addr) {
 			ERR("%s(): get_ION_kernel virtual addr failed\n",
 				 __func__);
@@ -935,7 +934,7 @@
 					VIDEO_DOMAIN, VIDEO_MAIN_POOL,
 					SZ_4K, 0, (unsigned long *)&iova,
 					(unsigned long *)&buffer_size,
-					UNCACHED, 0);
+					0, 0);
 			if (rc || !iova) {
 				ERR(
 				"%s():get_ION_kernel physical addr fail, rc = %d iova = 0x%lx\n",
@@ -1298,7 +1297,7 @@
 						kernel_vaddr,
 						buffer_index,
 						&buff_handle);
-			if (ion_flag == CACHED && buff_handle) {
+			if (ion_flag == ION_FLAG_CACHED && buff_handle) {
 				msm_ion_do_cache_op(client_ctx->user_ion_client,
 				buff_handle,
 				(unsigned long *)kernel_vaddr,
@@ -1812,7 +1811,7 @@
 			}
 			ker_vaddr = (unsigned long) ion_map_kernel(
 				client_ctx->user_ion_client,
-				client_ctx->seq_hdr_ion_handle, ionflag);
+				client_ctx->seq_hdr_ion_handle);
 			if (!ker_vaddr) {
 				ERR("%s():get_ION_kernel virtual addr fail\n",
 							 __func__);
diff --git a/drivers/video/msm/vidc/common/enc/venc.c b/drivers/video/msm/vidc/common/enc/venc.c
index 67917b9..c7237e4 100644
--- a/drivers/video/msm/vidc/common/enc/venc.c
+++ b/drivers/video/msm/vidc/common/enc/venc.c
@@ -267,7 +267,7 @@
 		ion_flag = vidc_get_fd_info(client_ctx, BUFFER_TYPE_OUTPUT,
 					pmem_fd, kernel_vaddr, buffer_index,
 					&buff_handle);
-		if (ion_flag == CACHED && buff_handle) {
+		if (ion_flag == ION_FLAG_CACHED && buff_handle) {
 			msm_ion_do_cache_op(client_ctx->user_ion_client,
 				buff_handle,
 				(unsigned long *) kernel_vaddr,
diff --git a/drivers/video/msm/vidc/common/enc/venc_internal.c b/drivers/video/msm/vidc/common/enc/venc_internal.c
index 5ee0a3d..8779432 100644
--- a/drivers/video/msm/vidc/common/enc/venc_internal.c
+++ b/drivers/video/msm/vidc/common/enc/venc_internal.c
@@ -1688,7 +1688,7 @@
 				&buff_handle);
 
 		if (vcd_input_buffer.data_len > 0) {
-			if (ion_flag == CACHED && buff_handle) {
+			if (ion_flag == ION_FLAG_CACHED && buff_handle) {
 				msm_ion_do_cache_op(
 				client_ctx->user_ion_client,
 				buff_handle,
@@ -1837,8 +1837,7 @@
 		}
 		control->kernel_virtual_addr = (u8 *) ion_map_kernel(
 			client_ctx->user_ion_client,
-			client_ctx->recon_buffer_ion_handle[i],
-			ionflag);
+			client_ctx->recon_buffer_ion_handle[i]);
 		if (!control->kernel_virtual_addr) {
 			ERR("%s(): get_ION_kernel virtual addr fail\n",
 				 __func__);
@@ -1867,7 +1866,7 @@
 					0,
 					(unsigned long *)&iova,
 					(unsigned long *)&buffer_size,
-					UNCACHED, 0);
+					0, 0);
 			if (rc || !iova) {
 				ERR(
 				"%s():ION map iommu addr fail, rc = %d, iova = 0x%lx\n",
diff --git a/drivers/video/msm/vidc/common/init/vidc_init.c b/drivers/video/msm/vidc/common/init/vidc_init.c
index 221c154..65dde68 100644
--- a/drivers/video/msm/vidc/common/init/vidc_init.c
+++ b/drivers/video/msm/vidc/common/init/vidc_init.c
@@ -647,8 +647,7 @@
 			*kernel_vaddr = (unsigned long)
 				ion_map_kernel(
 				client_ctx->user_ion_client,
-				buff_ion_handle,
-				ionflag);
+				buff_ion_handle);
 			if (IS_ERR_OR_NULL((void *)*kernel_vaddr)) {
 				ERR("%s():ION virtual addr fail\n",
 				 __func__);
@@ -678,7 +677,7 @@
 						length,
 						(unsigned long *) &iova,
 						(unsigned long *) &buffer_size,
-						UNCACHED,
+						0,
 						ION_IOMMU_UNMAP_DELAYED);
 				if (ret || !iova) {
 					ERR(
diff --git a/drivers/video/msm/vidc/common/vcd/vcd_sub.c b/drivers/video/msm/vidc/common/vcd/vcd_sub.c
index 71e8df8..6e332ef 100644
--- a/drivers/video/msm/vidc/common/vcd/vcd_sub.c
+++ b/drivers/video/msm/vidc/common/vcd/vcd_sub.c
@@ -92,7 +92,7 @@
 	} else {
 		map_buffer->alloc_handle = ion_alloc(
 			    cctxt->vcd_ion_client, sz, SZ_4K,
-			    memtype);
+			    memtype, 0);
 		if (!map_buffer->alloc_handle) {
 			pr_err("%s() ION alloc failed", __func__);
 			goto bailout;
@@ -105,8 +105,7 @@
 		}
 		*kernel_vaddr = (u8 *) ion_map_kernel(
 				cctxt->vcd_ion_client,
-				map_buffer->alloc_handle,
-				ionflag);
+				map_buffer->alloc_handle);
 		if (!(*kernel_vaddr)) {
 			pr_err("%s() ION map failed", __func__);
 			goto ion_free_bailout;
@@ -120,7 +119,7 @@
 				0,
 				(unsigned long *)&iova,
 				(unsigned long *)&buffer_size,
-				UNCACHED, 0);
+				0, 0);
 			if (ret || !iova) {
 				pr_err(
 				"%s() ION iommu map failed, ret = %d, iova = 0x%lx",
diff --git a/include/linux/ion.h b/include/linux/ion.h
index 6ac2835..85bb182 100644
--- a/include/linux/ion.h
+++ b/include/linux/ion.h
@@ -51,6 +51,14 @@
 #define ION_HEAP_CARVEOUT_MASK		(1 << ION_HEAP_TYPE_CARVEOUT)
 #define ION_HEAP_CP_MASK		(1 << ION_HEAP_TYPE_CP)
 
+/**
+ * heap flags - the lower 16 bits are used by core ion, the upper 16
+ * bits are reserved for use by the heaps themselves.
+ */
+#define ION_FLAG_CACHED 1		/* mappings of this buffer should be
+					   cached, ion will do cache
+					   maintenance when the buffer is
+					   mapped for dma */
 
 /**
  * These are the only ids that should be used for Ion heap ids.
@@ -115,14 +123,11 @@
 #define ION_QSECOM_HEAP_NAME	"qsecom"
 #define ION_FMEM_HEAP_NAME	"fmem"
 
-#define CACHED          1
-#define UNCACHED        0
+#define ION_SET_CACHED(__cache)		(__cache | ION_FLAG_CACHED)
+#define ION_SET_UNCACHED(__cache)	(__cache & ~ION_FLAG_CACHED)
 
-#define ION_CACHE_SHIFT 0
+#define ION_IS_CACHED(__flags)	((__flags) & ION_FLAG_CACHED)
 
-#define ION_SET_CACHE(__cache)  ((__cache) << ION_CACHE_SHIFT)
-
-#define ION_IS_CACHED(__flags)	((__flags) & (1 << ION_CACHE_SHIFT))
 
 /*
  * This flag allows clients when mapping into the IOMMU to specify to
@@ -305,14 +310,18 @@
  * @len:	size of the allocation
  * @align:	requested allocation alignment, lots of hardware blocks have
  *		alignment requirements of some kind
- * @flags:	mask of heaps to allocate from, if multiple bits are set
+ * @heap_mask:	mask of heaps to allocate from, if multiple bits are set
  *		heaps will be tried in order from lowest to highest order bit
+ * @flags:	heap flags, the low 16 bits are consumed by ion, the high 16
+ *		bits are passed on to the respective heap and can be heap
+ *		custom
  *
  * Allocate memory in one of the heaps provided in heap mask and return
  * an opaque handle to it.
  */
 struct ion_handle *ion_alloc(struct ion_client *client, size_t len,
-			     size_t align, unsigned int flags);
+			     size_t align, unsigned int heap_mask,
+			     unsigned int flags);
 
 /**
  * ion_free - free a handle
@@ -363,8 +372,7 @@
  * can be used to access this address. If no flags are specified, this
  * will return a non-secure uncached mapping.
  */
-void *ion_map_kernel(struct ion_client *client, struct ion_handle *handle,
-			unsigned long flags);
+void *ion_map_kernel(struct ion_client *client, struct ion_handle *handle);
 
 /**
  * ion_unmap_kernel() - destroy a kernel mapping for a handle
@@ -418,7 +426,6 @@
  *		address space will be mapped to a dummy buffer.
  * @iova - pointer to store the iova address
  * @buffer_size - pointer to store the size of the buffer
- * @flags - flags for options to map
  * @iommu_flags - flags specific to the iommu.
  *
  * Maps the handle into the iova space specified via domain number. Iova
@@ -574,7 +581,9 @@
 static inline void ion_client_destroy(struct ion_client *client) { }
 
 static inline struct ion_handle *ion_alloc(struct ion_client *client,
-			size_t len, size_t align, unsigned int flags)
+					size_t len, size_t align,
+					unsigned int heap_mask,
+					unsigned int flags)
 {
 	return ERR_PTR(-ENODEV);
 }
@@ -695,6 +704,7 @@
  * struct ion_allocation_data - metadata passed from userspace for allocations
  * @len:	size of the allocation
  * @align:	required alignment of the allocation
+ * @heap_mask:	mask of heaps to allocate from
  * @flags:	flags passed to heap
  * @handle:	pointer that will be populated with a cookie to use to refer
  *		to this allocation
diff --git a/include/linux/mfd/wcd9xxx/core.h b/include/linux/mfd/wcd9xxx/core.h
index f6d164d..c306c75 100644
--- a/include/linux/mfd/wcd9xxx/core.h
+++ b/include/linux/mfd/wcd9xxx/core.h
@@ -37,6 +37,12 @@
 #define SITAR_IS_1P1(ver) \
 	((ver == SITAR_VERSION_1P1) ? 1 : 0)
 
+
+#define TAIKO_VERSION_1_0	0
+#define TAIKO_IS_1_0(ver) \
+	((ver == TAIKO_VERSION_1_0) ? 1 : 0)
+
+
 enum {
 	TABLA_IRQ_SLIMBUS = 0,
 	TABLA_IRQ_MBHC_REMOVAL,
diff --git a/include/linux/mfd/wcd9xxx/wcd9320_registers.h b/include/linux/mfd/wcd9xxx/wcd9320_registers.h
index 5725e6e..4b8626a 100644
--- a/include/linux/mfd/wcd9xxx/wcd9320_registers.h
+++ b/include/linux/mfd/wcd9xxx/wcd9320_registers.h
@@ -701,45 +701,45 @@
 #define TAIKO_A_CDC_TX10_VOL_CTL_CFG			(0x26A)
 #define TAIKO_A_CDC_TX10_VOL_CTL_CFG__POR				(0x00)
 #define TAIKO_A_CDC_TX1_MUX_CTL			(0x223)
-#define TAIKO_A_CDC_TX1_MUX_CTL__POR				(0x00)
+#define TAIKO_A_CDC_TX1_MUX_CTL__POR				(0x08)
 #define TAIKO_A_CDC_TX2_MUX_CTL			(0x22B)
-#define TAIKO_A_CDC_TX2_MUX_CTL__POR				(0x00)
+#define TAIKO_A_CDC_TX2_MUX_CTL__POR				(0x08)
 #define TAIKO_A_CDC_TX3_MUX_CTL			(0x233)
-#define TAIKO_A_CDC_TX3_MUX_CTL__POR				(0x00)
+#define TAIKO_A_CDC_TX3_MUX_CTL__POR				(0x08)
 #define TAIKO_A_CDC_TX4_MUX_CTL			(0x23B)
-#define TAIKO_A_CDC_TX4_MUX_CTL__POR				(0x00)
+#define TAIKO_A_CDC_TX4_MUX_CTL__POR				(0x08)
 #define TAIKO_A_CDC_TX5_MUX_CTL			(0x243)
-#define TAIKO_A_CDC_TX5_MUX_CTL__POR				(0x00)
+#define TAIKO_A_CDC_TX5_MUX_CTL__POR				(0x08)
 #define TAIKO_A_CDC_TX6_MUX_CTL			(0x24B)
-#define TAIKO_A_CDC_TX6_MUX_CTL__POR				(0x00)
+#define TAIKO_A_CDC_TX6_MUX_CTL__POR				(0x08)
 #define TAIKO_A_CDC_TX7_MUX_CTL			(0x253)
-#define TAIKO_A_CDC_TX7_MUX_CTL__POR				(0x00)
+#define TAIKO_A_CDC_TX7_MUX_CTL__POR				(0x08)
 #define TAIKO_A_CDC_TX8_MUX_CTL			(0x25B)
-#define TAIKO_A_CDC_TX8_MUX_CTL__POR				(0x00)
+#define TAIKO_A_CDC_TX8_MUX_CTL__POR				(0x08)
 #define TAIKO_A_CDC_TX9_MUX_CTL			(0x263)
-#define TAIKO_A_CDC_TX9_MUX_CTL__POR				(0x00)
+#define TAIKO_A_CDC_TX9_MUX_CTL__POR				(0x08)
 #define TAIKO_A_CDC_TX10_MUX_CTL			(0x26B)
-#define TAIKO_A_CDC_TX10_MUX_CTL__POR				(0x00)
+#define TAIKO_A_CDC_TX10_MUX_CTL__POR				(0x08)
 #define TAIKO_A_CDC_TX1_CLK_FS_CTL			(0x224)
-#define TAIKO_A_CDC_TX1_CLK_FS_CTL__POR				(0x00)
+#define TAIKO_A_CDC_TX1_CLK_FS_CTL__POR				(0x03)
 #define TAIKO_A_CDC_TX2_CLK_FS_CTL			(0x22C)
-#define TAIKO_A_CDC_TX2_CLK_FS_CTL__POR				(0x00)
+#define TAIKO_A_CDC_TX2_CLK_FS_CTL__POR				(0x03)
 #define TAIKO_A_CDC_TX3_CLK_FS_CTL			(0x234)
-#define TAIKO_A_CDC_TX3_CLK_FS_CTL__POR				(0x00)
+#define TAIKO_A_CDC_TX3_CLK_FS_CTL__POR				(0x03)
 #define TAIKO_A_CDC_TX4_CLK_FS_CTL			(0x23C)
-#define TAIKO_A_CDC_TX4_CLK_FS_CTL__POR				(0x00)
+#define TAIKO_A_CDC_TX4_CLK_FS_CTL__POR				(0x03)
 #define TAIKO_A_CDC_TX5_CLK_FS_CTL			(0x244)
-#define TAIKO_A_CDC_TX5_CLK_FS_CTL__POR				(0x00)
+#define TAIKO_A_CDC_TX5_CLK_FS_CTL__POR				(0x03)
 #define TAIKO_A_CDC_TX6_CLK_FS_CTL			(0x24C)
-#define TAIKO_A_CDC_TX6_CLK_FS_CTL__POR				(0x00)
+#define TAIKO_A_CDC_TX6_CLK_FS_CTL__POR				(0x03)
 #define TAIKO_A_CDC_TX7_CLK_FS_CTL			(0x254)
-#define TAIKO_A_CDC_TX7_CLK_FS_CTL__POR				(0x00)
+#define TAIKO_A_CDC_TX7_CLK_FS_CTL__POR				(0x03)
 #define TAIKO_A_CDC_TX8_CLK_FS_CTL			(0x25C)
-#define TAIKO_A_CDC_TX8_CLK_FS_CTL__POR				(0x00)
+#define TAIKO_A_CDC_TX8_CLK_FS_CTL__POR				(0x03)
 #define TAIKO_A_CDC_TX9_CLK_FS_CTL			(0x264)
-#define TAIKO_A_CDC_TX9_CLK_FS_CTL__POR				(0x00)
+#define TAIKO_A_CDC_TX9_CLK_FS_CTL__POR				(0x03)
 #define TAIKO_A_CDC_TX10_CLK_FS_CTL			(0x26C)
-#define TAIKO_A_CDC_TX10_CLK_FS_CTL__POR				(0x00)
+#define TAIKO_A_CDC_TX10_CLK_FS_CTL__POR				(0x03)
 #define TAIKO_A_CDC_TX1_DMIC_CTL			(0x225)
 #define TAIKO_A_CDC_TX1_DMIC_CTL__POR				(0x00)
 #define TAIKO_A_CDC_TX2_DMIC_CTL			(0x22D)
@@ -779,9 +779,9 @@
 #define TAIKO_A_CDC_SRC2_PDA_CFG			(0x2A8)
 #define TAIKO_A_CDC_SRC2_PDA_CFG__POR				(0x00)
 #define TAIKO_A_CDC_SRC1_FS_CTL			(0x2A1)
-#define TAIKO_A_CDC_SRC1_FS_CTL__POR				(0x00)
+#define TAIKO_A_CDC_SRC1_FS_CTL__POR				(0x1B)
 #define TAIKO_A_CDC_SRC2_FS_CTL			(0x2A9)
-#define TAIKO_A_CDC_SRC2_FS_CTL__POR				(0x00)
+#define TAIKO_A_CDC_SRC2_FS_CTL__POR				(0x1B)
 #define TAIKO_A_CDC_RX1_B1_CTL			(0x2B0)
 #define TAIKO_A_CDC_RX1_B1_CTL__POR				(0x00)
 #define TAIKO_A_CDC_RX2_B1_CTL			(0x2B8)
@@ -839,33 +839,33 @@
 #define TAIKO_A_CDC_RX7_B4_CTL			(0x2E3)
 #define TAIKO_A_CDC_RX7_B4_CTL__POR				(0x00)
 #define TAIKO_A_CDC_RX1_B5_CTL			(0x2B4)
-#define TAIKO_A_CDC_RX1_B5_CTL__POR				(0x00)
+#define TAIKO_A_CDC_RX1_B5_CTL__POR				(0x78)
 #define TAIKO_A_CDC_RX2_B5_CTL			(0x2BC)
-#define TAIKO_A_CDC_RX2_B5_CTL__POR				(0x00)
+#define TAIKO_A_CDC_RX2_B5_CTL__POR				(0x78)
 #define TAIKO_A_CDC_RX3_B5_CTL			(0x2C4)
-#define TAIKO_A_CDC_RX3_B5_CTL__POR				(0x00)
+#define TAIKO_A_CDC_RX3_B5_CTL__POR				(0x78)
 #define TAIKO_A_CDC_RX4_B5_CTL			(0x2CC)
-#define TAIKO_A_CDC_RX4_B5_CTL__POR				(0x00)
+#define TAIKO_A_CDC_RX4_B5_CTL__POR				(0x78)
 #define TAIKO_A_CDC_RX5_B5_CTL			(0x2D4)
-#define TAIKO_A_CDC_RX5_B5_CTL__POR				(0x00)
+#define TAIKO_A_CDC_RX5_B5_CTL__POR				(0x78)
 #define TAIKO_A_CDC_RX6_B5_CTL			(0x2DC)
-#define TAIKO_A_CDC_RX6_B5_CTL__POR				(0x00)
+#define TAIKO_A_CDC_RX6_B5_CTL__POR				(0x78)
 #define TAIKO_A_CDC_RX7_B5_CTL			(0x2E4)
-#define TAIKO_A_CDC_RX7_B5_CTL__POR				(0x00)
+#define TAIKO_A_CDC_RX7_B5_CTL__POR				(0x78)
 #define TAIKO_A_CDC_RX1_B6_CTL			(0x2B5)
-#define TAIKO_A_CDC_RX1_B6_CTL__POR				(0x00)
+#define TAIKO_A_CDC_RX1_B6_CTL__POR				(0x80)
 #define TAIKO_A_CDC_RX2_B6_CTL			(0x2BD)
-#define TAIKO_A_CDC_RX2_B6_CTL__POR				(0x00)
+#define TAIKO_A_CDC_RX2_B6_CTL__POR				(0x80)
 #define TAIKO_A_CDC_RX3_B6_CTL			(0x2C5)
-#define TAIKO_A_CDC_RX3_B6_CTL__POR				(0x00)
+#define TAIKO_A_CDC_RX3_B6_CTL__POR				(0x80)
 #define TAIKO_A_CDC_RX4_B6_CTL			(0x2CD)
-#define TAIKO_A_CDC_RX4_B6_CTL__POR				(0x00)
+#define TAIKO_A_CDC_RX4_B6_CTL__POR				(0x80)
 #define TAIKO_A_CDC_RX5_B6_CTL			(0x2D5)
-#define TAIKO_A_CDC_RX5_B6_CTL__POR				(0x00)
+#define TAIKO_A_CDC_RX5_B6_CTL__POR				(0x80)
 #define TAIKO_A_CDC_RX6_B6_CTL			(0x2DD)
-#define TAIKO_A_CDC_RX6_B6_CTL__POR				(0x00)
+#define TAIKO_A_CDC_RX6_B6_CTL__POR				(0x80)
 #define TAIKO_A_CDC_RX7_B6_CTL			(0x2E5)
-#define TAIKO_A_CDC_RX7_B6_CTL__POR				(0x00)
+#define TAIKO_A_CDC_RX7_B6_CTL__POR				(0x80)
 #define TAIKO_A_CDC_RX1_VOL_CTL_B1_CTL			(0x2B6)
 #define TAIKO_A_CDC_RX1_VOL_CTL_B1_CTL__POR				(0x00)
 #define TAIKO_A_CDC_RX2_VOL_CTL_B1_CTL			(0x2BE)
@@ -1041,9 +1041,9 @@
 #define TAIKO_A_CDC_IIR2_GAIN_B8_CTL			(0x357)
 #define TAIKO_A_CDC_IIR2_GAIN_B8_CTL__POR				(0x00)
 #define TAIKO_A_CDC_IIR1_CTL			(0x348)
-#define TAIKO_A_CDC_IIR1_CTL__POR				(0x00)
+#define TAIKO_A_CDC_IIR1_CTL__POR				(0x40)
 #define TAIKO_A_CDC_IIR2_CTL			(0x358)
-#define TAIKO_A_CDC_IIR2_CTL__POR				(0x00)
+#define TAIKO_A_CDC_IIR2_CTL__POR				(0x40)
 #define TAIKO_A_CDC_IIR1_GAIN_TIMER_CTL			(0x349)
 #define TAIKO_A_CDC_IIR1_GAIN_TIMER_CTL__POR				(0x00)
 #define TAIKO_A_CDC_IIR2_GAIN_TIMER_CTL			(0x359)
@@ -1059,35 +1059,35 @@
 #define TAIKO_A_CDC_TOP_GAIN_UPDATE			(0x360)
 #define TAIKO_A_CDC_TOP_GAIN_UPDATE__POR				(0x00)
 #define TAIKO_A_CDC_COMP0_B1_CTL			(0x368)
-#define TAIKO_A_CDC_COMP0_B1_CTL__POR				(0x00)
+#define TAIKO_A_CDC_COMP0_B1_CTL__POR				(0x30)
 #define TAIKO_A_CDC_COMP1_B1_CTL			(0x370)
-#define TAIKO_A_CDC_COMP1_B1_CTL__POR				(0x00)
+#define TAIKO_A_CDC_COMP1_B1_CTL__POR				(0x30)
 #define TAIKO_A_CDC_COMP2_B1_CTL			(0x378)
-#define TAIKO_A_CDC_COMP2_B1_CTL__POR				(0x00)
+#define TAIKO_A_CDC_COMP2_B1_CTL__POR				(0x30)
 #define TAIKO_A_CDC_COMP0_B2_CTL			(0x369)
-#define TAIKO_A_CDC_COMP0_B2_CTL__POR				(0x00)
+#define TAIKO_A_CDC_COMP0_B2_CTL__POR				(0xB5)
 #define TAIKO_A_CDC_COMP1_B2_CTL			(0x371)
-#define TAIKO_A_CDC_COMP1_B2_CTL__POR				(0x00)
+#define TAIKO_A_CDC_COMP1_B2_CTL__POR				(0xB5)
 #define TAIKO_A_CDC_COMP2_B2_CTL			(0x379)
-#define TAIKO_A_CDC_COMP2_B2_CTL__POR				(0x00)
+#define TAIKO_A_CDC_COMP2_B2_CTL__POR				(0xB5)
 #define TAIKO_A_CDC_COMP0_B3_CTL			(0x36A)
-#define TAIKO_A_CDC_COMP0_B3_CTL__POR				(0x00)
+#define TAIKO_A_CDC_COMP0_B3_CTL__POR				(0x28)
 #define TAIKO_A_CDC_COMP1_B3_CTL			(0x372)
-#define TAIKO_A_CDC_COMP1_B3_CTL__POR				(0x00)
+#define TAIKO_A_CDC_COMP1_B3_CTL__POR				(0x28)
 #define TAIKO_A_CDC_COMP2_B3_CTL			(0x37A)
-#define TAIKO_A_CDC_COMP2_B3_CTL__POR				(0x00)
+#define TAIKO_A_CDC_COMP2_B3_CTL__POR				(0x28)
 #define TAIKO_A_CDC_COMP0_B4_CTL			(0x36B)
-#define TAIKO_A_CDC_COMP0_B4_CTL__POR				(0x00)
+#define TAIKO_A_CDC_COMP0_B4_CTL__POR				(0x3C)
 #define TAIKO_A_CDC_COMP1_B4_CTL			(0x373)
-#define TAIKO_A_CDC_COMP1_B4_CTL__POR				(0x00)
+#define TAIKO_A_CDC_COMP1_B4_CTL__POR				(0x3C)
 #define TAIKO_A_CDC_COMP2_B4_CTL			(0x37B)
-#define TAIKO_A_CDC_COMP2_B4_CTL__POR				(0x00)
+#define TAIKO_A_CDC_COMP2_B4_CTL__POR				(0x3C)
 #define TAIKO_A_CDC_COMP0_B5_CTL			(0x36C)
-#define TAIKO_A_CDC_COMP0_B5_CTL__POR				(0x00)
+#define TAIKO_A_CDC_COMP0_B5_CTL__POR				(0x1F)
 #define TAIKO_A_CDC_COMP1_B5_CTL			(0x374)
-#define TAIKO_A_CDC_COMP1_B5_CTL__POR				(0x00)
+#define TAIKO_A_CDC_COMP1_B5_CTL__POR				(0x1F)
 #define TAIKO_A_CDC_COMP2_B5_CTL			(0x37C)
-#define TAIKO_A_CDC_COMP2_B5_CTL__POR				(0x00)
+#define TAIKO_A_CDC_COMP2_B5_CTL__POR				(0x1F)
 #define TAIKO_A_CDC_COMP0_B6_CTL			(0x36D)
 #define TAIKO_A_CDC_COMP0_B6_CTL__POR				(0x00)
 #define TAIKO_A_CDC_COMP1_B6_CTL			(0x375)
@@ -1095,17 +1095,17 @@
 #define TAIKO_A_CDC_COMP2_B6_CTL			(0x37D)
 #define TAIKO_A_CDC_COMP2_B6_CTL__POR				(0x00)
 #define TAIKO_A_CDC_COMP0_SHUT_DOWN_STATUS			(0x36E)
-#define TAIKO_A_CDC_COMP0_SHUT_DOWN_STATUS__POR				(0x00)
+#define TAIKO_A_CDC_COMP0_SHUT_DOWN_STATUS__POR				(0x03)
 #define TAIKO_A_CDC_COMP1_SHUT_DOWN_STATUS			(0x376)
-#define TAIKO_A_CDC_COMP1_SHUT_DOWN_STATUS__POR				(0x00)
+#define TAIKO_A_CDC_COMP1_SHUT_DOWN_STATUS__POR				(0x03)
 #define TAIKO_A_CDC_COMP2_SHUT_DOWN_STATUS			(0x37E)
-#define TAIKO_A_CDC_COMP2_SHUT_DOWN_STATUS__POR				(0x00)
+#define TAIKO_A_CDC_COMP2_SHUT_DOWN_STATUS__POR				(0x03)
 #define TAIKO_A_CDC_COMP0_FS_CFG			(0x36F)
-#define TAIKO_A_CDC_COMP0_FS_CFG__POR				(0x00)
+#define TAIKO_A_CDC_COMP0_FS_CFG__POR				(0x03)
 #define TAIKO_A_CDC_COMP1_FS_CFG			(0x377)
-#define TAIKO_A_CDC_COMP1_FS_CFG__POR				(0x00)
+#define TAIKO_A_CDC_COMP1_FS_CFG__POR				(0x03)
 #define TAIKO_A_CDC_COMP2_FS_CFG			(0x37F)
-#define TAIKO_A_CDC_COMP2_FS_CFG__POR				(0x00)
+#define TAIKO_A_CDC_COMP2_FS_CFG__POR				(0x03)
 #define TAIKO_A_CDC_CONN_RX1_B1_CTL			(0x380)
 #define TAIKO_A_CDC_CONN_RX1_B1_CTL__POR				(0x00)
 #define TAIKO_A_CDC_CONN_RX1_B2_CTL			(0x381)
diff --git a/include/linux/mmc/card.h b/include/linux/mmc/card.h
index a80eb59..87e06ed 100644
--- a/include/linux/mmc/card.h
+++ b/include/linux/mmc/card.h
@@ -79,10 +79,13 @@
 	bool			hpi_en;			/* HPI enablebit */
 	bool			hpi;			/* HPI support bit */
 	unsigned int		hpi_cmd;		/* cmd used as HPI */
+	bool			bkops;		/* background support bit */
+	bool			bkops_en;	/* background enable bit */
 	unsigned int            data_sector_size;       /* 512 bytes or 4KB */
 	unsigned int            data_tag_unit_size;     /* DATA TAG UNIT size */
 	unsigned int		boot_ro_lock;		/* ro lock support */
 	bool			boot_ro_lockable;
+	u8			raw_exception_status;	/* 53 */
 	u8			raw_partition_support;	/* 160 */
 	u8			raw_erased_mem_count;	/* 181 */
 	u8			raw_ext_csd_structure;	/* 194 */
@@ -96,6 +99,7 @@
 	u8			raw_sec_erase_mult;	/* 230 */
 	u8			raw_sec_feature_support;/* 231 */
 	u8			raw_trim_mult;		/* 232 */
+	u8			raw_bkops_status;	/* 246 */
 	u8			raw_sectors[4];		/* 212 - 4 bytes */
 
 	unsigned int            feature_support;
@@ -247,6 +251,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_SLEEP		(1<<9)		/* card is in sleep state */
+#define MMC_STATE_DOING_BKOPS	(1<<10)		/* card is doing 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 */
@@ -415,6 +420,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_is_sleep(c)	((c)->state & MMC_STATE_SLEEP)
+#define mmc_card_doing_bkops(c)	((c)->state & MMC_STATE_DOING_BKOPS)
 
 #define mmc_card_set_present(c)	((c)->state |= MMC_STATE_PRESENT)
 #define mmc_card_set_readonly(c) ((c)->state |= MMC_STATE_READONLY)
@@ -427,7 +433,9 @@
 #define mmc_card_set_ext_capacity(c) ((c)->state |= MMC_CARD_SDXC)
 #define mmc_card_set_removed(c) ((c)->state |= MMC_CARD_REMOVED)
 #define mmc_card_set_sleep(c)	((c)->state |= MMC_STATE_SLEEP)
+#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_clr_sleep(c)	((c)->state &= ~MMC_STATE_SLEEP)
 /*
  * Quirk add/remove for MMC products.
diff --git a/include/linux/mmc/core.h b/include/linux/mmc/core.h
index 817862f..3f26a80 100644
--- a/include/linux/mmc/core.h
+++ b/include/linux/mmc/core.h
@@ -138,6 +138,8 @@
 struct mmc_card;
 struct mmc_async_req;
 
+extern int mmc_stop_bkops(struct mmc_card *);
+extern int mmc_read_bkops_status(struct mmc_card *);
 extern struct mmc_async_req *mmc_start_req(struct mmc_host *,
 					   struct mmc_async_req *, int *);
 extern int mmc_interrupt_hpi(struct mmc_card *);
@@ -146,6 +148,8 @@
 extern int mmc_app_cmd(struct mmc_host *, struct mmc_card *);
 extern int mmc_wait_for_app_cmd(struct mmc_host *, struct mmc_card *,
 	struct mmc_command *, int);
+extern void mmc_start_bkops(struct mmc_card *card, bool from_exception);
+extern int __mmc_switch(struct mmc_card *, u8, u8, u8, unsigned int, bool);
 extern int mmc_switch(struct mmc_card *, u8, u8, u8, unsigned int);
 extern int mmc_send_ext_csd(struct mmc_card *card, u8 *ext_csd);
 
diff --git a/include/linux/mmc/mmc.h b/include/linux/mmc/mmc.h
index ce4d3c2..87cdba8 100644
--- a/include/linux/mmc/mmc.h
+++ b/include/linux/mmc/mmc.h
@@ -139,6 +139,7 @@
 #define R1_CURRENT_STATE(x)	((x & 0x00001E00) >> 9)	/* sx, b (4 bits) */
 #define R1_READY_FOR_DATA	(1 << 8)	/* sx, a */
 #define R1_SWITCH_ERROR		(1 << 7)	/* sx, c */
+#define R1_EXCEPTION_EVENT	(1 << 6)	/* sx, a */
 #define R1_APP_CMD		(1 << 5)	/* sr, c */
 #define R1_EXP_EVENT		(1 << 6)	/* sr, a */
 
@@ -286,6 +287,8 @@
 #define EXT_CSD_PARTITION_SUPPORT	160	/* RO */
 #define EXT_CSD_HPI_MGMT		161	/* R/W */
 #define EXT_CSD_RST_N_FUNCTION		162	/* R/W */
+#define EXT_CSD_BKOPS_EN		163	/* R/W */
+#define EXT_CSD_BKOPS_START		164	/* W */
 #define EXT_CSD_SANITIZE_START		165     /* W */
 #define EXT_CSD_WR_REL_PARAM		166	/* RO */
 #define EXT_CSD_BOOT_WP			173	/* R/W */
@@ -319,6 +322,7 @@
 #define EXT_CSD_PWR_CL_200_360		237	/* RO */
 #define EXT_CSD_PWR_CL_DDR_52_195	238	/* RO */
 #define EXT_CSD_PWR_CL_DDR_52_360	239	/* RO */
+#define EXT_CSD_BKOPS_STATUS		246	/* RO */
 #define EXT_CSD_POWER_OFF_LONG_TIME	247	/* RO */
 #define EXT_CSD_GENERIC_CMD6_TIME	248	/* RO */
 #define EXT_CSD_CACHE_SIZE		249	/* RO, 4 bytes */
@@ -326,6 +330,7 @@
 #define EXT_CSD_DATA_TAG_SUPPORT	499	/* RO */
 #define EXT_CSD_MAX_PACKED_WRITES	500	/* RO */
 #define EXT_CSD_MAX_PACKED_READS	501	/* RO */
+#define EXT_CSD_BKOPS_SUPPORT		502	/* RO */
 #define EXT_CSD_HPI_FEATURES		503	/* RO */
 
 /*
@@ -397,12 +402,23 @@
 
 #define EXT_CSD_PACKED_EVENT_EN	(1 << 3)
 
-#define EXT_CSD_PACKED_FAILURE	(1 << 3)
-
 #define EXT_CSD_PACKED_GENERIC_ERROR	(1 << 0)
 #define EXT_CSD_PACKED_INDEXED_ERROR	(1 << 1)
 
 /*
+ * EXCEPTION_EVENT_STATUS field
+ */
+#define EXT_CSD_URGENT_BKOPS		BIT(0)
+#define EXT_CSD_DYNCAP_NEEDED		BIT(1)
+#define EXT_CSD_SYSPOOL_EXHAUSTED	BIT(2)
+#define EXT_CSD_PACKED_FAILURE		BIT(3)
+
+/*
+ * BKOPS status level
+ */
+#define EXT_CSD_BKOPS_LEVEL_2		0x2
+
+/*
  * MMC_SWITCH access modes
  */
 
diff --git a/include/linux/msm_ion.h b/include/linux/msm_ion.h
index 0e28e54..e7959d1 100644
--- a/include/linux/msm_ion.h
+++ b/include/linux/msm_ion.h
@@ -1,5 +1,4 @@
 /*
- * include/linux/ion.h
  *
  * Copyright (c) 2012, Code Aurora Forum. All rights reserved.
  *
diff --git a/include/linux/msm_mdp.h b/include/linux/msm_mdp.h
index d03ecfa..861084a 100644
--- a/include/linux/msm_mdp.h
+++ b/include/linux/msm_mdp.h
@@ -276,6 +276,8 @@
 #define MDP_PP_OPS_READ 0x2
 #define MDP_PP_OPS_WRITE 0x4
 #define MDP_PP_OPS_DISABLE 0x8
+#define MDP_PP_IGC_FLAG_ROM0	0x10
+#define MDP_PP_IGC_FLAG_ROM1	0x20
 
 struct mdp_qseed_cfg {
 	uint32_t table_num;
@@ -405,7 +407,7 @@
 
 struct mdp_histogram_data {
 	uint32_t block;
-	uint8_t bin_cnt;
+	uint32_t bin_cnt;
 	uint32_t *c0;
 	uint32_t *c1;
 	uint32_t *c2;
@@ -422,6 +424,8 @@
 	struct mdp_pcc_coeff r, g, b;
 };
 
+#define MDP_GAMUT_TABLE_NUM		8
+
 enum {
 	mdp_lut_igc,
 	mdp_lut_pgc,
@@ -484,6 +488,24 @@
 	uint32_t cont_adj;
 };
 
+struct mdp_dither_cfg_data {
+	uint32_t block;
+	uint32_t flags;
+	uint32_t g_y_depth;
+	uint32_t r_cr_depth;
+	uint32_t b_cb_depth;
+};
+
+struct mdp_gamut_cfg_data {
+	uint32_t block;
+	uint32_t flags;
+	uint32_t gamut_first;
+	uint32_t tbl_size[MDP_GAMUT_TABLE_NUM];
+	uint16_t *r_tbl[MDP_GAMUT_TABLE_NUM];
+	uint16_t *g_tbl[MDP_GAMUT_TABLE_NUM];
+	uint16_t *b_tbl[MDP_GAMUT_TABLE_NUM];
+};
+
 enum {
 	mdp_op_pcc_cfg,
 	mdp_op_csc_cfg,
@@ -491,6 +513,8 @@
 	mdp_op_qseed_cfg,
 	mdp_bl_scale_cfg,
 	mdp_op_pa_cfg,
+	mdp_op_dither_cfg,
+	mdp_op_gamut_cfg,
 	mdp_op_max,
 };
 
@@ -503,6 +527,8 @@
 		struct mdp_qseed_cfg_data qseed_cfg_data;
 		struct mdp_bl_scale_data bl_scale_data;
 		struct mdp_pa_cfg_data pa_cfg_data;
+		struct mdp_dither_cfg_data dither_cfg_data;
+		struct mdp_gamut_cfg_data gamut_cfg_data;
 	} data;
 };
 
diff --git a/include/linux/videodev2.h b/include/linux/videodev2.h
index 7b5aa0b..b265eb9 100644
--- a/include/linux/videodev2.h
+++ b/include/linux/videodev2.h
@@ -1618,6 +1618,7 @@
 	V4L2_MPEG_VIDEO_MPEG4_PROFILE_ADVANCED_CODING_EFFICIENCY	= 4,
 };
 #define V4L2_CID_MPEG_VIDEO_MPEG4_QPEL		(V4L2_CID_MPEG_BASE+407)
+#define V4L2_CID_QCOM_VIDEO_SYNC_FRAME_SEQ_HDR		(V4L2_CID_MPEG_BASE+408)
 
 /*  MPEG-class control IDs specific to the CX2341x driver as defined by V4L2 */
 #define V4L2_CID_MPEG_CX2341X_BASE 				(V4L2_CTRL_CLASS_MPEG | 0x1000)
diff --git a/include/media/videobuf2-core.h b/include/media/videobuf2-core.h
index 2918b94..a15d1f1 100644
--- a/include/media/videobuf2-core.h
+++ b/include/media/videobuf2-core.h
@@ -289,7 +289,6 @@
 	atomic_t			queued_count;
 	struct list_head		done_list;
 	spinlock_t			done_lock;
-	struct mutex		q_lock;
 	wait_queue_head_t		done_wq;
 
 	void				*alloc_ctx[VIDEO_MAX_PLANES];
diff --git a/include/sound/compress_params.h b/include/sound/compress_params.h
index 31d684b..54af7d6a 100644
--- a/include/sound/compress_params.h
+++ b/include/sound/compress_params.h
@@ -86,6 +86,7 @@
 #define SND_AUDIOCODEC_DTS_PASS_THROUGH      ((__u32) 0x00000012)
 #define SND_AUDIOCODEC_DTS_LBR               ((__u32) 0x00000013)
 #define SND_AUDIOCODEC_DTS_TRANSCODE_LOOPBACK ((__u32) 0x00000014)
+#define SND_AUDIOCODEC_PASS_THROUGH          ((__u32) 0x00000015)
 
 /*
  * Profile and modes are listed with bit masks. This allows for a
@@ -331,6 +332,10 @@
 	__u32 bw;	/* encoder bandwidth */
 	__s32 reserved[15];
 };
+struct snd_dec_dts {
+	__u32 modelIdLength;
+	__u8 *modelId;
+};
 
 union snd_codec_options {
 	struct snd_enc_wma wma;
@@ -338,6 +343,7 @@
 	struct snd_enc_real real;
 	struct snd_enc_flac flac;
 	struct snd_enc_generic generic;
+	struct snd_dec_dts dts;
 };
 
 /** struct snd_codec_desc - description of codec capabilities
diff --git a/include/sound/q6asm.h b/include/sound/q6asm.h
index 4021d48..32d3aef 100644
--- a/include/sound/q6asm.h
+++ b/include/sound/q6asm.h
@@ -49,6 +49,7 @@
 #define FORMAT_MAT	0x0017
 #define FORMAT_AAC	0x0018
 #define FORMAT_DTS_LBR 0x0019
+#define FORMAT_PASS_THROUGH 0x0020
 
 #define ENCDEC_SBCBITRATE   0x0001
 #define ENCDEC_IMMEDIATE_DECODE 0x0002
diff --git a/kernel/trace/Kconfig b/kernel/trace/Kconfig
index a1d2849..5ba1770 100644
--- a/kernel/trace/Kconfig
+++ b/kernel/trace/Kconfig
@@ -418,6 +418,19 @@
 
 	  If in doubt, say N.
 
+config CPU_FREQ_SWITCH_PROFILER
+	bool "CPU frequency switch time profiler"
+	select GENERIC_TRACER
+	help
+	  This option enables the CPU frequency switch profiler. A file is
+	  created in debugfs called "cpu_freq_switch_profile_enabled", which
+	  defaults to zero. When a 1 is echoed into this file, profiling begins.
+	  When a zero is echoed, profiling stops. A "cpu_freq_switch" file is
+	  also created in the trace_stats directory; this file shows the
+	  switches that have occurred and duration statistics.
+
+	  If in doubt, say N.
+
 config FTRACE_MCOUNT_RECORD
 	def_bool y
 	depends on DYNAMIC_FTRACE
diff --git a/kernel/trace/Makefile b/kernel/trace/Makefile
index 5f39a07..3c13931 100644
--- a/kernel/trace/Makefile
+++ b/kernel/trace/Makefile
@@ -36,6 +36,7 @@
 obj-$(CONFIG_IRQSOFF_TRACER) += trace_irqsoff.o
 obj-$(CONFIG_PREEMPT_TRACER) += trace_irqsoff.o
 obj-$(CONFIG_SCHED_TRACER) += trace_sched_wakeup.o
+obj-$(CONFIG_CPU_FREQ_SWITCH_PROFILER) += trace_cpu_freq_switch.o
 obj-$(CONFIG_NOP_TRACER) += trace_nop.o
 obj-$(CONFIG_STACK_TRACER) += trace_stack.o
 obj-$(CONFIG_MMIOTRACE) += trace_mmiotrace.o
diff --git a/kernel/trace/trace_cpu_freq_switch.c b/kernel/trace/trace_cpu_freq_switch.c
new file mode 100644
index 0000000..7e7b104
--- /dev/null
+++ b/kernel/trace/trace_cpu_freq_switch.c
@@ -0,0 +1,311 @@
+/*
+ * 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/kernel.h>
+#include <linux/module.h>
+#include <linux/percpu.h>
+#include <linux/slab.h>
+#include <linux/rbtree.h>
+#include <linux/hrtimer.h>
+#include <linux/debugfs.h>
+#include <linux/ktime.h>
+#include <trace/events/power.h>
+#include "trace_stat.h"
+#include "trace.h"
+
+struct trans {
+	struct rb_node node;
+	unsigned int cpu;
+	unsigned int start_freq;
+	unsigned int end_freq;
+	unsigned int min_us;
+	unsigned int max_us;
+	ktime_t total_t;
+	unsigned int count;
+};
+static struct rb_root freq_trans_tree = RB_ROOT;
+
+static struct trans *tr_search(struct rb_root *root, unsigned int cpu,
+			       unsigned int start_freq, unsigned int end_freq)
+{
+	struct rb_node *node = root->rb_node;
+
+	while (node) {
+		struct trans *tr = container_of(node, struct trans, node);
+
+		if (cpu < tr->cpu)
+			node = node->rb_left;
+		else if (cpu > tr->cpu)
+			node = node->rb_right;
+		else if (start_freq < tr->start_freq)
+			node = node->rb_left;
+		else if (start_freq > tr->start_freq)
+			node = node->rb_right;
+		else if (end_freq < tr->end_freq)
+			node = node->rb_left;
+		else if (end_freq > tr->end_freq)
+			node = node->rb_right;
+		else
+			return tr;
+	}
+	return NULL;
+}
+
+static int tr_insert(struct rb_root *root, struct trans *tr)
+{
+	struct rb_node **new = &(root->rb_node), *parent = NULL;
+
+	while (*new) {
+		struct trans *this = container_of(*new, struct trans, node);
+
+		parent = *new;
+		if (tr->cpu < this->cpu)
+			new = &((*new)->rb_left);
+		else if (tr->cpu > this->cpu)
+			new = &((*new)->rb_right);
+		else if (tr->start_freq < this->start_freq)
+			new = &((*new)->rb_left);
+		else if (tr->start_freq > this->start_freq)
+			new = &((*new)->rb_right);
+		else if (tr->end_freq < this->end_freq)
+			new = &((*new)->rb_left);
+		else if (tr->end_freq > this->end_freq)
+			new = &((*new)->rb_right);
+		else
+			return -EINVAL;
+	}
+
+	rb_link_node(&tr->node, parent, new);
+	rb_insert_color(&tr->node, root);
+
+	return 0;
+}
+
+struct trans_state {
+	spinlock_t lock;
+	unsigned int start_freq;
+	unsigned int end_freq;
+	ktime_t start_t;
+	bool started;
+};
+static DEFINE_PER_CPU(struct trans_state, freq_trans_state);
+
+static DEFINE_SPINLOCK(state_lock);
+
+static void probe_start(void *ignore, unsigned int start_freq,
+			unsigned int end_freq, unsigned int cpu)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&state_lock, flags);
+	per_cpu(freq_trans_state, cpu).start_freq = start_freq;
+	per_cpu(freq_trans_state, cpu).end_freq = end_freq;
+	per_cpu(freq_trans_state, cpu).start_t = ktime_get();
+	per_cpu(freq_trans_state, cpu).started = true;
+	spin_unlock_irqrestore(&state_lock, flags);
+}
+
+static void probe_end(void *ignore, unsigned int cpu)
+{
+	unsigned long flags;
+	struct trans *tr;
+	s64 dur_us;
+	ktime_t dur_t, end_t = ktime_get();
+
+	spin_lock_irqsave(&state_lock, flags);
+
+	if (!per_cpu(freq_trans_state, cpu).started)
+		goto out;
+
+	dur_t = ktime_sub(end_t, per_cpu(freq_trans_state, cpu).start_t);
+	dur_us = ktime_to_us(dur_t);
+
+	tr = tr_search(&freq_trans_tree, cpu,
+		       per_cpu(freq_trans_state, cpu).start_freq,
+		       per_cpu(freq_trans_state, cpu).end_freq);
+	if (!tr) {
+		tr = kzalloc(sizeof(*tr), GFP_ATOMIC);
+		if (!tr) {
+			WARN_ONCE(1, "CPU frequency trace is now invalid!\n");
+			goto out;
+		}
+
+		tr->start_freq = per_cpu(freq_trans_state, cpu).start_freq;
+		tr->end_freq = per_cpu(freq_trans_state, cpu).end_freq;
+		tr->cpu = cpu;
+		tr->min_us = UINT_MAX;
+		tr_insert(&freq_trans_tree, tr);
+	}
+	tr->total_t = ktime_add(tr->total_t, dur_t);
+	tr->count++;
+
+	if (dur_us > tr->max_us)
+		tr->max_us = dur_us;
+	if (dur_us < tr->min_us)
+		tr->min_us = dur_us;
+
+	per_cpu(freq_trans_state, cpu).started = false;
+out:
+	spin_unlock_irqrestore(&state_lock, flags);
+}
+
+static void *freq_switch_stat_start(struct tracer_stat *trace)
+{
+	struct rb_node *n;
+	unsigned long flags;
+
+	spin_lock_irqsave(&state_lock, flags);
+	n = rb_first(&freq_trans_tree);
+	spin_unlock_irqrestore(&state_lock, flags);
+
+	return n;
+}
+
+static void *freq_switch_stat_next(void *prev, int idx)
+{
+	struct rb_node *n;
+	unsigned long flags;
+
+	spin_lock_irqsave(&state_lock, flags);
+	n = rb_next(prev);
+	spin_unlock_irqrestore(&state_lock, flags);
+
+	return n;
+}
+
+static int freq_switch_stat_show(struct seq_file *s, void *p)
+{
+	unsigned long flags;
+	struct trans *tr = p;
+
+	spin_lock_irqsave(&state_lock, flags);
+	seq_printf(s, "%3d %9d %8d %5d %6lld %6d %6d\n", tr->cpu,
+		   tr->start_freq, tr->end_freq, tr->count,
+		   div_s64(ktime_to_us(tr->total_t), tr->count),
+		   tr->min_us, tr->max_us);
+	spin_unlock_irqrestore(&state_lock, flags);
+
+	return 0;
+}
+
+static void freq_switch_stat_release(void *stat)
+{
+	struct trans *tr = stat;
+	unsigned long flags;
+
+	spin_lock_irqsave(&state_lock, flags);
+	rb_erase(&tr->node, &freq_trans_tree);
+	spin_unlock_irqrestore(&state_lock, flags);
+	kfree(tr);
+}
+
+static int freq_switch_stat_headers(struct seq_file *s)
+{
+	seq_printf(s, "CPU START_KHZ  END_KHZ COUNT AVG_US MIN_US MAX_US\n");
+	seq_printf(s, "  |         |        |     |      |      |      |\n");
+	return 0;
+}
+
+struct tracer_stat freq_switch_stats __read_mostly = {
+	.name = "cpu_freq_switch",
+	.stat_start = freq_switch_stat_start,
+	.stat_next = freq_switch_stat_next,
+	.stat_show = freq_switch_stat_show,
+	.stat_release = freq_switch_stat_release,
+	.stat_headers = freq_switch_stat_headers
+};
+
+static void trace_freq_switch_disable(void)
+{
+	unregister_stat_tracer(&freq_switch_stats);
+	unregister_trace_cpu_frequency_switch_end(probe_end, NULL);
+	unregister_trace_cpu_frequency_switch_start(probe_start, NULL);
+	pr_info("disabled cpu frequency switch time profiling\n");
+}
+
+static int trace_freq_switch_enable(void)
+{
+	int ret;
+
+	ret = register_trace_cpu_frequency_switch_start(probe_start, NULL);
+	if (ret)
+		goto out;
+
+	ret = register_trace_cpu_frequency_switch_end(probe_end, NULL);
+	if (ret)
+		goto err_register_switch_end;
+
+	ret = register_stat_tracer(&freq_switch_stats);
+	if (ret)
+		goto err_register_stat_tracer;
+
+	pr_info("enabled cpu frequency switch time profiling\n");
+	return 0;
+
+err_register_stat_tracer:
+	unregister_trace_cpu_frequency_switch_end(probe_end, NULL);
+err_register_switch_end:
+	register_trace_cpu_frequency_switch_start(probe_start, NULL);
+out:
+	pr_err("failed to enable cpu frequency switch time profiling\n");
+
+	return ret;
+}
+
+static DEFINE_MUTEX(debugfs_lock);
+static bool trace_freq_switch_enabled;
+
+static int debug_toggle_tracing(void *data, u64 val)
+{
+	int ret = 0;
+
+	mutex_lock(&debugfs_lock);
+
+	if (val == 1 && !trace_freq_switch_enabled)
+		ret = trace_freq_switch_enable();
+	else if (val == 0 && trace_freq_switch_enabled)
+		trace_freq_switch_disable();
+	else if (val > 1)
+		ret = -EINVAL;
+
+	if (!ret)
+		trace_freq_switch_enabled = val;
+
+	mutex_unlock(&debugfs_lock);
+
+	return ret;
+}
+
+static int debug_tracing_state_get(void *data, u64 *val)
+{
+	mutex_lock(&debugfs_lock);
+	*val = trace_freq_switch_enabled;
+	mutex_unlock(&debugfs_lock);
+
+	return 0;
+}
+DEFINE_SIMPLE_ATTRIBUTE(debug_tracing_state_fops, debug_tracing_state_get,
+			debug_toggle_tracing, "%llu\n");
+
+static int __init trace_freq_switch_init(void)
+{
+	struct dentry *d_tracer = tracing_init_dentry();
+	if (!d_tracer)
+		return 0;
+
+	debugfs_create_file("cpu_freq_switch_profile_enabled",
+		S_IRUGO | S_IWUSR, d_tracer, NULL, &debug_tracing_state_fops);
+
+	return 0;
+}
+late_initcall(trace_freq_switch_init);
diff --git a/sound/soc/codecs/wcd9320-tables.c b/sound/soc/codecs/wcd9320-tables.c
index 68a4670..c49c276 100644
--- a/sound/soc/codecs/wcd9320-tables.c
+++ b/sound/soc/codecs/wcd9320-tables.c
@@ -673,7 +673,7 @@
 	[TAIKO_A_CDC_MAD_BEACON_IIR_CTL_VAL] = 1,
 };
 
-const u8 taiko_reg_defaults[TAIKO_CACHE_SIZE] = {
+const u8 taiko_reset_reg_defaults[TAIKO_CACHE_SIZE] = {
 	[TAIKO_A_CHIP_CTL] = TAIKO_A_CHIP_CTL__POR,
 	[TAIKO_A_CHIP_STATUS] = TAIKO_A_CHIP_STATUS__POR,
 	[TAIKO_A_CHIP_ID_BYTE_0] = TAIKO_A_CHIP_ID_BYTE_0__POR,
diff --git a/sound/soc/codecs/wcd9320.c b/sound/soc/codecs/wcd9320.c
index 136024c..e8bb652 100644
--- a/sound/soc/codecs/wcd9320.c
+++ b/sound/soc/codecs/wcd9320.c
@@ -685,7 +685,7 @@
 				u32 compander, u32 enable, int event)
 {
 	int value = 0;
-	int mask = 1 << 4;
+	int mask = 1 << 5;
 	int gain = 0;
 	int gain_offset;
 	if (compander >= COMPANDER_MAX) {
@@ -828,19 +828,23 @@
 		break;
 	case SND_SOC_DAPM_PRE_PMD:
 		/* Halt the compander*/
-		snd_soc_update_bits(codec, TAIKO_A_CDC_COMP1_B1_CTL +
-			w->shift * 8, 1 << 2, 1 << 2);
+		if (taiko->comp_enabled[w->shift] != 0) {
+			snd_soc_update_bits(codec, TAIKO_A_CDC_COMP1_B1_CTL +
+				w->shift * 8, 1 << 2, 1 << 2);
+		}
 		break;
 	case SND_SOC_DAPM_POST_PMD:
 		/* Restore the gain */
-		taiko_config_gain_compander(codec, w->shift,
-				taiko->comp_enabled[w->shift], event);
-		/* Disable the compander*/
-		snd_soc_update_bits(codec, TAIKO_A_CDC_COMP1_B1_CTL +
-			w->shift * 8, 0x03, 0x00);
-		/* Turn off the clock for compander in pair*/
-		snd_soc_update_bits(codec, TAIKO_A_CDC_CLK_RX_B2_CTL,
-			0x03 << comp_shift[w->shift], 0);
+		if (taiko->comp_enabled[w->shift] != 0) {
+			taiko_config_gain_compander(codec, w->shift,
+					taiko->comp_enabled[w->shift], event);
+			/* Disable the compander*/
+			snd_soc_update_bits(codec, TAIKO_A_CDC_COMP1_B1_CTL +
+					w->shift * 8, 0x03, 0x00);
+			/* Turn off the clock for compander in pair*/
+			snd_soc_update_bits(codec, TAIKO_A_CDC_CLK_RX_B2_CTL,
+				0x03 << comp_shift[w->shift], 0);
+		}
 		break;
 	}
 	return 0;
@@ -1716,7 +1720,7 @@
 		usleep_range(100, 100);
 		taiko_codec_enable_audio_mode_bandgap(codec);
 	} else if (choice == TAIKO_BANDGAP_OFF) {
-		snd_soc_write(codec, TAIKO_A_BIAS_CENTRAL_BG_CTL, 0x00);
+		snd_soc_write(codec, TAIKO_A_BIAS_CENTRAL_BG_CTL, 0x50);
 	} else {
 		pr_err("%s: Error, Invalid bandgap settings\n", __func__);
 	}
@@ -1730,7 +1734,7 @@
 	snd_soc_update_bits(codec, TAIKO_A_CLK_BUFF_EN2, 0x04, 0x00);
 	usleep_range(50, 50);
 	snd_soc_update_bits(codec, TAIKO_A_CLK_BUFF_EN2, 0x02, 0x02);
-	snd_soc_update_bits(codec, TAIKO_A_CLK_BUFF_EN1, 0x05, 0x00);
+	snd_soc_update_bits(codec, TAIKO_A_CLK_BUFF_EN1, 0x01, 0x00);
 	usleep_range(50, 50);
 	taiko->clock_active = false;
 }
@@ -1815,10 +1819,9 @@
 		/* switch to MCLK */
 		snd_soc_update_bits(codec, TAIKO_A_CLK_BUFF_EN1, 0x08, 0x00);
 
-		if (taiko->mbhc_polling_active) {
+		if (taiko->mbhc_polling_active)
 			snd_soc_write(codec, TAIKO_A_CLK_BUFF_EN2, 0x02);
-			taiko_codec_enable_config_mode(codec, 0);
-		}
+		taiko_codec_enable_config_mode(codec, 0);
 	}
 
 	snd_soc_update_bits(codec, TAIKO_A_CLK_BUFF_EN1, 0x01, 0x01);
@@ -2658,7 +2661,7 @@
 	return ret;
 }
 
-static int taiko_codec_reset_interpolator(struct snd_soc_dapm_widget *w,
+static int taiko_codec_enable_interpolator(struct snd_soc_dapm_widget *w,
 	struct snd_kcontrol *kcontrol, int event)
 {
 	struct snd_soc_codec *codec = w->codec;
@@ -4295,25 +4298,25 @@
 			   SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
 
 	SND_SOC_DAPM_MIXER_E("RX1 MIX2", TAIKO_A_CDC_CLK_RX_B1_CTL, 0, 0, NULL,
-		0, taiko_codec_reset_interpolator, SND_SOC_DAPM_PRE_PMU |
+		0, taiko_codec_enable_interpolator, SND_SOC_DAPM_PRE_PMU |
 		SND_SOC_DAPM_POST_PMU),
 	SND_SOC_DAPM_MIXER_E("RX2 MIX2", TAIKO_A_CDC_CLK_RX_B1_CTL, 1, 0, NULL,
-		0, taiko_codec_reset_interpolator, SND_SOC_DAPM_PRE_PMU |
+		0, taiko_codec_enable_interpolator, SND_SOC_DAPM_PRE_PMU |
 		SND_SOC_DAPM_POST_PMU),
 	SND_SOC_DAPM_MIXER_E("RX7 MIX2", TAIKO_A_CDC_CLK_RX_B1_CTL, 2, 0, NULL,
-		0, taiko_codec_reset_interpolator, SND_SOC_DAPM_PRE_PMU |
+		0, taiko_codec_enable_interpolator, SND_SOC_DAPM_PRE_PMU |
 		SND_SOC_DAPM_POST_PMU),
 	SND_SOC_DAPM_MIXER_E("RX4 MIX1", TAIKO_A_CDC_CLK_RX_B1_CTL, 3, 0, NULL,
-		0, taiko_codec_reset_interpolator, SND_SOC_DAPM_PRE_PMU |
+		0, taiko_codec_enable_interpolator, SND_SOC_DAPM_PRE_PMU |
 		SND_SOC_DAPM_POST_PMU),
 	SND_SOC_DAPM_MIXER_E("RX5 MIX1", TAIKO_A_CDC_CLK_RX_B1_CTL, 4, 0, NULL,
-		0, taiko_codec_reset_interpolator, SND_SOC_DAPM_PRE_PMU |
+		0, taiko_codec_enable_interpolator, SND_SOC_DAPM_PRE_PMU |
 		SND_SOC_DAPM_POST_PMU),
 	SND_SOC_DAPM_MIXER_E("RX6 MIX1", TAIKO_A_CDC_CLK_RX_B1_CTL, 5, 0, NULL,
-		0, taiko_codec_reset_interpolator, SND_SOC_DAPM_PRE_PMU |
+		0, taiko_codec_enable_interpolator, SND_SOC_DAPM_PRE_PMU |
 		SND_SOC_DAPM_POST_PMU),
 	SND_SOC_DAPM_MIXER_E("RX7 MIX1", TAIKO_A_CDC_CLK_RX_B1_CTL, 6, 0, NULL,
-		0, taiko_codec_reset_interpolator, SND_SOC_DAPM_PRE_PMU |
+		0, taiko_codec_enable_interpolator, SND_SOC_DAPM_PRE_PMU |
 		SND_SOC_DAPM_POST_PMU),
 
 	SND_SOC_DAPM_MIXER("RX1 MIX1", SND_SOC_NOPM, 0, 0, NULL, 0),
@@ -4321,11 +4324,11 @@
 	SND_SOC_DAPM_MIXER("RX3 MIX1", SND_SOC_NOPM, 0, 0, NULL, 0),
 
 	SND_SOC_DAPM_MUX_E("RX4 DSM MUX", TAIKO_A_CDC_CLK_RX_B1_CTL, 3, 0,
-		&rx4_dsm_mux, taiko_codec_reset_interpolator,
+		&rx4_dsm_mux, taiko_codec_enable_interpolator,
 		SND_SOC_DAPM_PRE_PMU),
 
 	SND_SOC_DAPM_MUX_E("RX6 DSM MUX", TAIKO_A_CDC_CLK_RX_B1_CTL, 5, 0,
-		&rx6_dsm_mux, taiko_codec_reset_interpolator,
+		&rx6_dsm_mux, taiko_codec_enable_interpolator,
 		SND_SOC_DAPM_PRE_PMU),
 
 	SND_SOC_DAPM_MIXER("RX1 CHAIN", TAIKO_A_CDC_RX1_B6_CTL, 5, 0, NULL, 0),
@@ -4381,10 +4384,10 @@
 	SND_SOC_DAPM_SUPPLY("CLASS_H_EAR", TAIKO_A_CDC_CLSH_B1_CTL, 4, 0,
 		taiko_codec_enable_class_h, SND_SOC_DAPM_POST_PMU),
 
-	SND_SOC_DAPM_SUPPLY("CLASS_H_HPH_R", TAIKO_A_CDC_CLSH_B1_CTL, 3, 0,
+	SND_SOC_DAPM_SUPPLY("CLASS_H_HPH_L", TAIKO_A_CDC_CLSH_B1_CTL, 3, 0,
 		taiko_codec_enable_class_h, SND_SOC_DAPM_POST_PMU),
 
-	SND_SOC_DAPM_SUPPLY("CLASS_H_HPH_L", TAIKO_A_CDC_CLSH_B1_CTL, 2, 0,
+	SND_SOC_DAPM_SUPPLY("CLASS_H_HPH_R", TAIKO_A_CDC_CLSH_B1_CTL, 2, 0,
 		taiko_codec_enable_class_h, SND_SOC_DAPM_POST_PMU),
 
 	SND_SOC_DAPM_SUPPLY("CP", TAIKO_A_NCP_EN, 0, 0,
@@ -7088,7 +7091,7 @@
 	return rc;
 }
 
-static const struct taiko_reg_mask_val taiko_1_0_reg_defaults[] = {
+static const struct taiko_reg_mask_val taiko_reg_defaults[] = {
 
 	/* set MCLk to 9.6 */
 	TAIKO_REG_VAL(TAIKO_A_CHIP_CTL, 0x0A),
@@ -7096,14 +7099,10 @@
 
 	/* EAR PA deafults  */
 	TAIKO_REG_VAL(TAIKO_A_RX_EAR_CMBUFF, 0x05),
-	/* HPH PA */
-	TAIKO_REG_VAL(TAIKO_A_RX_HPH_BIAS_PA, 0x7A),
 
 	/** BUCK and NCP defaults for EAR and HS */
 	TAIKO_REG_VAL(TAIKO_A_BUCK_CTRL_CCL_4, 0x50),
-	TAIKO_REG_VAL(TAIKO_A_BUCK_CTRL_VCL_1, 0x08),
 	TAIKO_REG_VAL(TAIKO_A_BUCK_CTRL_CCL_1, 0x5B),
-	TAIKO_REG_VAL(TAIKO_A_NCP_CLK, 0xFC),
 
 	/* CLASS-H defaults for EAR and HS */
 	TAIKO_REG_VAL(TAIKO_A_CDC_CLSH_BUCK_NCP_VARS, 0x00),
@@ -7120,7 +7119,6 @@
 	 */
 	TAIKO_REG_VAL(TAIKO_A_CDC_CLSH_B1_CTL, 0x26),
 
-
 	/* RX deafults */
 	TAIKO_REG_VAL(TAIKO_A_CDC_RX1_B5_CTL, 0x78),
 	TAIKO_REG_VAL(TAIKO_A_CDC_RX2_B5_CTL, 0x78),
@@ -7142,20 +7140,50 @@
 	TAIKO_REG_VAL(TAIKO_A_CDC_RX7_B6_CTL, 0x80),
 };
 
+static const struct taiko_reg_mask_val taiko_1_0_reg_defaults[] = {
+	/*
+	 * The following only need to be written for Taiko 1.0 parts.
+	 * Taiko 2.0 will have appropriate defaults for these registers.
+	 */
+	/* Choose max non-overlap time for NCP */
+	TAIKO_REG_VAL(TAIKO_A_NCP_CLK, 0xFC),
+	/* Use 25mV/50mV for deltap/m to reduce ripple */
+	TAIKO_REG_VAL(TAIKO_A_BUCK_CTRL_VCL_1, 0x08),
+	/*
+	 * Set DISABLE_MODE_SEL<1:0> to 0b10 (disable PWM in auto mode).
+	 * Note that the other bits of this register will be changed during
+	 * Rx PA bring up.
+	 */
+	TAIKO_REG_VAL(TAIKO_A_BUCK_MODE_3, 0xCE),
+	/* Reduce HPH DAC bias to 70% */
+	TAIKO_REG_VAL(TAIKO_A_RX_HPH_BIAS_PA, 0x7A),
+	/*Reduce EAR DAC bias to 70% */
+	TAIKO_REG_VAL(TAIKO_A_RX_EAR_BIAS_PA, 0x76),
+	/* Reduce LINE DAC bias to 70% */
+	TAIKO_REG_VAL(TAIKO_A_RX_LINE_BIAS_PA, 0x78),
+};
+
 static void taiko_update_reg_defaults(struct snd_soc_codec *codec)
 {
 	u32 i;
+	struct wcd9xxx *taiko_core = dev_get_drvdata(codec->dev->parent);
 
-	for (i = 0; i < ARRAY_SIZE(taiko_1_0_reg_defaults); i++)
-		snd_soc_write(codec, taiko_1_0_reg_defaults[i].reg,
+	for (i = 0; i < ARRAY_SIZE(taiko_reg_defaults); i++)
+		snd_soc_write(codec, taiko_reg_defaults[i].reg,
+				taiko_reg_defaults[i].val);
+
+	if (TAIKO_IS_1_0(taiko_core->version)) {
+		for (i = 0; i < ARRAY_SIZE(taiko_1_0_reg_defaults); i++)
+			snd_soc_write(codec, taiko_1_0_reg_defaults[i].reg,
 				taiko_1_0_reg_defaults[i].val);
+	}
 }
 
 static const struct taiko_reg_mask_val taiko_codec_reg_init_val[] = {
 	/* Initialize current threshold to 350MA
 	 * number of wait and run cycles to 4096
 	 */
-	{TAIKO_A_RX_HPH_OCP_CTL, 0xE0, 0x60},
+	{TAIKO_A_RX_HPH_OCP_CTL, 0xE1, 0x61},
 	{TAIKO_A_RX_COM_OCP_COUNT, 0xFF, 0xFF},
 
 	/* Initialize gain registers to use register gain */
@@ -7185,7 +7213,7 @@
 
 	/* Use 16 bit sample size for RX */
 	{TAIKO_A_CDC_CONN_RX_SB_B1_CTL, 0xFF, 0xAA},
-	{TAIKO_A_CDC_CONN_RX_SB_B2_CTL, 0xFF, 0xAA},
+	{TAIKO_A_CDC_CONN_RX_SB_B2_CTL, 0xFF, 0x2A},
 
 	/*enable HPF filter for TX paths */
 	{TAIKO_A_CDC_TX1_MUX_CTL, 0x8, 0x0},
@@ -7601,7 +7629,7 @@
 	.volatile_register = taiko_volatile,
 
 	.reg_cache_size = TAIKO_CACHE_SIZE,
-	.reg_cache_default = taiko_reg_defaults,
+	.reg_cache_default = taiko_reset_reg_defaults,
 	.reg_word_size = 1,
 
 	.controls = taiko_snd_controls,
diff --git a/sound/soc/codecs/wcd9320.h b/sound/soc/codecs/wcd9320.h
index 739ab17..7ca8ff0 100644
--- a/sound/soc/codecs/wcd9320.h
+++ b/sound/soc/codecs/wcd9320.h
@@ -36,7 +36,7 @@
 				SND_JACK_BTN_6 | SND_JACK_BTN_7)
 
 extern const u8 taiko_reg_readable[TAIKO_CACHE_SIZE];
-extern const u8 taiko_reg_defaults[TAIKO_CACHE_SIZE];
+extern const u8 taiko_reset_reg_defaults[TAIKO_CACHE_SIZE];
 
 enum taiko_micbias_num {
 	TAIKO_MICBIAS1 = 0,
diff --git a/sound/soc/msm/apq8064-i2s.c b/sound/soc/msm/apq8064-i2s.c
index 162f39d..f57d686 100644
--- a/sound/soc/msm/apq8064-i2s.c
+++ b/sound/soc/msm/apq8064-i2s.c
@@ -208,6 +208,7 @@
 
 static struct snd_soc_jack hs_jack;
 static struct snd_soc_jack button_jack;
+static atomic_t auxpcm_rsc_ref;
 
 static int apq8064_i2s_hs_detect_use_gpio = -1;
 module_param(apq8064_i2s_hs_detect_use_gpio, int, 0444);
@@ -2095,8 +2096,10 @@
 {
 	int ret = 0;
 
-	pr_debug("%s(): substream = %s\n", __func__, substream->name);
-	ret = msm_aux_pcm_get_gpios();
+	pr_debug("%s(): substream = %s, auxpcm_rsc_ref counter = %d\n",
+		__func__, substream->name, atomic_read(&auxpcm_rsc_ref));
+	if (atomic_inc_return(&auxpcm_rsc_ref) == 1)
+		ret = msm_aux_pcm_get_gpios();
 	if (ret < 0) {
 		pr_err("%s: Aux PCM GPIO request failed\n", __func__);
 		return -EINVAL;
@@ -2120,8 +2123,10 @@
 static void msm_auxpcm_shutdown(struct snd_pcm_substream *substream)
 {
 
-	pr_debug("%s(): substream = %s\n", __func__, substream->name);
-	msm_aux_pcm_free_gpios();
+	pr_debug("%s(): substream = %s, auxpcm_rsc_ref counter = %d\n",
+		__func__, substream->name, atomic_read(&auxpcm_rsc_ref));
+	if (atomic_dec_return(&auxpcm_rsc_ref) == 0)
+		msm_aux_pcm_free_gpios();
 }
 
 static void msm_shutdown(struct snd_pcm_substream *substream)
@@ -2710,6 +2715,7 @@
 		.no_pcm = 1,
 		.be_id = MSM_BACKEND_DAI_AUXPCM_TX,
 		.be_hw_params_fixup = msm_auxpcm_be_params_fixup,
+		.ops = &msm_auxpcm_be_ops,
 	},
 };
 
@@ -2785,6 +2791,7 @@
 
 	mutex_init(&cdc_mclk_mutex);
 	atomic_set(&mi2s_rsc_ref, 0);
+	atomic_set(&auxpcm_rsc_ref, 0);
 	return ret;
 
 }
diff --git a/sound/soc/msm/apq8064.c b/sound/soc/msm/apq8064.c
index 80d6e5d..c8cf681 100644
--- a/sound/soc/msm/apq8064.c
+++ b/sound/soc/msm/apq8064.c
@@ -100,6 +100,7 @@
 
 static struct snd_soc_jack hs_jack;
 static struct snd_soc_jack button_jack;
+static atomic_t auxpcm_rsc_ref;
 
 static int apq8064_hs_detect_use_gpio = -1;
 module_param(apq8064_hs_detect_use_gpio, int, 0444);
@@ -1468,8 +1469,10 @@
 {
 	int ret = 0;
 
-	pr_debug("%s(): substream = %s\n", __func__, substream->name);
-	ret = msm_aux_pcm_get_gpios();
+	pr_debug("%s(): substream = %s, auxpcm_rsc_ref counter = %d\n",
+		__func__, substream->name, atomic_read(&auxpcm_rsc_ref));
+	if (atomic_inc_return(&auxpcm_rsc_ref) == 1)
+		ret = msm_aux_pcm_get_gpios();
 	if (ret < 0) {
 		pr_err("%s: Aux PCM GPIO request failed\n", __func__);
 		return -EINVAL;
@@ -1493,8 +1496,10 @@
 static void msm_auxpcm_shutdown(struct snd_pcm_substream *substream)
 {
 
-	pr_debug("%s(): substream = %s\n", __func__, substream->name);
-	msm_aux_pcm_free_gpios();
+	pr_debug("%s(): substream = %s, auxpcm_rsc_ref counter = %d\n",
+		__func__, substream->name, atomic_read(&auxpcm_rsc_ref));
+	if (atomic_dec_return(&auxpcm_rsc_ref) == 0)
+		msm_aux_pcm_free_gpios();
 }
 
 static void msm_shutdown(struct snd_pcm_substream *substream)
@@ -1933,6 +1938,7 @@
 		.no_pcm = 1,
 		.be_id = MSM_BACKEND_DAI_AUXPCM_TX,
 		.be_hw_params_fixup = msm_auxpcm_be_params_fixup,
+		.ops = &msm_auxpcm_be_ops,
 	},
 	{
 		.name = LPASS_BE_STUB_RX,
@@ -2127,6 +2133,7 @@
 	}
 
 	mutex_init(&cdc_mclk_mutex);
+	atomic_set(&auxpcm_rsc_ref, 0);
 	return ret;
 
 }
diff --git a/sound/soc/msm/mpq8064.c b/sound/soc/msm/mpq8064.c
index 499e4b6..957b656 100644
--- a/sound/soc/msm/mpq8064.c
+++ b/sound/soc/msm/mpq8064.c
@@ -134,7 +134,7 @@
 static int msm_slim_0_rx_ch = 1;
 static int msm_slim_0_tx_ch = 1;
 static int msm_hdmi_rx_ch = 8;
-
+static int mi2s_rate_variable;
 static struct clk *codec_clk;
 static int clk_users;
 
@@ -517,6 +517,7 @@
 static const char *slim0_tx_ch_text[] = {"One", "Two", "Three", "Four"};
 static const char * const hdmi_rx_ch_text[] = {"Two", "Three", "Four",
 					"Five", "Six", "Seven", "Eight"};
+static const char * const mi2s_rate[] = {"Default", "Variable"};
 
 
 static const struct soc_enum msm_enum[] = {
@@ -524,6 +525,7 @@
 	SOC_ENUM_SINGLE_EXT(2, slim0_rx_ch_text),
 	SOC_ENUM_SINGLE_EXT(4, slim0_tx_ch_text),
 	SOC_ENUM_SINGLE_EXT(7, hdmi_rx_ch_text),
+	SOC_ENUM_SINGLE_EXT(2, mi2s_rate),
 
 };
 
@@ -584,6 +586,20 @@
 	return 1;
 }
 
+static int msm_mi2s_rate_put(struct snd_kcontrol *kcontrol,
+				struct snd_ctl_elem_value *ucontrol)
+{
+	mi2s_rate_variable = ucontrol->value.integer.value[0];
+	pr_debug("%s: mi2s_rate_variable = %d\n", __func__, mi2s_rate_variable);
+	return 0;
+}
+
+static int msm_mi2s_rate_get(struct snd_kcontrol *kcontrol,
+				struct snd_ctl_elem_value *ucontrol)
+{
+	ucontrol->value.integer.value[0] = mi2s_rate_variable;
+	return 0;
+}
 
 static const struct snd_kcontrol_new tabla_msm_controls[] = {
 	SOC_ENUM_EXT("Speaker Function", msm_enum[0], msm_get_spk,
@@ -594,6 +610,9 @@
 		msm_slim_0_tx_ch_get, msm_slim_0_tx_ch_put),
 	SOC_ENUM_EXT("HDMI_RX Channels", msm_enum[3],
 		msm_hdmi_rx_ch_get, msm_hdmi_rx_ch_put),
+	SOC_ENUM_EXT("SEC RX Rate", msm_enum[4],
+					msm_mi2s_rate_get,
+					msm_mi2s_rate_put),
 
 };
 
@@ -813,11 +832,16 @@
 static int msm_be_i2s_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
 			struct snd_pcm_hw_params *params)
 {
+	struct snd_interval *rate = hw_param_interval(params,
+					SNDRV_PCM_HW_PARAM_RATE);
 
 	struct snd_interval *channels = hw_param_interval(params,
 					SNDRV_PCM_HW_PARAM_CHANNELS);
 
-	pr_debug("%s()\n", __func__);
+	pr_debug("%s mi2s_rate_variable = %d\n", __func__, mi2s_rate_variable);
+	/*Configure the sample rate as 48000 KHz for the LPCM playback*/
+	if (!mi2s_rate_variable)
+		rate->min = rate->max = 48000;
 	channels->min =  channels->max = 2;
 
 	return 0;
diff --git a/sound/soc/msm/msm-compr-q6.c b/sound/soc/msm/msm-compr-q6.c
index 78b3abc..172b02c 100644
--- a/sound/soc/msm/msm-compr-q6.c
+++ b/sound/soc/msm/msm-compr-q6.c
@@ -31,6 +31,7 @@
 #include <linux/dma-mapping.h>
 #include <linux/android_pmem.h>
 #include <sound/timer.h>
+#include <mach/qdsp6v2/q6core.h>
 
 #include "msm-compr-q6.h"
 #include "msm-pcm-routing.h"
@@ -499,6 +500,13 @@
 			pr_err("%s: CMD Format block" \
 				"failed: %d\n", __func__, ret);
 		break;
+	case SND_AUDIOCODEC_PCM:
+		pr_debug("SND_AUDIOCODEC_PCM\n");
+		ret = q6asm_enc_cfg_blk_multi_ch_pcm(prtd->audio_client,
+			 prtd->samp_rate, prtd->channel_mode);
+		if (ret < 0)
+			pr_info("%s: CMD Format block failed\n", __func__);
+		break;
 	default:
 		pr_debug("No config for codec %d\n", codec->id);
 	}
@@ -511,6 +519,7 @@
 		read_param.uid = i;
 		switch (codec->id) {
 		case SND_AUDIOCODEC_AMRWB:
+		case SND_AUDIOCODEC_PCM:
 			read_param.len = prtd->pcm_count
 					- COMPRE_CAPTURE_HEADER_SIZE;
 			read_param.paddr = (unsigned long)(buf[i].phys)
@@ -521,11 +530,15 @@
 					buf[i].data);
 			q6asm_async_read(prtd->audio_client, &read_param);
 			break;
-		default:
+		case SND_AUDIOCODEC_PASS_THROUGH:
 			read_param.paddr = (unsigned long)(buf[i].phys);
 			q6asm_async_read_compressed(prtd->audio_client,
 				&read_param);
 			break;
+		default:
+			pr_err("Invalid format");
+			ret = -EINVAL;
+			break;
 		}
 	}
 	prtd->periods = runtime->periods;
@@ -620,7 +633,7 @@
 {
 	pr_debug("%s\n", __func__);
 	/* MP3 Block */
-	compr->info.compr_cap.num_codecs = 10;
+	compr->info.compr_cap.num_codecs = 12;
 	compr->info.compr_cap.min_fragment_size = runtime->hw.period_bytes_min;
 	compr->info.compr_cap.max_fragment_size = runtime->hw.period_bytes_max;
 	compr->info.compr_cap.min_fragments = runtime->hw.periods_min;
@@ -635,6 +648,8 @@
 	compr->info.compr_cap.codecs[7] = SND_AUDIOCODEC_DTS_PASS_THROUGH;
 	compr->info.compr_cap.codecs[8] = SND_AUDIOCODEC_AMRWB;
 	compr->info.compr_cap.codecs[9] = SND_AUDIOCODEC_AMRWBPLUS;
+	compr->info.compr_cap.codecs[10] = SND_AUDIOCODEC_PASS_THROUGH;
+	compr->info.compr_cap.codecs[11] = SND_AUDIOCODEC_PCM;
 	/* Add new codecs here and update num_codecs*/
 }
 
@@ -909,12 +924,30 @@
 					prtd->audio_client->perf_mode,
 					prtd->session_id, substream->stream);
 			break;
-		default:
+		case SND_AUDIOCODEC_PCM:
+			pr_debug("q6asm_open_read(FORMAT_PCM)\n");
+			ret = q6asm_open_read(prtd->audio_client,
+				FORMAT_MULTI_CHANNEL_LINEAR_PCM);
+			if (ret < 0) {
+				pr_err("%s: compressed Session open failed\n",
+					__func__);
+				return -ENOMEM;
+			}
+			pr_debug("msm_pcm_routing_reg_phy_stream\n");
+			msm_pcm_routing_reg_phy_stream(
+					soc_prtd->dai_link->be_id,
+					prtd->audio_client->perf_mode,
+					prtd->session_id, substream->stream);
+			break;
+		case SND_AUDIOCODEC_PASS_THROUGH:
 			pr_debug("q6asm_open_read_compressed(COMPRESSED_META_DATA_MODE)\n");
 			ret = q6asm_open_read_compressed(prtd->audio_client,
 				MAX_NUM_FRAMES_PER_BUFFER,
 				COMPRESSED_META_DATA_MODE);
 			break;
+		default:
+			pr_err("Invalid codec for compressed session open\n");
+			return -EFAULT;
 		}
 
 		if (ret < 0) {
@@ -1047,13 +1080,37 @@
 			pr_debug("SND_AUDIOCODEC_DTS_PASS_THROUGH\n");
 			compr->codec = FORMAT_DTS;
 			break;
-		case SND_AUDIOCODEC_DTS:
+		case SND_AUDIOCODEC_DTS: {
+			char modelId[128];
+			struct snd_dec_dts opt_dts =
+				compr->info.codec_param.codec.options.dts;
+			int modelIdLength = opt_dts.modelIdLength;
 			pr_debug("SND_AUDIOCODEC_DTS\n");
+			if (copy_from_user(modelId, (void *)opt_dts.modelId,
+				modelIdLength))
+				pr_err("%s: ERROR: copy modelId\n", __func__);
+			modelId[modelIdLength] = '\0';
+			pr_debug("%s: Received modelId =%s,length=%d\n",
+				__func__, modelId, modelIdLength);
+			core_set_dts_model_id(modelIdLength, modelId);
 			compr->codec = FORMAT_DTS;
+			}
 			break;
-		case SND_AUDIOCODEC_DTS_LBR:
-			pr_debug("SND_AUDIOCODEC_DTS\n");
+		case SND_AUDIOCODEC_DTS_LBR:{
+			char modelId[128];
+			struct snd_dec_dts opt_dts =
+				compr->info.codec_param.codec.options.dts;
+			int modelIdLength = opt_dts.modelIdLength;
+			pr_debug("SND_AUDIOCODEC_DTS_LBR\n");
+			if (copy_from_user(modelId, (void *)opt_dts.modelId,
+					modelIdLength))
+				pr_err("%s: ERROR: copy modelId\n", __func__);
+			modelId[modelIdLength] = '\0';
+			pr_debug("%s: Received modelId =%s,length=%d\n",
+				__func__, modelId, modelIdLength);
+			core_set_dts_model_id(modelIdLength, modelId);
 			compr->codec = FORMAT_DTS_LBR;
+			}
 			break;
 		case SND_AUDIOCODEC_AMRWB:
 			pr_debug("msm_compr_ioctl SND_AUDIOCODEC_AMRWB\n");
@@ -1063,11 +1120,19 @@
 			pr_debug("msm_compr_ioctl SND_AUDIOCODEC_AMRWBPLUS\n");
 			compr->codec = FORMAT_AMR_WB_PLUS;
 			break;
-		default:
-			/*Needed for the HDMI IN compressed use case*/
-			pr_debug("FORMAT_LINEAR_PCM\n");
-			compr->codec = FORMAT_LINEAR_PCM;
+		case SND_AUDIOCODEC_PASS_THROUGH:
+			/* format pass through is used for HDMI IN compressed
+			   where the decoder format is indicated by LPASS */
+			pr_debug("msm_compr_ioctl SND_AUDIOCODEC_PASSTHROUGH\n");
+			compr->codec = FORMAT_PASS_THROUGH;
 			break;
+		case SND_AUDIOCODEC_PCM:
+			pr_debug("msm_compr_ioctl SND_AUDIOCODEC_PCM\n");
+			compr->codec = FORMAT_MULTI_CHANNEL_LINEAR_PCM;
+			break;
+		default:
+			pr_err("msm_compr_ioctl failed..unknown codec\n");
+			return -EFAULT;
 		}
 		return 0;
 	case SNDRV_PCM_IOCTL1_RESET:
diff --git a/sound/soc/msm/msm-pcm-routing.c b/sound/soc/msm/msm-pcm-routing.c
index 52f4644..4d0caa3 100644
--- a/sound/soc/msm/msm-pcm-routing.c
+++ b/sound/soc/msm/msm-pcm-routing.c
@@ -1749,6 +1749,9 @@
 	SOC_SINGLE_EXT("PRIMARY_I2S_TX", MSM_BACKEND_DAI_PRI_I2S_TX,
 	MSM_FRONTEND_DAI_VOICE_STUB, 1, 0, msm_routing_get_voice_stub_mixer,
 	msm_routing_put_voice_stub_mixer),
+	SOC_SINGLE_EXT("AFE_PCM_TX", MSM_BACKEND_DAI_AFE_PCM_TX,
+	MSM_FRONTEND_DAI_VOICE_STUB, 1, 0, msm_routing_get_voice_stub_mixer,
+	msm_routing_put_voice_stub_mixer),
 };
 
 static const struct snd_kcontrol_new sbus_0_rx_port_mixer_controls[] = {
@@ -1779,6 +1782,9 @@
 	SOC_SINGLE_EXT("INTERNAL_BT_SCO_TX", MSM_BACKEND_DAI_SLIMBUS_1_RX,
 	MSM_BACKEND_DAI_INT_BT_SCO_TX, 1, 0, msm_routing_get_port_mixer,
 	msm_routing_put_port_mixer),
+	SOC_SINGLE_EXT("AFE_PCM_TX", MSM_BACKEND_DAI_SLIMBUS_1_RX,
+	MSM_BACKEND_DAI_AFE_PCM_TX, 1, 0, msm_routing_get_port_mixer,
+	msm_routing_put_port_mixer),
 };
 
 static const struct snd_kcontrol_new sbus_3_rx_port_mixer_controls[] = {
@@ -1788,6 +1794,9 @@
 	SOC_SINGLE_EXT("MI2S_TX", MSM_BACKEND_DAI_SLIMBUS_3_RX,
 	MSM_BACKEND_DAI_MI2S_TX, 1, 0, msm_routing_get_port_mixer,
 	msm_routing_put_port_mixer),
+	SOC_SINGLE_EXT("AFE_PCM_RX", MSM_BACKEND_DAI_SLIMBUS_3_RX,
+	MSM_BACKEND_DAI_AFE_PCM_RX, 1, 0, msm_routing_get_port_mixer,
+	msm_routing_put_port_mixer),
 };
 static const struct snd_kcontrol_new bt_sco_rx_port_mixer_controls[] = {
 	SOC_SINGLE_EXT("SLIM_1_TX", MSM_BACKEND_DAI_INT_BT_SCO_RX,
@@ -1799,6 +1808,9 @@
 	SOC_SINGLE_EXT("INTERNAL_FM_TX", MSM_BACKEND_DAI_AFE_PCM_RX,
 	MSM_BACKEND_DAI_INT_FM_TX, 1, 0, msm_routing_get_port_mixer,
 	msm_routing_put_port_mixer),
+	SOC_SINGLE_EXT("SLIM_1_TX", MSM_BACKEND_DAI_AFE_PCM_RX,
+	MSM_BACKEND_DAI_SLIMBUS_1_TX, 1, 0, msm_routing_get_port_mixer,
+	msm_routing_put_port_mixer),
 };
 
 
@@ -2555,6 +2567,7 @@
 	{"SLIMBUS_0_RX Port Mixer", "MI2S_TX", "MI2S_TX"},
 	{"SLIMBUS_0_RX", NULL, "SLIMBUS_0_RX Port Mixer"},
 	{"AFE_PCM_RX Port Mixer", "INTERNAL_FM_TX", "INT_FM_TX"},
+	{"AFE_PCM_RX Port Mixer", "SLIM_1_TX", "SLIMBUS_1_TX"},
 	{"PCM_RX", NULL, "AFE_PCM_RX Port Mixer"},
 
 	{"AUXPCM_RX Port Mixer", "AUX_PCM_UL_TX", "AUX_PCM_TX"},
@@ -2568,6 +2581,7 @@
 	{"Voice Stub Tx Mixer", "MI2S_TX", "MI2S_TX"},
 	{"Voice Stub Tx Mixer", "SLIM_3_TX", "SLIMBUS_3_TX"},
 	{"Voice Stub Tx Mixer", "PRIMARY_I2S_TX", "PRI_I2S_TX"},
+	{"Voice Stub Tx Mixer", "AFE_PCM_TX", "PCM_TX"},
 	{"VOICE_STUB_UL", NULL, "Voice Stub Tx Mixer"},
 
 	{"STUB_RX Mixer", "Voice Stub", "VOICE_STUB_DL"},
@@ -2578,16 +2592,19 @@
 	{"MI2S_RX_Voice Mixer", "Voice Stub", "VOICE_STUB_DL"},
 	{"MI2S_RX", NULL, "MI2S_RX_Voice Mixer"},
 	{"HDMI_RX_Voice Mixer", "Voice Stub", "VOICE_STUB_DL"},
+	{"AFE_PCM_RX_Voice Mixer", "Voice Stub", "VOICE_STUB_DL"},
 
 	{"SLIMBUS_3_RX_Voice Mixer", "Voice Stub", "VOICE_STUB_DL"},
 	{"SLIMBUS_3_RX", NULL, "SLIMBUS_3_RX_Voice Mixer"},
 
 	{"SLIMBUS_1_RX Port Mixer", "INTERNAL_BT_SCO_TX", "INT_BT_SCO_TX"},
+	{"SLIMBUS_1_RX Port Mixer", "AFE_PCM_TX", "PCM_TX"},
 	{"SLIMBUS_1_RX", NULL, "SLIMBUS_1_RX Port Mixer"},
 	{"INTERNAL_BT_SCO_RX Port Mixer", "SLIM_1_TX", "SLIMBUS_1_TX"},
 	{"INT_BT_SCO_RX", NULL, "INTERNAL_BT_SCO_RX Port Mixer"},
 	{"SLIMBUS_3_RX Port Mixer", "INTERNAL_BT_SCO_RX", "INT_BT_SCO_RX"},
 	{"SLIMBUS_3_RX Port Mixer", "MI2S_TX", "MI2S_TX"},
+	{"SLIMBUS_3_RX Port Mixer", "AFE_PCM_RX", "PCM_RX"},
 	{"SLIMBUS_3_RX", NULL, "SLIMBUS_3_RX Port Mixer"},
 
 
diff --git a/sound/soc/msm/msm8930.c b/sound/soc/msm/msm8930.c
index c8d4b02..4725e8e 100644
--- a/sound/soc/msm/msm8930.c
+++ b/sound/soc/msm/msm8930.c
@@ -66,6 +66,7 @@
 
 static struct snd_soc_jack hs_jack;
 static struct snd_soc_jack button_jack;
+static atomic_t auxpcm_rsc_ref;
 
 static int msm8930_enable_codec_ext_clk(
 		struct snd_soc_codec *codec, int enable,
@@ -860,8 +861,10 @@
 {
 	int ret = 0;
 
-	pr_debug("%s(): substream = %s\n", __func__, substream->name);
-	ret = msm8930_aux_pcm_get_gpios();
+	pr_debug("%s(): substream = %s, auxpcm_rsc_ref counter = %d\n",
+		__func__, substream->name, atomic_read(&auxpcm_rsc_ref));
+	if (atomic_inc_return(&auxpcm_rsc_ref) == 1)
+		ret = msm8930_aux_pcm_get_gpios();
 	if (ret < 0) {
 		pr_err("%s: Aux PCM GPIO request failed\n", __func__);
 		return -EINVAL;
@@ -872,8 +875,10 @@
 
 static void msm8930_auxpcm_shutdown(struct snd_pcm_substream *substream)
 {
-	pr_debug("%s(): substream = %s\n", __func__, substream->name);
-	msm8930_aux_pcm_free_gpios();
+	pr_debug("%s(): substream = %s, auxpcm_rsc_ref counter = %d\n",
+		__func__, substream->name, atomic_read(&auxpcm_rsc_ref));
+	if (atomic_dec_return(&auxpcm_rsc_ref) == 0)
+		msm8930_aux_pcm_free_gpios();
 }
 
 static void msm8930_shutdown(struct snd_pcm_substream *substream)
@@ -1229,6 +1234,7 @@
 		.no_pcm = 1,
 		.be_id = MSM_BACKEND_DAI_AUXPCM_TX,
 		.be_hw_params_fixup = msm8930_auxpcm_be_params_fixup,
+		.ops = &msm8930_auxpcm_be_ops,
 	},
 	/* Incall Music BACK END DAI Link */
 	{
@@ -1336,6 +1342,7 @@
 	} else
 		msm8930_headset_gpios_configured = 1;
 
+	atomic_set(&auxpcm_rsc_ref, 0);
 	return ret;
 
 }
diff --git a/sound/soc/msm/msm8960.c b/sound/soc/msm/msm8960.c
index 1338e2f..59d118e 100644
--- a/sound/soc/msm/msm8960.c
+++ b/sound/soc/msm/msm8960.c
@@ -83,6 +83,7 @@
 
 static struct snd_soc_jack hs_jack;
 static struct snd_soc_jack button_jack;
+static atomic_t auxpcm_rsc_ref;
 
 static bool hs_detect_use_gpio;
 module_param(hs_detect_use_gpio, bool, 0444);
@@ -1131,8 +1132,11 @@
 {
 	int ret = 0;
 
-	pr_debug("%s(): substream = %s\n", __func__, substream->name);
-	ret = msm8960_aux_pcm_get_gpios();
+	pr_debug("%s(): substream = %s, auxpcm_rsc_ref counter = %d\n",
+		__func__, substream->name, atomic_read(&auxpcm_rsc_ref));
+	if (atomic_inc_return(&auxpcm_rsc_ref) == 1)
+		ret = msm8960_aux_pcm_get_gpios();
+
 	if (ret < 0) {
 		pr_err("%s: Aux PCM GPIO request failed\n", __func__);
 		return -EINVAL;
@@ -1142,9 +1146,10 @@
 
 static void msm8960_auxpcm_shutdown(struct snd_pcm_substream *substream)
 {
-
-	pr_debug("%s(): substream = %s\n", __func__, substream->name);
-	msm8960_aux_pcm_free_gpios();
+	pr_debug("%s(): substream = %s, auxpcm_rsc_ref counter = %d\n",
+		__func__, substream->name, atomic_read(&auxpcm_rsc_ref));
+	if (atomic_dec_return(&auxpcm_rsc_ref) == 0)
+		msm8960_aux_pcm_free_gpios();
 }
 
 static void msm8960_shutdown(struct snd_pcm_substream *substream)
@@ -1522,6 +1527,7 @@
 		.no_pcm = 1,
 		.be_id = MSM_BACKEND_DAI_AUXPCM_TX,
 		.be_hw_params_fixup = msm8960_auxpcm_be_params_fixup,
+		.ops = &msm8960_auxpcm_be_ops,
 	},
 	/* Incall Music BACK END DAI Link */
 	{
@@ -1819,7 +1825,7 @@
 	}
 
 	mutex_init(&cdc_mclk_mutex);
-
+	atomic_set(&auxpcm_rsc_ref, 0);
 	return ret;
 
 }
diff --git a/sound/soc/msm/msm8974.c b/sound/soc/msm/msm8974.c
index 7e56a42..92b7324 100644
--- a/sound/soc/msm/msm8974.c
+++ b/sound/soc/msm/msm8974.c
@@ -88,6 +88,7 @@
 static struct mutex cdc_mclk_mutex;
 static struct q_clkdiv *codec_clk;
 static int clk_users;
+static atomic_t auxpcm_rsc_ref;
 
 static void msm_enable_ext_spk_amp_gpio(u32 spk_amp_gpio)
 {
@@ -553,8 +554,10 @@
 {
 	int ret = 0;
 
-	pr_debug("%s(): substream = %s\n", __func__, substream->name);
-	ret = msm_aux_pcm_get_gpios();
+	pr_debug("%s(): substream = %s, auxpcm_rsc_ref counter = %d\n",
+		__func__, substream->name, atomic_read(&auxpcm_rsc_ref));
+	if (atomic_inc_return(&auxpcm_rsc_ref) == 1)
+		ret = msm_aux_pcm_get_gpios();
 	if (ret < 0) {
 		pr_err("%s: Aux PCM GPIO request failed\n", __func__);
 		return -EINVAL;
@@ -565,8 +568,10 @@
 static void msm_auxpcm_shutdown(struct snd_pcm_substream *substream)
 {
 
-	pr_debug("%s(): substream = %s\n", __func__, substream->name);
-	msm_aux_pcm_free_gpios();
+	pr_debug("%s(): substream = %s, auxpcm_rsc_ref counter = %d\n",
+		__func__, substream->name, atomic_read(&auxpcm_rsc_ref));
+	if (atomic_dec_return(&auxpcm_rsc_ref) == 0)
+		msm_aux_pcm_free_gpios();
 }
 static struct snd_soc_ops msm_auxpcm_be_ops = {
 	.startup = msm_auxpcm_startup,
@@ -904,6 +909,7 @@
 		.no_pcm = 1,
 		.be_id = MSM_BACKEND_DAI_AUXPCM_TX,
 		.be_hw_params_fixup = msm_auxpcm_be_params_fixup,
+		.ops = &msm_auxpcm_be_ops,
 	},
 	/* Backend DAI Links */
 	{
@@ -1041,6 +1047,8 @@
 		goto err;
 	}
 	mutex_init(&cdc_mclk_mutex);
+	atomic_set(&auxpcm_rsc_ref, 0);
+
 	return 0;
 err:
 	devm_kfree(&pdev->dev, pdata);
diff --git a/sound/soc/msm/qdsp6/q6asm.c b/sound/soc/msm/qdsp6/q6asm.c
index 3a226b4..b086b8e 100644
--- a/sound/soc/msm/qdsp6/q6asm.c
+++ b/sound/soc/msm/qdsp6/q6asm.c
@@ -529,7 +529,7 @@
 					}
 					buf[cnt].handle = ion_alloc
 						(buf[cnt].client, bufsz, SZ_4K,
-						(0x1 << ION_AUDIO_HEAP_ID));
+						(0x1 << ION_AUDIO_HEAP_ID), 0);
 					if (IS_ERR_OR_NULL((void *)
 						buf[cnt].handle)) {
 						pr_err("%s: ION memory allocation for AUDIO failed\n",
@@ -551,8 +551,7 @@
 					}
 
 					buf[cnt].data = ion_map_kernel
-					(buf[cnt].client, buf[cnt].handle,
-							 0);
+					(buf[cnt].client, buf[cnt].handle);
 					if (IS_ERR_OR_NULL((void *)
 						buf[cnt].data)) {
 						pr_err("%s: ION memory mapping for AUDIO failed\n",
@@ -665,7 +664,7 @@
 		goto fail;
 	}
 	buf[0].handle = ion_alloc(buf[0].client, bufsz * bufcnt, SZ_4K,
-				  (0x1 << ION_AUDIO_HEAP_ID));
+				  (0x1 << ION_AUDIO_HEAP_ID), 0);
 	if (IS_ERR_OR_NULL((void *) buf[0].handle)) {
 		pr_err("%s: ION memory allocation for AUDIO failed\n",
 			__func__);
@@ -682,7 +681,7 @@
 		goto fail;
 	}
 
-	buf[0].data = ion_map_kernel(buf[0].client, buf[0].handle, 0);
+	buf[0].data = ion_map_kernel(buf[0].client, buf[0].handle);
 	if (IS_ERR_OR_NULL((void *) buf[0].data)) {
 		pr_err("%s: ION memory mapping for AUDIO failed\n", __func__);
 		mutex_unlock(&ac->cmd_lock);
@@ -876,8 +875,9 @@
 		case ASM_STREAM_CMD_OPEN_READ_COMPRESSED:
 			if (atomic_read(&ac->cmd_state) && wakeup_flag) {
 				atomic_set(&ac->cmd_state, 0);
-				if (payload[1] == ADSP_EUNSUPPORTED) {
-					pr_debug("paload[1]:%d unsupported",
+				if (payload[1] == ADSP_EUNSUPPORTED ||
+					payload[1] == ADSP_EFAILED) {
+					pr_debug("payload[1]:%d unsupported",
 								payload[1]);
 					atomic_set(&ac->cmd_response, 1);
 				}
diff --git a/sound/soc/msm/qdsp6/q6voice.c b/sound/soc/msm/qdsp6/q6voice.c
index 2a21dfa..cb2e39b 100644
--- a/sound/soc/msm/qdsp6/q6voice.c
+++ b/sound/soc/msm/qdsp6/q6voice.c
@@ -4061,7 +4061,7 @@
 
 	common.ion_handle = ion_alloc(common.ion_client,
 				TOTAL_VOICE_CAL_SIZE,
-				SZ_4K, ION_HEAP(ION_AUDIO_HEAP_ID));
+				SZ_4K, ION_HEAP(ION_AUDIO_HEAP_ID), 0);
 	if (IS_ERR_OR_NULL((void *) common.ion_handle)) {
 		pr_err("%s: ION memory allocation failed\n",
 			__func__);
@@ -4076,8 +4076,7 @@
 		goto err_ion_handle;
 	}
 
-	kvptr = ion_map_kernel(common.ion_client,
-				common.ion_handle, 0);
+	kvptr = ion_map_kernel(common.ion_client, common.ion_handle);
 	if (IS_ERR_OR_NULL(kvptr)) {
 		pr_err("%s: ION memory mapping failed\n", __func__);
 		goto err_ion_handle;
diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-voip-v2.c b/sound/soc/msm/qdsp6v2/msm-pcm-voip-v2.c
index 492569b..c7a8031 100644
--- a/sound/soc/msm/qdsp6v2/msm-pcm-voip-v2.c
+++ b/sound/soc/msm/qdsp6v2/msm-pcm-voip-v2.c
@@ -32,8 +32,9 @@
 #include "q6voice.h"
 #include "audio_ocmem.h"
 
+#define SHARED_MEM_BUF 2
 #define VOIP_MAX_Q_LEN 10
-#define VOIP_MAX_VOC_PKT_SIZE 640
+#define VOIP_MAX_VOC_PKT_SIZE 4096
 #define VOIP_MIN_VOC_PKT_SIZE 320
 
 /* Length of the DSP frame info header added to the voc packet. */
@@ -259,8 +260,8 @@
 
 /* capture path */
 static void voip_process_ul_pkt(uint8_t *voc_pkt,
-					uint32_t pkt_len,
-					void *private_data)
+				uint32_t pkt_len,
+				void *private_data)
 {
 	struct voip_buf_node *buf_node = NULL;
 	struct voip_drv_info *prtd = private_data;
@@ -315,8 +316,8 @@
 		default: {
 			buf_node->frame.len = pkt_len;
 			memcpy(&buf_node->frame.voc_pkt[0],
-				voc_pkt,
-				buf_node->frame.len);
+			       voc_pkt,
+			       buf_node->frame.len);
 			list_add_tail(&buf_node->list, &prtd->out_queue);
 		}
 		}
@@ -334,15 +335,12 @@
 }
 
 /* playback path */
-static void voip_process_dl_pkt(uint8_t *voc_pkt,
-					uint32_t *pkt_len,
-					void *private_data)
+static void voip_process_dl_pkt(uint8_t *voc_pkt, void *private_data)
 {
 	struct voip_buf_node *buf_node = NULL;
 	struct voip_drv_info *prtd = private_data;
 	unsigned long dsp_flags;
 
-
 	if (prtd->playback_substream == NULL)
 		return;
 
@@ -355,14 +353,18 @@
 		switch (prtd->mode) {
 		case MODE_AMR:
 		case MODE_AMR_WB: {
-			/* Add the DSP frame info header. Header format:
+			*((uint32_t *)voc_pkt) = buf_node->frame.len +
+							DSP_FRAME_HDR_LEN;
+			/* Advance to the header of voip packet */
+			voc_pkt = voc_pkt + sizeof(uint32_t);
+			/*
+			 * Add the DSP frame info header. Header format:
 			 * Bits 0-3: Frame rate
 			 * Bits 4-7: Frame type
 			 */
 			*voc_pkt = ((buf_node->frame.header.frame_type &
 					0x0F) << 4) | (prtd->rate_type & 0x0F);
 			voc_pkt = voc_pkt + DSP_FRAME_HDR_LEN;
-			*pkt_len = buf_node->frame.len + DSP_FRAME_HDR_LEN;
 			memcpy(voc_pkt,
 				&buf_node->frame.voc_pkt[0],
 				buf_node->frame.len);
@@ -372,12 +374,16 @@
 		case MODE_IS127:
 		case MODE_4GV_NB:
 		case MODE_4GV_WB: {
-			/* Add the DSP frame info header. Header format:
+			*((uint32_t *)voc_pkt) = buf_node->frame.len +
+							 DSP_FRAME_HDR_LEN;
+			/* Advance to the header of voip packet */
+			voc_pkt = voc_pkt + sizeof(uint32_t);
+			/*
+			 * Add the DSP frame info header. Header format:
 			 * Bits 0-3 : Frame rate
-			*/
+			 */
 			*voc_pkt = buf_node->frame.header.packet_rate & 0x0F;
 			voc_pkt = voc_pkt + DSP_FRAME_HDR_LEN;
-			*pkt_len = buf_node->frame.len + DSP_FRAME_HDR_LEN;
 
 			memcpy(voc_pkt,
 				&buf_node->frame.voc_pkt[0],
@@ -387,22 +393,19 @@
 			break;
 		}
 		default: {
-			*pkt_len = buf_node->frame.len;
-
+			*((uint32_t *)voc_pkt) = buf_node->frame.len;
+			voc_pkt = voc_pkt + sizeof(uint32_t);
 			memcpy(voc_pkt,
-				&buf_node->frame.voc_pkt[0],
-				buf_node->frame.len);
-
+			       &buf_node->frame.voc_pkt[0],
+			       buf_node->frame.len);
 			list_add_tail(&buf_node->list, &prtd->free_in_queue);
 		}
 		}
-		pr_debug("dl_pkt: pkt_len=%d, frame_len=%d\n", *pkt_len,
-			buf_node->frame.len);
 		prtd->pcm_playback_irq_pos += prtd->pcm_count;
 		spin_unlock_irqrestore(&prtd->dsp_lock, dsp_flags);
 		snd_pcm_period_elapsed(prtd->playback_substream);
 	} else {
-		*pkt_len = 0;
+		*((uint32_t *)voc_pkt) = 0;
 		spin_unlock_irqrestore(&prtd->dsp_lock, dsp_flags);
 		pr_err("DL data not available\n");
 	}
@@ -556,7 +559,7 @@
 		pr_err("%s: No free DL buffs\n", __func__);
 		ret = -ETIMEDOUT;
 	} else {
-		pr_err("%s: playback copy  was interrupted\n", __func__);
+		pr_err("%s: playback copy was interrupted %d\n", __func__, ret);
 	}
 
 	return  ret;
diff --git a/sound/soc/msm/qdsp6v2/q6asm.c b/sound/soc/msm/qdsp6v2/q6asm.c
index 714b2ce..9f98c1b 100644
--- a/sound/soc/msm/qdsp6v2/q6asm.c
+++ b/sound/soc/msm/qdsp6v2/q6asm.c
@@ -632,7 +632,7 @@
 					}
 					buf[cnt].handle = ion_alloc
 						(buf[cnt].client, bufsz, SZ_4K,
-						(0x1 << ION_AUDIO_HEAP_ID));
+						(0x1 << ION_AUDIO_HEAP_ID), 0);
 					if (IS_ERR_OR_NULL((void *)
 						buf[cnt].handle)) {
 						pr_err("%s: ION memory allocation for AUDIO failed\n",
@@ -652,8 +652,7 @@
 					}
 
 					buf[cnt].data = ion_map_kernel
-					(buf[cnt].client, buf[cnt].handle,
-							 0);
+					(buf[cnt].client, buf[cnt].handle);
 					if (IS_ERR_OR_NULL((void *)
 						buf[cnt].data)) {
 						pr_err("%s: ION memory mapping for AUDIO failed\n",
@@ -729,7 +728,7 @@
 		goto fail;
 	}
 	buf[0].handle = ion_alloc(buf[0].client, bufsz * bufcnt, SZ_4K,
-				  (0x1 << ION_AUDIO_HEAP_ID));
+				  (0x1 << ION_AUDIO_HEAP_ID), 0);
 	if (IS_ERR_OR_NULL((void *) buf[0].handle)) {
 		pr_err("%s: ION memory allocation for AUDIO failed\n",
 			__func__);
@@ -744,7 +743,7 @@
 		goto fail;
 	}
 
-	buf[0].data = ion_map_kernel(buf[0].client, buf[0].handle, 0);
+	buf[0].data = ion_map_kernel(buf[0].client, buf[0].handle);
 	if (IS_ERR_OR_NULL((void *) buf[0].data)) {
 		pr_err("%s: ION memory mapping for AUDIO failed\n", __func__);
 		goto fail;
diff --git a/sound/soc/msm/qdsp6v2/q6voice.c b/sound/soc/msm/qdsp6v2/q6voice.c
index f84b456..1f6dbf1 100644
--- a/sound/soc/msm/qdsp6v2/q6voice.c
+++ b/sound/soc/msm/qdsp6v2/q6voice.c
@@ -50,6 +50,15 @@
 static int voice_send_set_device_cmd(struct voice_data *v);
 static int voice_send_disable_vocproc_cmd(struct voice_data *v);
 static int voice_send_vol_index_cmd(struct voice_data *v);
+static int voice_send_mvm_map_memory_physical_cmd(struct voice_data *v);
+static int voice_send_mvm_unmap_memory_physical_cmd(struct voice_data *v,
+						    unsigned int bufcnt);
+static int voice_send_mvm_cal_network_cmd(struct voice_data *v);
+static int voice_send_mvm_media_type_cmd(struct voice_data *v);
+static int voice_send_cvs_data_exchange_mode_cmd(struct voice_data *v);
+static int voice_send_cvs_packet_exchange_config_cmd(struct voice_data *v);
+static int voice_set_packet_exchange_mode_and_config(uint16_t session_id,
+						     uint32_t mode);
 static int voice_cvs_stop_playback(struct voice_data *v);
 static int voice_cvs_start_playback(struct voice_data *v);
 static int voice_cvs_start_record(struct voice_data *v, uint32_t rec_mode);
@@ -594,7 +603,6 @@
 		detach_stream.detach_stream.handle = cvs_handle;
 
 		v->mvm_state = CMD_STATUS_FAIL;
-
 		ret = apr_send_pkt(apr_mvm, (uint32_t *) &detach_stream);
 		if (ret < 0) {
 			pr_err("%s: Error %d sending DETACH_STREAM\n",
@@ -608,6 +616,7 @@
 			pr_err("%s: wait event timeout\n", __func__);
 			goto fail;
 		}
+
 		/* Destroy CVS. */
 		pr_debug("%s: CVS destroy session\n", __func__);
 
@@ -622,7 +631,6 @@
 		cvs_destroy.opcode = APRV2_IBASIC_CMD_DESTROY_SESSION;
 
 		v->cvs_state = CMD_STATUS_FAIL;
-
 		ret = apr_send_pkt(apr_cvs, (uint32_t *) &cvs_destroy);
 		if (ret < 0) {
 			pr_err("%s: Error %d sending CVS DESTROY\n",
@@ -640,6 +648,13 @@
 		cvs_handle = 0;
 		voice_set_cvs_handle(v, cvs_handle);
 
+		ret = voice_send_mvm_unmap_memory_physical_cmd(v,
+							       NUM_OF_BUFFERS);
+		if (ret < 0) {
+			pr_err("%s CMD Memory_unmap_regions failed %d\n",
+				__func__, ret);
+		}
+
 		/* Destroy MVM. */
 		pr_debug("MVM destroy session\n");
 
@@ -667,7 +682,6 @@
 					 msecs_to_jiffies(TIMEOUT_MS));
 		if (!ret) {
 			pr_err("%s: wait event timeout\n", __func__);
-
 			goto fail;
 		}
 		mvm_handle = 0;
@@ -788,6 +802,58 @@
 	return 0;
 }
 
+static int voice_send_mvm_media_type_cmd(struct voice_data *v)
+{
+	struct vss_imvm_cmd_set_cal_media_type_t mvm_set_cal_media_type;
+	int ret = 0;
+	void *apr_mvm;
+	u16 mvm_handle;
+
+	if (v == NULL) {
+		pr_err("%s: v is NULL\n", __func__);
+		return -EINVAL;
+	}
+	apr_mvm = common.apr_q6_mvm;
+
+	if (!apr_mvm) {
+		pr_err("%s: apr_mvm is NULL.\n", __func__);
+		return -EINVAL;
+	}
+	mvm_handle = voice_get_mvm_handle(v);
+
+	mvm_set_cal_media_type.hdr.hdr_field =
+					APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
+					APR_HDR_LEN(APR_HDR_SIZE),
+					APR_PKT_VER);
+	mvm_set_cal_media_type.hdr.pkt_size = APR_PKT_SIZE(APR_HDR_SIZE,
+					sizeof(mvm_set_cal_media_type) -
+					APR_HDR_SIZE);
+	mvm_set_cal_media_type.hdr.src_port = v->session_id;
+	mvm_set_cal_media_type.hdr.dest_port = mvm_handle;
+	mvm_set_cal_media_type.hdr.token = 0;
+	mvm_set_cal_media_type.hdr.opcode = VSS_IMVM_CMD_SET_CAL_MEDIA_TYPE;
+	mvm_set_cal_media_type.media_id = common.mvs_info.media_type;
+	pr_debug("%s: setting media_id as %x\n",
+		 __func__ , mvm_set_cal_media_type.media_id);
+
+	v->mvm_state = CMD_STATUS_FAIL;
+	ret = apr_send_pkt(apr_mvm, (uint32_t *) &mvm_set_cal_media_type);
+	if (ret < 0) {
+		pr_err("%s: Error %d sending media type\n", __func__, ret);
+		goto fail;
+	}
+
+	ret = wait_event_timeout(v->mvm_wait,
+				(v->mvm_state == CMD_STATUS_SUCCESS),
+				 msecs_to_jiffies(TIMEOUT_MS));
+	if (!ret) {
+		pr_err("%s: wait_event timeout %d\n", __func__, ret);
+		goto fail;
+	}
+	return 0;
+fail:
+	return -EINVAL;
+}
 static int voice_config_cvs_vocoder(struct voice_data *v)
 {
 	int ret = 0;
@@ -813,7 +879,8 @@
 						APR_HDR_LEN(APR_HDR_SIZE),
 						APR_PKT_VER);
 	cvs_set_media_cmd.hdr.pkt_size = APR_PKT_SIZE(APR_HDR_SIZE,
-				      sizeof(cvs_set_media_cmd) - APR_HDR_SIZE);
+						sizeof(cvs_set_media_cmd) -
+						APR_HDR_SIZE);
 	cvs_set_media_cmd.hdr.src_port = v->session_id;
 	cvs_set_media_cmd.hdr.dest_port = cvs_handle;
 	cvs_set_media_cmd.hdr.token = 0;
@@ -826,7 +893,7 @@
 	ret = apr_send_pkt(apr_cvs, (uint32_t *) &cvs_set_media_cmd);
 	if (ret < 0) {
 		pr_err("%s: Error %d sending SET_MEDIA_TYPE\n",
-		       __func__, ret);
+			__func__, ret);
 
 		goto fail;
 	}
@@ -1196,6 +1263,102 @@
 	return -EINVAL;
 }
 
+static int voice_send_mvm_map_memory_physical_cmd(struct voice_data *v)
+{
+	struct vss_imemory_cmd_map_physical_t mvm_map_phys_cmd;
+	uint32_t *memtable;
+	int ret = 0;
+	void *apr_mvm;
+	u16 mvm_handle;
+
+	if (v == NULL) {
+		pr_err("%s: v is NULL\n", __func__);
+		return -EINVAL;
+	}
+
+	apr_mvm = common.apr_q6_mvm;
+
+	if (!apr_mvm) {
+		pr_err("%s: apr_mvm is NULL.\n", __func__);
+		return -EINVAL;
+	}
+
+	if (!v->shmem_info.memtbl.data) {
+		pr_err("%s: shmem_info.memtbl.data is NULL.\n", __func__);
+		return -EINVAL;
+	}
+
+	memtable = (uint32_t *)v->shmem_info.memtbl.data;
+
+	/*
+	 * Store next table descriptor's address(64 bit) as NULL as there
+	 * is only one memory block
+	 */
+	memtable[0] = (uint32_t)NULL;
+	memtable[1] = (uint32_t)NULL;
+
+	/* Store next table descriptor's size */
+	memtable[2] = 0;
+
+	/* Store shared mem add */
+	memtable[3] = v->shmem_info.sh_buf.buf[0].phys;
+	memtable[4] = 0;
+
+	/* Store shared memory size */
+	memtable[5] = v->shmem_info.sh_buf.buf[0].size * NUM_OF_BUFFERS;
+
+	mvm_handle = voice_get_mvm_handle(v);
+
+	mvm_map_phys_cmd.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
+				APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
+	mvm_map_phys_cmd.hdr.pkt_size = APR_PKT_SIZE(APR_HDR_SIZE,
+				sizeof(mvm_map_phys_cmd) - APR_HDR_SIZE);
+	mvm_map_phys_cmd.hdr.src_port = v->session_id;
+	mvm_map_phys_cmd.hdr.dest_port = mvm_handle;
+	mvm_map_phys_cmd.hdr.token = 0;
+	mvm_map_phys_cmd.hdr.opcode = VSS_IMEMORY_CMD_MAP_PHYSICAL;
+
+	mvm_map_phys_cmd.table_descriptor.mem_address =
+						v->shmem_info.memtbl.phys;
+	mvm_map_phys_cmd.table_descriptor.mem_size =
+			sizeof(struct vss_imemory_block_t) +
+			sizeof(struct vss_imemory_table_descriptor_t);
+	mvm_map_phys_cmd.is_cached = true;
+	mvm_map_phys_cmd.cache_line_size = 128;
+	mvm_map_phys_cmd.access_mask = 3;
+	mvm_map_phys_cmd.page_align = 4096;
+	mvm_map_phys_cmd.min_data_width = 8;
+	mvm_map_phys_cmd.max_data_width = 64;
+
+	pr_debug("%s: ntd->add: %lld, ntd->size: %d, table->add: 0x%x\n",
+		__func__,
+		*((uint64_t *)v->shmem_info.memtbl.data),
+		*(((uint32_t *)(v->shmem_info.memtbl.data)) + 2),
+		*(((uint32_t *)(v->shmem_info.memtbl.data)) + 3));
+	pr_debug("%s: table->size: %d, pkt_size: %d, mvm_handle: 0x%x\n",
+		__func__,
+		*(((uint32_t *)(v->shmem_info.memtbl.data)) + 5),
+		mvm_map_phys_cmd.hdr.pkt_size, mvm_handle);
+
+	v->mvm_state = CMD_STATUS_FAIL;
+	ret = apr_send_pkt(apr_mvm, (uint32_t *) &mvm_map_phys_cmd);
+	if (ret < 0) {
+		pr_err("Fail: sending mvm map phy cmd %d\n", ret);
+		goto fail;
+	}
+
+	ret = wait_event_timeout(v->mvm_wait,
+			(v->mvm_state == CMD_STATUS_SUCCESS),
+			msecs_to_jiffies(TIMEOUT_MS));
+	if (!ret) {
+		pr_err("%s: wait_event timeout %d\n", __func__, ret);
+		goto fail;
+	}
+
+	return 0;
+fail:
+	return -EINVAL;
+}
 
 static int voice_setup_vocproc(struct voice_data *v)
 {
@@ -1225,7 +1388,7 @@
 	cvp_session_cmd.hdr.dest_port = 0;
 	cvp_session_cmd.hdr.token = 0;
 	cvp_session_cmd.hdr.opcode =
-			VSS_IVOCPROC_CMD_CREATE_FULL_CONTROL_SESSION;
+			VSS_IVOCPROC_CMD_CREATE_FULL_CONTROL_SESSION_V2;
 
 	/* Use default topology if invalid value in ACDB */
 	cvp_session_cmd.cvp_session.tx_topology_id =
@@ -1241,16 +1404,24 @@
 			VSS_IVOCPROC_TOPOLOGY_ID_RX_DEFAULT;
 
 	cvp_session_cmd.cvp_session.direction = 2; /*tx and rx*/
-	cvp_session_cmd.cvp_session.network_id = VSS_NETWORK_ID_DEFAULT;
 	cvp_session_cmd.cvp_session.tx_port_id = v->dev_tx.port_id;
 	cvp_session_cmd.cvp_session.rx_port_id = v->dev_rx.port_id;
+	cvp_session_cmd.cvp_session.profile_id =
+					 VSS_ICOMMON_CAL_NETWORK_ID_NONE;
+	cvp_session_cmd.cvp_session.vocproc_mode =
+				 VSS_IVOCPROC_VOCPROC_MODE_EC_INT_MIXING;
+	cvp_session_cmd.cvp_session.ec_ref_port_id =
+						 VSS_IVOCPROC_PORT_ID_NONE;
 
-	pr_debug("topology=%d net_id=%d, dir=%d tx_port_id=%d, rx_port_id=%d\n",
+	pr_debug("tx_topology: %d tx_port_id=%d, rx_port_id=%d, mode: 0x%x\n",
 		cvp_session_cmd.cvp_session.tx_topology_id,
-		cvp_session_cmd.cvp_session.network_id,
-		cvp_session_cmd.cvp_session.direction,
 		cvp_session_cmd.cvp_session.tx_port_id,
-		cvp_session_cmd.cvp_session.rx_port_id);
+		cvp_session_cmd.cvp_session.rx_port_id,
+		cvp_session_cmd.cvp_session.vocproc_mode);
+	pr_debug("rx_topology: %d, profile_id: 0x%x, pkt_size: %d\n",
+		cvp_session_cmd.cvp_session.rx_topology_id,
+		cvp_session_cmd.cvp_session.profile_id,
+		cvp_session_cmd.hdr.pkt_size);
 
 	v->cvp_state = CMD_STATUS_FAIL;
 	ret = apr_send_pkt(apr_cvp, (uint32_t *) &cvp_session_cmd);
@@ -1266,7 +1437,6 @@
 		goto fail;
 	}
 
-
 	/* enable vocproc */
 	ret = voice_send_enable_vocproc_cmd(v);
 	if (ret < 0)
@@ -1280,9 +1450,19 @@
 	/* send tty mode if tty device is used */
 	voice_send_tty_mode_cmd(v);
 
+	if (is_voip_session(v->session_id)) {
+		ret = voice_send_mvm_cal_network_cmd(v);
+		if (ret < 0)
+			pr_err("%s: voice_send_mvm_cal_network_cmd: %d\n",
+				__func__, ret);
 
-	if (is_voip_session(v->session_id))
+		ret = voice_send_mvm_media_type_cmd(v);
+		if (ret < 0)
+			pr_err("%s: voice_send_mvm_media_type_cmd: %d\n",
+				__func__, ret);
+
 		voice_send_netid_timing_cmd(v);
+	}
 
 	/* Start in-call music delivery if this feature is enabled */
 	if (v->music_info.play_enable)
@@ -1350,6 +1530,55 @@
 	return -EINVAL;
 }
 
+static int voice_send_mvm_cal_network_cmd(struct voice_data *v)
+{
+	struct vss_imvm_cmd_set_cal_network_t mvm_set_cal_network;
+	int ret = 0;
+	void *apr_mvm;
+	u16 mvm_handle;
+
+	if (v == NULL) {
+		pr_err("%s: v is NULL\n", __func__);
+		return -EINVAL;
+	}
+	apr_mvm = common.apr_q6_mvm;
+
+	if (!apr_mvm) {
+		pr_err("%s: apr_mvm is NULL.\n", __func__);
+		return -EINVAL;
+	}
+	mvm_handle = voice_get_mvm_handle(v);
+
+	mvm_set_cal_network.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
+						APR_HDR_LEN(APR_HDR_SIZE),
+						APR_PKT_VER);
+	mvm_set_cal_network.hdr.pkt_size = APR_PKT_SIZE(APR_HDR_SIZE,
+				sizeof(mvm_set_cal_network) - APR_HDR_SIZE);
+	mvm_set_cal_network.hdr.src_port = v->session_id;
+	mvm_set_cal_network.hdr.dest_port = mvm_handle;
+	mvm_set_cal_network.hdr.token = 0;
+	mvm_set_cal_network.hdr.opcode = VSS_IMVM_CMD_SET_CAL_NETWORK;
+	mvm_set_cal_network.network_id = VSS_ICOMMON_CAL_NETWORK_ID_NONE;
+
+	v->mvm_state = CMD_STATUS_FAIL;
+	ret = apr_send_pkt(apr_mvm, (uint32_t *) &mvm_set_cal_network);
+	if (ret < 0) {
+		pr_err("%s: Error %d sending SET_NETWORK\n", __func__, ret);
+		goto fail;
+	}
+
+	ret = wait_event_timeout(v->mvm_wait,
+				(v->mvm_state == CMD_STATUS_SUCCESS),
+				 msecs_to_jiffies(TIMEOUT_MS));
+	if (!ret) {
+		pr_err("%s: wait_event timeout %d\n", __func__, ret);
+		goto fail;
+	}
+	return 0;
+fail:
+	return -EINVAL;
+}
+
 static int voice_send_netid_timing_cmd(struct voice_data *v)
 {
 	int ret = 0;
@@ -1590,10 +1819,177 @@
 
 	cvp_handle = 0;
 	voice_set_cvp_handle(v, cvp_handle);
+	return 0;
+fail:
+	return -EINVAL;
+}
 
+static int voice_send_mvm_unmap_memory_physical_cmd(struct voice_data *v,
+							 unsigned int bufcnt)
+{
+	struct vss_imemory_cmd_unmap_t mem_unmap;
+	int ret = 0;
+	void *apr_mvm;
+	u16 mvm_handle;
+
+	if (v == NULL) {
+		pr_err("%s: v is NULL\n", __func__);
+		return -EINVAL;
+	}
+	apr_mvm = common.apr_q6_mvm;
+
+	if (!apr_mvm) {
+		pr_err("%s: apr_mvm is NULL.\n", __func__);
+		return -EINVAL;
+	}
+	mvm_handle = voice_get_mvm_handle(v);
+
+	mem_unmap.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
+						APR_HDR_LEN(APR_HDR_SIZE),
+						APR_PKT_VER);
+	mem_unmap.hdr.pkt_size = APR_PKT_SIZE(APR_HDR_SIZE,
+				sizeof(mem_unmap) - APR_HDR_SIZE);
+	mem_unmap.hdr.src_port = v->session_id;
+	mem_unmap.hdr.dest_port = mvm_handle;
+	mem_unmap.hdr.token = 0;
+	mem_unmap.hdr.opcode = VSS_IMEMORY_CMD_UNMAP;
+	mem_unmap.mem_handle = v->shmem_info.mem_handle;
+
+	pr_debug("%s: mem_handle: ox%x\n", __func__, mem_unmap.mem_handle);
+
+	v->mvm_state = CMD_STATUS_FAIL;
+	ret = apr_send_pkt(apr_mvm, (uint32_t *) &mem_unmap);
+	if (ret < 0) {
+		pr_err("mem_unmap op[0x%x]ret[%d]\n",
+			mem_unmap.hdr.opcode, ret);
+		goto fail;
+	}
+
+	ret = wait_event_timeout(v->mvm_wait,
+				 (v->mvm_state == CMD_STATUS_SUCCESS),
+				 msecs_to_jiffies(TIMEOUT_MS));
+	if (!ret) {
+		pr_err("%s: wait_event timeout %d\n", __func__, ret);
+		goto fail;
+	}
 	return 0;
 
 fail:
+	return ret;
+}
+
+static int voice_send_cvs_packet_exchange_config_cmd(struct voice_data *v)
+{
+	struct vss_istream_cmd_set_oob_packet_exchange_config_t
+						 packet_exchange_config_pkt;
+	int ret = 0;
+	uint64_t *dec_buf;
+	uint64_t *enc_buf;
+	void *apr_cvs;
+	u16 cvs_handle;
+	dec_buf = (uint64_t *)v->shmem_info.sh_buf.buf[0].phys;
+	enc_buf = (uint64_t *)v->shmem_info.sh_buf.buf[1].phys;
+
+	if (v == NULL) {
+		pr_err("%s: v is NULL\n", __func__);
+		return -EINVAL;
+	}
+	apr_cvs = common.apr_q6_cvs;
+
+	if (!apr_cvs) {
+		pr_err("%s: apr_cvs is NULL.\n", __func__);
+		return -EINVAL;
+	}
+	cvs_handle = voice_get_cvs_handle(v);
+
+	packet_exchange_config_pkt.hdr.hdr_field = APR_HDR_FIELD(
+						APR_MSG_TYPE_SEQ_CMD,
+						APR_HDR_LEN(APR_HDR_SIZE),
+						APR_PKT_VER);
+	packet_exchange_config_pkt.hdr.pkt_size = APR_PKT_SIZE(APR_HDR_SIZE,
+					sizeof(packet_exchange_config_pkt) -
+					 APR_HDR_SIZE);
+	packet_exchange_config_pkt.hdr.src_port = v->session_id;
+	packet_exchange_config_pkt.hdr.dest_port = cvs_handle;
+	packet_exchange_config_pkt.hdr.token = 0;
+	packet_exchange_config_pkt.hdr.opcode =
+			 VSS_ISTREAM_CMD_SET_OOB_PACKET_EXCHANGE_CONFIG;
+	packet_exchange_config_pkt.mem_handle = v->shmem_info.mem_handle;
+	packet_exchange_config_pkt.dec_buf_addr = (uint32_t)dec_buf;
+	packet_exchange_config_pkt.dec_buf_size = 4096;
+	packet_exchange_config_pkt.enc_buf_addr = (uint32_t)enc_buf;
+	packet_exchange_config_pkt.enc_buf_size = 4096;
+
+	pr_debug("%s: dec buf: add %p, size %d, enc buf: add %p, size %d\n",
+		__func__,
+		dec_buf,
+		packet_exchange_config_pkt.dec_buf_size,
+		enc_buf,
+		packet_exchange_config_pkt.enc_buf_size);
+
+	v->cvs_state = CMD_STATUS_FAIL;
+	ret = apr_send_pkt(apr_cvs, (uint32_t *) &packet_exchange_config_pkt);
+	if (ret < 0) {
+		pr_err("Failed to send packet exchange config cmd %d\n", ret);
+		goto fail;
+	}
+
+	ret = wait_event_timeout(v->cvs_wait,
+				 (v->cvs_state == CMD_STATUS_SUCCESS),
+				 msecs_to_jiffies(TIMEOUT_MS));
+	if (!ret)
+		pr_err("%s: wait_event timeout %d\n", __func__, ret);
+
+	return 0;
+fail:
+	return -EINVAL;
+}
+
+static int voice_send_cvs_data_exchange_mode_cmd(struct voice_data *v)
+{
+	struct vss_istream_cmd_set_packet_exchange_mode_t data_exchange_pkt;
+	int ret = 0;
+	void *apr_cvs;
+	u16 cvs_handle;
+
+	if (v == NULL) {
+		pr_err("%s: v is NULL\n", __func__);
+		return -EINVAL;
+	}
+	apr_cvs = common.apr_q6_cvs;
+
+	if (!apr_cvs) {
+		pr_err("%s: apr_cvs is NULL.\n", __func__);
+		return -EINVAL;
+	}
+	cvs_handle = voice_get_cvs_handle(v);
+
+	data_exchange_pkt.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
+						APR_HDR_LEN(APR_HDR_SIZE),
+						APR_PKT_VER);
+	data_exchange_pkt.hdr.pkt_size = APR_PKT_SIZE(APR_HDR_SIZE,
+				sizeof(data_exchange_pkt) - APR_HDR_SIZE);
+	data_exchange_pkt.hdr.src_port = v->session_id;
+	data_exchange_pkt.hdr.dest_port = cvs_handle;
+	data_exchange_pkt.hdr.token = 0;
+	data_exchange_pkt.hdr.opcode = VSS_ISTREAM_CMD_SET_PACKET_EXCHANGE_MODE;
+	data_exchange_pkt.mode = VSS_ISTREAM_PACKET_EXCHANGE_MODE_OUT_OF_BAND;
+
+	v->cvs_state = CMD_STATUS_FAIL;
+	ret = apr_send_pkt(apr_cvs, (uint32_t *) &data_exchange_pkt);
+	if (ret < 0) {
+		pr_err("Failed to send data exchange mode %d\n", ret);
+		goto fail;
+	}
+
+	ret = wait_event_timeout(v->cvs_wait,
+				 (v->cvs_state == CMD_STATUS_SUCCESS),
+				 msecs_to_jiffies(TIMEOUT_MS));
+	if (!ret)
+		pr_err("%s: wait_event timeout %d\n", __func__, ret);
+
+	return 0;
+fail:
 	return -EINVAL;
 }
 
@@ -1878,7 +2274,6 @@
 	return 0;
 
 fail:
-
 	return ret;
 }
 
@@ -2202,16 +2597,54 @@
 			pr_err("%s:  set device failed\n", __func__);
 			goto fail;
 		}
-		/* send tty mode if tty device is used */
-		voice_send_tty_mode_cmd(v);
 
-		v->voc_state = VOC_RUN;
+	ret = voice_send_enable_vocproc_cmd(v);
+	if (ret < 0) {
+		pr_err("%s: enable vocproc failed %d\n", __func__, ret);
+		goto fail;
+	}
+
+	/* Send tty mode if tty device is used */
+	voice_send_tty_mode_cmd(v);
+
+	v->voc_state = VOC_RUN;
 	}
 
 fail:
 	mutex_unlock(&v->lock);
+	return ret;
+}
+
+static int voice_set_packet_exchange_mode_and_config(uint16_t session_id,
+						 uint32_t mode)
+{
+	struct voice_data *v = voice_get_session(session_id);
+	int ret = 0;
+
+	if (v == NULL) {
+		pr_err("%s: invalid session_id 0x%x\n", __func__, session_id);
+		return -EINVAL;
+	}
+
+	if (v->voc_state != VOC_RUN)
+		ret = voice_send_cvs_data_exchange_mode_cmd(v);
+
+	if (ret) {
+		pr_err("%s: Error voice_send_data_exchange_mode_cmd %d\n",
+			__func__, ret);
+		goto fail;
+	}
+
+	ret = voice_send_cvs_packet_exchange_config_cmd(v);
+	if (ret) {
+		pr_err("%s: Error: voice_send_packet_exchange_config_cmd %d\n",
+			__func__, ret);
+		goto fail;
+	}
 
 	return ret;
+fail:
+	return -EINVAL;
 }
 
 int voc_set_tx_mute(uint16_t session_id, uint32_t dir, uint32_t mute)
@@ -2552,6 +2985,22 @@
 			pr_err("create mvm and cvs failed\n");
 			goto fail;
 		}
+		if (is_voip_session(session_id)) {
+			ret = voice_send_mvm_map_memory_physical_cmd(v);
+			if (ret) {
+				pr_err("%s: mvm_map_memory_phy failed %d\n",
+					__func__, ret);
+				goto fail;
+			}
+			ret = voice_set_packet_exchange_mode_and_config(
+				session_id,
+				VSS_ISTREAM_PACKET_EXCHANGE_MODE_OUT_OF_BAND);
+			if (ret) {
+				pr_err("%s: Err: exchange_mode_and_config  %d\n",
+					__func__, ret);
+				goto fail;
+			}
+		}
 		ret = voice_send_dual_control_cmd(v);
 		if (ret < 0) {
 			pr_err("Err Dual command failed\n");
@@ -2570,7 +3019,8 @@
 
 		v->voc_state = VOC_RUN;
 	}
-fail:	mutex_unlock(&v->lock);
+fail:
+	mutex_unlock(&v->lock);
 	return ret;
 }
 
@@ -2638,6 +3088,7 @@
 		if (data->payload_size) {
 			ptr = data->payload;
 
+			pr_info("%x %x\n", ptr[0], ptr[1]);
 			/* ping mvm service ACK */
 			switch (ptr[0]) {
 			case VSS_IMVM_CMD_CREATE_PASSIVE_CONTROL_SESSION:
@@ -2666,6 +3117,9 @@
 			case VSS_ICOMMON_CMD_SET_VOICE_TIMING:
 			case VSS_IWIDEVOICE_CMD_SET_WIDEVOICE:
 			case VSS_IMVM_CMD_SET_POLICY_DUAL_CONTROL:
+			case VSS_IMVM_CMD_SET_CAL_NETWORK:
+			case VSS_IMVM_CMD_SET_CAL_MEDIA_TYPE:
+			case VSS_IMEMORY_CMD_UNMAP:
 				pr_debug("%s: cmd = 0x%x\n", __func__, ptr[0]);
 				v->mvm_state = CMD_STATUS_SUCCESS;
 				wake_up(&v->mvm_wait);
@@ -2676,8 +3130,19 @@
 				break;
 			}
 		}
+	} else if (data->opcode == VSS_IMEMORY_RSP_MAP) {
+		pr_debug("%s, Revd VSS_IMEMORY_RSP_MAP response\n", __func__);
+		if (data->payload_size) {
+			ptr = data->payload;
+			if (ptr[0]) {
+				v->shmem_info.mem_handle = ptr[0];
+				pr_debug("%s: shared mem_handle: 0x[%x]\n",
+					 __func__, v->shmem_info.mem_handle);
+				v->mvm_state = CMD_STATUS_SUCCESS;
+				wake_up(&v->mvm_wait);
+			}
+		}
 	}
-
 	return 0;
 }
 
@@ -2725,6 +3190,7 @@
 		if (data->payload_size) {
 			ptr = data->payload;
 
+			pr_info("%x %x\n", ptr[0], ptr[1]);
 			/*response from  CVS */
 			switch (ptr[0]) {
 			case VSS_ISTREAM_CMD_CREATE_PASSIVE_CONTROL_SESSION:
@@ -2754,6 +3220,8 @@
 			case VSS_ISTREAM_CMD_STOP_PLAYBACK:
 			case VSS_ISTREAM_CMD_START_RECORD:
 			case VSS_ISTREAM_CMD_STOP_RECORD:
+			case VSS_ISTREAM_CMD_SET_PACKET_EXCHANGE_MODE:
+			case VSS_ISTREAM_CMD_SET_OOB_PACKET_EXCHANGE_CONFIG:
 				pr_debug("%s: cmd = 0x%x\n", __func__, ptr[0]);
 				v->cvs_state = CMD_STATUS_SUCCESS;
 				wake_up(&v->cvs_wait);
@@ -2765,63 +3233,117 @@
 				break;
 			}
 		}
-	} else if (data->opcode == VSS_ISTREAM_EVT_SEND_ENC_BUFFER) {
-		uint32_t *voc_pkt = data->payload;
-		uint32_t pkt_len = data->payload_size;
-
-		if (voc_pkt != NULL && c->mvs_info.ul_cb != NULL) {
-			pr_debug("%s: Media type is 0x%x\n",
-				 __func__, voc_pkt[0]);
-
-			/* Remove media ID from payload. */
-			voc_pkt++;
-			pkt_len = pkt_len - 4;
-
-			c->mvs_info.ul_cb((uint8_t *)voc_pkt,
-					  pkt_len,
-					  c->mvs_info.private_data);
-		} else
-			pr_err("%s: voc_pkt is 0x%x ul_cb is 0x%x\n",
-			       __func__, (unsigned int)voc_pkt,
-			       (unsigned int) c->mvs_info.ul_cb);
-	} else if (data->opcode == VSS_ISTREAM_EVT_REQUEST_DEC_BUFFER) {
-		struct cvs_send_dec_buf_cmd send_dec_buf;
+	} else if (data->opcode ==
+			 VSS_ISTREAM_EVT_OOB_NOTIFY_ENC_BUFFER_READY) {
 		int ret = 0;
-		uint32_t pkt_len = 0;
+		u16 cvs_handle;
+		uint32_t *cvs_voc_pkt;
+		struct cvs_enc_buffer_consumed_cmd send_enc_buf_consumed_cmd;
+		void *apr_cvs;
 
-		if (c->mvs_info.dl_cb != NULL) {
-			send_dec_buf.dec_buf.media_id = c->mvs_info.media_type;
+		pr_debug("Encoder buffer is ready\n");
 
-			c->mvs_info.dl_cb(
-				(uint8_t *)&send_dec_buf.dec_buf.packet_data,
-				&pkt_len,
-				c->mvs_info.private_data);
+		apr_cvs = common.apr_q6_cvs;
+		if (!apr_cvs) {
+			pr_err("%s: apr_cvs is NULL\n", __func__);
+			return -EINVAL;
+		}
+		cvs_handle = voice_get_cvs_handle(v);
 
-			send_dec_buf.hdr.hdr_field =
-					APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
-					APR_HDR_LEN(APR_HDR_SIZE),
-					APR_PKT_VER);
-			send_dec_buf.hdr.pkt_size = APR_PKT_SIZE(APR_HDR_SIZE,
-			       sizeof(send_dec_buf.dec_buf.media_id) + pkt_len);
-			send_dec_buf.hdr.src_port = v->session_id;
-			send_dec_buf.hdr.dest_port = voice_get_cvs_handle(v);
-			send_dec_buf.hdr.token = 0;
-			send_dec_buf.hdr.opcode =
-					VSS_ISTREAM_EVT_SEND_DEC_BUFFER;
+		send_enc_buf_consumed_cmd.hdr.hdr_field =
+				APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
+				APR_HDR_LEN(APR_HDR_SIZE),
+				APR_PKT_VER);
+		send_enc_buf_consumed_cmd.hdr.pkt_size =
+			APR_PKT_SIZE(APR_HDR_SIZE,
+			sizeof(send_enc_buf_consumed_cmd) - APR_HDR_SIZE);
 
-			ret = apr_send_pkt(c->apr_q6_cvs,
-					   (uint32_t *) &send_dec_buf);
+		send_enc_buf_consumed_cmd.hdr.src_port = v->session_id;
+		send_enc_buf_consumed_cmd.hdr.dest_port = cvs_handle;
+		send_enc_buf_consumed_cmd.hdr.token = 0;
+		send_enc_buf_consumed_cmd.hdr.opcode =
+			VSS_ISTREAM_EVT_OOB_NOTIFY_ENC_BUFFER_CONSUMED;
+
+		cvs_voc_pkt = v->shmem_info.sh_buf.buf[1].data;
+		if (cvs_voc_pkt != NULL &&  common.mvs_info.ul_cb != NULL) {
+			common.mvs_info.ul_cb((uint8_t *)&cvs_voc_pkt[3],
+					      cvs_voc_pkt[2],
+					      common.mvs_info.private_data);
+		} else
+			pr_err("%s: cvs_voc_pkt or ul_cb is NULL\n", __func__);
+
+		ret = apr_send_pkt(apr_cvs,
+			(uint32_t *) &send_enc_buf_consumed_cmd);
+		if (ret < 0) {
+			pr_err("%s: Err send ENC_BUF_CONSUMED_NOTIFY %d\n",
+				__func__, ret);
+			goto fail;
+		}
+	} else if (data->opcode == VSS_ISTREAM_EVT_SEND_ENC_BUFFER) {
+		pr_debug("Recd VSS_ISTREAM_EVT_SEND_ENC_BUFFER\n");
+	} else if (data->opcode ==
+			 VSS_ISTREAM_EVT_OOB_NOTIFY_DEC_BUFFER_REQUEST) {
+		int ret = 0;
+		u16 cvs_handle;
+		uint32_t *cvs_voc_pkt;
+		struct cvs_dec_buffer_ready_cmd send_dec_buf;
+		void *apr_cvs;
+		apr_cvs = common.apr_q6_cvs;
+
+		if (!apr_cvs) {
+			pr_err("%s: apr_cvs is NULL\n", __func__);
+			return -EINVAL;
+		}
+		cvs_handle = voice_get_cvs_handle(v);
+
+		send_dec_buf.hdr.hdr_field =
+				APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
+				APR_HDR_LEN(APR_HDR_SIZE),
+				APR_PKT_VER);
+
+		send_dec_buf.hdr.pkt_size = APR_PKT_SIZE(APR_HDR_SIZE,
+					sizeof(send_dec_buf) - APR_HDR_SIZE);
+
+		send_dec_buf.hdr.src_port = v->session_id;
+		send_dec_buf.hdr.dest_port = cvs_handle;
+		send_dec_buf.hdr.token = 0;
+		send_dec_buf.hdr.opcode =
+				 VSS_ISTREAM_EVT_OOB_NOTIFY_DEC_BUFFER_READY;
+
+		cvs_voc_pkt = (uint32_t *)(v->shmem_info.sh_buf.buf[0].data);
+		if (cvs_voc_pkt != NULL && common.mvs_info.dl_cb != NULL) {
+			/* Set timestamp to 0 and advance the pointer */
+			cvs_voc_pkt[0] = 0;
+			/* Set media_type and advance the pointer */
+			cvs_voc_pkt[1] = common.mvs_info.media_type;
+			common.mvs_info.dl_cb(
+					      (uint8_t *)&cvs_voc_pkt[2],
+					      common.mvs_info.private_data);
+			ret = apr_send_pkt(apr_cvs, (uint32_t *) &send_dec_buf);
 			if (ret < 0) {
-				pr_err("%s: Error %d sending DEC_BUF\n",
-				       __func__, ret);
+				pr_err("%s: Err send DEC_BUF_READY_NOTIFI %d\n",
+					__func__, ret);
 				goto fail;
 			}
-		} else
-			pr_debug("%s: dl_cb is NULL\n", __func__);
+		} else {
+			pr_debug("%s: voc_pkt or dl_cb is NULL\n", __func__);
+			goto fail;
+		}
+	} else if (data->opcode == VSS_ISTREAM_EVT_REQUEST_DEC_BUFFER) {
+		pr_debug("Recd VSS_ISTREAM_EVT_REQUEST_DEC_BUFFER\n");
 	} else if (data->opcode == VSS_ISTREAM_EVT_SEND_DEC_BUFFER) {
 		pr_debug("Send dec buf resp\n");
+	} else if (data->opcode == APR_RSP_ACCEPTED) {
+		ptr = data->payload;
+		if (ptr[0])
+			pr_debug("%s: APR_RSP_ACCEPTED for 0x%x:\n",
+				 __func__, ptr[0]);
+	} else if (data->opcode == VSS_ISTREAM_EVT_NOT_READY) {
+		pr_debug("Recd VSS_ISTREAM_EVT_NOT_READY\n");
+	} else if (data->opcode == VSS_ISTREAM_EVT_READY) {
+		pr_debug("Recd VSS_ISTREAM_EVT_READY\n");
 	} else
-		pr_debug("Unknown opcode 0x%x\n", data->opcode);
+		pr_err("Unknown opcode 0x%x\n", data->opcode);
 
 fail:
 	return 0;
@@ -2869,13 +3391,15 @@
 		if (data->payload_size) {
 			ptr = data->payload;
 
+			pr_info("%x %x\n", ptr[0], ptr[1]);
 			switch (ptr[0]) {
-			case VSS_IVOCPROC_CMD_CREATE_FULL_CONTROL_SESSION:
+			case VSS_IVOCPROC_CMD_CREATE_FULL_CONTROL_SESSION_V2:
 			/*response from  CVP */
 				pr_debug("%s: cmd = 0x%x\n", __func__, ptr[0]);
 				if (!ptr[1]) {
 					voice_set_cvp_handle(v, data->src_port);
-					pr_debug("cvphdl=%d\n", data->src_port);
+					pr_debug("status: %d, cvphdl=%d\n",
+						 ptr[1], data->src_port);
 				} else
 					pr_err("got NACK from CVP create session response\n");
 				v->cvp_state = CMD_STATUS_SUCCESS;
@@ -2908,6 +3432,137 @@
 	return 0;
 }
 
+static int voice_alloc_oob_shared_mem(void)
+{
+	int cnt = 0;
+	int rc = 0;
+	int len;
+	void *mem_addr;
+	dma_addr_t phys;
+	int bufsz = BUFFER_BLOCK_SIZE;
+	int bufcnt = NUM_OF_BUFFERS;
+	struct voice_data *v = voice_get_session(
+				common.voice[VOC_PATH_FULL].session_id);
+
+	v->shmem_info.sh_buf.client = msm_ion_client_create(UINT_MAX,
+							    "voip_client");
+	if (IS_ERR_OR_NULL((void *)v->shmem_info.sh_buf.client)) {
+		pr_err("%s: ION create client failed\n", __func__);
+		goto err;
+	}
+
+	v->shmem_info.sh_buf.handle = ion_alloc(v->shmem_info.sh_buf.client,
+						bufsz * bufcnt, SZ_4K,
+						(0x1 << ION_AUDIO_HEAP_ID), 0);
+	if (IS_ERR_OR_NULL((void *)v->shmem_info.sh_buf.handle)) {
+		pr_err("%s: ION memory allocation failed\n",
+			__func__);
+		goto err_ion_client;
+	}
+
+	rc = ion_phys(v->shmem_info.sh_buf.client, v->shmem_info.sh_buf.handle,
+		  (ion_phys_addr_t *)&phys, (size_t *)&len);
+	if (rc) {
+		pr_err("%s: ION Get Physical failed, rc = %d\n",
+			__func__, rc);
+		goto err_ion_handle;
+	}
+
+	mem_addr = ion_map_kernel(v->shmem_info.sh_buf.client,
+				  v->shmem_info.sh_buf.handle);
+	if (IS_ERR_OR_NULL(mem_addr)) {
+		pr_err("%s: ION memory mapping failed\n", __func__);
+		goto err_ion_handle;
+	}
+
+	while (cnt < bufcnt) {
+		v->shmem_info.sh_buf.buf[cnt].data =  mem_addr  + (cnt * bufsz);
+		v->shmem_info.sh_buf.buf[cnt].phys =  phys + (cnt * bufsz);
+		v->shmem_info.sh_buf.buf[cnt].size = bufsz;
+		cnt++;
+	}
+
+	pr_debug("%s buf[0].data:[%p], buf[0].phys:[%p], &buf[0].phys:[%p],\n",
+		 __func__,
+		(void *)v->shmem_info.sh_buf.buf[0].data,
+		(void *)v->shmem_info.sh_buf.buf[0].phys,
+		(void *)&v->shmem_info.sh_buf.buf[0].phys);
+	pr_debug("%s: buf[1].data:[%p], buf[1].phys[%p], &buf[1].phys[%p]\n",
+		__func__,
+		(void *)v->shmem_info.sh_buf.buf[1].data,
+		(void *)v->shmem_info.sh_buf.buf[1].phys,
+		(void *)&v->shmem_info.sh_buf.buf[1].phys);
+
+	memset((void *)v->shmem_info.sh_buf.buf[0].data, 0, (bufsz * bufcnt));
+
+	return 0;
+
+err_ion_handle:
+	ion_free(v->shmem_info.sh_buf.client, v->shmem_info.sh_buf.handle);
+err_ion_client:
+	ion_client_destroy(v->shmem_info.sh_buf.client);
+err:
+	return -EINVAL;
+}
+
+static int voice_alloc_oob_mem_table(void)
+{
+	int rc = 0;
+	int len;
+	struct voice_data *v = voice_get_session(
+				common.voice[VOC_PATH_FULL].session_id);
+
+	v->shmem_info.memtbl.client = msm_ion_client_create(UINT_MAX,
+							      "voip_client");
+	if (IS_ERR_OR_NULL((void *)v->shmem_info.memtbl.client)) {
+		pr_err("%s: ION create client for memtbl failed\n", __func__);
+		goto err;
+	}
+
+	v->shmem_info.memtbl.handle = ion_alloc(v->shmem_info.memtbl.client,
+				sizeof(struct vss_imemory_table_t), SZ_4K,
+				(0x1 << ION_AUDIO_HEAP_ID), 0);
+	if (IS_ERR_OR_NULL((void *) v->shmem_info.memtbl.handle)) {
+		pr_err("%s: ION memory allocation for memtbl failed\n",
+			__func__);
+		goto err_ion_client;
+	}
+
+	rc = ion_phys(v->shmem_info.memtbl.client, v->shmem_info.memtbl.handle,
+		(ion_phys_addr_t *)&v->shmem_info.memtbl.phys, (size_t *)&len);
+	if (rc) {
+		pr_err("%s: ION Get Physical for memtbl failed, rc = %d\n",
+			__func__, rc);
+		goto err_ion_handle;
+	}
+
+	v->shmem_info.memtbl.data = ion_map_kernel(v->shmem_info.memtbl.client,
+						   v->shmem_info.memtbl.handle);
+	if (IS_ERR_OR_NULL((void *)v->shmem_info.memtbl.data)) {
+		pr_err("%s: ION memory mapping for memtbl failed\n",
+				__func__);
+		goto err_ion_handle;
+	}
+
+	memset(v->shmem_info.memtbl.data, 0,
+	       sizeof(struct vss_imemory_table_t));
+
+	v->shmem_info.memtbl.size = sizeof(struct vss_imemory_table_t);
+
+	pr_debug("%s data[%p]phys[%p][%p]\n", __func__,
+		 (void *)v->shmem_info.memtbl.data,
+		 (void *)v->shmem_info.memtbl.phys,
+		 (void *)&v->shmem_info.memtbl.phys);
+
+	return 0;
+
+err_ion_handle:
+	ion_free(v->shmem_info.memtbl.client, v->shmem_info.memtbl.handle);
+err_ion_client:
+	ion_client_destroy(v->shmem_info.memtbl.client);
+err:
+	return -EINVAL;
+}
 
 static int __init voice_init(void)
 {
@@ -2946,6 +3601,17 @@
 		mutex_init(&common.voice[i].lock);
 	}
 
+	/* Allocate shared memory for OOB Voip */
+	rc = voice_alloc_oob_shared_mem();
+	if (rc < 0)
+		pr_err("failed to alloc shared memory for OOB %d\n", rc);
+	else {
+		/* Allocate mem map table for OOB */
+		rc = voice_alloc_oob_mem_table();
+		if (rc < 0)
+			pr_err("failed to alloc mem map talbe %d\n", rc);
+	}
+
 	return rc;
 }
 
diff --git a/sound/soc/msm/qdsp6v2/q6voice.h b/sound/soc/msm/qdsp6v2/q6voice.h
index 8bafe04..df0cbec 100644
--- a/sound/soc/msm/qdsp6v2/q6voice.h
+++ b/sound/soc/msm/qdsp6v2/q6voice.h
@@ -17,6 +17,13 @@
 
 #define MAX_VOC_PKT_SIZE 642
 #define SESSION_NAME_LEN 20
+#define NUM_OF_MEMORY_BLOCKS 1
+#define NUM_OF_BUFFERS 2
+/*
+ * BUFFER BLOCK SIZE based on
+ * the supported page size
+ */
+#define BUFFER_BLOCK_SIZE       4096
 
 #define VOC_REC_UPLINK		0x00
 #define VOC_REC_DOWNLINK	0x01
@@ -60,6 +67,26 @@
 	VOC_RELEASE,
 };
 
+struct mem_buffer {
+	dma_addr_t		phys;
+	void			*data;
+	uint32_t		size; /* size of buffer */
+};
+
+struct share_mem_buf {
+	struct ion_handle	*handle;
+	struct ion_client	*client;
+	struct mem_buffer	buf[NUM_OF_BUFFERS];
+};
+
+struct mem_map_table {
+	dma_addr_t		phys;
+	void			*data;
+	uint32_t		size; /* size of buffer */
+	struct ion_handle	*handle;
+	struct ion_client	*client;
+};
+
 /* Common */
 #define VSS_ICOMMON_CMD_SET_UI_PROPERTY 0x00011103
 /* Set a UI property */
@@ -119,8 +146,6 @@
 #define VSS_IMVM_CMD_CREATE_FULL_CONTROL_SESSION	0x000110FE
 /* Create a new full control MVM session. */
 
-#define VSS_IVOCPROC_CMD_CREATE_FULL_CONTROL_SESSION_V2	0x000112BF
-
 #define APRV2_IBASIC_CMD_DESTROY_SESSION		0x0001003C
 /**< No payload. Wait for APRV2_IBASIC_RSP_RESULT response. */
 
@@ -165,6 +190,12 @@
 #define VSS_IWIDEVOICE_CMD_SET_WIDEVOICE                0x00011243
 /* Enable/disable WideVoice */
 
+#define VSS_IMEMORY_CMD_MAP_PHYSICAL			0x00011334
+#define VSS_IMEMORY_RSP_MAP				0x00011336
+#define VSS_IMEMORY_CMD_UNMAP				0x00011337
+#define VSS_IMVM_CMD_SET_CAL_NETWORK			0x0001137A
+#define VSS_IMVM_CMD_SET_CAL_MEDIA_TYPE		0x0001137B
+
 enum msm_audio_voc_rate {
 		VOC_0_RATE, /* Blank frame */
 		VOC_8_RATE, /* 1/8 rate    */
@@ -311,6 +342,92 @@
 	struct vss_iwidevoice_cmd_set_widevoice_t vss_set_wv;
 } __packed;
 
+struct vss_imemory_table_descriptor_t {
+	uint64_t mem_address;
+	/*
+	 * Base physical address of the table. The address must be aligned
+	 * to LCM( cache_line_size, page_align, max_data_width ), where the
+	 * attributes are specified in #VSS_IMEMORY_CMD_MAP_PHYSICAL, and
+	 * LCM = Least Common Multiple. The table at the address must have
+	 * the format specified by #vss_imemory_table_t.
+	 */
+	uint32_t mem_size;
+	/* Size in bytes of the table. */
+} __packed;
+
+struct vss_imemory_block_t {
+	uint64_t mem_address;
+	/*
+	 * Base address of the memory block. The address is virtual for virtual
+	 * memory and physical for physical memory. The address must be aligned
+	 * to LCM( cache_line_size, page_align, max_data_width ), where the
+	 * attributes are specified in VSS_IMEMORY_CMD_MAP_VIRTUAL or
+	 * VSS_IMEMORY_CMD_MAP_PHYSICAL, and LCM = Least Common Multiple.
+	 */
+	uint32_t mem_size;
+	/*
+	 * Size in bytes of the memory block. The size must be multiple of
+	 * page_align, where page_align is specified in
+	 * VSS_IMEMORY_CMD_MAP_VIRTUAL or #VSS_IMEMORY_CMD_MAP_PHYSICAL.
+	 */
+} __packed;
+
+struct vss_imemory_table_t {
+	struct vss_imemory_table_descriptor_t next_table_descriptor;
+	/*
+	 * Specifies the next table. If there is no next table,
+	 * set the size of the table to 0 and the table address is ignored.
+	 */
+	struct vss_imemory_block_t blocks[NUM_OF_MEMORY_BLOCKS];
+	/* Specifies one ore more memory blocks. */
+} __packed;
+
+struct vss_imemory_cmd_map_physical_t {
+	struct apr_hdr hdr;
+	struct vss_imemory_table_descriptor_t table_descriptor;
+	bool is_cached;
+	/*
+	 * Indicates cached or uncached memory. Supported values:
+	 * TRUE - Cached.
+	 */
+	uint16_t cache_line_size;
+	/* Cache line size in bytes. Supported values: 128 */
+	uint32_t access_mask;
+	/*
+	 * CVD's access permission to the memory while it is mapped.
+	 * Supported values:
+	 * bit 0 - If set, the memory is readable.
+	 * bit 1 - If set, the memory is writable.
+	 */
+	uint32_t page_align;
+	/* Page frame alignment in bytes. Supported values: 4096 */
+	uint8_t min_data_width;
+	/*
+	 * Minimum native data type width in bits that can be accessed.
+	 * Supported values: 8
+	 */
+	uint8_t max_data_width;
+	/*
+	 * Maximum native data type width in bits that can be accessed.
+	 * Supported values: 64
+	 */
+} __packed;
+
+struct vss_imvm_cmd_set_cal_network_t {
+	struct apr_hdr hdr;
+	uint32_t network_id;
+} __packed;
+
+struct vss_imvm_cmd_set_cal_media_type_t {
+	struct apr_hdr hdr;
+	uint32_t media_id;
+} __packed;
+
+struct vss_imemory_cmd_unmap_t {
+	struct apr_hdr hdr;
+	uint32_t mem_handle;
+} __packed;
+
 /* TO CVS commands */
 #define VSS_ISTREAM_CMD_CREATE_PASSIVE_CONTROL_SESSION	0x00011140
 /**< Wait for APRV2_IBASIC_RSP_RESULT response. */
@@ -337,6 +454,8 @@
  * The client should respond with a VSS_ISTREAM_EVT_SEND_DEC_BUFFER event.
  */
 
+#define VSS_ISTREAM_EVT_OOB_NOTIFY_DEC_BUFFER_REQUEST	0x0001136E
+
 #define VSS_ISTREAM_EVT_SEND_DEC_BUFFER			0x00011016
 /* Event sent by the client to the stream in response to a
  * VSS_ISTREAM_EVT_REQUEST_DEC_BUFFER event, providing a decoder packet.
@@ -376,6 +495,29 @@
 #define VSS_TAP_POINT_STREAM_END                        0x00010F79
 /* Indicates that specified path should be tapped at the end of the stream. */
 
+#define VSS_ISTREAM_EVT_NOT_READY			0x000110FD
+
+#define VSS_ISTREAM_EVT_READY				0x000110FC
+
+#define VSS_ISTREAM_EVT_OOB_NOTIFY_DEC_BUFFER_READY	0x0001136F
+/*notify dsp that decoder buffer is ready*/
+
+#define VSS_ISTREAM_EVT_OOB_NOTIFY_ENC_BUFFER_READY	0x0001136C
+/*dsp notifying client that encoder buffer is ready*/
+
+#define VSS_ISTREAM_EVT_OOB_NOTIFY_ENC_BUFFER_CONSUMED	0x0001136D
+/*notify dsp that encoder buffer is consumed*/
+
+#define VSS_ISTREAM_CMD_SET_OOB_PACKET_EXCHANGE_CONFIG	0x0001136B
+
+#define VSS_ISTREAM_PACKET_EXCHANGE_MODE_INBAND	0
+/* In-band packet exchange mode. */
+
+#define VSS_ISTREAM_PACKET_EXCHANGE_MODE_OUT_OF_BAND	1
+/* Out-of-band packet exchange mode. */
+
+#define VSS_ISTREAM_CMD_SET_PACKET_EXCHANGE_MODE	0x0001136A
+
 struct vss_istream_cmd_start_record_t {
 	uint32_t rx_tap_point;
 	/* Tap point to use on the Rx path. Supported values are:
@@ -614,6 +756,28 @@
 	struct vss_istream_cmd_start_record_t rec_mode;
 } __packed;
 
+struct cvs_dec_buffer_ready_cmd {
+	struct apr_hdr hdr;
+} __packed;
+
+struct cvs_enc_buffer_consumed_cmd {
+	struct apr_hdr hdr;
+} __packed;
+
+struct vss_istream_cmd_set_oob_packet_exchange_config_t {
+	struct apr_hdr hdr;
+	uint32_t mem_handle;
+	uint64_t enc_buf_addr;
+	uint32_t enc_buf_size;
+	uint64_t dec_buf_addr;
+	uint32_t dec_buf_size;
+} __packed;
+
+struct vss_istream_cmd_set_packet_exchange_mode_t {
+	struct apr_hdr hdr;
+	uint32_t mode;
+} __packed;
+
 /* TO CVP commands */
 
 #define VSS_IVOCPROC_CMD_CREATE_FULL_CONTROL_SESSION	0x000100C3
@@ -646,6 +810,17 @@
 #define VSS_IVOCPROC_TOPOLOGY_ID_RX_DEFAULT		0x00010F77
 
 /* Newtwork IDs */
+#define VSS_ICOMMON_CAL_NETWORK_ID_NONE		0x0001135E
+
+/* Select internal mixing mode. */
+#define VSS_IVOCPROC_VOCPROC_MODE_EC_INT_MIXING	0x00010F7C
+
+/* Select external mixing mode. */
+#define VSS_IVOCPROC_VOCPROC_MODE_EC_EXT_MIXING	0x00010F7D
+
+/* Default AFE port ID. Applicable to Tx and Rx. */
+#define VSS_IVOCPROC_PORT_ID_NONE			0xFFFF
+
 #define VSS_NETWORK_ID_DEFAULT				0x00010037
 #define VSS_NETWORK_ID_VOIP_NB				0x00011240
 #define VSS_NETWORK_ID_VOIP_WB				0x00011241
@@ -678,73 +853,92 @@
 #define VOICE_CMD_GET_PARAM				0x00011007
 #define VOICE_EVT_GET_PARAM_ACK				0x00011008
 
-struct vss_ivocproc_cmd_create_full_control_session_t {
+#define VSS_IVOCPROC_CMD_CREATE_FULL_CONTROL_SESSION_V2	0x000112BF
+
+struct vss_ivocproc_cmd_create_full_control_session_v2_t {
 	uint16_t direction;
 	/*
-	 * stream direction.
-	 * 0 : TX only
-	 * 1 : RX only
-	 * 2 : TX and RX
+	 * Vocproc direction. The supported values:
+	 * VSS_IVOCPROC_DIRECTION_RX
+	 * VSS_IVOCPROC_DIRECTION_TX
+	 * VSS_IVOCPROC_DIRECTION_RX_TX
 	 */
-	uint32_t tx_port_id;
+	uint16_t tx_port_id;
 	/*
-	 * TX device port ID which vocproc will connect to. If not supplying a
-	 * port ID set to VSS_IVOCPROC_PORT_ID_NONE.
+	 * Tx device port ID to which the vocproc connects. If a port ID is
+	 * not being supplied, set this to #VSS_IVOCPROC_PORT_ID_NONE.
 	 */
 	uint32_t tx_topology_id;
 	/*
-	 * Tx leg topology ID. If not supplying a topology ID set to
-	 * VSS_IVOCPROC_TOPOLOGY_ID_NONE.
+	 * Tx path topology ID. If a topology ID is not being supplied, set
+	 * this to #VSS_IVOCPROC_TOPOLOGY_ID_NONE.
 	 */
-	uint32_t rx_port_id;
+	uint16_t rx_port_id;
 	/*
-	 * RX device port ID which vocproc will connect to. If not supplying a
-	 * port ID set to VSS_IVOCPROC_PORT_ID_NONE.
+	 * Rx device port ID to which the vocproc connects. If a port ID is
+	 * not being supplied, set this to #VSS_IVOCPROC_PORT_ID_NONE.
 	 */
 	uint32_t rx_topology_id;
 	/*
-	 * Rx leg topology ID. If not supplying a topology ID set to
-	 * VSS_IVOCPROC_TOPOLOGY_ID_NONE.
+	 * Rx path topology ID. If a topology ID is not being supplied, set
+	 * this to #VSS_IVOCPROC_TOPOLOGY_ID_NONE.
 	 */
-	int32_t network_id;
+	uint32_t profile_id;
+	/* Voice calibration profile ID. */
+	uint32_t vocproc_mode;
 	/*
-	 * Network ID. (Refer to VSS_NETWORK_ID_XXX). If not supplying a network
-	 * ID set to VSS_NETWORK_ID_DEFAULT.
+	 * Vocproc mode. The supported values:
+	 * VSS_IVOCPROC_VOCPROC_MODE_EC_INT_MIXING
+	 * VSS_IVOCPROC_VOCPROC_MODE_EC_EXT_MIXING
+	 */
+	uint16_t ec_ref_port_id;
+	/*
+	 * Port ID to which the vocproc connects for receiving echo
+	 * cancellation reference signal. If a port ID is not being supplied,
+	 * set this to #VSS_IVOCPROC_PORT_ID_NONE. This parameter value is
+	 * ignored when the vocproc_mode parameter is set to
+	 * VSS_IVOCPROC_VOCPROC_MODE_EC_INT_MIXING.
+	 */
+	char name[SESSION_NAME_LEN];
+	/*
+	 * Session name string used to identify a session that can be shared
+	 * with passive controllers (optional). The string size, including the
+	 * NULL termination character, is limited to 31 characters.
 	 */
 } __packed;
 
 struct vss_ivocproc_cmd_set_volume_index_t {
 	uint16_t vol_index;
-	/**<
-	* Volume index utilized by the vocproc to index into the volume table
-	* provided in VSS_IVOCPROC_CMD_CACHE_VOLUME_CALIBRATION_TABLE and set
-	* volume on the VDSP.
-	*/
+	/*
+	 * Volume index utilized by the vocproc to index into the volume table
+	 * provided in VSS_IVOCPROC_CMD_CACHE_VOLUME_CALIBRATION_TABLE and set
+	 * volume on the VDSP.
+	 */
 } __packed;
 
 struct vss_ivocproc_cmd_set_device_t {
 	uint32_t tx_port_id;
-	/**<
-	* TX device port ID which vocproc will connect to.
-	* VSS_IVOCPROC_PORT_ID_NONE means vocproc will not connect to any port.
-	*/
+	/*
+	 * TX device port ID which vocproc will connect to.
+	 * VSS_IVOCPROC_PORT_ID_NONE means vocproc will not connect to any port.
+	 */
 	uint32_t tx_topology_id;
-	/**<
-	* TX leg topology ID.
-	* VSS_IVOCPROC_TOPOLOGY_ID_NONE means vocproc does not contain any
-	* pre/post-processing blocks and is pass-through.
-	*/
+	/*
+	 * TX leg topology ID.
+	 * VSS_IVOCPROC_TOPOLOGY_ID_NONE means vocproc does not contain any
+	 * pre/post-processing blocks and is pass-through.
+	 */
 	int32_t rx_port_id;
-	/**<
-	* RX device port ID which vocproc will connect to.
-	* VSS_IVOCPROC_PORT_ID_NONE means vocproc will not connect to any port.
-	*/
+	/*
+	 * RX device port ID which vocproc will connect to.
+	 * VSS_IVOCPROC_PORT_ID_NONE means vocproc will not connect to any port.
+	 */
 	uint32_t rx_topology_id;
-	/**<
-	* RX leg topology ID.
-	* VSS_IVOCPROC_TOPOLOGY_ID_NONE means vocproc does not contain any
-	* pre/post-processing blocks and is pass-through.
-	*/
+	/*
+	 * RX leg topology ID.
+	 * VSS_IVOCPROC_TOPOLOGY_ID_NONE means vocproc does not contain any
+	 * pre/post-processing blocks and is pass-through.
+	 */
 } __packed;
 
 struct vss_ivocproc_cmd_register_calibration_data_t {
@@ -784,7 +978,7 @@
 
 struct cvp_create_full_ctl_session_cmd {
 	struct apr_hdr hdr;
-	struct vss_ivocproc_cmd_create_full_control_session_t cvp_session;
+	struct vss_ivocproc_cmd_create_full_control_session_v2_t cvp_session;
 } __packed;
 
 struct cvp_command {
@@ -835,7 +1029,6 @@
 
 /* CB for down-link packets. */
 typedef void (*dl_cb_fn)(uint8_t *voc_pkt,
-			 uint32_t *pkt_len,
 			 void *private_data);
 
 
@@ -862,9 +1055,18 @@
 	int force;
 };
 
+struct share_memory_info {
+	u32			mem_handle;
+	struct share_mem_buf	sh_buf;
+	struct mem_map_table	memtbl;
+};
+
 struct voice_data {
 	int voc_state;/*INIT, CHANGE, RELEASE, RUN */
 
+	/* Shared mem to store decoder and encoder packets */
+	struct share_memory_info	shmem_info;
+
 	wait_queue_head_t mvm_wait;
 	wait_queue_head_t cvs_wait;
 	wait_queue_head_t cvp_wait;
@@ -959,7 +1161,8 @@
 };
 
 /* called  by alsa driver */
-int voc_set_pp_enable(uint16_t session_id, uint32_t module_id, uint32_t enable);
+int voc_set_pp_enable(uint16_t session_id, uint32_t module_id,
+		      uint32_t enable);
 int voc_get_pp_enable(uint16_t session_id, uint32_t module_id);
 int voc_set_widevoice_enable(uint16_t session_id, uint32_t wv_enable);
 uint32_t voc_get_widevoice_enable(uint16_t session_id);