Merge "msm: mdss: Reorder code to avoid null pointer dereference"
diff --git a/Documentation/devicetree/bindings/coresight/coresight.txt b/Documentation/devicetree/bindings/coresight/coresight.txt
index 7f7ee25..17ff3f0 100644
--- a/Documentation/devicetree/bindings/coresight/coresight.txt
+++ b/Documentation/devicetree/bindings/coresight/coresight.txt
@@ -95,16 +95,24 @@
 - coresight-ctis : list of ctis that this component interacts with
 - qcom,pc-save : program counter save implemented
 - qcom,blk-size : block size for tmc-etr to usb transfers
+- qcom,memory-size : size of coherent memory to be allocated for tmc-etr buffer
 - qcom,round-robin : indicates if per core etms are allowed round-robin access
 		     by the funnel
 - qcom,reset-flush-race : indicates if a race exists between flushing and ddr
 			  being put into self-refresh during watchdog reset
 - qcom,write-64bit : only 64bit data writes supported by stm
-- vdd-supply: phandle to the regulator device tree node. Used for tpiu component
-- qcom,vdd-voltage-level : specifies voltage level for vdd supply. Should be
-			   specified in pairs (min, max) with units being uV
-- qcom,vdd-current-level : specifies current load levels for vdd supply. Should
-			   be specified in paris (lpm, hpm) with units being uA
+- <supply-name>-supply: phandle to the regulator device tree node. The required
+			<supply-name> is "vdd" for SD card and "vdd-io" for SD
+			I/O supply. Used for tpiu component
+- qcom,<supply>-voltage-level : specifies voltage level for vdd supply. Should
+				be specified in pairs (min, max) with units
+				being uV. Here <supply> can be "vdd" for SD card
+				vdd supply or "vdd-io" for SD I/O vdd supply.
+- qcom,<supply>-current-level : specifies current load levels for vdd supply.
+				Should be specified in pairs (lpm, hpm) with
+				units being uA. Here <supply> can be "vdd" for
+				SD card vdd supply or "vdd-io" for SD I/O vdd
+				supply.
 - qcom,seta-gpios : specifies gpios included in set A that are routed to the
 		    mictor connector. Used for tpiu component
 - qcom,seta-gpios-func : active function select for set A gpios
@@ -138,6 +146,7 @@
 		interrupt-names = "byte-cntr-irq";
 
 		qcom,byte-cntr-absent;
+		qcom,memory-size = <0x100000>;
 
 		coresight-id = <0>;
 		coresight-name = "coresight-tmc-etr";
diff --git a/Documentation/devicetree/bindings/fb/mdss-dsi-ctrl.txt b/Documentation/devicetree/bindings/fb/mdss-dsi-ctrl.txt
index 4cec0cd..7187908 100644
--- a/Documentation/devicetree/bindings/fb/mdss-dsi-ctrl.txt
+++ b/Documentation/devicetree/bindings/fb/mdss-dsi-ctrl.txt
@@ -12,6 +12,7 @@
 - vdda-supply:				Phandle for vreg regulator device node.
 - qcom,mdss-fb-map:			pHandle that specifies the framebuffer to which the
 					interface is mapped.
+- qcom,mdss-mdp:			pHandle that specifies the mdss-mdp device.
 - qcom,platform-regulator-settings:	An array of length 7 that specifies the PHY
 					regulator settings.
 - qcom,platform-strength-ctrl:		An array of length 2 that specifies the PHY
@@ -20,6 +21,8 @@
 					BIST ctrl settings.
 - qcom,platform-lane-config:		An array of length 45 that specifies the PHY
 					lane configuration settings.
+- qcom,dsi-pref-prim-pan:		phandle that specifies the primary panel to be used
+					with the controller.
 
 Optional properties:
 - label:		        	A string used to describe the controller used.
@@ -41,6 +44,8 @@
 - qcom,platform-enable-gpio:		Specifies the panel lcd/display enable gpio.
 - qcom,platform-reset-gpio:		Specifies the panel reset gpio.
 - qcom,platform-te-gpio:		Specifies the gpio used for TE.
+- qcom,platform-mode-gpio:		Select video/command mode of panel through gpio when it supports
+					both modes.
 - qcom,platform-reset-sequence:		An array that lists the
 					sequence of reset gpio values and sleeps
 					Each command will have the format defined
@@ -57,6 +62,7 @@
 		vdd-supply = <&pm8226_l15>;
 		vddio-supply = <&pm8226_l8>;
 		vdda-supply = <&pm8226_l4>;
+		qcom,dsi-pref-prim-pan = <&dsi_tosh_720_vid>;
 		qcom,platform-strength-ctrl = [ff 06];
 		qcom,platform-bist-ctrl = [00 00 b1 ff 00 00];
 		qcom,platform-regulator-settings = [07 09 03 00 20 00 01];
@@ -66,9 +72,11 @@
 			00 00 00 00 0f 00 00 01 97
 			00 c0 00 00 00 00 00 01 bb];
 		qcom,mdss-fb-map = <&mdss_fb0>;
+		qcom,mdss-mdp = <&mdss_mdp>;
 		qcom,platform-reset-gpio = <&msmgpio 25 1>;
 		qcom,platform-te-gpio = <&msmgpio 24 0>;
 		qcom,platform-enable-gpio = <&msmgpio 58 1>;
+		qcom,platform-mode-gpio = <&msmgpio 7 0>;
 		qcom,platform-reset-sequence = <1 25 0 20 1 10>;
 		qcom,platform-supply-entry1 {
 			qcom,supply-name = "vdd";
diff --git a/Documentation/devicetree/bindings/fb/mdss-dsi-panel.txt b/Documentation/devicetree/bindings/fb/mdss-dsi-panel.txt
index 49cd567..9ad8abe 100644
--- a/Documentation/devicetree/bindings/fb/mdss-dsi-panel.txt
+++ b/Documentation/devicetree/bindings/fb/mdss-dsi-panel.txt
@@ -4,14 +4,23 @@
 are compatable with MIPI display serial interface specification.
 
 Required properties:
-- compatible:				Specifies the version for DSI HW. that
-					this panel will be worked with
-					"qcom,mdss-dsi-panel" = DSI v6.0
+- compatible:				This property applies to DSI V2 panels only.
+					This property should not be added for panels
+					that work based on version "V6.0"
+					DSI panels that are of different versions
+					are initialized by the drivers for dsi controller.
+					This property specifies the version
+					for DSI HW that this panel will work with
 					"qcom,dsi-panel-v2" = DSI V2.0
-- status:        			A string that has to be set to "okay/ok" to enable
-					the panel driver. By default this property will be
-					set to "disable". Will be set to "ok/okay" status
-					for specific platforms.
+- status:        			This property applies to DSI V2 panels only.
+					This property should not be added for panels
+					that work based on version "V6.0"
+					DSI panels that are of different versions
+					are initialized by the drivers for dsi controller.
+					A string that has to be set to "okay/ok"
+					to enable the panel driver. By default this property
+					will be set to "disable". Will be set to "ok/okay"
+					status for specific platforms.
 - qcom,mdss-dsi-panel-controller:	Specifies the phandle for the DSI controller that
 					this panel will be mapped to.
 - qcom,mdss-dsi-panel-width:		Specifies panel width in pixels.
@@ -219,17 +228,19 @@
 					to the physical width in the framebuffer information.
 - qcom,mdss-pan-physical-height-dimension:	Specifies panel physical height in mm which corresponds
 					to the physical height in the framebuffer information.
+- qcom,mdss-dsi-panel-mode-gpio-state:	String that specifies the mode state for panel if it is defined
+					in dsi controller.
+					"high" = Set GPIO to HIGH
+					"low" = Set GPIO to LOW
 
 
 Note, if a given optional qcom,* binding is not present, then the driver will configure
 the default values specified.
 
 Example:
-&soc {
-	qcom,mdss_dsi_sim_video {
-		compatible = "qcom,mdss-dsi-panel";
+&mdss_mdp {
+	dsi_sim_vid: qcom,mdss_dsi_sim_video {
 		qcom,mdss-dsi-panel-name = "simulator video mode dsi panel";
-		status = "disable";
 		qcom,mdss-dsi-panel-controller = <&mdss_dsi0>;
 		qcom,mdss-dsi-panel-height = <1280>;
 		qcom,mdss-dsi-panel-width = <720>;
@@ -309,5 +320,6 @@
 		qcom,mdss-dsi-pwm-gpio = <&pm8941_mpps 5 0>;
 		qcom,mdss-pan-physical-width-dimension = <60>;
 		qcom,mdss-pan-physical-height-dimension = <140>;
+		qcom,mdss-dsi-panel-mode-gpio-state = "low";
 	};
 };
diff --git a/Documentation/devicetree/bindings/fb/mdss-mdp.txt b/Documentation/devicetree/bindings/fb/mdss-mdp.txt
index 7ba9a88..829cce2 100644
--- a/Documentation/devicetree/bindings/fb/mdss-mdp.txt
+++ b/Documentation/devicetree/bindings/fb/mdss-mdp.txt
@@ -94,7 +94,16 @@
 				The offsets are calculated from "mdp_phys"
 				defined in reg property. The number of offsets
 				defiend should reflect the number of progammable
-				interface blocks avaialble in hardware.
+				interface blocks available in hardware.
+- qcom,mdss-pref-prim-intf:	A string which indicates the configured hardware
+				interface between MDP and the primary panel.
+				Individual panel controller drivers initialize
+				hardware based on this property.
+				Based on the interfaces supported at present,
+				possible values are:
+				- "dsi"
+				- "edp"
+				- "hdmi"
 
 Optional properties:
 - qcom,vbif-settings :	Array with key-value pairs of constant VBIF register
@@ -156,7 +165,7 @@
 			 size is greater than max mixer width.
 
 Example:
-	qcom,mdss_mdp@fd900000 {
+	mdss_mdp: qcom,mdss_mdp@fd900000 {
 		compatible = "qcom,mdss_mdp";
 		reg = <0xfd900000 0x22100>,
 			<0xfd924000 0x1000>;
@@ -179,6 +188,7 @@
 		qcom,mdss-smp-data = <22 4096>;
 		qcom,mdss-rot-block-size = <64>;
 		qcom,mdss-smp-mb-per-pipe = <2>;
+		qcom,mdss-pref-prim-intf = "dsi";
 		qcom,mdss-has-bwc;
 		qcom,mdss-has-decimation;
 		qcom,mdss-has-wfd-blk;
diff --git a/Documentation/devicetree/bindings/input/misc/stk-stk3x1x.txt b/Documentation/devicetree/bindings/input/misc/stk-stk3x1x.txt
index aa50140..59136ee 100644
--- a/Documentation/devicetree/bindings/input/misc/stk-stk3x1x.txt
+++ b/Documentation/devicetree/bindings/input/misc/stk-stk3x1x.txt
@@ -25,6 +25,10 @@
  - stk,ps-thdl	: Low threshold for proximity sensor, sensor will report
 				"far" if the proximity sensor reading is larger than this value.
 
+Optional properties:
+
+ - stk,use-fir	: Boolean to enable light data jitter suppressing FIR filter.
+
 Example:
 	i2c@f9925000 {
 		stk@48 {
@@ -43,4 +47,5 @@
 			stk,wait-reg = <0x07>;
 			stk,ps-thdh = <1700>;
 			stk,ps-thdl = <1500>;
+			stk,use-fir;
 		};
diff --git a/Documentation/devicetree/bindings/media/video/msm-vidc.txt b/Documentation/devicetree/bindings/media/video/msm-vidc.txt
index cc2506d..6f6f68d 100644
--- a/Documentation/devicetree/bindings/media/video/msm-vidc.txt
+++ b/Documentation/devicetree/bindings/media/video/msm-vidc.txt
@@ -12,6 +12,7 @@
 Optional properties:
 - reg : offset and length of the register set for the device.
 - interrupts : should contain the vidc interrupt.
+- vdd-supply : regulator to supply venus.
 - qcom,vidc-cp-map : start and size of device virtual address range for
   secure buffers. Video hardware uses this address range to identify if
   the buffers are secure or non-secure.
@@ -66,6 +67,7 @@
 		compatible = "qcom,msm-vidc";
 		reg = <0xfdc00000 0xff000>;
 		interrupts = <0 44 0>;
+		vdd-supply = <&gdsc_venus>;
 		qcom,vidc-cp-map = <0x1000000 0x40000000>;
 		qcom,vidc-ns-map = <0x40000000 0x40000000>;
 		qcom,load-freq-tbl = <979200 410000000>,
diff --git a/Documentation/devicetree/bindings/power/qpnp-bms.txt b/Documentation/devicetree/bindings/power/qpnp-bms.txt
index 1162298..b076475 100644
--- a/Documentation/devicetree/bindings/power/qpnp-bms.txt
+++ b/Documentation/devicetree/bindings/power/qpnp-bms.txt
@@ -13,7 +13,15 @@
 		to determine whether the BMS is using an internal or external
 		rsense to accumulate the Coulomb Counter and read current.
 
-Additionally, an optional subnode may be included:
+Additionally, optional subnodes may be included:
+- qcom,batt-pres-status : A subnode with a register address for the SMBB
+		battery interface's BATT_PRES_STATUS register. If this node is
+		added, then the BMS will try to detect offmode battery removal
+		via the battery interface's offmode battery removal circuit.
+- qcom,soc-storage-reg : A subnode with a register address to a spare PMIC
+		register. If this node is included, then the BMS will store its
+		shutdown SOC in the specified register instead of the default
+		BMS data register.
 - qcom,battery-data : A phandle to a node containing the available batterydata
 		profiles. See the batterydata bindings documentation for more
 		details.
@@ -75,8 +83,8 @@
 - qcom,min-fcc-learning-soc: An interger value which defines the minimum SOC
 			to start FCC learning. This is applicable only if
 			FCC learning is enabled.
-- qcom,min-fcc-ocv-pc:	An interger value which defines the minimum PC-lookup(OCV)
-			to start FCC learning. This is applicable only if
+- qcom,min-fcc-ocv-pc:	An interger value which defines the minimum PC-lookup
+			(OCV) to start FCC learning. This is applicable only if
 			FCC learning is enabled.
 - qcom,min-fcc-learning-samples: An interger value which defines the minimum
 			number of the FCC measurement cycles required to
@@ -103,14 +111,23 @@
 - qcom,use-ocv-thresholds : A boolean that controls whether BMS will take
 			new OCVs only between the defined thresholds.
 - qcom,enable-fcc-learning: A boolean that defines if FCC learning is enabled.
-- qcom,bms-adc_tm: Corresponding ADC_TM device's phandle to set recurring measurements
-		and receive notifications for die_temperature, vbatt.
+- qcom,bms-adc_tm: Corresponding ADC_TM device's phandle to set recurring
+			measurements and receive notifications for
+			die_temperature and vbatt.
 
+qcom,batt-pres-status node required properties:
+- reg : offset and length of the PMIC SMBB battery interface BATT_PRES_STATUS
+		register.
 
-All sub node required properties:
+qcom,soc-storage-reg node required properties:
+- reg : address and length of the spare PMIC register that the BMS will store
+		shutdown SoC in.
+
+qcom,bms-iadc node required properties:
 - reg : offset and length of the PMIC peripheral register map.
 
 qcom,bms-bms node required properties:
+- reg : offset and length of the PMIC peripheral register map.
 - interrupts : the interrupt mappings.
 		The format should be
 		<slave-id peripheral-id interrupt-number>.
@@ -156,6 +173,10 @@
 	qcom,bms-iadc = <&pm8941_iadc>;
 	qcom,bms-adc_tm = <&pm8941_adc_tm>;
 
+	qcom,batt-pres-status@1208 {
+		reg = <0x1208 0x1>;
+	}
+
 	qcom,bms-iadc@3800 {
 		reg = <0x3800 0x100>;
 	};
diff --git a/Documentation/devicetree/bindings/usb/msm-hsusb.txt b/Documentation/devicetree/bindings/usb/msm-hsusb.txt
index ad1b5ad..44ed2dc 100644
--- a/Documentation/devicetree/bindings/usb/msm-hsusb.txt
+++ b/Documentation/devicetree/bindings/usb/msm-hsusb.txt
@@ -164,7 +164,8 @@
   for DMA latency in microsecs.
 - qcom,android-usb-cdrom : if this property is present then device creates
   a new LUN as CD-ROM
-
+- qcom,android-usb-internal-ums : if this property is present then device
+  creates a new LUN as internal usb mass storage
 Example Android USB device node :
 	android_usb@fc42b0c8 {
 		compatible = "qcom,android-usb";
diff --git a/Documentation/devicetree/bindings/usb/msm-ssusb.txt b/Documentation/devicetree/bindings/usb/msm-ssusb.txt
index f2a9940..53e912a 100644
--- a/Documentation/devicetree/bindings/usb/msm-ssusb.txt
+++ b/Documentation/devicetree/bindings/usb/msm-ssusb.txt
@@ -52,6 +52,10 @@
 - qcom,dwc_usb3-adc_tm: Corresponding ADC_TM device's phandle to set recurring
 		measurements on USB_ID channel when using ADC and receive
 		notifications for set thresholds.
+- qcom,dwc-usb3-msm-tx-fifo-size: If present, represents RAM size available for
+		TX fifo allocation in bytes
+- qcom,dwc-usb3-msm-qdss-tx-fifo-size: If present, represent RAM size available
+		for TX fifo allocation in QDSS composition
 
 Sub nodes:
 - Sub node for "DWC3- USB3 controller".
@@ -76,6 +80,8 @@
 		qcom,vdd-voltage-level = <1 5 7>;
 		qcom,dwc-hsphy-init = <0x00D195A4>;
 		qcom,dwc_usb3-adc_tm = <&pm8941_adc_tm>;
+		qcom,dwc-usb3-msm-tx-fifo-size = <29696>;
+		qcom,dwc-usb3-msm-qdss-tx-fifo-size = <16384>;
 
 		qcom,msm_bus,name = "usb3";
 		qcom,msm_bus,num_cases = <2>;
diff --git a/arch/arm/boot/dts/apq8084.dtsi b/arch/arm/boot/dts/apq8084.dtsi
index 943f2a3..8eed58e 100644
--- a/arch/arm/boot/dts/apq8084.dtsi
+++ b/arch/arm/boot/dts/apq8084.dtsi
@@ -75,8 +75,6 @@
 		compatible = "qcom,cache_dump";
 		qcom,l1-dump-size = <0x100000>;
 		qcom,l2-dump-size = <0x500000>;
-		qcom,memory-reservation-type = "EBI1";
-		qcom,memory-reservation-size = <0x600000>; /* 6M EBI1 buffer */
 	};
 
 	rpm_bus: qcom,rpm-smd {
diff --git a/arch/arm/boot/dts/dsi-panel-generic-720p-cmd.dtsi b/arch/arm/boot/dts/dsi-panel-generic-720p-cmd.dtsi
new file mode 100644
index 0000000..23091f0
--- /dev/null
+++ b/arch/arm/boot/dts/dsi-panel-generic-720p-cmd.dtsi
@@ -0,0 +1,80 @@
+/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+/*---------------------------------------------------------------------------
+ * This file is autogenerated file using gcdb parser. Please do not edit it.
+ * Update input XML file to add a new entry or update variable in this file
+ * VERSION = "1.0"
+ *---------------------------------------------------------------------------*/
+&mdss_mdp {
+	dsi_generic_720p_cmd: qcom,mdss_dsi_generic_720p_cmd {
+		qcom,mdss-dsi-panel-name = "generic 720p cmd mode dsi panel";
+		qcom,mdss-dsi-panel-controller = <&mdss_dsi0>;
+		qcom,mdss-dsi-panel-type = "dsi_cmd_mode";
+		qcom,mdss-dsi-panel-destination = "display_1";
+		qcom,mdss-dsi-panel-framerate = <60>;
+		qcom,mdss-dsi-stream = <0>;
+		qcom,mdss-dsi-panel-width = <768>;
+		qcom,mdss-dsi-panel-height = <1280>;
+		qcom,mdss-dsi-h-front-porch = <26>;
+		qcom,mdss-dsi-h-back-porch = <26>;
+		qcom,mdss-dsi-h-pulse-width = <26>;
+		qcom,mdss-dsi-h-sync-skew = <0>;
+		qcom,mdss-dsi-v-back-porch = <2>;
+		qcom,mdss-dsi-v-front-porch = <2>;
+		qcom,mdss-dsi-v-pulse-width = <2>;
+		qcom,mdss-dsi-h-left-border = <0>;
+		qcom,mdss-dsi-h-right-border = <0>;
+		qcom,mdss-dsi-v-top-border = <0>;
+		qcom,mdss-dsi-v-bottom-border = <0>;
+		qcom,mdss-dsi-bpp = <24>;
+		qcom,mdss-dsi-color-order = <0>;
+		qcom,mdss-dsi-underflow-color = <0xff>;
+		qcom,mdss-dsi-border-color = <0>;
+		qcom,mdss-dsi-on-command = [05 01 00 00 78 00 01 11
+				15 01 00 00 0a 00 02 36 00
+				05 01 00 00 0a 00 01 29
+				15 01 00 00 0a 00 02 53 24
+				15 01 00 00 0a 00 02 35 00];
+		qcom,mdss-dsi-off-command = [05 01 00 00 0a 00 01 34
+				 05 01 00 00 78 00 01 10
+				05 01 00 00 78 00 01 28
+				 15 01 00 00 0a 00 02 53 00];
+		qcom,mdss-dsi-on-command-state = "dsi_lp_mode";
+		qcom,mdss-dsi-off-command-state = "dsi_hs_mode";
+		qcom,mdss-dsi-h-sync-pulse = <0>;
+		qcom,mdss-dsi-traffic-mode = <1>;
+		qcom,mdss-dsi-lane-map = <0>;
+		qcom,mdss-dsi-bllp-eof-power-mode;
+		qcom,mdss-dsi-bllp-power-mode;
+		qcom,mdss-dsi-lane-0-state;
+		qcom,mdss-dsi-lane-1-state;
+		qcom,mdss-dsi-lane-2-state;
+		qcom,mdss-dsi-lane-3-state;
+		qcom,mdss-dsi-te-pin-select = <1>;
+		qcom,mdss-dsi-te-v-sync-rd-ptr-irq-line = <0x2c>;
+		qcom,mdss-dsi-te-v-sync-continues-lines = <0x3c>;
+		qcom,mdss-dsi-te-dcs-command = <1>;
+		qcom,mdss-dsi-te-check-enable;
+		qcom,mdss-dsi-te-using-te-pin;
+		qcom,mdss-dsi-panel-timings = [6e 26 1b 00 35 34 20 28 17 03 04 00];
+		qcom,mdss-dsi-t-clk-post = <0x20>;
+		qcom,mdss-dsi-t-clk-pre = <0x2a>;
+		qcom,mdss-dsi-bl-min-level = <1>;
+		qcom,mdss-dsi-bl-max-level = <255>;
+		qcom,mdss-dsi-bl-pmic-pwm-frequency = <100>;
+		qcom,mdss-dsi-bl-pmic-bank-select = <7>;
+		qcom,mdss-dsi-dma-trigger = <4>;
+		qcom,mdss-dsi-mdp-trigger = <0>;
+		qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_pwm";
+	};
+};
diff --git a/arch/arm/boot/dts/dsi-panel-hx8379a-wvga-video.dtsi b/arch/arm/boot/dts/dsi-panel-hx8379a-wvga-video.dtsi
new file mode 100644
index 0000000..645e91b
--- /dev/null
+++ b/arch/arm/boot/dts/dsi-panel-hx8379a-wvga-video.dtsi
@@ -0,0 +1,76 @@
+/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+/*---------------------------------------------------------------------------
+ * This file is autogenerated file using gcdb parser. Please do not edit it.
+ * Update input XML file to add a new entry or update variable in this file
+ * VERSION = "1.0"
+ *---------------------------------------------------------------------------*/
+&mdss_mdp {
+	dsi_hx8379a_wvga_vid: qcom,mdss_dsi_hx8379a_wvga_video {
+		qcom,mdss-dsi-panel-name = "HX8379A wvga video mode dsi panel";
+		qcom,mdss-dsi-panel-controller = <&mdss_dsi0>;
+		qcom,mdss-dsi-panel-type = "dsi_video_mode";
+		qcom,mdss-dsi-panel-destination = "display_1";
+		qcom,mdss-dsi-panel-framerate = <60>;
+		qcom,mdss-dsi-virtual-channel-id = <0>;
+		qcom,mdss-dsi-stream = <0>;
+		qcom,mdss-dsi-panel-width = <480>;
+		qcom,mdss-dsi-panel-height = <800>;
+		qcom,mdss-dsi-h-front-porch = <90>;
+		qcom,mdss-dsi-h-back-porch = <90>;
+		qcom,mdss-dsi-h-pulse-width = <17>;
+		qcom,mdss-dsi-h-sync-skew = <0>;
+		qcom,mdss-dsi-v-back-porch = <2>;
+		qcom,mdss-dsi-v-front-porch = <11>;
+		qcom,mdss-dsi-v-pulse-width = <3>;
+		qcom,mdss-dsi-h-left-border = <0>;
+		qcom,mdss-dsi-h-right-border = <0>;
+		qcom,mdss-dsi-v-top-border = <0>;
+		qcom,mdss-dsi-v-bottom-border = <0>;
+		qcom,mdss-dsi-bpp = <24>;
+		qcom,mdss-dsi-color-order = <0>;
+		qcom,mdss-dsi-underflow-color = <0xff>;
+		qcom,mdss-dsi-border-color = <0>;
+		qcom,mdss-dsi-on-command = [29 01 00 00 01 00 04 B9 FF 83 79
+			23 01 00 00 01 00 02 BA 51
+			29 01 00 00 01 00 14 B1 00 50 44 EA 8D 08 11 0F 0F 24 2C 9A 1A 42 0B 6E F1 00 E6
+			29 01 00 00 01 00 0e B2 00 00 3C 08 04 19 22 00 FF 08 04 19 20
+			29 01 00 00 01 00 20 B4 80 08 00 32 10 03 32 13 70 32 10 08 37 01 28 05 37 08 3C 20 44 44 08 00 40 08 28 08 30 30 04
+			23 01 00 00 01 00 02 cc 02
+			29 01 00 00 01 00 30 D5 00 00 08 00 01 05 00 03 00 88 88 88 88 23 01 67 45 02 13 88 88 88 88 88 88 88 88 88 88 54 76 10 32 31 20 88 88 88 88 88 88 00 00 00 00 00 00
+			29 01 00 00 01 00 24 E0 79 00 00 02 1C 1F 33 28 3E 07 0E 0F 15 17 16 16 13 19 00 00 02 1C 1F 33 28 3E 07 0E 0F 15 17 16 16 13 19
+			29 01 00 00 01 00 05 B6 00 A6 00 A6
+			05 01 00 00 96 00 02 11 00
+			05 01 00 00 78 00 02 29 00];
+		qcom,mdss-dsi-off-command = [05 01 00 00 32 00 02 28 00
+					05 01 00 00 78 00 02 10 00];
+		qcom,mdss-dsi-on-command-state = "dsi_lp_mode";
+		qcom,mdss-dsi-off-command-state = "dsi_lp_mode";
+		qcom,mdss-dsi-h-sync-pulse = <1>;
+		qcom,mdss-dsi-traffic-mode = <2>;
+		qcom,mdss-dsi-lane-map = <1>;
+		qcom,mdss-dsi-bllp-eof-power-mode;
+		qcom,mdss-dsi-bllp-power-mode;
+		qcom,mdss-dsi-lane-0-state;
+		qcom,mdss-dsi-lane-1-state;
+		qcom,mdss-dsi-panel-timings = [5d 12 0c 00 33 39 10 16 15 03 04 00];
+		qcom,mdss-dsi-t-clk-post = <0x04>;
+		qcom,mdss-dsi-t-clk-pre = <0x1b>;
+		qcom,mdss-dsi-bl-min-level = <1>;
+		qcom,mdss-dsi-bl-max-level = <255>;
+		qcom,mdss-dsi-dma-trigger = <4>;
+		qcom,mdss-dsi-mdp-trigger = <0>;
+		qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_wled";
+
+	};
+};
diff --git a/arch/arm/boot/dts/dsi-panel-hx8394a-720p-video.dtsi b/arch/arm/boot/dts/dsi-panel-hx8394a-720p-video.dtsi
index c8d150a..c9d887b 100644
--- a/arch/arm/boot/dts/dsi-panel-hx8394a-720p-video.dtsi
+++ b/arch/arm/boot/dts/dsi-panel-hx8394a-720p-video.dtsi
@@ -15,10 +15,8 @@
  * Update input XML file to add a new entry or update variable in this file
  * VERSION = "1.0"
  *---------------------------------------------------------------------------*/
-&soc {
-	qcom,mdss_dsi_hx8394a_720p_video {
-		compatible = "qcom,mdss-dsi-panel";
-		status = "disable";
+&mdss_mdp {
+	dsi_hx8394a_720_vid: qcom,mdss_dsi_hx8394a_720p_video {
 		qcom,mdss-dsi-panel-name = "hx8394a 720p video mode dsi panel";
 		qcom,mdss-dsi-panel-controller = <&mdss_dsi0>;
 		qcom,mdss-dsi-panel-type = "dsi_video_mode";
diff --git a/arch/arm/boot/dts/dsi-panel-nt35521-720p-video.dtsi b/arch/arm/boot/dts/dsi-panel-nt35521-720p-video.dtsi
index 0b3fec4..357b024 100644
--- a/arch/arm/boot/dts/dsi-panel-nt35521-720p-video.dtsi
+++ b/arch/arm/boot/dts/dsi-panel-nt35521-720p-video.dtsi
@@ -15,10 +15,8 @@
  * Update input XML file to add a new entry or update variable in this file
  * VERSION = "1.0"
  *---------------------------------------------------------------------------*/
-&soc {
-	qcom,mdss_dsi_nt35521_720p_video {
-		compatible = "qcom,mdss-dsi-panel";
-		status = "disable";
+&mdss_mdp {
+	dsi_nt35521_720_vid: qcom,mdss_dsi_nt35521_720p_video {
 		qcom,mdss-dsi-panel-name = "nt35521 720p video mode dsi panel";
 		qcom,mdss-dsi-panel-controller = <&mdss_dsi0>;
 		qcom,mdss-dsi-panel-type = "dsi_video_mode";
diff --git a/arch/arm/boot/dts/dsi-panel-nt35590-720p-cmd.dtsi b/arch/arm/boot/dts/dsi-panel-nt35590-720p-cmd.dtsi
index d0b4da8..0918cf4 100644
--- a/arch/arm/boot/dts/dsi-panel-nt35590-720p-cmd.dtsi
+++ b/arch/arm/boot/dts/dsi-panel-nt35590-720p-cmd.dtsi
@@ -15,10 +15,8 @@
  * Update input XML file to add a new entry or update variable in this file
  * VERSION = "1.0"
  *---------------------------------------------------------------------------*/
-&soc {
-	qcom,mdss_dsi_nt35590_720p_cmd {
-		compatible = "qcom,mdss-dsi-panel";
-		status = "disable";
+&mdss_mdp {
+	dsi_nt35590_720_cmd: qcom,mdss_dsi_nt35590_720p_cmd {
 		qcom,mdss-dsi-panel-name = "nt35590 720p command mode dsi panel";
 		qcom,mdss-dsi-panel-controller = <&mdss_dsi0>;
 		qcom,mdss-dsi-panel-type = "dsi_cmd_mode";
diff --git a/arch/arm/boot/dts/dsi-panel-nt35590-720p-video.dtsi b/arch/arm/boot/dts/dsi-panel-nt35590-720p-video.dtsi
index a171a5c..6d68a3e 100644
--- a/arch/arm/boot/dts/dsi-panel-nt35590-720p-video.dtsi
+++ b/arch/arm/boot/dts/dsi-panel-nt35590-720p-video.dtsi
@@ -15,10 +15,8 @@
  * Update input XML file to add a new entry or update variable in this file
  * VERSION = "1.0"
  *---------------------------------------------------------------------------*/
-&soc {
-	qcom,mdss_dsi_nt35590_720p_video {
-		compatible = "qcom,mdss-dsi-panel";
-		status = "disable";
+&mdss_mdp {
+	dsi_nt35590_720_vid: qcom,mdss_dsi_nt35590_720p_video {
 		qcom,mdss-dsi-panel-name = "nt35590 720p video mode dsi panel";
 		qcom,mdss-dsi-panel-controller = <&mdss_dsi0>;
 		qcom,mdss-dsi-panel-type = "dsi_video_mode";
diff --git a/arch/arm/boot/dts/dsi-panel-nt35596-1080p-video.dtsi b/arch/arm/boot/dts/dsi-panel-nt35596-1080p-video.dtsi
index 998799a..49aef24 100644
--- a/arch/arm/boot/dts/dsi-panel-nt35596-1080p-video.dtsi
+++ b/arch/arm/boot/dts/dsi-panel-nt35596-1080p-video.dtsi
@@ -15,10 +15,8 @@
  * Update input XML file to add a new entry or update variable in this file
  * VERSION = "1.0"
  *---------------------------------------------------------------------------*/
-&soc {
-	qcom,mdss_dsi_nt35596_1080p_video {
-		compatible = "qcom,mdss-dsi-panel";
-		status = "disable";
+&mdss_mdp {
+	dsi_nt35596_1080_vid: qcom,mdss_dsi_nt35596_1080p_video {
 		qcom,mdss-dsi-panel-name = "nt35596 1080p video mode dsi panel";
 		qcom,mdss-dsi-panel-controller = <&mdss_dsi0>;
 		qcom,mdss-dsi-panel-type = "dsi_video_mode";
diff --git a/arch/arm/boot/dts/dsi-panel-orise-720p-video.dtsi b/arch/arm/boot/dts/dsi-panel-orise-720p-video.dtsi
index 478541f..30eda91 100644
--- a/arch/arm/boot/dts/dsi-panel-orise-720p-video.dtsi
+++ b/arch/arm/boot/dts/dsi-panel-orise-720p-video.dtsi
@@ -10,11 +10,9 @@
  * GNU General Public License for more details.
  */
 
-&soc {
-	qcom,mdss_dsi_orise_720p_video {
-		compatible = "qcom,mdss-dsi-panel";
+&mdss_mdp {
+	dsi_orise_720_vid: qcom,mdss_dsi_orise_720p_video {
 		label = "orise 720p video mode dsi panel";
-		status = "disable";
 		qcom,dsi-ctrl-phandle = <&mdss_dsi1>;
 		qcom,mdss-pan-res = <720 1280>;
 		qcom,mdss-pan-bpp = <24>;
diff --git a/arch/arm/boot/dts/dsi-panel-otm8018b-fwvga-video.dtsi b/arch/arm/boot/dts/dsi-panel-otm8018b-fwvga-video.dtsi
new file mode 100644
index 0000000..74e7ffc
--- /dev/null
+++ b/arch/arm/boot/dts/dsi-panel-otm8018b-fwvga-video.dtsi
@@ -0,0 +1,149 @@
+/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+/*---------------------------------------------------------------------------
+ * This file is autogenerated file using gcdb parser. Please do not edit it.
+ * Update input XML file to add a new entry or update variable in this file
+ * VERSION = "1.0"
+ *---------------------------------------------------------------------------*/
+&mdss_mdp {
+	dsi_otm8018b_fwvga_vid: qcom,mdss_dsi_otm8018b_fwvga_video {
+		qcom,mdss-dsi-panel-name = "OTM8018b fwvga video mode dsi panel";
+		qcom,mdss-dsi-panel-controller = <&mdss_dsi0>;
+		qcom,mdss-dsi-panel-type = "dsi_video_mode";
+		qcom,mdss-dsi-panel-destination = "display_1";
+		qcom,mdss-dsi-panel-framerate = <60>;
+		qcom,mdss-dsi-virtual-channel-id = <0>;
+		qcom,mdss-dsi-stream = <0>;
+		qcom,mdss-dsi-panel-width = <480>;
+		qcom,mdss-dsi-panel-height = <800>;
+		qcom,mdss-dsi-h-front-porch = <80>;
+		qcom,mdss-dsi-h-back-porch = <54>;
+		qcom,mdss-dsi-h-pulse-width = <8>;
+		qcom,mdss-dsi-h-sync-skew = <0>;
+		qcom,mdss-dsi-v-back-porch = <16>;
+		qcom,mdss-dsi-v-front-porch = <12>;
+		qcom,mdss-dsi-v-pulse-width = <2>;
+		qcom,mdss-dsi-h-left-border = <0>;
+		qcom,mdss-dsi-h-right-border = <0>;
+		qcom,mdss-dsi-v-top-border = <0>;
+		qcom,mdss-dsi-v-bottom-border = <0>;
+		qcom,mdss-dsi-bpp = <24>;
+		qcom,mdss-dsi-color-order = <0>;
+		qcom,mdss-dsi-underflow-color = <0xff>;
+		qcom,mdss-dsi-border-color = <0>;
+		qcom,mdss-dsi-on-command = [29 01 00 00 00 00 02 00 00
+					29 01 00 00 00 00 04 ff 80 09 01
+					29 01 00 00 00 00 02 00 80
+					29 01 00 00 00 00 03 ff 80 09
+					29 01 00 00 00 00 02 00 80
+					29 01 00 00 00 00 02 d6 48
+					29 01 00 00 00 00 02 00 03
+					29 01 00 00 00 00 02 ff 01
+					29 01 00 00 00 00 02 00 B4
+					29 01 00 00 00 00 02 C0 10
+					29 01 00 00 00 00 02 00 82
+					29 01 00 00 00 00 02 C5 A3
+					29 01 00 00 00 00 02 00 90
+					29 01 00 00 00 00 03 C5 96 87
+					29 01 00 00 00 00 02 00 00
+					29 01 00 00 00 00 03 D8 74 72
+					29 01 00 00 00 00 02 00 00
+					29 01 00 00 00 00 02 D9 56
+					29 01 00 00 00 00 02 00 00
+					29 01 00 00 00 00 11 E1 00 06 0A 07 03 16 08 0A 04 06 07 08 0F 23 22 05
+					29 01 00 00 00 00 02 00 00
+					29 01 00 00 00 00 11 E2 00 06 0A 07 03 16 08 0A 04 06 07 08 0F 23 22 05
+					29 01 00 00 00 00 02 00 81
+					29 01 00 00 00 00 02 C1 77
+					29 01 00 00 00 00 02 00 A0
+					29 01 00 00 00 00 02 C1 EA
+					29 01 00 00 00 00 02 00 A1
+					29 01 00 00 00 00 02 C1 08
+					29 01 00 00 00 00 02 00 89
+					29 01 00 00 00 00 02 C4 08
+					29 01 00 00 00 00 02 00 81
+					29 01 00 00 00 00 02 C4 83
+					29 01 00 00 00 00 02 00 92
+					29 01 00 00 00 00 02 C5 01
+					29 01 00 00 00 00 02 00 B1
+					29 01 00 00 00 00 02 C5 A9
+					29 01 00 00 00 00 02 00 92
+					29 01 00 00 00 00 02 B3 45
+					29 01 00 00 00 00 02 00 90
+					29 01 00 00 00 00 02 B3 02
+					29 01 00 00 00 00 02 00 80
+					29 01 00 00 00 00 06 C0 00 58 00 14 16
+					29 01 00 00 00 00 02 00 80
+					29 01 00 00 00 00 02 C4 30
+					29 01 00 00 00 00 02 00 90
+					29 01 00 00 00 00 07 C0 00 44 00 00 00 03
+					29 01 00 00 00 00 02 00 A6
+					29 01 00 00 00 00 04 C1 01 00 00
+					29 01 00 00 00 00 02 00 80
+					29 01 00 00 00 00 0D CE 87 03 00 85 03 00 86 03 00 84 03 00
+					29 01 00 00 00 00 02 00 A0
+					29 01 00 00 00 00 0f CE 38 03 03 58 00 00 00 38 02 03 59 00 00 00
+					29 01 00 00 00 00 02 00 B0
+					29 01 00 00 00 00 0f CE 38 01 03 5A 00 00 00 38 00 03 5B 00 00 00
+					29 01 00 00 00 00 02 00 C0
+					29 01 00 00 00 00 0f CE 30 00 03 5C 00 00 00 30 01 03 5D 00 00 00
+					29 01 00 00 00 00 02 00 D0
+					29 01 00 00 00 00 0f CE 30 02 03 5E 00 00 00 30 03 03 5F 00 00 00
+					29 01 00 00 00 00 02 00 C7
+					29 01 00 00 00 00 02 CF 00
+					29 01 00 00 00 00 02 00 C9
+					29 01 00 00 00 00 02 CF 00
+					29 01 00 00 00 00 02 00 D0
+					29 01 00 00 00 00 02 CF 00
+					29 01 00 00 00 00 02 00 C4
+					29 01 00 00 00 00 07 CB 04 04 04 04 04 04
+					29 01 00 00 00 00 02 00 D9
+					29 01 00 00 00 00 07 CB 04 04 04 04 04 04
+					29 01 00 00 00 00 02 00 84
+					29 01 00 00 00 00 07 CC 0C 0A 10 0E 03 04
+					29 01 00 00 00 00 02 00 9E
+					29 01 00 00 00 00 02 CC 0B
+					29 01 00 00 00 00 02 00 A0
+					29 01 00 00 00 00 06 CC 09 0F 0D 01 02
+					29 01 00 00 00 00 02 00 B4
+					29 01 00 00 00 00 07 CC 0D 0F 09 0B 02 01
+					29 01 00 00 00 00 02 00 CE
+					29 01 00 00 00 00 02 CC 0E
+					29 01 00 00 00 00 02 00 D0
+					29 01 00 00 00 00 06 CC 10 0A 0C 04 03
+					29 01 00 00 00 00 02 00 00
+					29 01 00 00 00 00 04 ff ff ff ff
+					05 01 00 00 78 00 02 11 00
+					05 01 00 00 32 00 02 29 00];
+		qcom,mdss-dsi-off-command = [05 01 00 00 32 00 02 28 00
+					05 01 00 00 78 00 02 10 00];
+		qcom,mdss-dsi-on-command-state = "dsi_lp_mode";
+		qcom,mdss-dsi-off-command-state = "dsi_lp_mode";
+		qcom,mdss-dsi-h-sync-pulse = <1>;
+		qcom,mdss-dsi-traffic-mode = <2>;
+		qcom,mdss-dsi-lane-map = <1>;
+		qcom,mdss-dsi-bllp-eof-power-mode;
+		qcom,mdss-dsi-bllp-power-mode;
+		qcom,mdss-dsi-lane-0-state;
+		qcom,mdss-dsi-lane-1-state;
+		qcom,mdss-dsi-panel-timings = [8B 1F 14 00 45 4A 19 23 23 03 04 00];
+		qcom,mdss-dsi-t-clk-post = <0x04>;
+		qcom,mdss-dsi-t-clk-pre = <0x1b>;
+		qcom,mdss-dsi-bl-min-level = <1>;
+		qcom,mdss-dsi-bl-max-level = <255>;
+		qcom,mdss-dsi-dma-trigger = <4>;
+		qcom,mdss-dsi-mdp-trigger = <0>;
+		qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_wled";
+
+	};
+};
diff --git a/arch/arm/boot/dts/dsi-panel-sharp-qhd-video.dtsi b/arch/arm/boot/dts/dsi-panel-sharp-qhd-video.dtsi
index 7fe0f7f..c627e7a 100644
--- a/arch/arm/boot/dts/dsi-panel-sharp-qhd-video.dtsi
+++ b/arch/arm/boot/dts/dsi-panel-sharp-qhd-video.dtsi
@@ -15,10 +15,8 @@
  * Update input XML file to add a new entry or update variable in this file
  * VERSION = "1.0"
  *---------------------------------------------------------------------------*/
-&soc {
-	qcom,mdss_dsi_sharp_qhd_video {
-		compatible = "qcom,mdss-dsi-panel";
-		status = "disable";
+&mdss_mdp {
+	dsi_sharp_qhd_vid: qcom,mdss_dsi_sharp_qhd_video {
 		qcom,mdss-dsi-panel-name = "sharp QHD LS043T1LE01 video mode dsi panel";
 		qcom,mdss-dsi-panel-controller = <&mdss_dsi0>;
 		qcom,mdss-dsi-panel-type = "dsi_video_mode";
diff --git a/arch/arm/boot/dts/dsi-panel-sim-video.dtsi b/arch/arm/boot/dts/dsi-panel-sim-video.dtsi
index 271e373..ccbb659 100644
--- a/arch/arm/boot/dts/dsi-panel-sim-video.dtsi
+++ b/arch/arm/boot/dts/dsi-panel-sim-video.dtsi
@@ -10,12 +10,9 @@
  * GNU General Public License for more details.
  */
 
-&soc {
-
-	qcom,mdss_dsi_sim_video {
-		compatible = "qcom,mdss-dsi-panel";
+&mdss_mdp {
+	dsi_sim_vid: qcom,mdss_dsi_sim_video {
 		label = "simulator video mode dsi panel";
-		status = "disable";
 		qcom,dsi-ctrl-phandle = <&mdss_dsi0>;
 		qcom,mdss-pan-res = <640 480>;
 		qcom,mdss-pan-bpp = <24>;
diff --git a/arch/arm/boot/dts/dsi-panel-toshiba-720p-video.dtsi b/arch/arm/boot/dts/dsi-panel-toshiba-720p-video.dtsi
index a824d45..0b98db7 100644
--- a/arch/arm/boot/dts/dsi-panel-toshiba-720p-video.dtsi
+++ b/arch/arm/boot/dts/dsi-panel-toshiba-720p-video.dtsi
@@ -15,10 +15,8 @@
  * Update input XML file to add a new entry or update variable in this file
  * VERSION = "1.0"
  *---------------------------------------------------------------------------*/
-&soc {
-	qcom,mdss_dsi_toshiba_720p_video {
-		compatible = "qcom,mdss-dsi-panel";
-		status = "disable";
+&mdss_mdp {
+	dsi_tosh_720_vid: qcom,mdss_dsi_toshiba_720p_video {
 		qcom,mdss-dsi-panel-name = "toshiba 720p video mode dsi panel";
 		qcom,mdss-dsi-panel-controller = <&mdss_dsi0>;
 		qcom,mdss-dsi-panel-type = "dsi_video_mode";
diff --git a/arch/arm/boot/dts/dsi-panel-truly-wvga-cmd.dtsi b/arch/arm/boot/dts/dsi-panel-truly-wvga-cmd.dtsi
new file mode 100644
index 0000000..f0957f8
--- /dev/null
+++ b/arch/arm/boot/dts/dsi-panel-truly-wvga-cmd.dtsi
@@ -0,0 +1,95 @@
+/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+/*---------------------------------------------------------------------------
+ * This file is autogenerated file using gcdb parser. Please do not edit it.
+ * Update input XML file to add a new entry or update variable in this file
+ * VERSION = "1.0"
+ *---------------------------------------------------------------------------*/
+&mdss_mdp {
+	dsi_truly_wvga_cmd: qcom,mdss_dsi_truly_wvga_cmd {
+		qcom,mdss-dsi-panel-name = "Truly WVGA command mode dsi panel";
+		qcom,mdss-dsi-panel-controller = <&mdss_dsi0>;
+		qcom,mdss-dsi-panel-type = "dsi_cmd_mode";
+		qcom,mdss-dsi-panel-destination = "display_1";
+		qcom,mdss-dsi-panel-mode-gpio-state = "low";
+		qcom,mdss-dsi-panel-framerate = <60>;
+		qcom,mdss-dsi-virtual-channel-id = <0>;
+		qcom,mdss-dsi-stream = <0>;
+		qcom,mdss-dsi-panel-width = <480>;
+		qcom,mdss-dsi-panel-height = <800>;
+		qcom,mdss-dsi-h-front-porch = <160>;
+		qcom,mdss-dsi-h-back-porch = <40>;
+		qcom,mdss-dsi-h-pulse-width = <8>;
+		qcom,mdss-dsi-h-sync-skew = <0>;
+		qcom,mdss-dsi-v-back-porch = <10>;
+		qcom,mdss-dsi-v-front-porch = <12>;
+		qcom,mdss-dsi-v-pulse-width = <2>;
+		qcom,mdss-dsi-h-left-border = <0>;
+		qcom,mdss-dsi-h-right-border = <0>;
+		qcom,mdss-dsi-v-top-border = <0>;
+		qcom,mdss-dsi-v-bottom-border = <0>;
+		qcom,mdss-dsi-bpp = <24>;
+		qcom,mdss-dsi-color-order = <0>;
+		qcom,mdss-dsi-underflow-color = <0xff>;
+		qcom,mdss-dsi-border-color = <0>;
+		qcom,mdss-dsi-on-command = [05 01 00 00 00 00 02 01 00
+		23 01 00 00 00 00 02 b0 04
+		29 01 00 00 00 00 03 b3 02 00
+		23 01 00 00 00 00 02 bd 00
+		29 01 00 00 00 00 03 c0 18 66
+		29 01 00 00 00 00 10 c1 23 31 99 21 20 00 30 28 0c 0c 00 00 00 21 01
+		29 01 00 00 00 00 07 c2 00 06 06 01 03 00
+		29 01 00 00 00 00 19 c8 04 10 18 20 2e 46 3c 28 1f 18 10 04 04 10 18 20 2e 46 3c 28 1f 18 10 04
+		29 01 00 00 00 00 19 c9 04 10 18 20 2e 46 3c 28 1f 18 10 04 04 10 18 20 2e 46 3c 28 1f 18 10 04
+		29 01 00 00 00 00 19 ca 04 10 18 20 2e 46 3c 28 1f 18 10 04 04 10 18 20 2e 46 3c 28 1f 18 10 04
+		29 01 00 00 00 00 11 d0 29 03 ce a6 00 43 20 10 01 00 01 01 00 03 01 00
+		29 01 00 00 00 00 08 d1 18 0C 23 03 75 02 50
+		23 01 00 00 00 00 02 d3 11
+		29 01 00 00 00 00 03 d5 2a 2a
+		29 01 00 00 00 00 03 de 01 51
+		23 01 00 00 00 00 02 e6 51
+		23 01 00 00 00 00 02 fa 03
+		23 01 00 00 64 00 02 d6 28
+		15 01 00 00 64 00 02 36 41
+		39 01 00 00 00 00 05 2a 00 00 01 df
+		39 01 00 00 00 00 05 2b 00 00 03 1f
+		15 01 00 00 00 00 02 35 00
+		39 01 00 00 00 00 03 44 00 50
+		05 01 00 00 7D 00 02 11 00
+		05 01 00 00 14 00 02 29 00];
+		qcom,mdss-dsi-off-command = [05 01 00 00 32 00 02 28 00
+				05 01 00 00 78 00 02 10 00];
+		qcom,mdss-dsi-on-command-state = "dsi_lp_mode";
+		qcom,mdss-dsi-off-command-state = "dsi_lp_mode";
+		qcom,mdss-dsi-h-sync-pulse = <0>;
+		qcom,mdss-dsi-traffic-mode = <1>;
+		qcom,mdss-dsi-lane-map = <0>;
+		qcom,mdss-dsi-bllp-eof-power-mode;
+		qcom,mdss-dsi-bllp-power-mode;
+		qcom,mdss-dsi-lane-0-state;
+		qcom,mdss-dsi-lane-1-state;
+		qcom,mdss-dsi-te-pin-select = <1>;
+		qcom,mdss-dsi-te-v-sync-rd-ptr-irq-line = <0x2c>;
+		qcom,mdss-dsi-te-dcs-command = <1>;
+		qcom,mdss-dsi-te-check-enable;
+		qcom,mdss-dsi-te-using-te-pin;
+		qcom,mdss-dsi-panel-timings = [5D 12 0C 00 33 38 10 16 1E 03 04 00];
+		qcom,mdss-dsi-t-clk-post = <0x04>;
+		qcom,mdss-dsi-t-clk-pre = <0x1b>;
+		qcom,mdss-dsi-bl-min-level = <1>;
+		qcom,mdss-dsi-bl-max-level = <255>;
+		qcom,mdss-dsi-dma-trigger = <4>;
+		qcom,mdss-dsi-mdp-trigger = <2>;
+		qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_wled";
+	};
+};
diff --git a/arch/arm/boot/dts/dsi-panel-truly-wvga-video.dtsi b/arch/arm/boot/dts/dsi-panel-truly-wvga-video.dtsi
new file mode 100644
index 0000000..32af837
--- /dev/null
+++ b/arch/arm/boot/dts/dsi-panel-truly-wvga-video.dtsi
@@ -0,0 +1,91 @@
+/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+/*---------------------------------------------------------------------------
+ * This file is autogenerated file using gcdb parser. Please do not edit it.
+ * Update input XML file to add a new entry or update variable in this file
+ * VERSION = "1.0"
+ *---------------------------------------------------------------------------*/
+&mdss_mdp {
+	dsi_truly_wvga_vid: qcom,mdss_dsi_truly_wvga_video {
+		qcom,mdss-dsi-panel-name = "Truly WVGA video mode dsi panel";
+		qcom,mdss-dsi-panel-controller = <&mdss_dsi0>;
+		qcom,mdss-dsi-panel-type = "dsi_video_mode";
+		qcom,mdss-dsi-panel-destination = "display_1";
+		qcom,mdss-dsi-panel-mode-gpio-state = "high";
+		qcom,mdss-dsi-panel-framerate = <60>;
+		qcom,mdss-dsi-virtual-channel-id = <0>;
+		qcom,mdss-dsi-stream = <0>;
+		qcom,mdss-dsi-panel-width = <480>;
+		qcom,mdss-dsi-panel-height = <800>;
+		qcom,mdss-dsi-h-front-porch = <160>;
+		qcom,mdss-dsi-h-back-porch = <40>;
+		qcom,mdss-dsi-h-pulse-width = <8>;
+		qcom,mdss-dsi-h-sync-skew = <0>;
+		qcom,mdss-dsi-v-back-porch = <10>;
+		qcom,mdss-dsi-v-front-porch = <12>;
+		qcom,mdss-dsi-v-pulse-width = <2>;
+		qcom,mdss-dsi-h-left-border = <0>;
+		qcom,mdss-dsi-h-right-border = <0>;
+		qcom,mdss-dsi-v-top-border = <0>;
+		qcom,mdss-dsi-v-bottom-border = <0>;
+		qcom,mdss-dsi-bpp = <24>;
+		qcom,mdss-dsi-color-order = <0>;
+		qcom,mdss-dsi-underflow-color = <0xff>;
+		qcom,mdss-dsi-border-color = <0>;
+		qcom,mdss-dsi-on-command = [05 01 00 00 00 00 02 01 00
+		23 01 00 00 00 00 02 b0 04
+		29 01 00 00 00 00 03 b3 02 00
+		23 01 00 00 00 00 02 bd 00
+		29 01 00 00 00 00 03 c0 18 66
+		29 01 00 00 00 00 10 c1 23 31 99 21 20 00 30 28 0c 0c 00 00 00 21 01
+		29 01 00 00 00 00 07 c2 00 06 06 01 03 00
+		29 01 00 00 00 00 19 c8 04 10 18 20 2e 46 3c 28 1f 18 10 04 04 10 18 20 2e 46 3c 28 1f 18 10 04
+		29 01 00 00 00 00 19 c9 04 10 18 20 2e 46 3c 28 1f 18 10 04 04 10 18 20 2e 46 3c 28 1f 18 10 04
+		29 01 00 00 00 00 19 ca 04 10 18 20 2e 46 3c 28 1f 18 10 04 04 10 18 20 2e 46 3c 28 1f 18 10 04
+		29 01 00 00 00 00 11 d0 29 03 ce a6 00 43 20 10 01 00 01 01 00 03 01 00
+		29 01 00 00 00 00 08 d1 18 0C 23 03 75 02 50
+		23 01 00 00 00 00 02 d3 11
+		29 01 00 00 00 00 03 d5 2a 2a
+		29 01 00 00 00 00 03 de 01 51
+		23 01 00 00 00 00 02 e6 51
+		23 01 00 00 00 00 02 fa 03
+		23 01 00 00 64 00 02 d6 28
+		39 01 00 00 00 00 05 2a 00 00 01 df
+		39 01 00 00 00 00 05 2b 00 00 03 1f
+		15 01 00 00 00 00 02 35 00
+		39 01 00 00 00 00 03 44 00 50
+		15 01 00 00 00 00 02 36 c1
+		15 01 00 00 00 00 02 3a 77
+		05 01 00 00 00 00 02 11 00
+		05 01 00 00 00 00 02 29 00];
+		qcom,mdss-dsi-off-command = [05 01 00 00 32 00 02 28 00
+					05 01 00 00 78 00 02 10 00];
+		qcom,mdss-dsi-on-command-state = "dsi_lp_mode";
+		qcom,mdss-dsi-off-command-state = "dsi_lp_mode";
+		qcom,mdss-dsi-h-sync-pulse = <0>;
+		qcom,mdss-dsi-traffic-mode = <1>;
+		qcom,mdss-dsi-lane-map = <0>;
+		qcom,mdss-dsi-bllp-eof-power-mode;
+		qcom,mdss-dsi-bllp-power-mode;
+		qcom,mdss-dsi-lane-0-state;
+		qcom,mdss-dsi-lane-1-state;
+		qcom,mdss-dsi-panel-timings = [5D 12 0C 00 33 38 10 16 1E 03 04 00];
+		qcom,mdss-dsi-t-clk-post = <0x04>;
+		qcom,mdss-dsi-t-clk-pre = <0x1b>;
+		qcom,mdss-dsi-bl-min-level = <1>;
+		qcom,mdss-dsi-bl-max-level = <255>;
+		qcom,mdss-dsi-dma-trigger = <4>;
+		qcom,mdss-dsi-mdp-trigger = <0>;
+		qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_wled";
+	};
+};
diff --git a/arch/arm/boot/dts/fsm9900.dtsi b/arch/arm/boot/dts/fsm9900.dtsi
index b74e58f..1c48bf0 100644
--- a/arch/arm/boot/dts/fsm9900.dtsi
+++ b/arch/arm/boot/dts/fsm9900.dtsi
@@ -78,8 +78,6 @@
 		compatible = "qcom,cache_dump";
 		qcom,l1-dump-size = <0x100000>;
 		qcom,l2-dump-size = <0x500000>;
-		qcom,memory-reservation-type = "EBI1";
-		qcom,memory-reservation-size = <0x600000>; /* 6M EBI1 buffer */
 	};
 
 	qcom,ion {
diff --git a/arch/arm/boot/dts/msm-iommu-v0.dtsi b/arch/arm/boot/dts/msm-iommu-v0.dtsi
index 2cfc5cf..8ab9985 100644
--- a/arch/arm/boot/dts/msm-iommu-v0.dtsi
+++ b/arch/arm/boot/dts/msm-iommu-v0.dtsi
@@ -29,7 +29,6 @@
 						0x80>;
 		qcom,msm-bus,name = "lpass_ebi";
 		qcom,msm-bus,num-cases = <2>;
-		qcom,msm-bus,active-only;
 		qcom,msm-bus,num-paths = <1>;
 		qcom,msm-bus,vectors-KBps =
 				<11 512 0 0>,
@@ -87,7 +86,6 @@
 						0x80>;
 		qcom,msm-bus,name = "copss_ebi";
 		qcom,msm-bus,num-cases = <2>;
-		qcom,msm-bus,active-only;
 		qcom,msm-bus,num-paths = <1>;
 		qcom,msm-bus,vectors-KBps =
 				<88 512 0 0>,
@@ -178,7 +176,6 @@
 						0x80>;
 		qcom,msm-bus,name = "mdpe_ebi";
 		qcom,msm-bus,num-cases = <2>;
-		qcom,msm-bus,active-only;
 		qcom,msm-bus,num-paths = <1>;
 		qcom,msm-bus,vectors-KBps =
 				<92 512 0 0>,
@@ -220,7 +217,6 @@
 						0x80>;
 		qcom,msm-bus,name = "mdps_ebi";
 		qcom,msm-bus,num-cases = <2>;
-		qcom,msm-bus,active-only;
 		qcom,msm-bus,num-paths = <1>;
 		qcom,msm-bus,vectors-KBps =
 				<22 512 0 0>,
@@ -263,7 +259,6 @@
 						0x80>;
 		qcom,msm-bus,name = "gfx_ebi";
 		qcom,msm-bus,num-cases = <2>;
-		qcom,msm-bus,active-only;
 		qcom,msm-bus,num-paths = <1>;
 		qcom,msm-bus,vectors-KBps =
 				<26 512 0 0>,
@@ -315,7 +310,6 @@
 						0x80>;
 		qcom,msm-bus,name = "vfe_ebi";
 		qcom,msm-bus,num-cases = <2>;
-		qcom,msm-bus,active-only;
 		qcom,msm-bus,num-paths = <1>;
 		qcom,msm-bus,vectors-KBps =
 				<29 512 0 0>,
diff --git a/arch/arm/boot/dts/msm-iommu-v1.dtsi b/arch/arm/boot/dts/msm-iommu-v1.dtsi
index cd5adaa..c767b37 100644
--- a/arch/arm/boot/dts/msm-iommu-v1.dtsi
+++ b/arch/arm/boot/dts/msm-iommu-v1.dtsi
@@ -24,7 +24,6 @@
 		status = "disabled";
 		qcom,msm-bus,name = "jpeg_ebi";
 		qcom,msm-bus,num-cases = <2>;
-		qcom,msm-bus,active-only;
 		qcom,msm-bus,num-paths = <1>;
 		qcom,msm-bus,vectors-KBps =
 				<62 512 0 0>,
@@ -119,7 +118,6 @@
 		label = "mdp_iommu";
 		qcom,msm-bus,name = "mdp_ebi";
 		qcom,msm-bus,num-cases = <2>;
-		qcom,msm-bus,active-only;
 		qcom,msm-bus,num-paths = <1>;
 		qcom,msm-bus,vectors-KBps =
 				<22 512 0 0>,
@@ -225,7 +223,6 @@
 		label = "venus_iommu";
 		qcom,msm-bus,name = "venus_ebi";
 		qcom,msm-bus,num-cases = <2>;
-		qcom,msm-bus,active-only;
 		qcom,msm-bus,num-paths = <1>;
 		qcom,msm-bus,vectors-KBps =
 				<63 512 0 0>,
@@ -340,7 +337,6 @@
 		label = "kgsl_iommu";
 		qcom,msm-bus,name = "kgsl_ebi";
 		qcom,msm-bus,num-cases = <2>;
-		qcom,msm-bus,active-only;
 		qcom,msm-bus,num-paths = <1>;
 		qcom,msm-bus,vectors-KBps =
 				<26 512 0 0>,
@@ -431,7 +427,6 @@
 		label = "vfe_iommu";
 		qcom,msm-bus,name = "vfe_ebi";
 		qcom,msm-bus,num-cases = <2>;
-		qcom,msm-bus,active-only;
 		qcom,msm-bus,num-paths = <1>;
 		qcom,msm-bus,vectors-KBps =
 				<29 512 0 0>,
@@ -532,7 +527,6 @@
 		label = "copss_iommu";
 		qcom,msm-bus,name = "copss_ebi";
 		qcom,msm-bus,num-cases = <2>;
-		qcom,msm-bus,active-only;
 		qcom,msm-bus,num-paths = <1>;
 		qcom,msm-bus,vectors-KBps =
 				<88 512 0 0>,
@@ -691,7 +685,6 @@
 		label = "vpu_iommu";
 		qcom,msm-bus,name = "vpu_ebi";
 		qcom,msm-bus,num-cases = <2>;
-		qcom,msm-bus,active-only;
 		qcom,msm-bus,num-paths = <1>;
 		qcom,msm-bus,vectors-KBps =
 				<93 512 0 0>,
@@ -822,7 +815,6 @@
 		label = "lpass_qdsp_iommu";
 		qcom,msm-bus,name = "lpass_qdsp_ebi";
 		qcom,msm-bus,num-cases = <2>;
-		qcom,msm-bus,active-only;
 		qcom,msm-bus,num-paths = <1>;
 		qcom,msm-bus,vectors-KBps =
 				<11 512 0 0>,
@@ -949,7 +941,6 @@
 		label = "lpass_core_iommu";
 		qcom,msm-bus,name = "lpass_core_ebi";
 		qcom,msm-bus,num-cases = <2>;
-		qcom,msm-bus,active-only;
 		qcom,msm-bus,num-paths = <1>;
 		qcom,msm-bus,vectors-KBps =
 				<52 512 0 0>,
@@ -1070,7 +1061,6 @@
 		status = "disabled";
 		qcom,msm-bus,name = "vcap_ebi";
 		qcom,msm-bus,num-cases = <2>;
-		qcom,msm-bus,active-only;
 		qcom,msm-bus,num-paths = <1>;
 		qcom,msm-bus,vectors-KBps =
 			<48 512 0 0>,
diff --git a/arch/arm/boot/dts/msm8226-cdp.dtsi b/arch/arm/boot/dts/msm8226-cdp.dtsi
index 253ce3f..066d6c2 100644
--- a/arch/arm/boot/dts/msm8226-cdp.dtsi
+++ b/arch/arm/boot/dts/msm8226-cdp.dtsi
@@ -10,7 +10,6 @@
  * GNU General Public License for more details.
  */
 
-/include/ "dsi-panel-nt35590-720p-video.dtsi"
 /include/ "msm8226-camera-sensor-cdp.dtsi"
 
 &soc {
@@ -18,11 +17,6 @@
 		status = "ok";
 	};
 
-	qcom,mdss_dsi_nt35590_720p_video {
-		status = "ok";
-		qcom,cont-splash-enabled;
-	};
-
 	i2c@f9927000 { /* BLSP1 QUP5 */
 		synaptics@20 {
 			compatible = "synaptics,rmi4";
@@ -462,3 +456,15 @@
 		qcom,fast-avg-setup = <0>;
 	};
 };
+
+&mdss_mdp {
+	qcom,mdss-pref-prim-intf = "dsi";
+};
+
+&mdss_dsi0 {
+	qcom,dsi-pref-prim-pan = <&dsi_nt35590_720_vid>;
+};
+
+&dsi_nt35590_720_vid {
+	qcom,cont-splash-enabled;
+};
diff --git a/arch/arm/boot/dts/msm8226-coresight.dtsi b/arch/arm/boot/dts/msm8226-coresight.dtsi
index cbfdfc9..ec3f248 100644
--- a/arch/arm/boot/dts/msm8226-coresight.dtsi
+++ b/arch/arm/boot/dts/msm8226-coresight.dtsi
@@ -19,8 +19,7 @@
 		interrupts = <0 166 0>;
 		interrupt-names = "byte-cntr-irq";
 
-		qcom,memory-reservation-type = "EBI1";
-		qcom,memory-reservation-size = <0x100000>; /* 1M EBI1 buffer */
+		qcom,memory-size = <0x100000>;
 
 		coresight-id = <0>;
 		coresight-name = "coresight-tmc-etr";
@@ -41,6 +40,11 @@
 
 		qcom,vdd-voltage-level = <2950000 2950000>;
 		qcom,vdd-current-level = <9000 800000>;
+
+		vdd-io-supply = <&pm8226_l21>;
+
+		qcom,vdd-io-voltage-level = <2950000 2950000>;
+		qcom,vdd-io-current-level = <6 22000>;
 	};
 
 	replicator: replicator@fc31c000 {
diff --git a/arch/arm/boot/dts/msm8226-mdss-panels.dtsi b/arch/arm/boot/dts/msm8226-mdss-panels.dtsi
new file mode 100644
index 0000000..8194bf6
--- /dev/null
+++ b/arch/arm/boot/dts/msm8226-mdss-panels.dtsi
@@ -0,0 +1,17 @@
+/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+/include/ "dsi-panel-hx8394a-720p-video.dtsi"
+/include/ "dsi-panel-nt35590-720p-video.dtsi"
+/include/ "dsi-panel-nt35521-720p-video.dtsi"
+/include/ "dsi-panel-nt35596-1080p-video.dtsi"
+/include/ "dsi-panel-nt35590-720p-cmd.dtsi"
diff --git a/arch/arm/boot/dts/msm8226-mdss.dtsi b/arch/arm/boot/dts/msm8226-mdss.dtsi
index 8852a8d..2ec7b6c 100644
--- a/arch/arm/boot/dts/msm8226-mdss.dtsi
+++ b/arch/arm/boot/dts/msm8226-mdss.dtsi
@@ -11,7 +11,7 @@
  */
 
 &soc {
-	qcom,mdss_mdp@fd900000 {
+	mdss_mdp: qcom,mdss_mdp@fd900000 {
 		compatible = "qcom,mdss_mdp";
 		reg = <0xfd900000 0x22100>,
 			<0xfd924000 0x1000>;
@@ -63,10 +63,11 @@
 		cell-index = <0>;
 		reg = <0xfd922800 0x600>;
 		qcom,mdss-fb-map = <&mdss_fb0>;
+		qcom,mdss-mdp = <&mdss_mdp>;
 		vdd-supply = <&pm8226_l15>;
 		vddio-supply = <&pm8226_l8>;
 		vdda-supply = <&pm8226_l4>;
-		qcom,platform-reset-gpio = <&msmgpio 25 1>;
+		qcom,platform-reset-gpio = <&msmgpio 25 0>;
 		qcom,platform-te-gpio = <&msmgpio 24 0>;
 		qcom,platform-strength-ctrl = [ff 06];
 		qcom,platform-bist-ctrl = [00 00 b1 ff 00 00];
@@ -119,3 +120,5 @@
 		qcom,mdss-fb-map = <&mdss_fb1>;
 	};
 };
+
+/include/ "msm8226-mdss-panels.dtsi"
diff --git a/arch/arm/boot/dts/msm8226-mtp.dtsi b/arch/arm/boot/dts/msm8226-mtp.dtsi
index 68621fc..f4f7442 100644
--- a/arch/arm/boot/dts/msm8226-mtp.dtsi
+++ b/arch/arm/boot/dts/msm8226-mtp.dtsi
@@ -10,7 +10,6 @@
  * GNU General Public License for more details.
  */
 
-/include/ "dsi-panel-nt35590-720p-video.dtsi"
 /include/ "msm8226-camera-sensor-mtp.dtsi"
 
 &soc {
@@ -18,11 +17,6 @@
 		status = "ok";
 	};
 
-	qcom,mdss_dsi_nt35590_720p_video {
-		status = "ok";
-		qcom,cont-splash-enabled;
-	};
-
 	i2c@f9927000 { /* BLSP1 QUP5 */
 		synaptics@20 {
 			compatible = "synaptics,rmi4";
@@ -484,3 +478,15 @@
 		qcom,cdc-micbias1-ext-cap;
 	};
 };
+
+&mdss_mdp {
+	qcom,mdss-pref-prim-intf = "dsi";
+};
+
+&mdss_dsi0 {
+	qcom,dsi-pref-prim-pan = <&dsi_nt35590_720_vid>;
+};
+
+&dsi_nt35590_720_vid {
+	qcom,cont-splash-enabled;
+};
diff --git a/arch/arm/boot/dts/msm8226-qrd.dtsi b/arch/arm/boot/dts/msm8226-qrd.dtsi
index 88c44e6..a574bb0 100644
--- a/arch/arm/boot/dts/msm8226-qrd.dtsi
+++ b/arch/arm/boot/dts/msm8226-qrd.dtsi
@@ -10,7 +10,6 @@
  * GNU General Public License for more details.
  */
 
-/include/ "dsi-panel-nt35596-1080p-video.dtsi"
 /include/ "msm8226-camera-sensor-qrd.dtsi"
 
 &soc {
@@ -473,4 +472,17 @@
 
 &android_usb {
 	qcom,android-usb-cdrom;
+	qcom,android-usb-internal-ums;
+};
+
+&mdss_mdp {
+	qcom,mdss-pref-prim-intf = "dsi";
+};
+
+&mdss_dsi0 {
+	qcom,dsi-pref-prim-pan = <&dsi_nt35596_1080_vid>;
+};
+
+&dsi_nt35596_1080_vid {
+	qcom,cont-splash-enabled;
 };
diff --git a/arch/arm/boot/dts/msm8226-v1-qrd-dvt.dts b/arch/arm/boot/dts/msm8226-v1-qrd-dvt.dts
index 4acfa0f..f8fd0c2 100644
--- a/arch/arm/boot/dts/msm8226-v1-qrd-dvt.dts
+++ b/arch/arm/boot/dts/msm8226-v1-qrd-dvt.dts
@@ -13,7 +13,6 @@
 /dts-v1/;
 /include/ "msm8226-v1.dtsi"
 /include/ "msm8226-qrd.dtsi"
-/include/ "dsi-panel-hx8394a-720p-video.dtsi"
 
 / {
 	model = "Qualcomm MSM 8226 QRD";
@@ -29,9 +28,10 @@
 		      <223 0x2000b 0>;
 };
 
-&soc {
-        qcom,mdss_dsi_hx8394a_720p_video {
-                status = "ok";
-		qcom,cont-splash-enabled;
-        };
+&mdss_dsi0 {
+	qcom,dsi-pref-prim-pan = <&dsi_hx8394a_720_vid>;
+};
+
+&dsi_hx8394a_720_vid {
+	qcom,cont-splash-enabled;
 };
diff --git a/arch/arm/boot/dts/msm8226-v1-qrd-evt.dts b/arch/arm/boot/dts/msm8226-v1-qrd-evt.dts
index 507a92a..bc5d8e7 100644
--- a/arch/arm/boot/dts/msm8226-v1-qrd-evt.dts
+++ b/arch/arm/boot/dts/msm8226-v1-qrd-evt.dts
@@ -13,7 +13,6 @@
 /dts-v1/;
 /include/ "msm8226-v1.dtsi"
 /include/ "msm8226-qrd.dtsi"
-/include/ "dsi-panel-nt35590-720p-video.dtsi"
 
 / {
 	model = "Qualcomm MSM 8226 QRD";
@@ -29,9 +28,10 @@
 		      <223 11 0>;
 };
 
-&soc {
-        qcom,mdss_dsi_nt35590_720p_video {
-                status = "ok";
-		qcom,cont-splash-enabled;
-        };
+&mdss_dsi0 {
+	qcom,dsi-pref-prim-pan = <&dsi_nt35590_720_vid>;
+};
+
+&dsi_nt35590_720_vid {
+	qcom,cont-splash-enabled;
 };
diff --git a/arch/arm/boot/dts/msm8226-v1-qrd-skuf.dts b/arch/arm/boot/dts/msm8226-v1-qrd-skuf.dts
index faad6f3..cbafe80 100644
--- a/arch/arm/boot/dts/msm8226-v1-qrd-skuf.dts
+++ b/arch/arm/boot/dts/msm8226-v1-qrd-skuf.dts
@@ -13,7 +13,6 @@
 /dts-v1/;
 /include/ "msm8226-v1.dtsi"
 /include/ "msm8226-qrd.dtsi"
-/include/ "dsi-panel-nt35521-720p-video.dtsi"
 
 / {
 	model = "Qualcomm MSM 8226v1 QRD";
@@ -22,11 +21,6 @@
 };
 
 &soc {
-	qcom,mdss_dsi_nt35521_720p_video {
-		status = "ok";
-		qcom,cont-splash-enabled;
-	};
-
 	sound {
 		qcom,model = "msm8226-tapan-skuf-snd-card";
 
@@ -176,3 +170,11 @@
 &pm8226_chg {
 	qcom,battery-data = <&qrd_batterydata>;
 };
+
+&mdss_dsi0 {
+	qcom,dsi-pref-prim-pan = <&dsi_nt35521_720_vid>;
+};
+
+&dsi_nt35521_720_vid {
+	qcom,cont-splash-enabled;
+};
diff --git a/arch/arm/boot/dts/msm8226-v2-qrd-dvt.dts b/arch/arm/boot/dts/msm8226-v2-qrd-dvt.dts
index 9cf8224..e492720 100644
--- a/arch/arm/boot/dts/msm8226-v2-qrd-dvt.dts
+++ b/arch/arm/boot/dts/msm8226-v2-qrd-dvt.dts
@@ -13,7 +13,6 @@
 /dts-v1/;
 /include/ "msm8226-v2.dtsi"
 /include/ "msm8226-qrd.dtsi"
-/include/ "dsi-panel-hx8394a-720p-video.dtsi"
 
 / {
 	model = "Qualcomm MSM 8226v2 QRD";
@@ -29,11 +28,12 @@
 		      <223 0x2000b 0x20000>;
 };
 
-&soc {
-        qcom,mdss_dsi_hx8394a_720p_video {
-                status = "ok";
-		qcom,cont-splash-enabled;
-        };
+&mdss_dsi0 {
+	qcom,dsi-pref-prim-pan = <&dsi_hx8394a_720_vid>;
+};
+
+&dsi_hx8394a_720_vid {
+	qcom,cont-splash-enabled;
 };
 
 &pm8226_bms {
diff --git a/arch/arm/boot/dts/msm8226-v2-qrd-evt.dts b/arch/arm/boot/dts/msm8226-v2-qrd-evt.dts
index 98de659..83c7034 100644
--- a/arch/arm/boot/dts/msm8226-v2-qrd-evt.dts
+++ b/arch/arm/boot/dts/msm8226-v2-qrd-evt.dts
@@ -13,7 +13,6 @@
 /dts-v1/;
 /include/ "msm8226-v2.dtsi"
 /include/ "msm8226-qrd.dtsi"
-/include/ "dsi-panel-nt35590-720p-video.dtsi"
 
 / {
 	model = "Qualcomm MSM 8226v2 QRD";
@@ -29,9 +28,10 @@
 		      <223 11 0x20000>;
 };
 
-&soc {
-        qcom,mdss_dsi_nt35590_720p_video {
-                status = "ok";
-		qcom,cont-splash-enabled;
-        };
+&mdss_dsi0 {
+	qcom,dsi-pref-prim-pan = <&dsi_nt35590_720_vid>;
+};
+
+&dsi_nt35590_720_vid {
+	qcom,cont-splash-enabled;
 };
diff --git a/arch/arm/boot/dts/msm8226-v2-qrd-skuf.dts b/arch/arm/boot/dts/msm8226-v2-qrd-skuf.dts
index 0d89e00..77037be 100644
--- a/arch/arm/boot/dts/msm8226-v2-qrd-skuf.dts
+++ b/arch/arm/boot/dts/msm8226-v2-qrd-skuf.dts
@@ -13,7 +13,6 @@
 /dts-v1/;
 /include/ "msm8226-v2.dtsi"
 /include/ "msm8226-qrd.dtsi"
-/include/ "dsi-panel-nt35521-720p-video.dtsi"
 
 / {
 	model = "Qualcomm MSM 8226v2 QRD";
@@ -22,11 +21,6 @@
 };
 
 &soc {
-	qcom,mdss_dsi_nt35521_720p_video {
-		status = "ok";
-		qcom,cont-splash-enabled;
-	};
-
 	sound {
 		qcom,model = "msm8226-tapan-skuf-snd-card";
 
@@ -181,3 +175,11 @@
 &pm8226_iadc {
 	qcom,rsense = <10000000>;
 };
+
+&mdss_dsi0 {
+	qcom,dsi-pref-prim-pan = <&dsi_nt35521_720_vid>;
+};
+
+&dsi_nt35521_720_vid {
+	qcom,cont-splash-enabled;
+};
diff --git a/arch/arm/boot/dts/msm8226.dtsi b/arch/arm/boot/dts/msm8226.dtsi
index 0ae0fc6..7b944fc 100644
--- a/arch/arm/boot/dts/msm8226.dtsi
+++ b/arch/arm/boot/dts/msm8226.dtsi
@@ -33,7 +33,7 @@
 
 		adsp_mem: adsp_region {
 			linux,contiguous-region;
-			reg = <0 0x2000000>;
+			reg = <0 0xc00000>;
 			label = "adsp_mem";
 		};
 
@@ -158,6 +158,7 @@
 		compatible = "qcom,msm-vidc";
 		reg = <0xfdc00000 0xff000>;
 		interrupts = <0 44 0>;
+		vdd-supply = <&gdsc_venus>;
 		qcom,load-freq-tbl = <352800 160000000>,
 			<244800 133330000>,
 			<108000  66700000>;
diff --git a/arch/arm/boot/dts/msm8610-cdp.dtsi b/arch/arm/boot/dts/msm8610-cdp.dtsi
index 8403dfd..f0d1715 100644
--- a/arch/arm/boot/dts/msm8610-cdp.dtsi
+++ b/arch/arm/boot/dts/msm8610-cdp.dtsi
@@ -121,19 +121,16 @@
 		};
 	};
 
-    sound {
-        qcom,audio-routing =
-            "RX_BIAS", "MCLK",
-            "INT_LDO_H", "MCLK",
-            "MIC BIAS External", "Handset Mic",
-            "MIC BIAS Internal2", "Headset Mic",
-            "AMIC1", "MIC BIAS External",
-            "AMIC2", "MIC BIAS Internal2";
+	sound {
+		qcom,audio-routing =
+			"RX_BIAS", "MCLK",
+			"INT_LDO_H", "MCLK",
+			"MIC BIAS External", "Handset Mic",
+			"MIC BIAS Internal2", "Headset Mic",
+			"AMIC1", "MIC BIAS External",
+			"AMIC2", "MIC BIAS Internal2";
+		qcom,headset-jack-type-NC;
     };
-
-	qcom,dsi_v2_truly_wvga_video {
-		qcom,cont-splash-enabled;
-	};
 };
 
 &i2c_cdc  {
@@ -399,3 +396,19 @@
 	qcom,setb-gpios-pull = <0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0>;
 	qcom,setb-gpios-dir =  <2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2>;
 };
+
+&mdss_mdp {
+	qcom,mdss-pref-prim-intf = "dsi";
+};
+
+&mdss_dsi0 {
+	qcom,dsi-pref-prim-pan = <&dsi_truly_wvga_vid>;
+};
+
+&dsi_truly_wvga_vid {
+	qcom,cont-splash-enabled;
+};
+
+&dsi_truly_wvga_cmd {
+	qcom,cont-splash-enabled;
+};
diff --git a/arch/arm/boot/dts/msm8610-coresight.dtsi b/arch/arm/boot/dts/msm8610-coresight.dtsi
index 98a99a7..78a4b5a 100644
--- a/arch/arm/boot/dts/msm8610-coresight.dtsi
+++ b/arch/arm/boot/dts/msm8610-coresight.dtsi
@@ -19,8 +19,7 @@
 		interrupts = <0 166 0>;
 		interrupt-names = "byte-cntr-irq";
 
-		qcom,memory-reservation-type = "EBI1";
-		qcom,memory-reservation-size = <0x100000>; /* 1M EBI1 buffer */
+		qcom,memory-size = <0x100000>;
 
 		coresight-id = <0>;
 		coresight-name = "coresight-tmc-etr";
@@ -41,6 +40,11 @@
 
 		qcom,vdd-voltage-level = <2950000 2950000>;
 		qcom,vdd-current-level = <15000 400000>;
+
+		vdd-io-supply = <&pm8110_l21>;
+
+		qcom,vdd-io-voltage-level = <2950000 2950000>;
+		qcom,vdd-io-current-level = <200 50000>;
 	};
 
 	replicator: replicator@fc324000 {
diff --git a/arch/arm/boot/dts/msm8610-mdss-panels.dtsi b/arch/arm/boot/dts/msm8610-mdss-panels.dtsi
new file mode 100644
index 0000000..243d7e8
--- /dev/null
+++ b/arch/arm/boot/dts/msm8610-mdss-panels.dtsi
@@ -0,0 +1,17 @@
+/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+/include/ "dsi-panel-truly-wvga-video.dtsi"
+/include/ "dsi-panel-truly-wvga-cmd.dtsi"
+/include/ "dsi-panel-nt35590-720p-video.dtsi"
+/include/ "dsi-panel-otm8018b-fwvga-video.dtsi"
+/include/ "dsi-panel-hx8379a-wvga-video.dtsi"
diff --git a/arch/arm/boot/dts/msm8610-mdss.dtsi b/arch/arm/boot/dts/msm8610-mdss.dtsi
index d0fc1dc..f37a42b 100644
--- a/arch/arm/boot/dts/msm8610-mdss.dtsi
+++ b/arch/arm/boot/dts/msm8610-mdss.dtsi
@@ -11,7 +11,7 @@
  */
 
 &soc {
-	qcom,mdss_mdp@fd900000 {
+	mdss_mdp: qcom,mdss_mdp@fd900000 {
 		compatible = "qcom,mdss_mdp3";
 		reg = <0xfd900000 0x100000>;
 		reg-names = "mdp_phys";
@@ -29,7 +29,62 @@
 		cell-index = <0>;
 		reg = <0xfdd00000 0x100000>;
 		interrupts = <0 30 0>;
-		vdda-supply = <&pm8110_l4>;
+		vdd-supply = <&pm8110_l4>;
+		vdda-supply = <&pm8110_l19>;
+		vddio-supply = <&pm8110_l14>;
 		qcom,mdss-fb-map = <&mdss_fb0>;
+		qcom,mdss-mdp = <&mdss_mdp>;
+		qcom,platform-reset-gpio = <&msmgpio 41 0>;
+		qcom,platform-te-gpio = <&msmgpio 12 0>;
+		qcom,platform-mode-gpio = <&msmgpio 7 0>;
+
+		qcom,platform-reset-sequence = <1 20 0 2 1 20 2>;
+
+		qcom,platform-strength-ctrl = [ff 06];
+		qcom,platform-bist-ctrl = [03 03 00 00 0f 00];
+		qcom,platform-regulator-settings = [02 08 05 00 20 03];
+		qcom,platform-lane-config = [80 45 00 00 01 66
+		80 45 00 00 01 66
+		80 45 00 00 01 66
+		80 45 00 00 01 66
+		40 67 00 00 01 88];
+
+		qcom,platform-supply-entry1 {
+			qcom,supply-name = "vdd";
+			qcom,supply-min-voltage = <1200000>;
+			qcom,supply-max-voltage = <1200000>;
+			qcom,supply-enable-load = <100000>;
+			qcom,supply-disable-load = <100>;
+			qcom,supply-pre-on-sleep = <0>;
+			qcom,supply-post-on-sleep = <20>;
+			qcom,supply-pre-off-sleep = <0>;
+			qcom,supply-post-off-sleep = <20>;
+		};
+
+		qcom,platform-supply-entry2 {
+			qcom,supply-name = "vddio";
+			qcom,supply-min-voltage = <1800000>;
+			qcom,supply-max-voltage = <1800000>;
+			qcom,supply-enable-load = <100000>;
+			qcom,supply-disable-load = <100>;
+			qcom,supply-pre-on-sleep = <0>;
+			qcom,supply-post-on-sleep = <0>;
+			qcom,supply-pre-off-sleep = <0>;
+			qcom,supply-post-off-sleep = <0>;
+		};
+
+		qcom,platform-supply-entry3 {
+			qcom,supply-name = "vdda";
+			qcom,supply-min-voltage = <2850000>;
+			qcom,supply-max-voltage = <2850000>;
+			qcom,supply-enable-load = <100000>;
+			qcom,supply-disable-load = <100>;
+			qcom,supply-pre-on-sleep = <0>;
+			qcom,supply-post-on-sleep = <0>;
+			qcom,supply-pre-off-sleep = <0>;
+			qcom,supply-post-off-sleep = <0>;
+		};
 	};
 };
+
+/include/ "msm8610-mdss-panels.dtsi"
diff --git a/arch/arm/boot/dts/msm8610-mtp.dtsi b/arch/arm/boot/dts/msm8610-mtp.dtsi
index 798fab4..56ef7ca 100644
--- a/arch/arm/boot/dts/msm8610-mtp.dtsi
+++ b/arch/arm/boot/dts/msm8610-mtp.dtsi
@@ -187,10 +187,6 @@
             "AMIC2", "MIC BIAS Internal2",
             "AMIC3", "MIC BIAS External";
     };
-
-	qcom,dsi_v2_truly_wvga_video {
-		qcom,cont-splash-enabled;
-	};
 };
 
 &i2c_cdc  {
@@ -414,3 +410,19 @@
 &pm8110_bms {
 	status = "ok";
 };
+
+&mdss_mdp {
+	qcom,mdss-pref-prim-intf = "dsi";
+};
+
+&mdss_dsi0 {
+	qcom,dsi-pref-prim-pan = <&dsi_truly_wvga_vid>;
+};
+
+&dsi_truly_wvga_vid {
+	qcom,cont-splash-enabled;
+};
+
+&dsi_truly_wvga_cmd {
+	qcom,cont-splash-enabled;
+};
diff --git a/arch/arm/boot/dts/msm8610-qrd-skuaa.dtsi b/arch/arm/boot/dts/msm8610-qrd-skuaa.dtsi
index ae28e2c..86f1210 100644
--- a/arch/arm/boot/dts/msm8610-qrd-skuaa.dtsi
+++ b/arch/arm/boot/dts/msm8610-qrd-skuaa.dtsi
@@ -28,10 +28,6 @@
         qcom,ext-spk-amp-gpio = <&msmgpio 92 0x0>;
     };
 
-	qcom,dsi_v2_hx8379a_wvga_video {
-		qcom,cont-splash-enabled;
-	};
-
 	usb@f9a55000 {
 		qcom,hsusb-otg-phy-init-seq =
 		<0x44 0x80 0x6a 0x81 0x34 0x82 0x13 0x83 0xffffffff>;
@@ -62,3 +58,15 @@
 		qcom,scale-function = <7>;
 	};
 };
+
+&mdss_mdp {
+	qcom,mdss-pref-prim-intf = "dsi";
+};
+
+&mdss_dsi0 {
+	qcom,dsi-pref-prim-pan = <&dsi_hx8379a_wvga_vid>;
+};
+
+&dsi_hx8379a_wvga_vid {
+	qcom,cont-splash-enabled;
+};
diff --git a/arch/arm/boot/dts/msm8610-qrd-skuab.dtsi b/arch/arm/boot/dts/msm8610-qrd-skuab.dtsi
index 649bc71..17bf329 100644
--- a/arch/arm/boot/dts/msm8610-qrd-skuab.dtsi
+++ b/arch/arm/boot/dts/msm8610-qrd-skuab.dtsi
@@ -82,6 +82,7 @@
 			stk,wait-reg = <0x07>;
 			stk,ps-thdh = <150>;
 			stk,ps-thdl = <100>;
+			stk,use-fir;
 		};
 	};
 
@@ -89,10 +90,6 @@
                qcom,hsusb-otg-phy-init-seq =
                        <0x44 0x80 0x6a 0x81 0x34 0x82 0x23 0x83 0xffffffff>;
 	};
-
-	qcom,dsi_v2_otm8018b_fwvga_video {
-		qcom,cont-splash-enabled;
-	};
 };
 
 / {
@@ -112,3 +109,15 @@
 &pm8110_chg {
 	qcom,battery-data = <&qrd_batterydata>;
 };
+
+&mdss_mdp {
+	qcom,mdss-pref-prim-intf = "dsi";
+};
+
+&mdss_dsi0 {
+	qcom,dsi-pref-prim-pan = <&dsi_otm8018b_fwvga_vid>;
+};
+
+&dsi_otm8018b_fwvga_vid {
+	qcom,cont-splash-enabled;
+};
diff --git a/arch/arm/boot/dts/msm8610-qrd.dtsi b/arch/arm/boot/dts/msm8610-qrd.dtsi
index 1688890..df61ca6 100644
--- a/arch/arm/boot/dts/msm8610-qrd.dtsi
+++ b/arch/arm/boot/dts/msm8610-qrd.dtsi
@@ -277,8 +277,6 @@
 	qcom,vdd-current-level = <15000 400000>;
 
 	vdd-io-supply = <&pm8110_l21>;
-	qcom,vdd-io-always-on;
-	qcom,vdd-io-lpm-sup;
 	qcom,vdd-io-voltage-level = <1800000 2950000>;
 	qcom,vdd-io-current-level = <200 50000>;
 
diff --git a/arch/arm/boot/dts/msm8610-v1-cdp.dts b/arch/arm/boot/dts/msm8610-v1-cdp.dts
index ba0851f..beb3976 100644
--- a/arch/arm/boot/dts/msm8610-v1-cdp.dts
+++ b/arch/arm/boot/dts/msm8610-v1-cdp.dts
@@ -14,7 +14,6 @@
 
 /include/ "msm8610-v1.dtsi"
 /include/ "msm8610-cdp.dtsi"
-/include/ "dsi-v2-panel-truly-wvga-video.dtsi"
 /include/ "msm8610-camera-sensor-cdp-mtp.dtsi"
 
 / {
diff --git a/arch/arm/boot/dts/msm8610-v1-mtp.dts b/arch/arm/boot/dts/msm8610-v1-mtp.dts
index 010903f..82992a3 100644
--- a/arch/arm/boot/dts/msm8610-v1-mtp.dts
+++ b/arch/arm/boot/dts/msm8610-v1-mtp.dts
@@ -14,7 +14,6 @@
 
 /include/ "msm8610-v1.dtsi"
 /include/ "msm8610-mtp.dtsi"
-/include/ "dsi-v2-panel-truly-wvga-video.dtsi"
 /include/ "msm8610-camera-sensor-cdp-mtp.dtsi"
 
 / {
diff --git a/arch/arm/boot/dts/msm8610-v1-qrd-skuaa.dts b/arch/arm/boot/dts/msm8610-v1-qrd-skuaa.dts
index ba53acc..ec8c4c6 100644
--- a/arch/arm/boot/dts/msm8610-v1-qrd-skuaa.dts
+++ b/arch/arm/boot/dts/msm8610-v1-qrd-skuaa.dts
@@ -14,7 +14,6 @@
 
 /include/ "msm8610-v1.dtsi"
 /include/ "msm8610-qrd-skuaa.dtsi"
-/include/ "dsi-v2-panel-hx8379a-wvga-video.dtsi"
 /include/ "msm8610-qrd-camera-sensor.dtsi"
 
 / {
diff --git a/arch/arm/boot/dts/msm8610-v1-qrd-skuab.dts b/arch/arm/boot/dts/msm8610-v1-qrd-skuab.dts
index 5e19997..b3350bb 100644
--- a/arch/arm/boot/dts/msm8610-v1-qrd-skuab.dts
+++ b/arch/arm/boot/dts/msm8610-v1-qrd-skuab.dts
@@ -14,7 +14,6 @@
 
 /include/ "msm8610-v1.dtsi"
 /include/ "msm8610-qrd-skuab.dtsi"
-/include/ "dsi-v2-panel-otm8018b-fwvga-video.dtsi"
 /include/ "msm8612-qrd-camera-sensor.dtsi"
 
 / {
diff --git a/arch/arm/boot/dts/msm8610-v2-cdp.dts b/arch/arm/boot/dts/msm8610-v2-cdp.dts
index 51ef7a2..a6d1d9c 100644
--- a/arch/arm/boot/dts/msm8610-v2-cdp.dts
+++ b/arch/arm/boot/dts/msm8610-v2-cdp.dts
@@ -14,7 +14,6 @@
 
 /include/ "msm8610-v2.dtsi"
 /include/ "msm8610-cdp.dtsi"
-/include/ "dsi-v2-panel-truly-wvga-video.dtsi"
 /include/ "msm8610-camera-sensor-cdp-mtp.dtsi"
 
 / {
diff --git a/arch/arm/boot/dts/msm8610-v2-mtp.dts b/arch/arm/boot/dts/msm8610-v2-mtp.dts
index e1c9bb8..405a775 100644
--- a/arch/arm/boot/dts/msm8610-v2-mtp.dts
+++ b/arch/arm/boot/dts/msm8610-v2-mtp.dts
@@ -14,7 +14,6 @@
 
 /include/ "msm8610-v2.dtsi"
 /include/ "msm8610-mtp.dtsi"
-/include/ "dsi-v2-panel-truly-wvga-video.dtsi"
 /include/ "msm8610-camera-sensor-cdp-mtp.dtsi"
 
 / {
diff --git a/arch/arm/boot/dts/msm8610-v2-pm.dtsi b/arch/arm/boot/dts/msm8610-v2-pm.dtsi
index e593b31..257d7a4 100644
--- a/arch/arm/boot/dts/msm8610-v2-pm.dtsi
+++ b/arch/arm/boot/dts/msm8610-v2-pm.dtsi
@@ -212,45 +212,43 @@
 
 		qcom,gpio-parent = <&msmgpio>;
 		qcom,gpio-map = <3  1>,
-			<4  4 >,
-			<5  5 >,
-			<6  9 >,
-			<7  13>,
-			<8  17>,
-			<9  21>,
-			<10  27>,
-			<11  29>,
-			<12  31>,
-			<13  33>,
-			<14  35>,
-			<15  37>,
-			<16  38>,
-			<17  39>,
-			<18  41>,
-			<19  46>,
-			<20  48>,
-			<21  49>,
-			<22  50>,
-			<23  51>,
-			<24  52>,
-			<25  54>,
-			<26  62>,
-			<27  63>,
-			<28  64>,
-			<29  65>,
-			<30  66>,
-			<31  67>,
-			<32  68>,
-			<33  69>,
-			<34  71>,
-			<35  72>,
-			<36  106>,
-			<37  107>,
-			<38  108>,
-			<39  109>,
-			<40  110>,
-			<54  111>,
-			<55  113>;
+			<4  5 >,
+			<5  9 >,
+			<6  14>,
+			<7  15>,
+			<8  32>,
+			<9  33>,
+			<10  34>,
+			<11  35>,
+			<12  41>,
+			<13  42>,
+			<14  72>,
+			<15  73>,
+			<16  74>,
+			<17  75>,
+			<18  76>,
+			<19  77>,
+			<20  78>,
+			<21  79>,
+			<22  80>,
+			<23  81>,
+			<24  82>,
+			<25  83>,
+			<26  84>,
+			<27  85>,
+			<28  87>,
+			<29  90>,
+			<30  91>,
+			<31  92>,
+			<32  93>,
+			<33  94>,
+			<34  95>,
+			<35  96>,
+			<36  97>,
+			<37  98>,
+			<38  99>,
+			<39  100>,
+			<40  101>;
 	};
 
 	qcom,pm-8x60@fe805664 {
diff --git a/arch/arm/boot/dts/msm8610-v2-qrd-skuaa.dts b/arch/arm/boot/dts/msm8610-v2-qrd-skuaa.dts
index 677365f..44df025 100644
--- a/arch/arm/boot/dts/msm8610-v2-qrd-skuaa.dts
+++ b/arch/arm/boot/dts/msm8610-v2-qrd-skuaa.dts
@@ -14,7 +14,6 @@
 
 /include/ "msm8610-v2.dtsi"
 /include/ "msm8610-qrd-skuaa.dtsi"
-/include/ "dsi-v2-panel-hx8379a-wvga-video.dtsi"
 /include/ "msm8610-qrd-camera-sensor.dtsi"
 
 / {
diff --git a/arch/arm/boot/dts/msm8610-v2-qrd-skuab.dts b/arch/arm/boot/dts/msm8610-v2-qrd-skuab.dts
index ccc38fc..92908fb 100644
--- a/arch/arm/boot/dts/msm8610-v2-qrd-skuab.dts
+++ b/arch/arm/boot/dts/msm8610-v2-qrd-skuab.dts
@@ -14,7 +14,6 @@
 
 /include/ "msm8610-v2.dtsi"
 /include/ "msm8610-qrd-skuab.dtsi"
-/include/ "dsi-v2-panel-otm8018b-fwvga-video.dtsi"
 /include/ "msm8612-qrd-camera-sensor.dtsi"
 
 / {
diff --git a/arch/arm/boot/dts/msm8610.dtsi b/arch/arm/boot/dts/msm8610.dtsi
index 89a7cff..7dcb985 100644
--- a/arch/arm/boot/dts/msm8610.dtsi
+++ b/arch/arm/boot/dts/msm8610.dtsi
@@ -944,15 +944,11 @@
 
 &gdsc_vfe {
 	qcom,clock-names = "core_clk", "iface_clk", "bus_clk";
-	qcom,skip-logic-collapse;
-	qcom,retain-periph;
-	qcom,retain-mem;
 	status = "ok";
 };
 
 &gdsc_oxili_cx {
 	qcom,clock-names = "core_clk", "iface_clk", "mem_clk";
-	qcom,skip-logic-collapse;
 	status = "ok";
 };
 
diff --git a/arch/arm/boot/dts/msm8926-cdp.dts b/arch/arm/boot/dts/msm8926-cdp.dts
index 677ca7e..500c7d8 100644
--- a/arch/arm/boot/dts/msm8926-cdp.dts
+++ b/arch/arm/boot/dts/msm8926-cdp.dts
@@ -20,7 +20,9 @@
 	model = "Qualcomm MSM 8926 CDP";
 	compatible = "qcom,msm8926-cdp", "qcom,msm8926", "qcom,cdp";
 	qcom,msm-id = <200 1 0>,
-		      <224 1 0>;
+		      <224 1 0>,
+		      <200 1 0x10001>,
+		      <224 1 0x10001>;
 };
 
 &pm8226_chg {
diff --git a/arch/arm/boot/dts/msm8926-mtp.dts b/arch/arm/boot/dts/msm8926-mtp.dts
index 1c9b7dc..73635bc 100644
--- a/arch/arm/boot/dts/msm8926-mtp.dts
+++ b/arch/arm/boot/dts/msm8926-mtp.dts
@@ -20,5 +20,7 @@
 	model = "Qualcomm MSM 8926 MTP";
 	compatible = "qcom,msm8926-mtp", "qcom,msm8926", "qcom,mtp";
 	qcom,msm-id = <200 8 0>,
-		      <224 8 0>;
+		      <224 8 0>,
+		      <200 8 0x10001>,
+		      <224 8 0x10001>;
 };
diff --git a/arch/arm/boot/dts/msm8926-qrd.dts b/arch/arm/boot/dts/msm8926-qrd.dts
index 6a66e4b..5cae698 100644
--- a/arch/arm/boot/dts/msm8926-qrd.dts
+++ b/arch/arm/boot/dts/msm8926-qrd.dts
@@ -18,5 +18,7 @@
 	model = "Qualcomm MSM 8926 QRD";
 	compatible = "qcom,msm8926-qrd", "qcom,msm8926", "qcom,qrd";
 	qcom,msm-id = <200 11 0>,
-		      <224 11 0>;
+		      <224 11 0>,
+		      <200 11 0x10001>,
+		      <224 11 0x10001>;
 };
diff --git a/arch/arm/boot/dts/msm8926.dtsi b/arch/arm/boot/dts/msm8926.dtsi
index e27e6d1..5893a9b 100644
--- a/arch/arm/boot/dts/msm8926.dtsi
+++ b/arch/arm/boot/dts/msm8926.dtsi
@@ -23,7 +23,9 @@
 	model = "Qualcomm MSM 8926";
 	compatible = "qcom,msm8926";
 	qcom,msm-id = <200 0>,
-		      <224 0>;
+		      <224 0>,
+		      <200 0x10001>,
+		      <224 0x10001>;
 };
 
 &soc {
diff --git a/arch/arm/boot/dts/msm8974-cdp.dtsi b/arch/arm/boot/dts/msm8974-cdp.dtsi
index 9badf6d..d200100 100644
--- a/arch/arm/boot/dts/msm8974-cdp.dtsi
+++ b/arch/arm/boot/dts/msm8974-cdp.dtsi
@@ -10,8 +10,6 @@
  * GNU General Public License for more details.
  */
 
-/include/ "dsi-panel-toshiba-720p-video.dtsi"
-/include/ "dsi-panel-orise-720p-video.dtsi"
 /include/ "msm8974-leds.dtsi"
 /include/ "msm8974-camera-sensor-cdp.dtsi"
 
@@ -26,9 +24,12 @@
 		status = "ok";
 	};
 
-	qcom,mdss_dsi_toshiba_720p_video {
-		status = "ok";
-		qcom,cont-splash-enabled;
+	qcom,mdss_dsi@fd922800 {
+		qcom,dsi-pref-prim-pan = <&dsi_tosh_720_vid>;
+	};
+
+	qcom,mdss_mdp@fd900000 {
+		qcom,mdss-pref-prim-intf = "dsi";
 	};
 
 	qcom,mdss_dsi_orise_720p_video {
@@ -735,3 +736,7 @@
 		qcom,cdc-on-demand-supplies = "cdc-vdd-spkdrv";
 	};
 };
+
+&dsi_tosh_720_vid {
+       qcom,cont-splash-enabled;
+};
diff --git a/arch/arm/boot/dts/msm8974-coresight.dtsi b/arch/arm/boot/dts/msm8974-coresight.dtsi
index 9fd0cd9..a809c2b 100644
--- a/arch/arm/boot/dts/msm8974-coresight.dtsi
+++ b/arch/arm/boot/dts/msm8974-coresight.dtsi
@@ -19,8 +19,7 @@
 		interrupts = <0 166 0>;
 		interrupt-names = "byte-cntr-irq";
 
-		qcom,memory-reservation-type = "EBI1";
-		qcom,memory-reservation-size = <0x100000>; /* 1M EBI1 buffer */
+		qcom,memory-size = <0x100000>;
 
 		coresight-id = <0>;
 		coresight-name = "coresight-tmc-etr";
@@ -41,6 +40,11 @@
 
 		qcom,vdd-voltage-level = <2950000 2950000>;
 		qcom,vdd-current-level = <9000 800000>;
+
+		vdd-io-supply = <&pm8941_l13>;
+
+		qcom,vdd-io-voltage-level = <2950000 2950000>;
+		qcom,vdd-io-current-level = <6 22000>;
 	};
 
 	replicator: replicator@fc31c000 {
diff --git a/arch/arm/boot/dts/msm8974-fluid.dtsi b/arch/arm/boot/dts/msm8974-fluid.dtsi
index 9c2509a..d02021c 100644
--- a/arch/arm/boot/dts/msm8974-fluid.dtsi
+++ b/arch/arm/boot/dts/msm8974-fluid.dtsi
@@ -10,7 +10,6 @@
  * GNU General Public License for more details.
  */
 
-/include/ "dsi-panel-toshiba-720p-video.dtsi"
 /include/ "msm8974-camera-sensor-fluid.dtsi"
 /include/ "msm8974-leds.dtsi"
 
@@ -25,9 +24,12 @@
 		status = "ok";
 	};
 
-	qcom,mdss_dsi_toshiba_720p_video {
-		status = "ok";
-		qcom,cont-splash-enabled;
+	qcom,mdss_dsi@fd922800{
+		qcom,dsi-pref-prim-pan = <&dsi_tosh_720_vid>;
+	};
+
+	qcom,mdss_mdp@fd900000 {
+		qcom,mdss-pref-prim-intf = "dsi";
 	};
 
 	qcom,hdmi_tx@fd922100 {
@@ -675,3 +677,7 @@
 		qcom,channel-type = <0xf0000000>;
 	};
 };
+
+&dsi_tosh_720_vid {
+       qcom,cont-splash-enabled;
+};
diff --git a/arch/arm/boot/dts/msm8974-liquid.dtsi b/arch/arm/boot/dts/msm8974-liquid.dtsi
index 1803f91..73aba8f 100644
--- a/arch/arm/boot/dts/msm8974-liquid.dtsi
+++ b/arch/arm/boot/dts/msm8974-liquid.dtsi
@@ -24,9 +24,9 @@
 		status = "ok";
 	};
 
-	qcom,mdss_edp@fd923400 {
-		status = "ok";
-	};
+        qcom,mdss_mdp@fd900000 {
+                qcom,mdss-pref-prim-intf = "edp";
+        };
 
 	i2c@f9967000 {
 		battery@b {
diff --git a/arch/arm/boot/dts/msm8974-mdss-panels.dtsi b/arch/arm/boot/dts/msm8974-mdss-panels.dtsi
new file mode 100644
index 0000000..00fc779
--- /dev/null
+++ b/arch/arm/boot/dts/msm8974-mdss-panels.dtsi
@@ -0,0 +1,16 @@
+/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+/include/ "dsi-panel-orise-720p-video.dtsi"
+/include/ "dsi-panel-toshiba-720p-video.dtsi"
+/include/ "dsi-panel-sharp-qhd-video.dtsi"
+/include/ "dsi-panel-generic-720p-cmd.dtsi"
diff --git a/arch/arm/boot/dts/msm8974-mdss.dtsi b/arch/arm/boot/dts/msm8974-mdss.dtsi
index b615ebe..24b5860 100644
--- a/arch/arm/boot/dts/msm8974-mdss.dtsi
+++ b/arch/arm/boot/dts/msm8974-mdss.dtsi
@@ -86,9 +86,11 @@
 		vddio-supply = <&pm8941_l12>;
 		vdda-supply = <&pm8941_l2>;
 		qcom,mdss-fb-map = <&mdss_fb0>;
-		qcom,platform-reset-gpio = <&pm8941_gpios 19 1>;
-		qcom,platform-enable-gpio = <&msmgpio 58 1>;
+		qcom,mdss-mdp = <&mdss_mdp>;
+		qcom,platform-reset-gpio = <&pm8941_gpios 19 0>;
+		qcom,platform-enable-gpio = <&msmgpio 58 0>;
 		qcom,platform-reset-sequence = <1 20 0 200 1 20 2>;
+		qcom,platform-te-gpio = <&msmgpio 12 0>;
 		qcom,platform-strength-ctrl = [ff 06];
 		qcom,platform-bist-ctrl = [00 00 b1 ff 00 00];
 		qcom,platform-regulator-settings = [07 09 03 00 20 00 01];
@@ -141,6 +143,7 @@
 		vddio-supply = <&pm8941_l12>;
 		vdda-supply = <&pm8941_l2>;
 		qcom,mdss-fb-map = <&mdss_fb0>;
+		qcom,mdss-mdp = <&mdss_mdp>;
 	};
 
 	mdss_hdmi_tx: qcom,hdmi_tx@fd922100 {
@@ -187,8 +190,9 @@
 		gpio-panel-pwm = <&pm8941_gpios 36 0>;
 		qcom,panel-lpg-channel = <7>; /* LPG Channel 8 */
 		qcom,panel-pwm-period = <53>;
-		status = "disable";
 		qcom,mdss-fb-map = <&mdss_fb0>;
 		gpio-panel-hpd = <&msmgpio 102 0>;
 	};
 };
+
+/include/ "msm8974-mdss-panels.dtsi"
diff --git a/arch/arm/boot/dts/msm8974-mtp.dtsi b/arch/arm/boot/dts/msm8974-mtp.dtsi
index 6955597..22fff80 100644
--- a/arch/arm/boot/dts/msm8974-mtp.dtsi
+++ b/arch/arm/boot/dts/msm8974-mtp.dtsi
@@ -10,7 +10,6 @@
  * GNU General Public License for more details.
  */
 
-/include/ "dsi-panel-toshiba-720p-video.dtsi"
 /include/ "msm8974-camera-sensor-mtp.dtsi"
 /include/ "msm8974-leds.dtsi"
 
@@ -25,9 +24,12 @@
 		status = "ok";
 	};
 
-	qcom,mdss_dsi_toshiba_720p_video {
-		status = "ok";
-		qcom,cont-splash-enabled;
+	qcom,mdss_dsi@fd922800 {
+		qcom,dsi-pref-prim-pan = <&dsi_tosh_720_vid>;
+	};
+
+	qcom,mdss_mdp@fd900000 {
+		qcom,mdss-pref-prim-intf = "dsi";
 	};
 
 	qcom,hdmi_tx@fd922100 {
@@ -698,3 +700,7 @@
 		qcom,channel-type = <0x1540>;
 	};
 };
+
+&dsi_tosh_720_vid {
+       qcom,cont-splash-enabled;
+};
diff --git a/arch/arm/boot/dts/msm8974.dtsi b/arch/arm/boot/dts/msm8974.dtsi
index 1845e17..65307ae 100644
--- a/arch/arm/boot/dts/msm8974.dtsi
+++ b/arch/arm/boot/dts/msm8974.dtsi
@@ -211,6 +211,7 @@
 		compatible = "qcom,msm-vidc";
 		reg = <0xfdc00000 0xff000>;
 		interrupts = <0 44 0>;
+		vdd-supply = <&gdsc_venus>;
 		qcom,hfi = "venus";
 		qcom,has-ocmem;
 		qcom,max-hw-load = <1224450>; /* 4k @ 30 + 1080p @ 30*/
@@ -911,6 +912,8 @@
 		qcom,dwc-hsphy-init = <0x00D191A4>;
 		qcom,misc-ref = <&pm8941_misc>;
 		dwc_usb3-adc_tm = <&pm8941_adc_tm>;
+		qcom,dwc-usb3-msm-tx-fifo-size = <29696>;
+		qcom,dwc-usb3-msm-qdss-tx-fifo-size = <16384>;
 
 		qcom,msm-bus,name = "usb3";
 		qcom,msm-bus,num-cases = <2>;
@@ -924,6 +927,7 @@
 			interrupt-parent = <&intc>;
 			interrupts = <0 131 0>, <0 179 0>;
 			interrupt-names = "irq", "otg_irq";
+			tx-fifo-resize;
 		};
 	};
 
@@ -1391,8 +1395,6 @@
 		compatible = "qcom,cache_dump";
 		qcom,l1-dump-size = <0x100000>;
 		qcom,l2-dump-size = <0x500000>;
-		qcom,memory-reservation-type = "EBI1";
-		qcom,memory-reservation-size = <0x600000>; /* 6M EBI1 buffer */
 	};
 
 	tsens: tsens@fc4a8000 {
@@ -1481,7 +1483,7 @@
 			qcom,src-bam-pipe-index = <0>;
 			qcom,dst-bam-physical-address = <0xf9304000>;
 			qcom,dst-bam-pipe-index = <2>;
-			qcom,data-fifo-offset = <0xf0000>;
+			qcom,data-fifo-offset = <0xf2000>;
 			qcom,data-fifo-size = <0x1800>;
 			qcom,descriptor-fifo-offset = <0xf4000>;
 			qcom,descriptor-fifo-size = <0x1400>;
diff --git a/arch/arm/boot/dts/msm8974pro-ab-cdp.dts b/arch/arm/boot/dts/msm8974pro-ab-cdp.dts
index 74bd23d..fae72fa 100644
--- a/arch/arm/boot/dts/msm8974pro-ab-cdp.dts
+++ b/arch/arm/boot/dts/msm8974pro-ab-cdp.dts
@@ -24,5 +24,9 @@
 		      <214 1 0x10000>,
 		      <215 1 0x10000>,
 		      <217 1 0x10000>,
-		      <218 1 0x10000>;
+		      <218 1 0x10000>,
+		      <194 1 0x10000>,	/* 8974Pro-AC IDs */
+		      <210 1 0x10000>,
+		      <213 1 0x10000>,
+		      <216 1 0x10000>;
 };
diff --git a/arch/arm/boot/dts/msm8974pro-ac-pm8941.dtsi b/arch/arm/boot/dts/msm8974pro-ac-pm8941.dtsi
index 0989c34..cc4b6ed 100644
--- a/arch/arm/boot/dts/msm8974pro-ac-pm8941.dtsi
+++ b/arch/arm/boot/dts/msm8974pro-ac-pm8941.dtsi
@@ -94,6 +94,16 @@
 	regulator-name = "8941_smbb_otg";
 };
 
+&usb3 {
+	vbus_dwc3-supply = <&pm8941_mvs1>;
+	qcom,misc-ref = <&pm8941_misc>;
+	dwc_usb3-adc_tm = <&pm8941_adc_tm>;
+	interrupt-map-mask = <0x0 0xffffffff>;
+	interrupt-map = <0x0 0 &intc 0 133 0
+			0x0 1 &spmi_bus 0x0 0x2 0x9 0x0>;
+	interrupt-names = "hs_phy_irq", "pmic_id_irq";
+};
+
 /* Correct PM8941 local slave ID 0 to use global SID 4 for all interrupts. */
 &pm8941_lsid0 {
 	qcom,temp-alarm@2400 {
diff --git a/arch/arm/boot/dts/msm8974pro-ac.dtsi b/arch/arm/boot/dts/msm8974pro-ac.dtsi
index 4c55169..f8a371d 100644
--- a/arch/arm/boot/dts/msm8974pro-ac.dtsi
+++ b/arch/arm/boot/dts/msm8974pro-ac.dtsi
@@ -46,6 +46,7 @@
 
 	tpiu@fc318000 {
 		vdd-supply = <&pma8084_l21>;
+		vdd-io-supply = <&pma8084_l13>;
 	};
 
 	qcom,mdss_dsi@fd922800 {
@@ -161,6 +162,9 @@
 	qcom,msm-thermal {
 		vdd-dig-supply = <&pma8084_s2_floor_corner>;
 		vdd-gfx-supply = <&pma8084_s7_floor_corner>;
+		/delete-property/ qcom,pmic-sw-mode-temp;
+		/delete-property/ qcom,pmic-sw-mode-temp-hysteresis;
+		/delete-property/ qcom,pmic-sw-mode-regs;
 	};
 
 	qcom,lpm-resources {
diff --git a/arch/arm/boot/dts/msm8974pro.dtsi b/arch/arm/boot/dts/msm8974pro.dtsi
index 9b0638d..86f0058 100644
--- a/arch/arm/boot/dts/msm8974pro.dtsi
+++ b/arch/arm/boot/dts/msm8974pro.dtsi
@@ -33,6 +33,12 @@
 		compatible = "qcom,msm-imem";
 		reg = <0xfe805000 0x1000>; /* Address and size of IMEM */
 	};
+
+	qcom,msm-thermal {
+		/delete-property/ qcom,pmic-sw-mode-temp;
+		/delete-property/ qcom,pmic-sw-mode-temp-hysteresis;
+		/delete-property/ qcom,pmic-sw-mode-regs;
+	};
 };
 
 /* GPU overrides */
diff --git a/arch/arm/boot/dts/msm9625-coresight.dtsi b/arch/arm/boot/dts/msm9625-coresight.dtsi
index 4a903b7..4880f96 100644
--- a/arch/arm/boot/dts/msm9625-coresight.dtsi
+++ b/arch/arm/boot/dts/msm9625-coresight.dtsi
@@ -19,8 +19,7 @@
 		interrupts = <0 166 0>;
 		interrupt-names = "byte-cntr-irq";
 
-		qcom,memory-reservation-type = "EBI1";
-		qcom,memory-reservation-size = <0x20000>; /* 128K EBI1 buffer */
+		qcom,memory-size = <0x20000>;
 
 		coresight-id = <0>;
 		coresight-name = "coresight-tmc-etr";
@@ -121,13 +120,13 @@
 		coresight-child-ports = <7>;
 	};
 
-	etm: etm@fc332000 {
+	etm0: etm@fc332000 {
 		compatible = "arm,coresight-etm";
 		reg = <0xfc332000 0x1000>;
 		reg-names = "etm-base";
 
 		coresight-id = <8>;
-		coresight-name = "coresight-etm";
+		coresight-name = "coresight-etm0";
 		coresight-nr-inports = <0>;
 		coresight-outports = <0>;
 		coresight-child-list = <&funnel_in0>;
diff --git a/arch/arm/configs/apq8084_defconfig b/arch/arm/configs/apq8084_defconfig
index f4ad0c4..66d66fc 100644
--- a/arch/arm/configs/apq8084_defconfig
+++ b/arch/arm/configs/apq8084_defconfig
@@ -1,6 +1,7 @@
 # CONFIG_ARM_PATCH_PHYS_VIRT is not set
 CONFIG_EXPERIMENTAL=y
 CONFIG_SYSVIPC=y
+CONFIG_AUDIT=y
 CONFIG_RCU_FAST_NO_HZ=y
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
@@ -129,6 +130,7 @@
 CONFIG_NETFILTER=y
 CONFIG_NETFILTER_NETLINK_LOG=y
 CONFIG_NF_CONNTRACK=y
+CONFIG_NF_CONNTRACK_SECMARK=y
 CONFIG_NF_CONNTRACK_EVENTS=y
 CONFIG_NF_CT_PROTO_DCCP=y
 CONFIG_NF_CT_PROTO_SCTP=y
@@ -146,9 +148,11 @@
 CONFIG_NETFILTER_TPROXY=y
 CONFIG_NETFILTER_XT_TARGET_CLASSIFY=y
 CONFIG_NETFILTER_XT_TARGET_CONNMARK=y
+CONFIG_NETFILTER_XT_TARGET_CONNSECMARK=y
 CONFIG_NETFILTER_XT_TARGET_LOG=y
 CONFIG_NETFILTER_XT_TARGET_MARK=y
 CONFIG_NETFILTER_XT_TARGET_NFQUEUE=y
+CONFIG_NETFILTER_XT_TARGET_SECMARK=y
 CONFIG_NETFILTER_XT_MATCH_COMMENT=y
 CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=y
 CONFIG_NETFILTER_XT_MATCH_CONNMARK=y
@@ -182,6 +186,7 @@
 CONFIG_IP_NF_TARGET_REJECT=y
 CONFIG_IP_NF_MANGLE=y
 CONFIG_IP_NF_RAW=y
+CONFIG_IP_NF_SECURITY=y
 CONFIG_IP_NF_ARPTABLES=y
 CONFIG_IP_NF_ARPFILTER=y
 CONFIG_IP_NF_ARP_MANGLE=y
@@ -359,6 +364,7 @@
 CONFIG_EXT3_FS=y
 # CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
 CONFIG_EXT4_FS=y
+CONFIG_EXT4_FS_SECURITY=y
 CONFIG_FUSE_FS=y
 CONFIG_VFAT_FS=y
 CONFIG_TMPFS=y
@@ -393,6 +399,10 @@
 CONFIG_EARLY_PRINTK=y
 CONFIG_PID_IN_CONTEXTIDR=y
 CONFIG_KEYS=y
+CONFIG_SECURITY=y
+CONFIG_SECURITY_NETWORK=y
+CONFIG_LSM_MMAP_MIN_ADDR=4096
+CONFIG_SECURITY_SELINUX=y
 CONFIG_CRYPTO_MD4=y
 CONFIG_CRYPTO_SHA256=y
 CONFIG_CRYPTO_ARC4=y
diff --git a/arch/arm/configs/msm8226-perf_defconfig b/arch/arm/configs/msm8226-perf_defconfig
index 7d96cb1..9535e05 100644
--- a/arch/arm/configs/msm8226-perf_defconfig
+++ b/arch/arm/configs/msm8226-perf_defconfig
@@ -1,6 +1,7 @@
 # CONFIG_ARM_PATCH_PHYS_VIRT is not set
 CONFIG_EXPERIMENTAL=y
 CONFIG_SYSVIPC=y
+CONFIG_AUDIT=y
 CONFIG_RCU_FAST_NO_HZ=y
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
@@ -125,6 +126,7 @@
 CONFIG_NETFILTER=y
 CONFIG_NETFILTER_NETLINK_LOG=y
 CONFIG_NF_CONNTRACK=y
+CONFIG_NF_CONNTRACK_SECMARK=y
 CONFIG_NF_CONNTRACK_EVENTS=y
 CONFIG_NF_CT_PROTO_DCCP=y
 CONFIG_NF_CT_PROTO_SCTP=y
@@ -142,10 +144,12 @@
 CONFIG_NETFILTER_TPROXY=y
 CONFIG_NETFILTER_XT_TARGET_CLASSIFY=y
 CONFIG_NETFILTER_XT_TARGET_CONNMARK=y
+CONFIG_NETFILTER_XT_TARGET_CONNSECMARK=y
 CONFIG_NETFILTER_XT_TARGET_LOG=y
 CONFIG_NETFILTER_XT_TARGET_MARK=y
 CONFIG_NETFILTER_XT_TARGET_NFQUEUE=y
 CONFIG_NETFILTER_XT_TARGET_NOTRACK=y
+CONFIG_NETFILTER_XT_TARGET_SECMARK=y
 CONFIG_NETFILTER_XT_MATCH_COMMENT=y
 CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=y
 CONFIG_NETFILTER_XT_MATCH_CONNMARK=y
@@ -183,6 +187,7 @@
 CONFIG_IP_NF_TARGET_REDIRECT=y
 CONFIG_IP_NF_MANGLE=y
 CONFIG_IP_NF_RAW=y
+CONFIG_IP_NF_SECURITY=y
 CONFIG_IP_NF_ARPTABLES=y
 CONFIG_IP_NF_ARPFILTER=y
 CONFIG_IP_NF_ARP_MANGLE=y
@@ -319,6 +324,7 @@
 CONFIG_ION=y
 CONFIG_ION_MSM=y
 CONFIG_MSM_KGSL=y
+CONFIG_KGSL_PER_PROCESS_PAGE_TABLE=y
 CONFIG_FB=y
 CONFIG_FB_MSM=y
 # CONFIG_FB_MSM_BACKLIGHT is not set
@@ -404,6 +410,7 @@
 CONFIG_EXT3_FS=y
 # CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
 CONFIG_EXT4_FS=y
+CONFIG_EXT4_FS_SECURITY=y
 CONFIG_FUSE_FS=y
 CONFIG_VFAT_FS=y
 CONFIG_TMPFS=y
@@ -422,6 +429,10 @@
 CONFIG_DEBUG_SET_MODULE_RONX=y
 CONFIG_KEYS=y
 CONFIG_CRYPTO_NULL=y
+CONFIG_SECURITY=y
+CONFIG_SECURITY_NETWORK=y
+CONFIG_LSM_MMAP_MIN_ADDR=4096
+CONFIG_SECURITY_SELINUX=y
 CONFIG_CRYPTO_MD4=y
 CONFIG_CRYPTO_ARC4=y
 CONFIG_CRYPTO_XCBC=y
diff --git a/arch/arm/configs/msm8226_defconfig b/arch/arm/configs/msm8226_defconfig
index 1d5c492..176a8a2 100644
--- a/arch/arm/configs/msm8226_defconfig
+++ b/arch/arm/configs/msm8226_defconfig
@@ -1,6 +1,7 @@
 # CONFIG_ARM_PATCH_PHYS_VIRT is not set
 CONFIG_EXPERIMENTAL=y
 CONFIG_SYSVIPC=y
+CONFIG_AUDIT=y
 CONFIG_RCU_FAST_NO_HZ=y
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
@@ -126,6 +127,7 @@
 CONFIG_NETFILTER=y
 CONFIG_NETFILTER_NETLINK_LOG=y
 CONFIG_NF_CONNTRACK=y
+CONFIG_NF_CONNTRACK_SECMARK=y
 CONFIG_NF_CONNTRACK_EVENTS=y
 CONFIG_NF_CT_PROTO_DCCP=y
 CONFIG_NF_CT_PROTO_SCTP=y
@@ -143,10 +145,12 @@
 CONFIG_NETFILTER_TPROXY=y
 CONFIG_NETFILTER_XT_TARGET_CLASSIFY=y
 CONFIG_NETFILTER_XT_TARGET_CONNMARK=y
+CONFIG_NETFILTER_XT_TARGET_CONNSECMARK=y
 CONFIG_NETFILTER_XT_TARGET_LOG=y
 CONFIG_NETFILTER_XT_TARGET_MARK=y
 CONFIG_NETFILTER_XT_TARGET_NFQUEUE=y
 CONFIG_NETFILTER_XT_TARGET_NOTRACK=y
+CONFIG_NETFILTER_XT_TARGET_SECMARK=y
 CONFIG_NETFILTER_XT_MATCH_COMMENT=y
 CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=y
 CONFIG_NETFILTER_XT_MATCH_CONNMARK=y
@@ -184,6 +188,7 @@
 CONFIG_IP_NF_TARGET_REDIRECT=y
 CONFIG_IP_NF_MANGLE=y
 CONFIG_IP_NF_RAW=y
+CONFIG_IP_NF_SECURITY=y
 CONFIG_IP_NF_ARPTABLES=y
 CONFIG_IP_NF_ARPFILTER=y
 CONFIG_IP_NF_ARP_MANGLE=y
@@ -345,6 +350,7 @@
 CONFIG_ION=y
 CONFIG_ION_MSM=y
 CONFIG_MSM_KGSL=y
+CONFIG_KGSL_PER_PROCESS_PAGE_TABLE=y
 CONFIG_FB=y
 CONFIG_FB_MSM=y
 # CONFIG_FB_MSM_BACKLIGHT is not set
@@ -440,6 +446,7 @@
 CONFIG_EXT3_FS=y
 # CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
 CONFIG_EXT4_FS=y
+CONFIG_EXT4_FS_SECURITY=y
 CONFIG_FUSE_FS=y
 CONFIG_VFAT_FS=y
 CONFIG_TMPFS=y
@@ -473,6 +480,10 @@
 CONFIG_DEBUG_SET_MODULE_RONX=y
 CONFIG_KEYS=y
 CONFIG_CRYPTO_NULL=y
+CONFIG_SECURITY=y
+CONFIG_SECURITY_NETWORK=y
+CONFIG_LSM_MMAP_MIN_ADDR=4096
+CONFIG_SECURITY_SELINUX=y
 CONFIG_CRYPTO_MD4=y
 CONFIG_CRYPTO_ARC4=y
 CONFIG_CRYPTO_XCBC=y
diff --git a/arch/arm/configs/msm8610-perf_defconfig b/arch/arm/configs/msm8610-perf_defconfig
index 03ddb3a..970c03f 100644
--- a/arch/arm/configs/msm8610-perf_defconfig
+++ b/arch/arm/configs/msm8610-perf_defconfig
@@ -2,6 +2,7 @@
 CONFIG_EXPERIMENTAL=y
 CONFIG_LOCALVERSION="-perf"
 CONFIG_SYSVIPC=y
+CONFIG_AUDIT=y
 CONFIG_RCU_FAST_NO_HZ=y
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
@@ -121,6 +122,7 @@
 CONFIG_NETFILTER=y
 CONFIG_NETFILTER_NETLINK_LOG=y
 CONFIG_NF_CONNTRACK=y
+CONFIG_NF_CONNTRACK_SECMARK=y
 CONFIG_NF_CONNTRACK_EVENTS=y
 CONFIG_NF_CT_PROTO_DCCP=y
 CONFIG_NF_CT_PROTO_SCTP=y
@@ -138,9 +140,11 @@
 CONFIG_NETFILTER_TPROXY=y
 CONFIG_NETFILTER_XT_TARGET_CLASSIFY=y
 CONFIG_NETFILTER_XT_TARGET_CONNMARK=y
+CONFIG_NETFILTER_XT_TARGET_CONNSECMARK=y
 CONFIG_NETFILTER_XT_TARGET_LOG=y
 CONFIG_NETFILTER_XT_TARGET_MARK=y
 CONFIG_NETFILTER_XT_TARGET_NFQUEUE=y
+CONFIG_NETFILTER_XT_TARGET_SECMARK=y
 CONFIG_NETFILTER_XT_MATCH_COMMENT=y
 CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=y
 CONFIG_NETFILTER_XT_MATCH_CONNMARK=y
@@ -178,6 +182,7 @@
 CONFIG_IP_NF_TARGET_REDIRECT=y
 CONFIG_IP_NF_MANGLE=y
 CONFIG_IP_NF_RAW=y
+CONFIG_IP_NF_SECURITY=y
 CONFIG_IP_NF_ARPTABLES=y
 CONFIG_IP_NF_ARPFILTER=y
 CONFIG_IP_NF_ARP_MANGLE=y
@@ -365,6 +370,7 @@
 CONFIG_EXT3_FS=y
 # CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
 CONFIG_EXT4_FS=y
+CONFIG_EXT4_FS_SECURITY=y
 CONFIG_FUSE_FS=y
 CONFIG_VFAT_FS=y
 CONFIG_TMPFS=y
@@ -381,11 +387,23 @@
 CONFIG_DEBUG_USER=y
 CONFIG_DEBUG_SET_MODULE_RONX=y
 CONFIG_KEYS=y
+CONFIG_SECURITY=y
+CONFIG_SECURITY_NETWORK=y
+CONFIG_LSM_MMAP_MIN_ADDR=4096
+CONFIG_SECURITY_SELINUX=y
 CONFIG_CRYPTO_MD4=y
 CONFIG_CRYPTO_ARC4=y
 CONFIG_CRYPTO_TWOFISH=y
 # CONFIG_CRYPTO_HW is not set
 CONFIG_CRC_CCITT=y
+CONFIG_PPP=y
+CONFIG_PPP_ASYNC=y
+CONFIG_PPP_SYNC_TTY=y
+CONFIG_PPP_DEFLATE=y
+CONFIG_PPP_BSDCOMP=y
+CONFIG_PPPOE=y
+CONFIG_N_HDLC=y
+CONFIG_UNIX98_PTYS=y
 CONFIG_INPUT_KXTJ9=y
 CONFIG_MSM_RPM_RBCPR_STATS_V2_LOG=y
 CONFIG_SENSORS_STK3X1X=y
diff --git a/arch/arm/configs/msm8610_defconfig b/arch/arm/configs/msm8610_defconfig
index aad3540..54b1c14 100644
--- a/arch/arm/configs/msm8610_defconfig
+++ b/arch/arm/configs/msm8610_defconfig
@@ -1,6 +1,7 @@
 # CONFIG_ARM_PATCH_PHYS_VIRT is not set
 CONFIG_EXPERIMENTAL=y
 CONFIG_SYSVIPC=y
+CONFIG_AUDIT=y
 CONFIG_RCU_FAST_NO_HZ=y
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
@@ -122,6 +123,7 @@
 CONFIG_NETFILTER=y
 CONFIG_NETFILTER_NETLINK_LOG=y
 CONFIG_NF_CONNTRACK=y
+CONFIG_NF_CONNTRACK_SECMARK=y
 CONFIG_NF_CONNTRACK_EVENTS=y
 CONFIG_NF_CT_PROTO_DCCP=y
 CONFIG_NF_CT_PROTO_SCTP=y
@@ -139,9 +141,11 @@
 CONFIG_NETFILTER_TPROXY=y
 CONFIG_NETFILTER_XT_TARGET_CLASSIFY=y
 CONFIG_NETFILTER_XT_TARGET_CONNMARK=y
+CONFIG_NETFILTER_XT_TARGET_CONNSECMARK=y
 CONFIG_NETFILTER_XT_TARGET_LOG=y
 CONFIG_NETFILTER_XT_TARGET_MARK=y
 CONFIG_NETFILTER_XT_TARGET_NFQUEUE=y
+CONFIG_NETFILTER_XT_TARGET_SECMARK=y
 CONFIG_NETFILTER_XT_MATCH_COMMENT=y
 CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=y
 CONFIG_NETFILTER_XT_MATCH_CONNMARK=y
@@ -179,6 +183,7 @@
 CONFIG_IP_NF_TARGET_REDIRECT=y
 CONFIG_IP_NF_MANGLE=y
 CONFIG_IP_NF_RAW=y
+CONFIG_IP_NF_SECURITY=y
 CONFIG_IP_NF_ARPTABLES=y
 CONFIG_IP_NF_ARPFILTER=y
 CONFIG_IP_NF_ARP_MANGLE=y
@@ -398,6 +403,7 @@
 CONFIG_EXT3_FS=y
 # CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
 CONFIG_EXT4_FS=y
+CONFIG_EXT4_FS_SECURITY=y
 CONFIG_FUSE_FS=y
 CONFIG_VFAT_FS=y
 CONFIG_TMPFS=y
@@ -428,6 +434,10 @@
 CONFIG_DEBUG_USER=y
 CONFIG_DEBUG_SET_MODULE_RONX=y
 CONFIG_KEYS=y
+CONFIG_SECURITY=y
+CONFIG_SECURITY_NETWORK=y
+CONFIG_LSM_MMAP_MIN_ADDR=4096
+CONFIG_SECURITY_SELINUX=y
 CONFIG_CRYPTO_MD4=y
 CONFIG_CRYPTO_ARC4=y
 CONFIG_CRYPTO_TWOFISH=y
@@ -435,6 +445,14 @@
 CONFIG_CRYPTO_DEV_QCE=y
 CONFIG_CRYPTO_DEV_QCEDEV=m
 CONFIG_CRC_CCITT=y
+CONFIG_PPP=y
+CONFIG_PPP_ASYNC=y
+CONFIG_PPP_SYNC_TTY=y
+CONFIG_PPP_DEFLATE=y
+CONFIG_PPP_BSDCOMP=y
+CONFIG_PPPOE=y
+CONFIG_N_HDLC=y
+CONFIG_UNIX98_PTYS=y
 CONFIG_INPUT_KXTJ9=y
 CONFIG_MSM_RPM_RBCPR_STATS_V2_LOG=y
 CONFIG_SENSORS_STK3X1X=y
diff --git a/arch/arm/configs/msm8974-perf_defconfig b/arch/arm/configs/msm8974-perf_defconfig
index 3bc159a..a9e39ed 100644
--- a/arch/arm/configs/msm8974-perf_defconfig
+++ b/arch/arm/configs/msm8974-perf_defconfig
@@ -2,6 +2,7 @@
 CONFIG_EXPERIMENTAL=y
 CONFIG_LOCALVERSION="-perf"
 CONFIG_SYSVIPC=y
+CONFIG_AUDIT=y
 CONFIG_RCU_FAST_NO_HZ=y
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
@@ -139,6 +140,7 @@
 CONFIG_NETFILTER=y
 CONFIG_NETFILTER_NETLINK_LOG=y
 CONFIG_NF_CONNTRACK=y
+CONFIG_NF_CONNTRACK_SECMARK=y
 CONFIG_NF_CONNTRACK_EVENTS=y
 CONFIG_NF_CT_PROTO_DCCP=y
 CONFIG_NF_CT_PROTO_SCTP=y
@@ -156,10 +158,12 @@
 CONFIG_NETFILTER_TPROXY=y
 CONFIG_NETFILTER_XT_TARGET_CLASSIFY=y
 CONFIG_NETFILTER_XT_TARGET_CONNMARK=y
+CONFIG_NETFILTER_XT_TARGET_CONNSECMARK=y
 CONFIG_NETFILTER_XT_TARGET_LOG=y
 CONFIG_NETFILTER_XT_TARGET_MARK=y
 CONFIG_NETFILTER_XT_TARGET_NFQUEUE=y
 CONFIG_NETFILTER_XT_TARGET_NOTRACK=y
+CONFIG_NETFILTER_XT_TARGET_SECMARK=y
 CONFIG_NETFILTER_XT_MATCH_COMMENT=y
 CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=y
 CONFIG_NETFILTER_XT_MATCH_CONNMARK=y
@@ -197,6 +201,7 @@
 CONFIG_IP_NF_TARGET_REDIRECT=y
 CONFIG_IP_NF_MANGLE=y
 CONFIG_IP_NF_RAW=y
+CONFIG_IP_NF_SECURITY=y
 CONFIG_IP_NF_ARPTABLES=y
 CONFIG_IP_NF_ARPFILTER=y
 CONFIG_IP_NF_ARP_MANGLE=y
@@ -453,6 +458,7 @@
 CONFIG_EXT3_FS=y
 # CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
 CONFIG_EXT4_FS=y
+CONFIG_EXT4_FS_SECURITY=y
 CONFIG_FUSE_FS=y
 CONFIG_VFAT_FS=y
 CONFIG_TMPFS=y
@@ -472,6 +478,10 @@
 CONFIG_PID_IN_CONTEXTIDR=y
 CONFIG_DEBUG_SET_MODULE_RONX=y
 CONFIG_KEYS=y
+CONFIG_SECURITY=y
+CONFIG_SECURITY_NETWORK=y
+CONFIG_LSM_MMAP_MIN_ADDR=4096
+CONFIG_SECURITY_SELINUX=y
 CONFIG_CRYPTO_NULL=y
 CONFIG_CRYPTO_XCBC=y
 CONFIG_CRYPTO_MD4=y
diff --git a/arch/arm/configs/msm8974_defconfig b/arch/arm/configs/msm8974_defconfig
index 118fdd4..ee38cc8 100644
--- a/arch/arm/configs/msm8974_defconfig
+++ b/arch/arm/configs/msm8974_defconfig
@@ -1,6 +1,7 @@
 # CONFIG_ARM_PATCH_PHYS_VIRT is not set
 CONFIG_EXPERIMENTAL=y
 CONFIG_SYSVIPC=y
+CONFIG_AUDIT=y
 CONFIG_RCU_FAST_NO_HZ=y
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
@@ -145,6 +146,7 @@
 CONFIG_NETFILTER=y
 CONFIG_NETFILTER_NETLINK_LOG=y
 CONFIG_NF_CONNTRACK=y
+CONFIG_NF_CONNTRACK_SECMARK=y
 CONFIG_NF_CONNTRACK_EVENTS=y
 CONFIG_NF_CT_PROTO_DCCP=y
 CONFIG_NF_CT_PROTO_SCTP=y
@@ -162,10 +164,12 @@
 CONFIG_NETFILTER_TPROXY=y
 CONFIG_NETFILTER_XT_TARGET_CLASSIFY=y
 CONFIG_NETFILTER_XT_TARGET_CONNMARK=y
+CONFIG_NETFILTER_XT_TARGET_CONNSECMARK=y
 CONFIG_NETFILTER_XT_TARGET_LOG=y
 CONFIG_NETFILTER_XT_TARGET_MARK=y
 CONFIG_NETFILTER_XT_TARGET_NFQUEUE=y
 CONFIG_NETFILTER_XT_TARGET_NOTRACK=y
+CONFIG_NETFILTER_XT_TARGET_SECMARK=y
 CONFIG_NETFILTER_XT_MATCH_COMMENT=y
 CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=y
 CONFIG_NETFILTER_XT_MATCH_CONNMARK=y
@@ -203,6 +207,7 @@
 CONFIG_IP_NF_TARGET_REDIRECT=y
 CONFIG_IP_NF_MANGLE=y
 CONFIG_IP_NF_RAW=y
+CONFIG_IP_NF_SECURITY=y
 CONFIG_IP_NF_ARPTABLES=y
 CONFIG_IP_NF_ARPFILTER=y
 CONFIG_IP_NF_ARP_MANGLE=y
@@ -472,6 +477,7 @@
 CONFIG_EXT3_FS=y
 # CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
 CONFIG_EXT4_FS=y
+CONFIG_EXT4_FS_SECURITY=y
 CONFIG_FUSE_FS=y
 CONFIG_VFAT_FS=y
 CONFIG_TMPFS=y
@@ -507,6 +513,10 @@
 CONFIG_PID_IN_CONTEXTIDR=y
 CONFIG_DEBUG_SET_MODULE_RONX=y
 CONFIG_KEYS=y
+CONFIG_SECURITY=y
+CONFIG_SECURITY_NETWORK=y
+CONFIG_LSM_MMAP_MIN_ADDR=4096
+CONFIG_SECURITY_SELINUX=y
 CONFIG_CRYPTO_NULL=y
 CONFIG_CRYPTO_XCBC=y
 CONFIG_CRYPTO_MD4=y
diff --git a/arch/arm/mach-msm/acpuclock.c b/arch/arm/mach-msm/acpuclock.c
index 2c120da..42242d5 100644
--- a/arch/arm/mach-msm/acpuclock.c
+++ b/arch/arm/mach-msm/acpuclock.c
@@ -27,19 +27,10 @@
 
 int acpuclk_set_rate(int cpu, unsigned long rate, enum setrate_reason reason)
 {
-	int ret;
-
 	if (!acpuclk_data || !acpuclk_data->set_rate)
 		return 0;
 
-	trace_cpu_frequency_switch_start(acpuclk_get_rate(cpu), rate, cpu);
-	ret = acpuclk_data->set_rate(cpu, rate, reason);
-	if (!ret) {
-		trace_cpu_frequency_switch_end(cpu);
-		trace_cpu_frequency(rate, cpu);
-	}
-
-	return ret;
+	return acpuclk_data->set_rate(cpu, rate, reason);
 }
 
 uint32_t acpuclk_get_switch_time(void)
diff --git a/arch/arm/mach-msm/board-8226-gpiomux.c b/arch/arm/mach-msm/board-8226-gpiomux.c
index 300ac4f..dcce820 100644
--- a/arch/arm/mach-msm/board-8226-gpiomux.c
+++ b/arch/arm/mach-msm/board-8226-gpiomux.c
@@ -184,24 +184,28 @@
 	{
 		.gpio      = 14,	/* BLSP1 QUP4 I2C_SDA */
 		.settings = {
+			[GPIOMUX_ACTIVE] = &gpio_i2c_config,
 			[GPIOMUX_SUSPENDED] = &gpio_i2c_config,
 		},
 	},
 	{
 		.gpio      = 15,	/* BLSP1 QUP4 I2C_SCL */
 		.settings = {
+			[GPIOMUX_ACTIVE] = &gpio_i2c_config,
 			[GPIOMUX_SUSPENDED] = &gpio_i2c_config,
 		},
 	},
 	{
 		.gpio      = 18,		/* BLSP1 QUP5 I2C_SDA */
 		.settings = {
+			[GPIOMUX_ACTIVE] = &gpio_i2c_config,
 			[GPIOMUX_SUSPENDED] = &gpio_i2c_config,
 		},
 	},
 	{
 		.gpio      = 19,		/* BLSP1 QUP5 I2C_SCL */
 		.settings = {
+			[GPIOMUX_ACTIVE] = &gpio_i2c_config,
 			[GPIOMUX_SUSPENDED] = &gpio_i2c_config,
 		},
 	},
@@ -214,12 +218,14 @@
 	{					/*  NFC   */
 		.gpio      = 10,		/* BLSP1 QUP3 I2C_DAT */
 		.settings = {
+			[GPIOMUX_ACTIVE] = &gpio_i2c_config,
 			[GPIOMUX_SUSPENDED] = &gpio_i2c_config,
 		},
 	},
 	{					/*  NFC   */
 		.gpio      = 11,		/* BLSP1 QUP3 I2C_CLK */
 		.settings = {
+			[GPIOMUX_ACTIVE] = &gpio_i2c_config,
 			[GPIOMUX_SUSPENDED] = &gpio_i2c_config,
 		},
 	},
@@ -336,12 +342,14 @@
 	{
 		.gpio      = 18,		/* BLSP1 QUP5 I2C_SDA */
 		.settings = {
+			[GPIOMUX_ACTIVE] = &gpio_i2c_config,
 			[GPIOMUX_SUSPENDED] = &gpio_i2c_config,
 		},
 	},
 	{
 		.gpio      = 19,		/* BLSP1 QUP5 I2C_SCL */
 		.settings = {
+			[GPIOMUX_ACTIVE] = &gpio_i2c_config,
 			[GPIOMUX_SUSPENDED] = &gpio_i2c_config,
 		},
 	},
@@ -410,12 +418,14 @@
 	{					/*  NFC   */
 		.gpio      = 10,		/* BLSP1 QUP3 I2C_DAT */
 		.settings = {
+			[GPIOMUX_ACTIVE] = &gpio_i2c_config,
 			[GPIOMUX_SUSPENDED] = &gpio_i2c_config,
 		},
 	},
 	{					/*  NFC   */
 		.gpio      = 11,		/* BLSP1 QUP3 I2C_CLK */
 		.settings = {
+			[GPIOMUX_ACTIVE] = &gpio_i2c_config,
 			[GPIOMUX_SUSPENDED] = &gpio_i2c_config,
 		},
 	},
diff --git a/arch/arm/mach-msm/board-8610-gpiomux.c b/arch/arm/mach-msm/board-8610-gpiomux.c
index dc9c13d..e9ad86f 100644
--- a/arch/arm/mach-msm/board-8610-gpiomux.c
+++ b/arch/arm/mach-msm/board-8610-gpiomux.c
@@ -188,36 +188,42 @@
 	{
 		.gpio      = 2,		/* BLSP1 QUP1 I2C_SDA */
 		.settings = {
+			[GPIOMUX_ACTIVE] = &gpio_i2c_config,
 			[GPIOMUX_SUSPENDED] = &gpio_i2c_config,
 		},
 	},
 	{
 		.gpio      = 3,		/* BLSP1 QUP1 I2C_SCL */
 		.settings = {
+			[GPIOMUX_ACTIVE] = &gpio_i2c_config,
 			[GPIOMUX_SUSPENDED] = &gpio_i2c_config,
 		},
 	},
 	{
 		.gpio      = 10,	/* BLSP1 QUP3 I2C_SDA */
 		.settings = {
+			[GPIOMUX_ACTIVE] = &gpio_i2c_config,
 			[GPIOMUX_SUSPENDED] = &gpio_i2c_config,
 		},
 	},
 	{
 		.gpio      = 11,	/* BLSP1 QUP3 I2C_SCL */
 		.settings = {
+			[GPIOMUX_ACTIVE] = &gpio_i2c_config,
 			[GPIOMUX_SUSPENDED] = &gpio_i2c_config,
 		},
 	},
 	{
 		.gpio      = 16,	/* BLSP1 QUP6 I2C_SDA */
 		.settings = {
+			[GPIOMUX_ACTIVE] = &gpio_cam_i2c_config,
 			[GPIOMUX_SUSPENDED] = &gpio_cam_i2c_config,
 		},
 	},
 	{
 		.gpio      = 17,	/* BLSP1 QUP6 I2C_SCL */
 		.settings = {
+			[GPIOMUX_ACTIVE] = &gpio_cam_i2c_config,
 			[GPIOMUX_SUSPENDED] = &gpio_cam_i2c_config,
 		},
 	},
diff --git a/arch/arm/mach-msm/board-8974-gpiomux.c b/arch/arm/mach-msm/board-8974-gpiomux.c
index 6165c32..f170b7b 100644
--- a/arch/arm/mach-msm/board-8974-gpiomux.c
+++ b/arch/arm/mach-msm/board-8974-gpiomux.c
@@ -1346,6 +1346,11 @@
 		return;
 	}
 
+	pr_err("%s:%d socinfo_get_version %x\n", __func__, __LINE__,
+		socinfo_get_version());
+	if (socinfo_get_version() >= 0x20000)
+		msm_tlmm_misc_reg_write(TLMM_SPARE_REG, 0xf);
+
 #if defined(CONFIG_KS8851) || defined(CONFIG_KS8851_MODULE)
 	if (!(of_board_is_dragonboard() && machine_is_apq8074()))
 		msm_gpiomux_install(msm_eth_configs, \
diff --git a/arch/arm/mach-msm/clock-8226.c b/arch/arm/mach-msm/clock-8226.c
index b72cdab..ba792ab 100644
--- a/arch/arm/mach-msm/clock-8226.c
+++ b/arch/arm/mach-msm/clock-8226.c
@@ -1603,7 +1603,15 @@
 	{ &gcc_ce1_axi_clk.c,  GCC_BASE, 0x0139 },
 	{ &gcc_ce1_ahb_clk.c,  GCC_BASE, 0x013a },
 	{ &gcc_lpass_q6_axi_clk.c,  GCC_BASE, 0x0160 },
-	{&dummy_clk, N_BASES, 0x0000},
+	{ &pnoc_clk.c, GCC_BASE, 0x010},
+	{ &snoc_clk.c, GCC_BASE, 0x000},
+	{ &cnoc_clk.c, GCC_BASE, 0x008},
+	/*
+	 * measure the gcc_bimc_kpss_axi_clk instead to account for the DDR
+	 * rate being gcc_bimc_clk/2.
+	 */
+	{ &bimc_clk.c, GCC_BASE, 0x155},
+	{ &dummy_clk, N_BASES, 0x0000},
 };
 
 static struct pll_vote_clk mmpll0_pll = {
@@ -2725,6 +2733,7 @@
 	{ &camss_csi1rdi_clk.c,  MMSS_BASE, 0x0049 },
 	{ &camss_csi1pix_clk.c,  MMSS_BASE, 0x004a },
 	{ &camss_ispif_ahb_clk.c,  MMSS_BASE, 0x0055 },
+	{ &mmssnoc_ahb_clk.c,  MMSS_BASE, 0x0001 },
 	{&dummy_clk, N_BASES, 0x0000},
 };
 
diff --git a/arch/arm/mach-msm/clock-8974.c b/arch/arm/mach-msm/clock-8974.c
index cd6d582..3b80374 100644
--- a/arch/arm/mach-msm/clock-8974.c
+++ b/arch/arm/mach-msm/clock-8974.c
@@ -5077,14 +5077,14 @@
 	CLK_LOOKUP("vsync_clk", mdss_vsync_clk.c, "mdp.0"),
 
 	/* MM sensor clocks */
-	CLK_LOOKUP("cam_src_clk", mclk0_clk_src.c, "6e.qcom,camera"),
-	CLK_LOOKUP("cam_src_clk", mclk0_clk_src.c, "20.qcom,camera"),
-	CLK_LOOKUP("cam_src_clk", mclk2_clk_src.c, "6c.qcom,camera"),
-	CLK_LOOKUP("cam_src_clk", mclk1_clk_src.c, "90.qcom,camera"),
-	CLK_LOOKUP("cam_clk", camss_mclk0_clk.c, "6e.qcom,camera"),
-	CLK_LOOKUP("cam_clk", camss_mclk0_clk.c, "20.qcom,camera"),
-	CLK_LOOKUP("cam_clk", camss_mclk2_clk.c, "6c.qcom,camera"),
-	CLK_LOOKUP("cam_clk", camss_mclk1_clk.c, "90.qcom,camera"),
+	CLK_LOOKUP("cam_src_clk", mmss_gp0_clk_src.c, "6e.qcom,camera"),
+	CLK_LOOKUP("cam_src_clk", mmss_gp0_clk_src.c, "20.qcom,camera"),
+	CLK_LOOKUP("cam_src_clk", gp1_clk_src.c, "6c.qcom,camera"),
+	CLK_LOOKUP("cam_src_clk", mmss_gp1_clk_src.c, "90.qcom,camera"),
+	CLK_LOOKUP("cam_clk", camss_gp0_clk.c, "6e.qcom,camera"),
+	CLK_LOOKUP("cam_clk", camss_gp0_clk.c, "20.qcom,camera"),
+	CLK_LOOKUP("cam_clk", gcc_gp1_clk.c, "6c.qcom,camera"),
+	CLK_LOOKUP("cam_clk", camss_gp1_clk.c, "90.qcom,camera"),
 	CLK_LOOKUP("cam_clk", camss_mclk1_clk.c, ""),
 	CLK_LOOKUP("cam_clk", camss_mclk2_clk.c, ""),
 	CLK_LOOKUP("cam_clk", camss_mclk3_clk.c, ""),
diff --git a/arch/arm/mach-msm/clock-mdss-8974.c b/arch/arm/mach-msm/clock-mdss-8974.c
index 47332a4..3bb4c57 100644
--- a/arch/arm/mach-msm/clock-mdss-8974.c
+++ b/arch/arm/mach-msm/clock-mdss-8974.c
@@ -31,8 +31,8 @@
 #define DSS_REG_W(base, offset, data)	REG_W((data), (base) + (offset))
 #define DSS_REG_R(base, offset)		REG_R((base) + (offset))
 
-#define GDSC_PHYS		0xFD8C2304
-#define GDSC_SIZE		0x4
+#define GDSC_PHYS		0xFD8C2300
+#define GDSC_SIZE		0x8
 
 #define DSI_PHY_PHYS		0xFD922A00
 #define DSI_PHY_SIZE		0x000000D4
@@ -163,7 +163,8 @@
 	if (!gdsc_base)
 		return 0;
 
-	return !!(readl_relaxed(gdsc_base) & BIT(31));
+	return (readl_relaxed(gdsc_base + 0x4) & BIT(31)) &&
+		(!(readl_relaxed(gdsc_base) & BIT(0)));
 }
 
 void hdmi_pll_disable(void)
@@ -1140,6 +1141,11 @@
 	int i, rc = 0;
 	struct dsi_pll_vco_clk *vco = to_vco_clk(c);
 
+	if (!mdss_gdsc_enabled()) {
+		pr_err("%s: mdss GDSC is not enabled\n", __func__);
+		return -EPERM;
+	}
+
 	rc = clk_enable(mdss_ahb_clk);
 	if (rc) {
 		pr_err("%s: failed to enable mdss ahb clock. rc=%d\n",
@@ -1167,6 +1173,12 @@
 {
 	int rc = 0;
 
+	if (!mdss_gdsc_enabled()) {
+		pr_warn("%s: mdss GDSC disabled before disabling DSI PLL\n",
+			__func__);
+		return;
+	}
+
 	rc = clk_enable(mdss_ahb_clk);
 	if (rc) {
 		pr_err("%s: failed to enable mdss ahb clock. rc=%d\n",
diff --git a/arch/arm/mach-msm/cpufreq.c b/arch/arm/mach-msm/cpufreq.c
index e02df3e..a6c86af 100644
--- a/arch/arm/mach-msm/cpufreq.c
+++ b/arch/arm/mach-msm/cpufreq.c
@@ -27,6 +27,7 @@
 #include <linux/cpumask.h>
 #include <linux/sched.h>
 #include <linux/suspend.h>
+#include <trace/events/power.h>
 #include <mach/socinfo.h>
 #include <mach/cpufreq.h>
 
@@ -98,9 +99,12 @@
 
 	cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
 
+	trace_cpu_frequency_switch_start(freqs.old, freqs.new, policy->cpu);
 	ret = acpuclk_set_rate(policy->cpu, new_freq, SETRATE_CPUFREQ);
-	if (!ret)
+	if (!ret) {
+		trace_cpu_frequency_switch_end(policy->cpu);
 		cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
+	}
 
 	/* Restore priority after clock ramp-up */
 	if (freqs.new > freqs.old && saved_sched_policy >= 0) {
diff --git a/arch/arm/mach-msm/include/mach/gpiomux.h b/arch/arm/mach-msm/include/mach/gpiomux.h
index 9aae3fb..bd1a4a2 100644
--- a/arch/arm/mach-msm/include/mach/gpiomux.h
+++ b/arch/arm/mach-msm/include/mach/gpiomux.h
@@ -113,6 +113,7 @@
 enum msm_tlmm_misc_reg {
 	TLMM_ETM_MODE_REG = 0x2014,
 	TLMM_SDC2_HDRV_PULL_CTL = 0x2048,
+	TLMM_SPARE_REG = 0x2024,
 };
 
 void msm_tlmm_misc_reg_write(enum msm_tlmm_misc_reg misc_reg, int val);
diff --git a/arch/arm/mach-msm/include/mach/qdsp6v2/rtac.h b/arch/arm/mach-msm/include/mach/qdsp6v2/rtac.h
index 07be428..0a1cdd4 100644
--- a/arch/arm/mach-msm/include/mach/qdsp6v2/rtac.h
+++ b/arch/arm/mach-msm/include/mach/qdsp6v2/rtac.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2011, 2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -19,6 +19,31 @@
 #define RTAC_CVS		1
 #define RTAC_VOICE_MODES	2
 
+enum {
+	ADM_RTAC_CAL,
+	ASM_RTAC_CAL,
+	VOICE_RTAC_CAL,
+	MAX_RTAC_BLOCKS
+};
+
+struct rtac_cal_mem_map_data {
+	uint32_t		map_size;
+	uint32_t		map_handle;
+	struct ion_client	*ion_client;
+	struct ion_handle	*ion_handle;
+};
+
+struct rtac_cal_data {
+	uint32_t		size;
+	uint32_t		kvaddr;
+	uint32_t		paddr;
+};
+
+struct rtac_cal_block_data {
+	struct rtac_cal_mem_map_data	map_data;
+	struct rtac_cal_data		cal_data;
+};
+
 void rtac_add_adm_device(u32 port_id, u32 copp_id, u32 path_id, u32 popp_id);
 void rtac_remove_adm_device(u32 port_id);
 void rtac_remove_popp_from_adm_devices(u32 popp_id);
@@ -35,5 +60,6 @@
 void rtac_set_voice_handle(u32 mode, void *handle);
 bool rtac_make_voice_callback(u32 mode, uint32_t *payload, u32 payload_size);
 void rtac_copy_voice_payload_to_user(void *payload, u32 payload_size);
+int rtac_clear_mapping(uint32_t cal_type);
 
 #endif
diff --git a/arch/arm/mach-msm/peripheral-loader.c b/arch/arm/mach-msm/peripheral-loader.c
index 94281b1..157dc01 100644
--- a/arch/arm/mach-msm/peripheral-loader.c
+++ b/arch/arm/mach-msm/peripheral-loader.c
@@ -482,6 +482,9 @@
 	if (ret)
 		return ret;
 
+	pil_info(desc, "loading from %pa to %pa\n", &priv->region_start,
+							&priv->region_end);
+
 	for (i = 0; i < mdt->hdr.e_phnum; i++) {
 		phdr = &mdt->phdr[i];
 		if (!segment_is_loadable(phdr))
diff --git a/arch/arm/mach-msm/pil-venus.c b/arch/arm/mach-msm/pil-venus.c
index a7ebbf7..e826a44 100644
--- a/arch/arm/mach-msm/pil-venus.c
+++ b/arch/arm/mach-msm/pil-venus.c
@@ -65,7 +65,7 @@
 
 
 /* PIL proxy vote timeout */
-#define VENUS_PROXY_TIMEOUT				10000
+#define VENUS_PROXY_TIMEOUT				2000
 
 /* Poll interval in uS */
 #define POLL_INTERVAL_US				50
@@ -288,17 +288,6 @@
 	unsigned long iova;
 	u32 ver, cpa_start_addr, cpa_end_addr, fw_start_addr, fw_end_addr;
 
-	/*
-	 * GDSC needs to remain on till Venus is shutdown. So, enable
-	 * the GDSC here again to make sure it remains on beyond the
-	 * expiry of the proxy vote timer.
-	 */
-	rc = regulator_enable(drv->gdsc);
-	if (rc) {
-		dev_err(pil->dev, "GDSC enable failed\n");
-		return rc;
-	}
-
 	/* Get Venus version number */
 	if (!drv->hw_ver_checked) {
 		ver = readl_relaxed(wrapper_base + VENUS_WRAPPER_HW_VERSION);
@@ -344,7 +333,7 @@
 	rc = iommu_attach_device(drv->iommu_fw_domain, drv->iommu_fw_ctx);
 	if (rc) {
 		dev_err(pil->dev, "venus fw iommu attach failed\n");
-		goto err_iommu_attach;
+		return rc;
 	}
 
 	/* Map virtual addr space 0 - fw_sz to firmware physical addr space */
@@ -366,9 +355,6 @@
 err_iommu_map:
 	iommu_detach_device(drv->iommu_fw_domain, drv->iommu_fw_ctx);
 
-err_iommu_attach:
-	regulator_disable(drv->gdsc);
-
 	return rc;
 }
 
@@ -424,8 +410,6 @@
 
 	venus_clock_disable_unprepare(pil->dev);
 
-	regulator_disable(drv->gdsc);
-
 	drv->is_booted = 0;
 
 	return 0;
@@ -454,22 +438,8 @@
 static int pil_venus_reset_trusted(struct pil_desc *pil)
 {
 	int rc;
-	struct venus_data *drv = dev_get_drvdata(pil->dev);
-
-	/*
-	 * GDSC needs to remain on till Venus is shutdown. So, enable
-	 * the GDSC here again to make sure it remains on beyond the
-	 * expiry of the proxy vote timer.
-	 */
-	rc = regulator_enable(drv->gdsc);
-	if (rc) {
-		dev_err(pil->dev, "GDSC enable failed\n");
-		return rc;
-	}
 
 	rc = pas_auth_and_reset(PAS_VIDC);
-	if (rc)
-		regulator_disable(drv->gdsc);
 
 	return rc;
 }
@@ -477,7 +447,6 @@
 static int pil_venus_shutdown_trusted(struct pil_desc *pil)
 {
 	int rc;
-	struct venus_data *drv = dev_get_drvdata(pil->dev);
 
 	venus_clock_prepare_enable(pil->dev);
 
@@ -485,8 +454,6 @@
 
 	venus_clock_disable_unprepare(pil->dev);
 
-	regulator_disable(drv->gdsc);
-
 	return rc;
 }
 
diff --git a/arch/arm/mach-msm/qdsp6v2/rtac.c b/arch/arm/mach-msm/qdsp6v2/rtac.c
index 1881607..65543a4 100644
--- a/arch/arm/mach-msm/qdsp6v2/rtac.c
+++ b/arch/arm/mach-msm/qdsp6v2/rtac.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2011, 2013 The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -42,6 +42,7 @@
 void rtac_set_voice_handle(u32 mode, void *handle) {}
 bool rtac_make_voice_callback(u32 mode, uint32_t *payload,
 		u32 payload_size) {return false; }
+int rtac_clear_mapping(uint32_t cal_type) {return false; }
 
 #else
 
@@ -123,6 +124,8 @@
 struct mutex			rtac_voice_mutex;
 struct mutex			rtac_voice_apr_mutex;
 
+int rtac_clear_mapping(uint32_t cal_type) {return false; }
+
 static int rtac_open(struct inode *inode, struct file *f)
 {
 	pr_debug("%s\n", __func__);
diff --git a/drivers/char/adsprpc.c b/drivers/char/adsprpc.c
index a740be6..4507f80 100644
--- a/drivers/char/adsprpc.c
+++ b/drivers/char/adsprpc.c
@@ -232,7 +232,7 @@
 	buf->virt = 0;
 	heap = me->smmu.enabled ? ION_HEAP(ION_IOMMU_HEAP_ID) :
 		ION_HEAP(ION_ADSP_HEAP_ID) | ION_HEAP(ION_AUDIO_HEAP_ID);
-	buf->handle = ion_alloc(clnt, buf->size, SZ_4K, heap, 0);
+	buf->handle = ion_alloc(clnt, buf->size, SZ_4K, heap, ION_FLAG_CACHED);
 	VERIFY(err, 0 == IS_ERR_OR_NULL(buf->handle));
 	if (err)
 		goto bail;
diff --git a/drivers/char/diag/diag_masks.c b/drivers/char/diag/diag_masks.c
index 9c27180..69e6250 100644
--- a/drivers/char/diag/diag_masks.c
+++ b/drivers/char/diag/diag_masks.c
@@ -368,7 +368,7 @@
 			driver->log_mask->status = DIAG_CTRL_MASK_INVALID;
 		}
 
-		if (driver->msg_mask->status == DIAG_CTRL_MASK_INVALID) {
+		if (driver->log_mask->status == DIAG_CTRL_MASK_INVALID) {
 			mutex_unlock(&driver->diag_cntl_mutex);
 			return;
 		}
diff --git a/drivers/coresight/coresight-csr.c b/drivers/coresight/coresight-csr.c
index 16338a9..6b20b20 100644
--- a/drivers/coresight/coresight-csr.c
+++ b/drivers/coresight/coresight-csr.c
@@ -94,7 +94,7 @@
 	csr_writel(drvdata, usbbamctrl, CSR_USBBAMCTRL);
 
 	usbflshctrl = csr_readl(drvdata, CSR_USBFLSHCTRL);
-	usbflshctrl = (usbflshctrl & ~0x3FFFC) | (0x1000 << 2);
+	usbflshctrl = (usbflshctrl & ~0x3FFFC) | (0xFFFF << 2);
 	csr_writel(drvdata, usbflshctrl, CSR_USBFLSHCTRL);
 	usbflshctrl |= 0x2;
 	csr_writel(drvdata, usbflshctrl, CSR_USBFLSHCTRL);
diff --git a/drivers/coresight/coresight-cti.c b/drivers/coresight/coresight-cti.c
index 2a06f0a..6f7f743 100644
--- a/drivers/coresight/coresight-cti.c
+++ b/drivers/coresight/coresight-cti.c
@@ -295,6 +295,41 @@
 }
 EXPORT_SYMBOL(coresight_cti_unmap_trigout);
 
+static void __cti_reset(struct cti_drvdata *drvdata)
+{
+	int trig;
+
+	if (!drvdata->refcnt)
+		return;
+
+	CTI_UNLOCK(drvdata);
+
+	for (trig = 0; trig < CTI_MAX_TRIGGERS; trig++) {
+		cti_writel(drvdata, 0, CTIINEN(trig));
+		cti_writel(drvdata, 0, CTIOUTEN(trig));
+	}
+
+	CTI_LOCK(drvdata);
+
+	cti_disable(drvdata);
+	drvdata->refcnt = 0;
+}
+
+void coresight_cti_reset(struct coresight_cti *cti)
+{
+	struct cti_drvdata *drvdata;
+
+	if (IS_ERR_OR_NULL(cti))
+		return;
+
+	drvdata = to_cti_drvdata(cti);
+
+	mutex_lock(&drvdata->mutex);
+	__cti_reset(drvdata);
+	mutex_unlock(&drvdata->mutex);
+}
+EXPORT_SYMBOL(coresight_cti_reset);
+
 struct coresight_cti *coresight_cti_get(const char *name)
 {
 	struct coresight_cti *cti;
@@ -387,6 +422,24 @@
 }
 static DEVICE_ATTR(unmap_trigout, S_IWUSR, NULL, cti_store_unmap_trigout);
 
+static ssize_t cti_store_reset(struct device *dev,
+			       struct device_attribute *attr,
+			       const char *buf, size_t size)
+{
+	struct cti_drvdata *drvdata = dev_get_drvdata(dev->parent);
+	unsigned long val;
+
+	if (sscanf(buf, "%lx", &val) != 1)
+		return -EINVAL;
+
+	if (!val)
+		return -EINVAL;
+
+	coresight_cti_reset(&drvdata->cti);
+	return size;
+}
+static DEVICE_ATTR(reset, S_IWUSR, NULL, cti_store_reset);
+
 static ssize_t cti_show_trigin(struct device *dev,
 			       struct device_attribute *attr, char *buf)
 {
@@ -395,6 +448,10 @@
 	uint32_t ctien;
 	ssize_t size = 0;
 
+	mutex_lock(&cti_lock);
+	if (!drvdata->refcnt)
+		goto err;
+
 	for (trig = 0; trig < CTI_MAX_TRIGGERS; trig++) {
 		ctien = cti_readl(drvdata, CTIINEN(trig));
 		for (ch = 0; ch < CTI_MAX_CHANNELS; ch++) {
@@ -415,6 +472,7 @@
 	}
 err:
 	size += scnprintf(&buf[size], 2, "\n");
+	mutex_unlock(&cti_lock);
 	return size;
 }
 static DEVICE_ATTR(show_trigin, S_IRUGO, cti_show_trigin, NULL);
@@ -427,6 +485,10 @@
 	uint32_t ctien;
 	ssize_t size = 0;
 
+	mutex_lock(&cti_lock);
+	if (!drvdata->refcnt)
+		goto err;
+
 	for (trig = 0; trig < CTI_MAX_TRIGGERS; trig++) {
 		ctien = cti_readl(drvdata, CTIOUTEN(trig));
 		for (ch = 0; ch < CTI_MAX_CHANNELS; ch++) {
@@ -447,6 +509,7 @@
 	}
 err:
 	size += scnprintf(&buf[size], 2, "\n");
+	mutex_unlock(&cti_lock);
 	return size;
 }
 static DEVICE_ATTR(show_trigout, S_IRUGO, cti_show_trigout, NULL);
@@ -456,6 +519,7 @@
 	&dev_attr_map_trigout.attr,
 	&dev_attr_unmap_trigin.attr,
 	&dev_attr_unmap_trigout.attr,
+	&dev_attr_reset.attr,
 	&dev_attr_show_trigin.attr,
 	&dev_attr_show_trigout.attr,
 	NULL,
diff --git a/drivers/coresight/coresight-tmc.c b/drivers/coresight/coresight-tmc.c
index 3225817..8267293 100644
--- a/drivers/coresight/coresight-tmc.c
+++ b/drivers/coresight/coresight-tmc.c
@@ -22,7 +22,6 @@
 #include <linux/miscdevice.h>
 #include <linux/uaccess.h>
 #include <linux/slab.h>
-#include <linux/memory_alloc.h>
 #include <linux/delay.h>
 #include <linux/spinlock.h>
 #include <linux/clk.h>
@@ -35,7 +34,7 @@
 #include <linux/interrupt.h>
 #include <linux/cdev.h>
 #include <linux/usb/usb_qdss.h>
-#include <mach/memory.h>
+#include <linux/dma-mapping.h>
 #include <mach/sps.h>
 #include <mach/usb_bam.h>
 #include <mach/msm_memory_dump.h>
@@ -154,7 +153,7 @@
 	bool			aborting;
 	char			*reg_buf;
 	char			*buf;
-	unsigned long		paddr;
+	dma_addr_t		paddr;
 	void __iomem		*vaddr;
 	uint32_t		size;
 	struct mutex		usb_lock;
@@ -273,9 +272,11 @@
 	axictl = (axictl & ~0x3) | 0x2;
 	tmc_writel(drvdata, axictl, TMC_AXICTL);
 
-	tmc_writel(drvdata, bamdata->data_fifo.phys_base, TMC_DBALO);
-	tmc_writel(drvdata, 0x0, TMC_DBAHI);
-	tmc_writel(drvdata, 0x103, TMC_FFCR);
+	tmc_writel(drvdata, (uint32_t)bamdata->data_fifo.phys_base, TMC_DBALO);
+	tmc_writel(drvdata, (((uint64_t)bamdata->data_fifo.phys_base) >> 32)
+		   & 0xFF, TMC_DBAHI);
+	/* Set FOnFlIn for periodic flush */
+	tmc_writel(drvdata, 0x133, TMC_FFCR);
 	tmc_writel(drvdata, drvdata->trigger_cntr, TMC_TRG);
 	__tmc_enable(drvdata);
 
@@ -341,7 +342,6 @@
 	TMC_UNLOCK(drvdata);
 
 	tmc_wait_for_flush(drvdata);
-	tmc_flush_and_stop(drvdata);
 	__tmc_disable(drvdata);
 
 	TMC_LOCK(drvdata);
@@ -470,8 +470,9 @@
 	axictl = (axictl & ~0x3) | 0x2;
 	tmc_writel(drvdata, axictl, TMC_AXICTL);
 
-	tmc_writel(drvdata, drvdata->paddr, TMC_DBALO);
-	tmc_writel(drvdata, 0x0, TMC_DBAHI);
+	tmc_writel(drvdata, (uint32_t)drvdata->paddr, TMC_DBALO);
+	tmc_writel(drvdata, (((uint64_t)drvdata->paddr) >> 32) & 0xFF,
+		   TMC_DBAHI);
 	tmc_writel(drvdata, 0x1133, TMC_FFCR);
 	tmc_writel(drvdata, drvdata->trigger_cntr, TMC_TRG);
 	__tmc_enable(drvdata);
@@ -1300,7 +1301,7 @@
 		return -EINVAL;
 	if ((drvdata->size / 8) < val)
 		return -EINVAL;
-	if (drvdata->size % (val * 8) != 0)
+	if (val && drvdata->size % (val * 8) != 0)
 		return -EINVAL;
 
 	drvdata->byte_cntr_value = val;
@@ -1564,7 +1565,8 @@
 	if (drvdata->config_type == TMC_CONFIG_TYPE_ETR) {
 		if (pdev->dev.of_node) {
 			ret = of_property_read_u32(pdev->dev.of_node,
-				"qcom,memory-reservation-size", &drvdata->size);
+						   "qcom,memory-size",
+						   &drvdata->size);
 			if (ret) {
 				clk_disable_unprepare(drvdata->clk);
 				return ret;
@@ -1577,17 +1579,11 @@
 	clk_disable_unprepare(drvdata->clk);
 
 	if (drvdata->config_type == TMC_CONFIG_TYPE_ETR) {
-		drvdata->paddr = allocate_contiguous_ebi_nomap(drvdata->size,
-							       SZ_4K);
-		if (!drvdata->paddr)
+		drvdata->vaddr = dma_zalloc_coherent(&pdev->dev, drvdata->size,
+						     &drvdata->paddr,
+						     GFP_KERNEL);
+		if (!drvdata->vaddr)
 			return -ENOMEM;
-		drvdata->vaddr = devm_ioremap(dev, drvdata->paddr,
-					      drvdata->size);
-		if (!drvdata->vaddr) {
-			ret = -ENOMEM;
-			goto err0;
-		}
-		memset(drvdata->vaddr, 0, drvdata->size);
 		drvdata->buf = drvdata->vaddr;
 		drvdata->out_mode = TMC_ETR_OUT_MODE_MEM;
 		if (pdev->dev.of_node)
@@ -1727,7 +1723,10 @@
 err1:
 	tmc_etr_byte_cntr_exit(drvdata);
 err0:
-	free_contiguous_memory_by_paddr(drvdata->paddr);
+	if (drvdata->vaddr)
+		dma_free_coherent(&pdev->dev, drvdata->size,
+				  drvdata->vaddr,
+				  drvdata->paddr);
 	return ret;
 }
 
@@ -1739,7 +1738,9 @@
 	misc_deregister(&drvdata->miscdev);
 	coresight_unregister(drvdata->csdev);
 	tmc_etr_bam_exit(drvdata);
-	free_contiguous_memory_by_paddr(drvdata->paddr);
+	if (drvdata->vaddr)
+		dma_free_coherent(&pdev->dev, drvdata->size, drvdata->vaddr,
+				  drvdata->paddr);
 	return 0;
 }
 
diff --git a/drivers/coresight/coresight-tpiu.c b/drivers/coresight/coresight-tpiu.c
index 032327c..1121f57 100644
--- a/drivers/coresight/coresight-tpiu.c
+++ b/drivers/coresight/coresight-tpiu.c
@@ -88,6 +88,11 @@
 	unsigned int		reg_high;
 	unsigned int		reg_lpm;
 	unsigned int		reg_hpm;
+	struct regulator        *reg_io;
+	unsigned int            reg_low_io;
+	unsigned int            reg_high_io;
+	unsigned int            reg_lpm_io;
+	unsigned int            reg_hpm_io;
 	enum tpiu_set		set;
 	unsigned int		seta_gpiocnt;
 	unsigned int		*seta_gpios;
@@ -240,7 +245,7 @@
 {
 	int ret;
 
-	if (!drvdata->reg)
+	if (!drvdata->reg || !drvdata->reg_io)
 		return -EINVAL;
 
 	ret = tpiu_reg_set_optimum_mode(drvdata->reg, drvdata->reg_hpm);
@@ -253,6 +258,20 @@
 	ret = regulator_enable(drvdata->reg);
 	if (ret)
 		goto err1;
+	ret = tpiu_reg_set_optimum_mode(drvdata->reg_io, drvdata->reg_hpm_io);
+	if (ret < 0)
+		goto err2;
+	ret = tpiu_reg_set_voltage(drvdata->reg_io, drvdata->reg_low_io,
+				   drvdata->reg_high_io);
+	if (ret)
+		goto err3;
+	ret = regulator_enable(drvdata->reg_io);
+	if (ret)
+		goto err4;
+
+	ret = clk_set_rate(drvdata->clk, CORESIGHT_CLK_RATE_FIXED);
+	if (ret)
+		goto err5;
 
 	msm_tlmm_misc_reg_write(TLMM_SDC2_HDRV_PULL_CTL, 0x16D);
 	msm_tlmm_misc_reg_write(TLMM_ETM_MODE_REG, 1);
@@ -265,6 +284,14 @@
 	TPIU_LOCK(drvdata);
 
 	return 0;
+err5:
+	regulator_disable(drvdata->reg_io);
+err4:
+	tpiu_reg_set_voltage(drvdata->reg_io, 0, drvdata->reg_high_io);
+err3:
+	tpiu_reg_set_optimum_mode(drvdata->reg_io, 0);
+err2:
+	regulator_disable(drvdata->reg);
 err1:
 	tpiu_reg_set_voltage(drvdata->reg, 0, drvdata->reg_high);
 err0:
@@ -342,9 +369,15 @@
 
 	msm_tlmm_misc_reg_write(TLMM_ETM_MODE_REG, 0);
 
+	clk_set_rate(drvdata->clk, CORESIGHT_CLK_RATE_TRACE);
+
 	regulator_disable(drvdata->reg);
-	tpiu_reg_set_optimum_mode(drvdata->reg, 0);
 	tpiu_reg_set_voltage(drvdata->reg, 0, drvdata->reg_high);
+	tpiu_reg_set_optimum_mode(drvdata->reg, 0);
+
+	regulator_disable(drvdata->reg_io);
+	tpiu_reg_set_voltage(drvdata->reg_io, 0, drvdata->reg_high_io);
+	tpiu_reg_set_optimum_mode(drvdata->reg_io, 0);
 }
 
 static void tpiu_disable(struct coresight_device *csdev)
@@ -566,6 +599,33 @@
 		dev_err(dev, "sdc voltage supply not specified or available\n");
 	}
 
+	reg_node = of_parse_phandle(node, "vdd-io-supply", 0);
+	if (reg_node) {
+		drvdata->reg_io = devm_regulator_get(dev, "vdd-io");
+		if (IS_ERR(drvdata->reg_io))
+			return PTR_ERR(drvdata->reg_io);
+
+		prop = of_get_property(node, "qcom,vdd-io-voltage-level", &len);
+		if (!prop || (len != (2 * sizeof(__be32)))) {
+			dev_err(dev, "sdc io voltage levels not specified\n");
+		} else {
+			drvdata->reg_low_io = be32_to_cpup(&prop[0]);
+			drvdata->reg_high_io = be32_to_cpup(&prop[1]);
+		}
+
+		prop = of_get_property(node, "qcom,vdd-io-current-level", &len);
+		if (!prop || (len != (2 * sizeof(__be32)))) {
+			dev_err(dev, "sdc io current levels not specified\n");
+		} else {
+			drvdata->reg_lpm_io = be32_to_cpup(&prop[0]);
+			drvdata->reg_hpm_io = be32_to_cpup(&prop[1]);
+		}
+		of_node_put(reg_node);
+	} else {
+		dev_err(dev,
+			"sdc io voltage supply not specified or available\n");
+	}
+
 	drvdata->out_mode = TPIU_OUT_MODE_MICTOR;
 	drvdata->set = TPIU_SET_B;
 
diff --git a/drivers/hwmon/qpnp-adc-current.c b/drivers/hwmon/qpnp-adc-current.c
index 2d70faa..adaff41 100644
--- a/drivers/hwmon/qpnp-adc-current.c
+++ b/drivers/hwmon/qpnp-adc-current.c
@@ -1249,8 +1249,7 @@
 			GFP_KERNEL);
 	if (!adc_qpnp) {
 		dev_err(&spmi->dev, "Unable to allocate memory\n");
-		rc = -ENOMEM;
-		goto fail;
+		return -ENOMEM;
 	}
 
 	iadc->dev = &(spmi->dev);
@@ -1259,7 +1258,7 @@
 	rc = qpnp_adc_get_devicetree_data(spmi, iadc->adc);
 	if (rc) {
 		dev_err(&spmi->dev, "failed to read device tree\n");
-		goto fail;
+		return rc;
 	}
 
 	iadc->vadc_dev = qpnp_get_vadc(&spmi->dev, "iadc");
@@ -1267,7 +1266,7 @@
 		rc = PTR_ERR(iadc->vadc_dev);
 		if (rc != -EPROBE_DEFER)
 			pr_err("vadc property missing, rc=%d\n", rc);
-		goto fail;
+		return rc;
 	}
 
 	mutex_init(&iadc->adc->adc_lock);
diff --git a/drivers/hwmon/qpnp-adc-voltage.c b/drivers/hwmon/qpnp-adc-voltage.c
index e37f75a..b2b846a 100644
--- a/drivers/hwmon/qpnp-adc-voltage.c
+++ b/drivers/hwmon/qpnp-adc-voltage.c
@@ -1365,21 +1365,6 @@
 	}
 	mutex_init(&vadc->adc->adc_lock);
 
-	vadc->vadc_poll_eoc = of_property_read_bool(node,
-						"qcom,vadc-poll-eoc");
-	if (!vadc->vadc_poll_eoc) {
-		rc = devm_request_irq(&spmi->dev, vadc->adc->adc_irq_eoc,
-				qpnp_vadc_isr, IRQF_TRIGGER_RISING,
-				"qpnp_vadc_interrupt", vadc);
-		if (rc) {
-			dev_err(&spmi->dev,
-			"failed to request adc irq with error %d\n", rc);
-			return rc;
-		} else {
-			enable_irq_wake(vadc->adc->adc_irq_eoc);
-		}
-	}
-
 	rc = qpnp_vadc_init_hwmon(vadc, spmi);
 	if (rc) {
 		dev_err(&spmi->dev, "failed to initialize qpnp hwmon adc\n");
@@ -1416,11 +1401,24 @@
 	}
 
 	INIT_WORK(&vadc->trigger_completion_work, qpnp_vadc_work);
-	if (vadc->vadc_poll_eoc)
+
+	vadc->vadc_poll_eoc = of_property_read_bool(node,
+						"qcom,vadc-poll-eoc");
+	if (!vadc->vadc_poll_eoc) {
+		rc = devm_request_irq(&spmi->dev, vadc->adc->adc_irq_eoc,
+				qpnp_vadc_isr, IRQF_TRIGGER_RISING,
+				"qpnp_vadc_interrupt", vadc);
+		if (rc) {
+			dev_err(&spmi->dev,
+			"failed to request adc irq with error %d\n", rc);
+			goto err_setup;
+		} else {
+			enable_irq_wake(vadc->adc->adc_irq_eoc);
+		}
+	} else
 		device_init_wakeup(vadc->dev, 1);
 
 	vadc->vadc_iadc_sync_lock = false;
-
 	dev_set_drvdata(&spmi->dev, vadc);
 	list_add(&vadc->list, &qpnp_vadc_device_list);
 
diff --git a/drivers/input/misc/mma8x5x.c b/drivers/input/misc/mma8x5x.c
index 8775ab9..f49ff14 100644
--- a/drivers/input/misc/mma8x5x.c
+++ b/drivers/input/misc/mma8x5x.c
@@ -43,7 +43,7 @@
 #define POLL_INTERVAL		100 /* msecs */
 
 /* if sensor is standby ,set POLL_STOP_TIME to slow down the poll */
-#define POLL_STOP_TIME		200
+#define POLL_STOP_TIME		10000
 #define INPUT_FUZZ			32
 #define INPUT_FLAT			32
 #define INPUT_DATA_DIVIDER	16
diff --git a/drivers/input/misc/stk3x1x.c b/drivers/input/misc/stk3x1x.c
index 61f3530..937bf6c 100644
--- a/drivers/input/misc/stk3x1x.c
+++ b/drivers/input/misc/stk3x1x.c
@@ -170,7 +170,7 @@
 #define MIN_ALS_POLL_DELAY_NS	110000000
 
 #define DEVICE_NAME		"stk_ps"
-#define ALS_NAME "lightsensor-level"
+#define ALS_NAME		"stk3x1x-ls"
 #define PS_NAME "proximity"
 
 /* POWER SUPPLY VOLTAGE RANGE */
@@ -179,6 +179,15 @@
 #define STK3X1X_VIO_MIN_UV	1750000
 #define STK3X1X_VIO_MAX_UV	1950000
 
+#define STK_FIR_LEN 16
+#define MAX_FIR_LEN 32
+struct data_filter {
+	u16 raw[MAX_FIR_LEN];
+	int sum;
+	int number;
+	int idx;
+};
+
 struct stk3x1x_data {
 	struct i2c_client *client;
 #if (!defined(STK_POLL_PS) || !defined(STK_POLL_ALS))
@@ -218,6 +227,9 @@
 	struct regulator *vdd;
 	struct regulator *vio;
 	bool power_enabled;
+	bool use_fir;
+	struct data_filter      fir;
+	atomic_t                firlength;
 };
 
 #if( !defined(CONFIG_STK_PS_ALS_USE_CHANGE_THRESHOLD))
@@ -387,6 +399,13 @@
 		printk(KERN_ERR "%s: write i2c error\n", __func__);
 		return ret;
 	}
+
+	ret = i2c_smbus_write_byte_data(ps_data->client, 0x87, 0x60);
+	if (ret < 0) {
+		dev_err(&ps_data->client->dev,
+			"%s: write i2c error\n", __func__);
+		return ret;
+	}
 	return 0;
 }
 
@@ -708,9 +727,32 @@
     return ret;
 }
 
+static inline int32_t stk3x1x_filter_reading(struct stk3x1x_data *ps_data,
+			int32_t word_data)
+{
+	int index;
+	int firlen = atomic_read(&ps_data->firlength);
+
+	if (ps_data->fir.number < firlen) {
+		ps_data->fir.raw[ps_data->fir.number] = word_data;
+		ps_data->fir.sum += word_data;
+		ps_data->fir.number++;
+		ps_data->fir.idx++;
+	} else {
+		index = ps_data->fir.idx % firlen;
+		ps_data->fir.sum -= ps_data->fir.raw[index];
+		ps_data->fir.raw[index] = word_data;
+		ps_data->fir.sum += word_data;
+		ps_data->fir.idx++;
+		word_data = ps_data->fir.sum/firlen;
+	}
+	return word_data;
+}
+
 static inline int32_t stk3x1x_get_als_reading(struct stk3x1x_data *ps_data)
 {
     int32_t word_data, tmp_word_data;
+
 	tmp_word_data = i2c_smbus_read_word_data(ps_data->client, STK_DATA1_ALS_REG);
 	if(tmp_word_data < 0)
 	{
@@ -718,6 +760,9 @@
 		return tmp_word_data;
 	}
 	word_data = ((tmp_word_data & 0xFF00) >> 8) | ((tmp_word_data & 0x00FF) << 8) ;
+	if (ps_data->use_fir)
+		word_data = stk3x1x_filter_reading(ps_data, word_data);
+
 	return word_data;
 }
 
@@ -912,7 +957,12 @@
 	return scnprintf(buf, PAGE_SIZE, "%lld\n", ktime_to_ns(ps_data->als_poll_delay));
 }
 
-
+static inline void stk_als_delay_store_fir(struct stk3x1x_data *ps_data)
+{
+	ps_data->fir.number = 0;
+	ps_data->fir.idx = 0;
+	ps_data->fir.sum = 0;
+}
 static ssize_t stk_als_delay_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size)
 {
     uint64_t value = 0;
@@ -936,6 +986,10 @@
 	mutex_lock(&ps_data->io_lock);
 	if(value != ktime_to_ns(ps_data->als_poll_delay))
 		ps_data->als_poll_delay = ns_to_ktime(value);
+
+	if (ps_data->use_fir)
+		stk_als_delay_store_fir(ps_data);
+
 	mutex_unlock(&ps_data->io_lock);
 	return size;
 }
@@ -948,6 +1002,77 @@
     return scnprintf(buf, PAGE_SIZE, "%d\n", reading);
 }
 
+static ssize_t stk_als_firlen_show(struct device *dev,
+			struct device_attribute *attr, char *buf)
+{
+	struct stk3x1x_data *ps_data =  dev_get_drvdata(dev);
+	int len = atomic_read(&ps_data->firlength);
+
+	dev_dbg(dev, "%s: len = %2d, idx = %2d\n",
+			__func__, len, ps_data->fir.idx);
+	dev_dbg(dev, "%s: sum = %5d, ave = %5d\n",
+			__func__, ps_data->fir.sum, ps_data->fir.sum/len);
+
+	return scnprintf(buf, PAGE_SIZE, "%d\n", len);
+}
+
+static ssize_t stk_als_firlen_store(struct device *dev,
+			struct device_attribute *attr,
+			const char *buf, size_t size)
+{
+	uint64_t value = 0;
+	int ret;
+	struct stk3x1x_data *ps_data =  dev_get_drvdata(dev);
+	ret = kstrtoull(buf, 10, &value);
+	if (ret < 0) {
+		dev_err(dev, "%s:strict_strtoull failed, ret=0x%x\n",
+			__func__, ret);
+		return ret;
+	}
+
+	if (value > MAX_FIR_LEN) {
+		dev_err(dev, "%s: firlen exceed maximum filter length\n",
+			__func__);
+	} else if (value < 1) {
+		atomic_set(&ps_data->firlength, 1);
+		memset(&ps_data->fir, 0x00, sizeof(ps_data->fir));
+	} else {
+		atomic_set(&ps_data->firlength, value);
+		memset(&ps_data->fir, 0x00, sizeof(ps_data->fir));
+	}
+	return size;
+}
+
+static ssize_t stk_als_fir_enable_show(struct device *dev,
+			struct device_attribute *attr, char *buf)
+{
+	struct stk3x1x_data *ps_data =  dev_get_drvdata(dev);
+
+	return scnprintf(buf, PAGE_SIZE, "%d\n", ps_data->use_fir);
+}
+
+static ssize_t stk_als_fir_enable_store(struct device *dev,
+			struct device_attribute *attr,
+			const char *buf, size_t size)
+{
+	uint64_t value = 0;
+	int ret;
+	struct stk3x1x_data *ps_data =  dev_get_drvdata(dev);
+	ret = kstrtoull(buf, 10, &value);
+	if (ret < 0) {
+		dev_err(dev, "%s:strict_strtoull failed, ret=0x%x\n",
+			__func__, ret);
+		return ret;
+	}
+
+	if (value) {
+		ps_data->use_fir = true;
+		memset(&ps_data->fir, 0x00, sizeof(ps_data->fir));
+	} else {
+		ps_data->use_fir = false;
+	}
+	return size;
+}
 static ssize_t stk_ps_code_show(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct stk3x1x_data *ps_data =  dev_get_drvdata(dev);
@@ -1432,6 +1557,11 @@
 static struct device_attribute als_poll_delay_attribute =
 	__ATTR(poll_delay, 0664, stk_als_delay_show, stk_als_delay_store);
 static struct device_attribute als_ir_code_attribute = __ATTR(ircode,0444,stk_als_ir_code_show,NULL);
+static struct device_attribute als_firlen_attribute =
+	__ATTR(firlen, 0664, stk_als_firlen_show, stk_als_firlen_store);
+static struct device_attribute als_fir_enable_attribute =
+	__ATTR(fir_enable, 0664, stk_als_fir_enable_show,
+	stk_als_fir_enable_store);
 
 static struct attribute *stk_als_attrs [] =
 {
@@ -1441,6 +1571,8 @@
     &als_transmittance_attribute.attr,
 	&als_poll_delay_attribute.attr,
 	&als_ir_code_attribute.attr,
+	&als_firlen_attribute.attr,
+	&als_fir_enable_attribute.attr,
     NULL
 };
 
@@ -1673,6 +1805,13 @@
 	return IRQ_HANDLED;
 }
 #endif	/*	#if (!defined(STK_POLL_PS) || !defined(STK_POLL_ALS))	*/
+
+static inline void stk3x1x_init_fir(struct stk3x1x_data *ps_data)
+{
+	memset(&ps_data->fir, 0x00, sizeof(ps_data->fir));
+	atomic_set(&ps_data->firlength, STK_FIR_LEN);
+}
+
 static int32_t stk3x1x_init_all_setting(struct i2c_client *client, struct stk3x1x_platform_data *plat_data)
 {
 	int32_t ret;
@@ -1697,6 +1836,10 @@
 #ifndef CONFIG_STK_PS_ALS_USE_CHANGE_THRESHOLD
 	stk_init_code_threshold_table(ps_data);
 #endif
+
+	if (plat_data->use_fir)
+		stk3x1x_init_fir(ps_data);
+
     return 0;
 }
 
@@ -1993,6 +2136,8 @@
 		return rc;
 	}
 
+	pdata->use_fir = of_property_read_bool(np, "stk,use-fir");
+
 	return 0;
 }
 #else
@@ -2059,6 +2204,7 @@
 	}
 	ps_data->als_transmittance = plat_data->transmittance;
 	ps_data->int_pin = plat_data->int_pin;
+	ps_data->use_fir = plat_data->use_fir;
 
 	if (ps_data->als_transmittance == 0) {
 		dev_err(&client->dev,
diff --git a/drivers/media/platform/msm/camera_v2/sensor/flash/msm_led_i2c_trigger.c b/drivers/media/platform/msm/camera_v2/sensor/flash/msm_led_i2c_trigger.c
index b5afa86..9caa270 100644
--- a/drivers/media/platform/msm/camera_v2/sensor/flash/msm_led_i2c_trigger.c
+++ b/drivers/media/platform/msm/camera_v2/sensor/flash/msm_led_i2c_trigger.c
@@ -19,6 +19,7 @@
 #include "msm_camera_io_util.h"
 #include "../msm_sensor.h"
 #include "msm_led_flash.h"
+#include <linux/debugfs.h>
 
 #define FLASH_NAME "camera-led-flash"
 
@@ -485,12 +486,44 @@
 		msm_camera_qup_i2c_write_table_w_microdelay,
 };
 
+#ifdef CONFIG_DEBUG_FS
+static int set_led_status(void *data, u64 val)
+{
+	struct msm_led_flash_ctrl_t *fctrl =
+		 (struct msm_led_flash_ctrl_t *)data;
+	int rc = -1;
+	pr_debug("set_led_status: Enter val: %llu", val);
+	if (!fctrl) {
+		pr_err("set_led_status: fctrl is NULL");
+		return rc;
+	}
+	if (!fctrl->func_tbl) {
+		pr_err("set_led_status: fctrl->func_tbl is NULL");
+		return rc;
+	}
+	if (val == 0) {
+		pr_debug("set_led_status: val is disable");
+		rc = msm_flash_led_off(fctrl);
+	} else {
+		pr_debug("set_led_status: val is enable");
+		rc = msm_flash_led_low(fctrl);
+	}
+
+	return rc;
+}
+
+DEFINE_SIMPLE_ATTRIBUTE(ledflashdbg_fops,
+	NULL, set_led_status, "%llu\n");
+#endif
+
 int msm_flash_i2c_probe(struct i2c_client *client,
 		const struct i2c_device_id *id)
 {
 	int rc = 0;
 	struct msm_led_flash_ctrl_t *fctrl = NULL;
-
+#ifdef CONFIG_DEBUG_FS
+	struct dentry *dentry;
+#endif
 	if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
 		pr_err("i2c_check_functionality failed\n");
 		goto probe_failure;
@@ -529,6 +562,12 @@
 			&msm_sensor_qup_func_tbl;
 
 	rc = msm_led_i2c_flash_create_v4lsubdev(fctrl);
+#ifdef CONFIG_DEBUG_FS
+	dentry = debugfs_create_file("ledflash", S_IRUGO, NULL, (void *)fctrl,
+		&ledflashdbg_fops);
+	if (!dentry)
+		pr_err("Failed to create the debugfs ledflash file");
+#endif
 	CDBG("%s:%d probe success\n", __func__, __LINE__);
 	return 0;
 
diff --git a/drivers/media/platform/msm/camera_v2/sensor/imx135.c b/drivers/media/platform/msm/camera_v2/sensor/imx135.c
index 8368a4d..c26e4ff 100644
--- a/drivers/media/platform/msm/camera_v2/sensor/imx135.c
+++ b/drivers/media/platform/msm/camera_v2/sensor/imx135.c
@@ -68,7 +68,7 @@
 	{
 		.seq_type = SENSOR_CLK,
 		.seq_val = SENSOR_CAM_MCLK,
-		.config_val = 0,
+		.config_val = 24000000,
 		.delay = 1,
 	},
 	{
diff --git a/drivers/media/platform/msm/camera_v2/sensor/msm_sensor.c b/drivers/media/platform/msm/camera_v2/sensor/msm_sensor.c
index 0447159..ddc168a 100644
--- a/drivers/media/platform/msm/camera_v2/sensor/msm_sensor.c
+++ b/drivers/media/platform/msm/camera_v2/sensor/msm_sensor.c
@@ -957,7 +957,7 @@
 };
 
 static struct msm_cam_clk_info cam_8974_clk_info[] = {
-	[SENSOR_CAM_MCLK] = {"cam_src_clk", 19200000},
+	[SENSOR_CAM_MCLK] = {"cam_src_clk", 24000000},
 	[SENSOR_CAM_CLK] = {"cam_clk", 0},
 };
 
diff --git a/drivers/media/platform/msm/vidc/hfi_response_handler.c b/drivers/media/platform/msm/vidc/hfi_response_handler.c
index 8350dde..2b6118a 100644
--- a/drivers/media/platform/msm/vidc/hfi_response_handler.c
+++ b/drivers/media/platform/msm/vidc/hfi_response_handler.c
@@ -78,7 +78,7 @@
 	return vidc_err;
 }
 
-static int sanitize_session_pkt(struct list_head *sessions,
+static int validate_session_pkt(struct list_head *sessions,
 		struct hal_session *sess, struct mutex *session_lock)
 {
 	struct hal_session *session;
@@ -184,8 +184,10 @@
 }
 static void hfi_process_event_notify(
 		msm_vidc_callback callback, u32 device_id,
-		struct hfi_msg_event_notify_packet *pkt)
+		struct hfi_msg_event_notify_packet *pkt,
+		struct list_head *sessions, struct mutex *session_lock)
 {
+	struct hal_session *sess = NULL;
 	dprintk(VIDC_DBG, "RECVD:EVENT_NOTIFY");
 
 	if (!callback || !pkt ||
@@ -193,6 +195,7 @@
 		dprintk(VIDC_ERR, "Invalid Params");
 		return;
 	}
+	sess = (struct hal_session *)pkt->session_id;
 
 	switch (pkt->event_id) {
 	case HFI_EVENT_SYS_ERROR:
@@ -202,11 +205,14 @@
 		break;
 	case HFI_EVENT_SESSION_ERROR:
 		dprintk(VIDC_ERR, "HFI_EVENT_SESSION_ERROR");
-		hfi_process_session_error(callback, device_id, pkt);
+		if (!validate_session_pkt(sessions, sess, session_lock))
+			hfi_process_session_error(callback, device_id, pkt);
 		break;
 	case HFI_EVENT_SESSION_SEQUENCE_CHANGED:
 		dprintk(VIDC_INFO, "HFI_EVENT_SESSION_SEQUENCE_CHANGED");
-		hfi_process_sess_evt_seq_changed(callback, device_id, pkt);
+		if (!validate_session_pkt(sessions, sess, session_lock))
+			hfi_process_sess_evt_seq_changed(callback,
+				device_id, pkt);
 		break;
 	case HFI_EVENT_SESSION_PROPERTY_CHANGED:
 		dprintk(VIDC_INFO, "HFI_EVENT_SESSION_PROPERTY_CHANGED");
@@ -1139,7 +1145,7 @@
 		struct list_head *sessions, struct mutex *session_lock)
 {
 	u32 rc = 0;
-	struct hal_session *sess;
+	struct hal_session *sess = NULL;
 	if (!callback || !msg_hdr || msg_hdr->size <
 		VIDC_IFACEQ_MIN_PKT_SIZE) {
 		dprintk(VIDC_ERR, "hal_process_msg_packet:bad"
@@ -1148,21 +1154,16 @@
 		return rc;
 	}
 
-#define SANITIZE_SESSION_PKT(msg_pkt) ({ \
-		sess = (struct hal_session *) \
-				(((struct vidc_hal_session_cmd_pkt *) \
-				msg_pkt)->session_id); \
-		if (sanitize_session_pkt(sessions, sess, session_lock)) \
-			break; \
-	})
-
 	dprintk(VIDC_INFO, "Received: 0x%x in ", msg_hdr->packet);
 	rc = (u32) msg_hdr->packet;
+	sess = (struct hal_session *)((struct
+			vidc_hal_session_cmd_pkt*) msg_hdr)->session_id;
+
 	switch (msg_hdr->packet) {
 	case HFI_MSG_EVENT_NOTIFY:
-		SANITIZE_SESSION_PKT(msg_hdr);
 		hfi_process_event_notify(callback, device_id,
-			(struct hfi_msg_event_notify_packet *) msg_hdr);
+			(struct hfi_msg_event_notify_packet *) msg_hdr,
+			sessions, session_lock);
 		break;
 	case  HFI_MSG_SYS_INIT_DONE:
 		hfi_process_sys_init_done(callback, device_id,
@@ -1170,12 +1171,13 @@
 					msg_hdr);
 		break;
 	case HFI_MSG_SYS_IDLE:
+	case HFI_MSG_SYS_PC_PREP_DONE:
 		break;
 	case HFI_MSG_SYS_SESSION_INIT_DONE:
-		SANITIZE_SESSION_PKT(msg_hdr);
-		hfi_process_session_init_done(callback, device_id,
-			(struct hfi_msg_sys_session_init_done_packet *)
-					msg_hdr);
+		if (!validate_session_pkt(sessions, sess, session_lock))
+			hfi_process_session_init_done(callback, device_id,
+				(struct hfi_msg_sys_session_init_done_packet *)
+						msg_hdr);
 		break;
 	case HFI_MSG_SYS_PROPERTY_INFO:
 		hfi_process_sys_property_info(
@@ -1183,85 +1185,85 @@
 			msg_hdr);
 		break;
 	case HFI_MSG_SYS_SESSION_END_DONE:
-		SANITIZE_SESSION_PKT(msg_hdr);
-		hfi_process_session_end_done(callback, device_id,
-			(struct hfi_msg_sys_session_end_done_packet *)
-					msg_hdr);
+		if (!validate_session_pkt(sessions, sess, session_lock))
+			hfi_process_session_end_done(callback, device_id,
+				(struct hfi_msg_sys_session_end_done_packet *)
+						msg_hdr);
 		break;
 	case HFI_MSG_SESSION_LOAD_RESOURCES_DONE:
-		SANITIZE_SESSION_PKT(msg_hdr);
-		hfi_process_session_load_res_done(callback, device_id,
+		if (!validate_session_pkt(sessions, sess, session_lock))
+			hfi_process_session_load_res_done(callback, device_id,
 			(struct hfi_msg_session_load_resources_done_packet *)
-					msg_hdr);
+						msg_hdr);
 		break;
 	case HFI_MSG_SESSION_START_DONE:
-		SANITIZE_SESSION_PKT(msg_hdr);
-		hfi_process_session_start_done(callback, device_id,
-			(struct hfi_msg_session_start_done_packet *)
-					msg_hdr);
+		if (!validate_session_pkt(sessions, sess, session_lock))
+			hfi_process_session_start_done(callback, device_id,
+				(struct hfi_msg_session_start_done_packet *)
+						msg_hdr);
 		break;
 	case HFI_MSG_SESSION_STOP_DONE:
-		SANITIZE_SESSION_PKT(msg_hdr);
-		hfi_process_session_stop_done(callback, device_id,
-			(struct hfi_msg_session_stop_done_packet *)
-					msg_hdr);
+		if (!validate_session_pkt(sessions, sess, session_lock))
+			hfi_process_session_stop_done(callback, device_id,
+				(struct hfi_msg_session_stop_done_packet *)
+						msg_hdr);
 		break;
 	case HFI_MSG_SESSION_EMPTY_BUFFER_DONE:
-		SANITIZE_SESSION_PKT(msg_hdr);
-		hfi_process_session_etb_done(callback, device_id,
+		if (!validate_session_pkt(sessions, sess, session_lock))
+			hfi_process_session_etb_done(callback, device_id,
 			(struct hfi_msg_session_empty_buffer_done_packet *)
-					msg_hdr);
+						msg_hdr);
 		break;
 	case HFI_MSG_SESSION_FILL_BUFFER_DONE:
-		SANITIZE_SESSION_PKT(msg_hdr);
-		hfi_process_session_ftb_done(callback, device_id, msg_hdr);
+		if (!validate_session_pkt(sessions, sess, session_lock))
+			hfi_process_session_ftb_done(callback, device_id,
+						msg_hdr);
 		break;
 	case HFI_MSG_SESSION_FLUSH_DONE:
-		SANITIZE_SESSION_PKT(msg_hdr);
-		hfi_process_session_flush_done(callback, device_id,
-			(struct hfi_msg_session_flush_done_packet *)
-					msg_hdr);
+		if (!validate_session_pkt(sessions, sess, session_lock))
+			hfi_process_session_flush_done(callback, device_id,
+				(struct hfi_msg_session_flush_done_packet *)
+						msg_hdr);
 		break;
 	case HFI_MSG_SESSION_PROPERTY_INFO:
-		SANITIZE_SESSION_PKT(msg_hdr);
-		hfi_process_session_prop_info(callback, device_id,
-			(struct hfi_msg_session_property_info_packet *)
-					msg_hdr);
+		if (!validate_session_pkt(sessions, sess, session_lock))
+			hfi_process_session_prop_info(callback, device_id,
+				(struct hfi_msg_session_property_info_packet *)
+						msg_hdr);
 		break;
 	case HFI_MSG_SESSION_RELEASE_RESOURCES_DONE:
-		SANITIZE_SESSION_PKT(msg_hdr);
-		hfi_process_session_rel_res_done(callback, device_id,
+		if (!validate_session_pkt(sessions, sess, session_lock))
+			hfi_process_session_rel_res_done(callback, device_id,
 			(struct hfi_msg_session_release_resources_done_packet *)
-					msg_hdr);
+						msg_hdr);
 		break;
 	case HFI_MSG_SYS_RELEASE_RESOURCE:
 		hfi_process_sys_rel_resource_done(callback, device_id,
 			(struct hfi_msg_sys_release_resource_done_packet *)
-			msg_hdr);
+						msg_hdr);
 		break;
 	case HFI_MSG_SESSION_GET_SEQUENCE_HEADER_DONE:
-		SANITIZE_SESSION_PKT(msg_hdr);
-		hfi_process_session_get_seq_hdr_done(
+		if (!validate_session_pkt(sessions, sess, session_lock))
+			hfi_process_session_get_seq_hdr_done(
 			callback, device_id, (struct
 			hfi_msg_session_get_sequence_header_done_packet*)
-			msg_hdr);
+						msg_hdr);
 		break;
 	case HFI_MSG_SESSION_RELEASE_BUFFERS_DONE:
-		SANITIZE_SESSION_PKT(msg_hdr);
-		hfi_process_session_rel_buf_done(
-			callback, device_id, (struct
-			hfi_msg_session_release_buffers_done_packet*)
-			msg_hdr);
+		if (!validate_session_pkt(sessions, sess, session_lock))
+			hfi_process_session_rel_buf_done(callback, device_id,
+			(struct hfi_msg_session_release_buffers_done_packet *)
+						msg_hdr);
 		break;
 	case HFI_MSG_SYS_SESSION_ABORT_DONE:
-		SANITIZE_SESSION_PKT(msg_hdr);
-		hfi_process_session_abort_done(callback, device_id, (struct
-			hfi_msg_sys_session_abort_done_packet*) msg_hdr);
+		if (!validate_session_pkt(sessions, sess, session_lock))
+			hfi_process_session_abort_done(callback, device_id,
+			(struct hfi_msg_sys_session_abort_done_packet *)
+						msg_hdr);
 		break;
 	default:
 		dprintk(VIDC_DBG, "UNKNOWN_MSG_TYPE : %d", msg_hdr->packet);
 		break;
 	}
-#undef SANITIZE_SESSION_PKT
 	return rc;
 }
diff --git a/drivers/media/platform/msm/vidc/msm_v4l2_vidc.c b/drivers/media/platform/msm/vidc/msm_v4l2_vidc.c
index 50149dc..e335ff0 100644
--- a/drivers/media/platform/msm/vidc/msm_v4l2_vidc.c
+++ b/drivers/media/platform/msm/vidc/msm_v4l2_vidc.c
@@ -36,6 +36,8 @@
 
 struct msm_vidc_drv *vidc_driver;
 
+uint32_t msm_vidc_pwr_collapse_delay = 2000;
+
 struct buffer_info {
 	struct list_head list;
 	int type;
@@ -781,6 +783,31 @@
 
 static DEVICE_ATTR(link_name, 0644, msm_vidc_link_name_show, NULL);
 
+static ssize_t store_pwr_collapse_delay(struct device *dev,
+		struct device_attribute *attr,
+		const char *buf, size_t count)
+{
+	unsigned long val = 0;
+	int rc = 0;
+	rc = kstrtoul(buf, 0, &val);
+	if (rc)
+		return rc;
+	else if (val == 0)
+		return -EINVAL;
+	msm_vidc_pwr_collapse_delay = val;
+	return count;
+}
+
+static ssize_t show_pwr_collapse_delay(struct device *dev,
+		struct device_attribute *attr,
+		char *buf)
+{
+	return snprintf(buf, PAGE_SIZE, "%u\n", msm_vidc_pwr_collapse_delay);
+}
+
+static DEVICE_ATTR(pwr_collapse_delay, 0644, show_pwr_collapse_delay,
+		store_pwr_collapse_delay);
+
 static int __devinit msm_vidc_probe(struct platform_device *pdev)
 {
 	int rc = 0;
@@ -800,6 +827,12 @@
 		dprintk(VIDC_ERR, "Failed to init core\n");
 		goto err_v4l2_register;
 	}
+	rc = device_create_file(&pdev->dev, &dev_attr_pwr_collapse_delay);
+	if (rc) {
+		dprintk(VIDC_ERR,
+				"Failed to create pwr_collapse_delay sysfs node");
+		goto err_v4l2_register;
+	}
 	if (core->hfi_type == VIDC_HFI_Q6) {
 		dprintk(VIDC_ERR, "Q6 hfi device probe called\n");
 		nr += MSM_VIDC_MAX_DEVICES;
diff --git a/drivers/media/platform/msm/vidc/msm_vidc.c b/drivers/media/platform/msm/vidc/msm_vidc.c
index b6d031a..10a0eac 100644
--- a/drivers/media/platform/msm/vidc/msm_vidc.c
+++ b/drivers/media/platform/msm/vidc/msm_vidc.c
@@ -497,9 +497,9 @@
 
 	setup_event_queue(inst, &core->vdev[core_id].vdev);
 
-	mutex_lock(&core->lock);
+	mutex_lock(&core->sync_lock);
 	list_add_tail(&inst->list, &core->instances);
-	mutex_unlock(&core->lock);
+	mutex_unlock(&core->sync_lock);
 	return inst;
 fail_init:
 	vb2_queue_release(&inst->bufq[OUTPUT_PORT].vb2_bufq);
diff --git a/drivers/media/platform/msm/vidc/msm_vidc_common.c b/drivers/media/platform/msm/vidc/msm_vidc_common.c
index 09f67a2..122f0e9 100644
--- a/drivers/media/platform/msm/vidc/msm_vidc_common.c
+++ b/drivers/media/platform/msm/vidc/msm_vidc_common.c
@@ -22,8 +22,6 @@
 #include "msm_smem.h"
 #include "msm_vidc_debug.h"
 
-#define HW_RESPONSE_TIMEOUT 1000
-
 #define IS_ALREADY_IN_STATE(__p, __d) ({\
 	int __rc = (__p >= __d);\
 	__rc; \
@@ -362,7 +360,7 @@
 	int rc = 0;
 	rc = wait_for_completion_timeout(
 		&inst->completions[SESSION_MSG_INDEX(cmd)],
-		msecs_to_jiffies(HW_RESPONSE_TIMEOUT));
+		msecs_to_jiffies(msm_vidc_hw_rsp_timeout));
 	if (!rc) {
 		dprintk(VIDC_ERR, "Wait interrupted or timeout: %d\n", rc);
 		msm_comm_recover_from_session_error(inst);
@@ -1128,7 +1126,7 @@
 	}
 	rc = wait_for_completion_timeout(
 		&core->completions[SYS_MSG_INDEX(RELEASE_RESOURCE_DONE)],
-		msecs_to_jiffies(HW_RESPONSE_TIMEOUT));
+		msecs_to_jiffies(msm_vidc_hw_rsp_timeout));
 	if (!rc) {
 		dprintk(VIDC_ERR, "Wait interrupted or timeout: %d\n", rc);
 		rc = -EIO;
@@ -1150,7 +1148,7 @@
 	dprintk(VIDC_DBG, "Waiting for SYS_INIT_DONE\n");
 	rc = wait_for_completion_timeout(
 		&core->completions[SYS_MSG_INDEX(SYS_INIT_DONE)],
-		msecs_to_jiffies(HW_RESPONSE_TIMEOUT));
+		msecs_to_jiffies(msm_vidc_hw_rsp_timeout));
 	if (!rc) {
 		dprintk(VIDC_ERR, "Wait interrupted or timeout: %d\n", rc);
 		rc = -EIO;
@@ -1431,8 +1429,11 @@
 		return -EINVAL;
 	}
 
+	mutex_lock(&inst->core->sync_lock);
 	num_mbs_per_sec = msm_comm_get_load(inst->core, MSM_VIDC_DECODER);
 	num_mbs_per_sec += msm_comm_get_load(inst->core, MSM_VIDC_ENCODER);
+	mutex_unlock(&inst->core->sync_lock);
+
 	if (num_mbs_per_sec > inst->core->resources.max_load) {
 		dprintk(VIDC_ERR, "HW is overloaded, needed: %d max: %d\n",
 			num_mbs_per_sec, inst->core->resources.max_load);
@@ -1451,8 +1452,10 @@
 	if (inst->core->resources.has_ocmem) {
 		ocmem_sz = get_ocmem_requirement(inst->prop.height,
 						inst->prop.width);
+		mutex_lock(&inst->core->sync_lock);
 		rc = msm_comm_scale_bus(inst->core, inst->session_type,
 					OCMEM_MEM);
+		mutex_unlock(&inst->core->sync_lock);
 		if (!rc) {
 			mutex_lock(&inst->core->sync_lock);
 			rc = call_hfi_op(hdev, alloc_ocmem,
@@ -2111,7 +2114,7 @@
 	}
 	rc = wait_for_completion_timeout(
 		&inst->completions[SESSION_MSG_INDEX(SESSION_PROPERTY_INFO)],
-		msecs_to_jiffies(HW_RESPONSE_TIMEOUT));
+		msecs_to_jiffies(msm_vidc_hw_rsp_timeout));
 	if (!rc) {
 		dprintk(VIDC_ERR,
 			"Wait interrupted or timeout: %d\n", rc);
@@ -2698,7 +2701,7 @@
 	}
 	rc = wait_for_completion_timeout(
 		&inst->completions[SESSION_MSG_INDEX(SESSION_ABORT_DONE)],
-		msecs_to_jiffies(HW_RESPONSE_TIMEOUT));
+		msecs_to_jiffies(msm_vidc_hw_rsp_timeout));
 	if (!rc) {
 		dprintk(VIDC_ERR, "%s: Wait interrupted or timeout: %d\n",
 			__func__, rc);
diff --git a/drivers/media/platform/msm/vidc/msm_vidc_debug.c b/drivers/media/platform/msm/vidc/msm_vidc_debug.c
index bea9070..03136ae 100644
--- a/drivers/media/platform/msm/vidc/msm_vidc_debug.c
+++ b/drivers/media/platform/msm/vidc/msm_vidc_debug.c
@@ -21,6 +21,7 @@
 int msm_fw_debug_mode = 0x1;
 int msm_fw_low_power_mode = 0x1;
 int msm_vp8_low_tier = 0x1;
+int msm_vidc_hw_rsp_timeout = 1000;
 
 struct debug_buffer {
 	char ptr[MAX_DBG_BUF_SIZE];
@@ -177,6 +178,11 @@
 		dprintk(VIDC_ERR, "debugfs_create_file: fail\n");
 		goto failed_create_dir;
 	}
+	if (!debugfs_create_u32("hw_rsp_timeout", S_IRUGO | S_IWUSR,
+			parent, &msm_vidc_hw_rsp_timeout)) {
+		dprintk(VIDC_ERR, "debugfs_create_file: fail\n");
+		goto failed_create_dir;
+	}
 failed_create_dir:
 	return dir;
 }
diff --git a/drivers/media/platform/msm/vidc/msm_vidc_debug.h b/drivers/media/platform/msm/vidc/msm_vidc_debug.h
index 5b572c9..c9ecc6f 100644
--- a/drivers/media/platform/msm/vidc/msm_vidc_debug.h
+++ b/drivers/media/platform/msm/vidc/msm_vidc_debug.h
@@ -53,6 +53,7 @@
 extern int msm_fw_debug_mode;
 extern int msm_fw_low_power_mode;
 extern int msm_vp8_low_tier;
+extern int msm_vidc_hw_rsp_timeout;
 
 #define dprintk(__level, __fmt, arg...)	\
 	do { \
diff --git a/drivers/media/platform/msm/vidc/msm_vidc_resources.h b/drivers/media/platform/msm/vidc/msm_vidc_resources.h
index 8176ea5..e75b410 100644
--- a/drivers/media/platform/msm/vidc/msm_vidc_resources.h
+++ b/drivers/media/platform/msm/vidc/msm_vidc_resources.h
@@ -87,5 +87,7 @@
 	return 0;
 }
 
+extern uint32_t msm_vidc_pwr_collapse_delay;
+
 #endif
 
diff --git a/drivers/media/platform/msm/vidc/venus_hfi.c b/drivers/media/platform/msm/vidc/venus_hfi.c
index 99c51bf..aaf1f50 100644
--- a/drivers/media/platform/msm/vidc/venus_hfi.c
+++ b/drivers/media/platform/msm/vidc/venus_hfi.c
@@ -62,6 +62,18 @@
 	int ret;
 };
 
+#define TZBSP_VIDEO_SET_STATE 0xa
+
+enum tzbsp_video_state {
+	TZBSP_VIDEO_STATE_SUSPEND = 0,
+	TZBSP_VIDEO_STATE_RESUME
+};
+
+struct tzbsp_video_set_state_req {
+	u32 state; /*shoud be tzbsp_video_state enum value*/
+	u32 spare; /*reserved for future, should be zero*/
+};
+
 static void venus_hfi_dump_packet(u8 *packet)
 {
 	u32 c = 0, packet_size = *(u32 *)packet;
@@ -492,38 +504,320 @@
 	rmb();
 	return rc;
 }
-static inline void venus_hfi_clk_gating_on(struct venus_hfi_device *device)
+
+static int venus_hfi_core_start_cpu(struct venus_hfi_device *device)
 {
+	u32 ctrl_status = 0, count = 0, rc = 0;
+	int max_tries = 100;
+	venus_hfi_write_register(device,
+			VIDC_WRAPPER_INTR_MASK, 0x8, 0);
+	venus_hfi_write_register(device,
+			VIDC_CPU_CS_SCIACMDARG3, 1, 0);
+
+	while (!ctrl_status && count < max_tries) {
+		ctrl_status = venus_hfi_read_register(
+				device,
+				VIDC_CPU_CS_SCIACMDARG0);
+		if ((ctrl_status & 0xFE) == 0x4) {
+			dprintk(VIDC_ERR, "invalid setting for UC_REGION\n");
+			break;
+		}
+		usleep_range(500, 1000);
+		count++;
+	}
+	if (count >= max_tries)
+		rc = -ETIME;
+	return rc;
+}
+
+static int venus_hfi_iommu_attach(struct venus_hfi_device *device)
+{
+	int rc = 0;
+	struct iommu_domain *domain;
 	int i;
-	struct venus_core_clock *cl;
-	if (!device) {
-		dprintk(VIDC_ERR, "Invalid params: %p\n", device);
+	struct iommu_set *iommu_group_set;
+	struct iommu_group *group;
+	struct iommu_info *iommu_map;
+
+	if (!device || !device->res)
+		return -EINVAL;
+
+	iommu_group_set = &device->res->iommu_group_set;
+	for (i = 0; i < iommu_group_set->count; i++) {
+		iommu_map = &iommu_group_set->iommu_maps[i];
+		group = iommu_map->group;
+		domain = msm_get_iommu_domain(iommu_map->domain);
+		if (IS_ERR_OR_NULL(domain)) {
+			dprintk(VIDC_ERR,
+				"Failed to get domain: %s\n", iommu_map->name);
+			rc = PTR_ERR(domain);
+			break;
+		}
+		rc = iommu_attach_group(domain, group);
+		if (rc) {
+			dprintk(VIDC_ERR,
+				"IOMMU attach failed: %s\n", iommu_map->name);
+			break;
+		}
+	}
+	if (i < iommu_group_set->count) {
+		i--;
+		for (; i >= 0; i--) {
+			iommu_map = &iommu_group_set->iommu_maps[i];
+			group = iommu_map->group;
+			domain = msm_get_iommu_domain(iommu_map->domain);
+			if (group && domain)
+				iommu_detach_group(domain, group);
+		}
+	}
+	return rc;
+}
+
+static void venus_hfi_iommu_detach(struct venus_hfi_device *device)
+{
+	struct iommu_group *group;
+	struct iommu_domain *domain;
+	struct iommu_set *iommu_group_set;
+	struct iommu_info *iommu_map;
+	int i;
+
+	if (!device || !device->res) {
+		dprintk(VIDC_ERR, "Invalid paramter: %p\n", device);
 		return;
 	}
-	if (!device->clocks_enabled) {
-		dprintk(VIDC_DBG, "Clocks are already disabled");
-		goto already_disabled;
+
+	iommu_group_set = &device->res->iommu_group_set;
+	for (i = 0; i < iommu_group_set->count; i++) {
+		iommu_map = &iommu_group_set->iommu_maps[i];
+		group = iommu_map->group;
+		domain = msm_get_iommu_domain(iommu_map->domain);
+		if (group && domain)
+			iommu_detach_group(domain, group);
 	}
-	for (i = 0; i <= device->clk_gating_level; i++) {
-		cl = &device->resources.clock[i];
-		clk_disable(cl->clk);
-	}
-already_disabled:
-	device->clocks_enabled = 0;
 }
-static inline int venus_hfi_clk_gating_off(struct venus_hfi_device *device)
+
+static int venus_hfi_unvote_bus(void *dev,
+				enum session_type type, enum mem_type mtype)
+{
+	int rc = 0;
+	u32 handle = 0;
+	struct venus_hfi_device *device = dev;
+
+	if (!device) {
+		dprintk(VIDC_ERR, "%s invalid device handle %p",
+			__func__, device);
+		return -EINVAL;
+	}
+
+	if (mtype & DDR_MEM)
+		handle = device->resources.bus_info.ddr_handle[type];
+	if (mtype & OCMEM_MEM)
+		handle = device->resources.bus_info.ocmem_handle[type];
+
+	if (handle) {
+		rc = msm_bus_scale_client_update_request(
+				handle, 0);
+		if (rc)
+			dprintk(VIDC_ERR, "Failed to unvote bus: %d\n", rc);
+	} else {
+		dprintk(VIDC_ERR, "Failed to unvote bus, mtype: %d\n",
+				mtype);
+		rc = -EINVAL;
+	}
+	return rc;
+}
+
+static void venus_hfi_unvote_buses(void *dev, enum mem_type mtype)
 {
 	int i;
-	struct venus_core_clock *cl;
+	struct venus_hfi_device *device = dev;
+
+	if (!device) {
+		dprintk(VIDC_ERR, "%s invalid parameters", __func__);
+		return;
+	}
+
+	for (i = 0; i < MSM_VIDC_MAX_DEVICES; i++) {
+		if ((mtype & DDR_MEM) &&
+			venus_hfi_unvote_bus(device, i, DDR_MEM))
+			dprintk(VIDC_WARN,
+				"Failed to unvote for DDR accesses\n");
+
+		if ((mtype & OCMEM_MEM) &&
+			venus_hfi_unvote_bus(device, i, OCMEM_MEM))
+			dprintk(VIDC_WARN,
+				"Failed to unvote for OCMEM accesses\n");
+	}
+}
+
+static const u32 venus_hfi_bus_table[] = {
+	36000,
+	110400,
+	244800,
+	489000,
+	783360,
+	979200,
+};
+
+static int venus_hfi_get_bus_vector(struct venus_hfi_device *device, int load,
+			enum session_type type, enum mem_type mtype)
+{
+	int num_rows = sizeof(venus_hfi_bus_table)/(sizeof(u32));
+	int i, j;
+	int idx = 0;
+
+	if (!device || (mtype != DDR_MEM && mtype != OCMEM_MEM) ||
+		(type != MSM_VIDC_ENCODER && type != MSM_VIDC_DECODER)) {
+		dprintk(VIDC_ERR, "%s invalid params", __func__);
+		return -EINVAL;
+	}
+
+	for (i = 0; i < num_rows; i++) {
+		if (load <= venus_hfi_bus_table[i])
+			break;
+	}
+
+	if (type == MSM_VIDC_ENCODER)
+		idx = (mtype == DDR_MEM) ? BUS_IDX_ENC_DDR : BUS_IDX_ENC_OCMEM;
+	else
+		idx = (mtype == DDR_MEM) ? BUS_IDX_DEC_DDR : BUS_IDX_DEC_OCMEM;
+
+	j = clamp(i, 0, num_rows-1) + 1;
+
+	/* Ensure bus index remains within the supported range,
+	* as specified in the device dtsi file */
+	j = clamp(j, 0, device->res->bus_pdata[idx].num_usecases - 1);
+
+	dprintk(VIDC_DBG, "Required bus = %d\n", j);
+	return j;
+}
+
+static int venus_hfi_scale_bus(void *dev, int load,
+				enum session_type type, enum mem_type mtype)
+{
 	int rc = 0;
+	u32 handle = 0;
+	struct venus_hfi_device *device = dev;
+	int bus_vector = 0;
+
+	if (!device) {
+		dprintk(VIDC_ERR, "%s invalid device handle %p",
+			__func__, device);
+		return -EINVAL;
+	}
+
+	if (mtype & DDR_MEM)
+		handle = device->resources.bus_info.ddr_handle[type];
+	if (mtype & OCMEM_MEM)
+		handle = device->resources.bus_info.ocmem_handle[type];
+
+	if (handle) {
+		bus_vector = venus_hfi_get_bus_vector(device, load,
+				type, mtype);
+		if (bus_vector < 0) {
+			dprintk(VIDC_ERR, "Failed to get bus vector\n");
+			return -EINVAL;
+		}
+		device->bus_load[type] = load;
+		rc = msm_bus_scale_client_update_request(handle, bus_vector);
+		if (rc)
+			dprintk(VIDC_ERR, "Failed to scale bus: %d\n", rc);
+	} else {
+		dprintk(VIDC_ERR, "Failed to scale bus, mtype: %d\n",
+				mtype);
+		rc = -EINVAL;
+	}
+
+	return rc;
+}
+
+static int venus_hfi_scale_buses(void *dev, enum mem_type mtype)
+{
+	int i, rc = 0;
+	struct venus_hfi_device *device = dev;
+
+	if (!device) {
+		dprintk(VIDC_ERR, "%s invalid parameters", __func__);
+		return -EINVAL;
+	}
+	for (i = 0; i < MSM_VIDC_MAX_DEVICES; i++) {
+		if (mtype & DDR_MEM) {
+			rc = venus_hfi_scale_bus(device, device->bus_load[i],
+					i, DDR_MEM);
+			if (rc) {
+				dprintk(VIDC_ERR,
+						"Failed to scale bus for DDR accesses, session type %d, load %u\n",
+						i, device->bus_load[i]);
+				goto err_scale_bus;
+			}
+		}
+
+		if (mtype & OCMEM_MEM) {
+			rc = venus_hfi_scale_bus(device, device->bus_load[i],
+					i, OCMEM_MEM);
+			if (rc) {
+				dprintk(VIDC_ERR,
+						"Failed to scale bus for OCMEM accesses, session type %d, load %u\n",
+						i, device->bus_load[i]);
+				goto err_scale_bus;
+			}
+		}
+	}
+err_scale_bus:
+	return rc;
+}
+
+static inline int venus_hfi_tzbsp_set_video_state(enum tzbsp_video_state state)
+{
+	struct tzbsp_video_set_state_req cmd = {0};
+	int tzbsp_rsp = 0;
+	int rc = 0;
+	cmd.state = state;
+	cmd.spare = 0;
+	rc = scm_call(SCM_SVC_BOOT, TZBSP_VIDEO_SET_STATE, &cmd, sizeof(cmd),
+			&tzbsp_rsp, sizeof(tzbsp_rsp));
+	if (rc) {
+		dprintk(VIDC_ERR, "Failed scm_call %d\n", rc);
+		return rc;
+	}
+	dprintk(VIDC_DBG, "Set state %d, resp %d\n", state, tzbsp_rsp);
+	if (tzbsp_rsp) {
+		dprintk(VIDC_ERR,
+				"Failed to set video core state to suspend: %d\n",
+				tzbsp_rsp);
+		return -EINVAL;
+	}
+	return 0;
+}
+
+static inline int venus_hfi_reset_core(struct venus_hfi_device *device)
+{
+	int rc = 0;
+	venus_hfi_write_register(device,
+			VIDC_CTRL_INIT, 0x1, 0);
+	rc = venus_hfi_core_start_cpu(device);
+	if (rc)
+		dprintk(VIDC_ERR, "Failed to start core");
+	return rc;
+}
+
+
+/*Calling function is responsible to acquire device->clk_pwr_lock*/
+static inline int venus_hfi_clk_enable(struct venus_hfi_device *device)
+{
+	int rc = 0;
+	int i;
+	struct venus_core_clock *cl;
+
 	if (!device) {
 		dprintk(VIDC_ERR, "Invalid params: %p\n", device);
 		return -EINVAL;
 	}
 	if (device->clocks_enabled) {
-		dprintk(VIDC_DBG, "Clocks are already enabled");
-		goto already_enabled;
+		dprintk(VIDC_DBG, "Clocks already enabled");
+		return 0;
 	}
+
 	for (i = 0; i <= device->clk_gating_level; i++) {
 		cl = &device->resources.clock[i];
 		rc = clk_enable(cl->clk);
@@ -534,17 +828,180 @@
 			dprintk(VIDC_DBG, "Clock: %s enabled\n", cl->name);
 		}
 	}
-already_enabled:
 	device->clocks_enabled = 1;
-	return rc;
+	return 0;
 fail_clk_enable:
-	for (; i >= 0; i--) {
+	for (i--; i >= 0; i--) {
 		cl = &device->resources.clock[i];
 		clk_disable(cl->clk);
 	}
 	return rc;
 }
 
+/*Calling function is responsible to acquire device->clk_pwr_lock*/
+static inline void venus_hfi_clk_disable(struct venus_hfi_device *device)
+{
+	int i;
+	struct venus_core_clock *cl;
+
+	if (!device) {
+		dprintk(VIDC_ERR, "Invalid params: %p\n", device);
+		return;
+	}
+	if (!device->clocks_enabled) {
+		dprintk(VIDC_DBG, "Clocks already disabled");
+		return;
+	}
+
+	for (i = 0; i <= device->clk_gating_level; i++) {
+		cl = &device->resources.clock[i];
+		clk_disable(cl->clk);
+	}
+	device->clocks_enabled = 0;
+}
+
+static DECLARE_COMPLETION(pc_prep_done);
+
+static inline int venus_hfi_power_off(struct venus_hfi_device *device)
+{
+	int rc = 0;
+	if (!device) {
+		dprintk(VIDC_ERR, "Invalid params: %p\n", device);
+		return -EINVAL;
+	}
+	if (!device->power_enabled) {
+		dprintk(VIDC_DBG, "Power already disabled");
+		goto already_disabled;
+	}
+
+	/*Temporarily enable clocks to make TZ call.*/
+	rc = venus_hfi_clk_enable(device);
+	if (rc) {
+		dprintk(VIDC_ERR, "Failed to enable clocks before TZ call");
+		return rc;
+	}
+	rc = venus_hfi_tzbsp_set_video_state(TZBSP_VIDEO_STATE_SUSPEND);
+	if (rc) {
+		dprintk(VIDC_ERR, "Failed to suspend video core %d\n", rc);
+		venus_hfi_clk_disable(device);
+		return rc;
+	}
+	venus_hfi_clk_disable(device);
+	venus_hfi_iommu_detach(device);
+	rc = regulator_disable(device->gdsc);
+	if (rc) {
+		dprintk(VIDC_ERR, "Failed to disable GDSC, %d", rc);
+		return rc;
+	}
+	if (device->res->has_ocmem)
+		venus_hfi_unvote_buses(device, DDR_MEM|OCMEM_MEM);
+	else
+		venus_hfi_unvote_buses(device, DDR_MEM);
+
+	device->power_enabled = 0;
+already_disabled:
+	return rc;
+}
+
+static inline int venus_hfi_power_on(struct venus_hfi_device *device)
+{
+	int rc = 0;
+	if (!device) {
+		dprintk(VIDC_ERR, "Invalid params: %p\n", device);
+		return -EINVAL;
+	}
+
+	if (device->res->has_ocmem)
+		rc = venus_hfi_scale_buses(device, DDR_MEM|OCMEM_MEM);
+	else
+		rc = venus_hfi_scale_buses(device, DDR_MEM);
+	if (rc) {
+		dprintk(VIDC_ERR, "Failed to scale buses");
+		goto err_scale_buses;
+	}
+
+	rc = regulator_enable(device->gdsc);
+	if (rc) {
+		dprintk(VIDC_ERR, "Failed to enable GDSC %d", rc);
+		goto err_enable_gdsc;
+	}
+
+	rc = venus_hfi_iommu_attach(device);
+	if (rc) {
+		dprintk(VIDC_ERR, "Failed to attach iommu after power on");
+		goto err_iommu_attach;
+	}
+
+	rc = venus_hfi_clk_enable(device);
+	if (rc) {
+		dprintk(VIDC_ERR, "Failed to enable clocks");
+		goto err_enable_clk;
+	}
+
+	rc = venus_hfi_tzbsp_set_video_state(TZBSP_VIDEO_STATE_RESUME);
+	if (rc) {
+		dprintk(VIDC_ERR, "Failed to resume video core %d\n", rc);
+		goto err_set_video_state;
+	}
+	rc = venus_hfi_reset_core(device);
+	if (rc) {
+		dprintk(VIDC_ERR, "Failed to reset venus core");
+		goto err_reset_core;
+	}
+	device->power_enabled = 1;
+	return rc;
+err_reset_core:
+	venus_hfi_tzbsp_set_video_state(TZBSP_VIDEO_STATE_SUSPEND);
+err_set_video_state:
+	venus_hfi_clk_disable(device);
+err_enable_clk:
+	venus_hfi_iommu_detach(device);
+err_iommu_attach:
+	regulator_disable(device->gdsc);
+err_enable_gdsc:
+	if (device->res->has_ocmem)
+		venus_hfi_unvote_buses(device, DDR_MEM|OCMEM_MEM);
+	else
+		venus_hfi_unvote_buses(device, DDR_MEM);
+err_scale_buses:
+	return rc;
+}
+
+static void venus_hfi_pm_hndlr(struct work_struct *work);
+static DECLARE_DELAYED_WORK(venus_hfi_pm_work, venus_hfi_pm_hndlr);
+
+static inline int venus_hfi_clk_gating_off(struct venus_hfi_device *device)
+{
+	int rc = 0;
+	if (!device) {
+		dprintk(VIDC_ERR, "Invalid params: %p\n", device);
+		return -EINVAL;
+	}
+	if (device->clocks_enabled) {
+		dprintk(VIDC_DBG, "Clocks are already enabled");
+		goto already_enabled;
+	}
+	cancel_delayed_work(&venus_hfi_pm_work);
+	if (!device->power_enabled) {
+		/*This will enable clocks as well*/
+		rc = venus_hfi_power_on(device);
+		if (rc) {
+			dprintk(VIDC_ERR, "Failed venus power on");
+			goto fail_clk_power_on;
+		}
+	} else {
+		rc = venus_hfi_clk_enable(device);
+		if (rc) {
+			dprintk(VIDC_ERR, "Failed venus clock enable");
+			goto fail_clk_power_on;
+		}
+	}
+already_enabled:
+	device->clocks_enabled = 1;
+fail_clk_power_on:
+	return rc;
+}
+
 static unsigned long venus_hfi_get_clock_rate(struct venus_core_clock *clock,
 	int num_mbs_per_sec)
 {
@@ -569,7 +1026,7 @@
 		dprintk(VIDC_ERR, "Invalid args: %p\n", device);
 		return -EINVAL;
 	}
-	device->load = load;
+	device->clk_load = load;
 	rc = clk_set_rate(device->resources.clock[VCODEC_CLK].clk,
 		venus_hfi_get_clock_rate(&device->resources.clock[VCODEC_CLK],
 			load));
@@ -595,14 +1052,14 @@
 		dprintk(VIDC_ERR, "cannot write to shared Q's");
 		goto err_q_null;
 	}
-	mutex_lock(&device->clock_lock);
+	mutex_lock(&device->clk_pwr_lock);
 	result = venus_hfi_clk_gating_off(device);
 	if (result) {
 		dprintk(VIDC_ERR, "%s : Clock enable failed\n",
 			__func__);
 		goto err_q_write;
 	}
-	result = venus_hfi_scale_clocks(device, device->load);
+	result = venus_hfi_scale_clocks(device, device->clk_load);
 	if (result) {
 		dprintk(VIDC_ERR, "Clock scaling failed\n");
 		goto err_q_write;
@@ -618,7 +1075,7 @@
 		dprintk(VIDC_ERR, "venus_hfi_iface_cmdq_write:queue_full");
 	}
 err_q_write:
-	mutex_unlock(&device->clock_lock);
+	mutex_unlock(&device->clk_pwr_lock);
 err_q_null:
 	mutex_unlock(&device->write_lock);
 	return result;
@@ -642,7 +1099,7 @@
 		goto read_error_null;
 	}
 	q_info = &device->iface_queues[VIDC_IFACEQ_MSGQ_IDX];
-	mutex_lock(&device->clock_lock);
+	mutex_lock(&device->clk_pwr_lock);
 	rc = venus_hfi_clk_gating_off(device);
 	if (rc) {
 		dprintk(VIDC_ERR,
@@ -661,7 +1118,7 @@
 		rc = -ENODATA;
 	}
 read_error:
-	mutex_unlock(&device->clock_lock);
+	mutex_unlock(&device->clk_pwr_lock);
 read_error_null:
 	mutex_unlock(&device->read_lock);
 	return rc;
@@ -684,7 +1141,7 @@
 		rc = -ENODATA;
 		goto dbg_error_null;
 	}
-	mutex_lock(&device->clock_lock);
+	mutex_lock(&device->clk_pwr_lock);
 	rc = venus_hfi_clk_gating_off(device);
 	if (rc) {
 		dprintk(VIDC_ERR,
@@ -704,7 +1161,7 @@
 		rc = -ENODATA;
 	}
 dbg_error:
-	mutex_unlock(&device->clock_lock);
+	mutex_unlock(&device->clk_pwr_lock);
 dbg_error_null:
 	mutex_unlock(&device->read_lock);
 	return rc;
@@ -954,31 +1411,6 @@
 	return -ENOMEM;
 }
 
-static int venus_hfi_core_start_cpu(struct venus_hfi_device *device)
-{
-	u32 ctrl_status = 0, count = 0, rc = 0;
-	int max_tries = 100;
-	venus_hfi_write_register(device,
-			VIDC_WRAPPER_INTR_MASK, 0x8, 0);
-	venus_hfi_write_register(device,
-			VIDC_CPU_CS_SCIACMDARG3, 1, 0);
-
-	while (!ctrl_status && count < max_tries) {
-		ctrl_status = venus_hfi_read_register(
-				device,
-				VIDC_CPU_CS_SCIACMDARG0);
-		if ((ctrl_status & 0xFE) == 0x4) {
-			dprintk(VIDC_ERR, "invalid setting for UC_REGION\n");
-			break;
-		}
-		usleep_range(500, 1000);
-		count++;
-	}
-	if (count >= max_tries)
-		rc = -ETIME;
-	return rc;
-}
-
 static void venus_hfi_set_registers(struct venus_hfi_device *device)
 {
 	struct reg_set *reg_set;
@@ -1111,12 +1543,12 @@
 		return -ENODEV;
 	}
 	if (dev->hal_client) {
-		mutex_lock(&dev->clock_lock);
+		mutex_lock(&dev->clk_pwr_lock);
 		rc = venus_hfi_clk_gating_off(device);
 		if (rc) {
 			dprintk(VIDC_ERR,
 				"%s : Clock enable failed\n", __func__);
-			mutex_unlock(&dev->clock_lock);
+			mutex_unlock(&dev->clk_pwr_lock);
 			return -EIO;
 		}
 		venus_hfi_write_register(dev,
@@ -1124,38 +1556,12 @@
 		if (!(dev->intr_status & VIDC_WRAPPER_INTR_STATUS_A2HWD_BMSK))
 			disable_irq_nosync(dev->hal_data->irq);
 		dev->intr_status = 0;
-		mutex_unlock(&dev->clock_lock);
+		mutex_unlock(&dev->clk_pwr_lock);
 	}
 	dprintk(VIDC_INFO, "HAL exited\n");
 	return 0;
 }
 
-int venus_hfi_core_pc_prep(void *device)
-{
-	struct hfi_cmd_sys_pc_prep_packet pkt;
-	int rc = 0;
-	struct venus_hfi_device *dev;
-
-	if (device) {
-		dev = device;
-	} else {
-		dprintk(VIDC_ERR, "invalid device");
-		return -ENODEV;
-	}
-
-	rc = create_pkt_cmd_sys_pc_prep(&pkt);
-	if (rc) {
-		dprintk(VIDC_ERR, "Failed to create sys pc prep pkt");
-		goto err_create_pkt;
-	}
-
-	if (venus_hfi_iface_cmdq_write(dev, &pkt))
-		rc = -ENOTEMPTY;
-
-err_create_pkt:
-	return rc;
-}
-
 static void venus_hfi_core_clear_interrupt(struct venus_hfi_device *device)
 {
 	u32 intr_status = 0;
@@ -1163,12 +1569,12 @@
 
 	if (!device->callback)
 		return;
-	mutex_lock(&device->clock_lock);
+	mutex_lock(&device->clk_pwr_lock);
 	rc = venus_hfi_clk_gating_off(device);
 	if (rc) {
 		dprintk(VIDC_ERR,
 			"%s : Clock enable failed\n", __func__);
-		mutex_unlock(&device->clock_lock);
+		mutex_unlock(&device->clk_pwr_lock);
 		return;
 	}
 	intr_status = venus_hfi_read_register(
@@ -1192,7 +1598,7 @@
 			VIDC_CPU_CS_A2HSOFTINTCLR, 1, 0);
 	venus_hfi_write_register(device,
 			VIDC_WRAPPER_INTR_CLEAR, intr_status, 0);
-	mutex_unlock(&device->clock_lock);
+	mutex_unlock(&device->clk_pwr_lock);
 	dprintk(VIDC_DBG, "Cleared WRAPPER/A2H interrupt");
 }
 
@@ -1930,6 +2336,91 @@
 	return rc;
 }
 
+static int venus_hfi_core_pc_prep(void *device)
+{
+	struct hfi_cmd_sys_pc_prep_packet pkt;
+	int rc = 0;
+	struct venus_hfi_device *dev;
+
+	if (device) {
+		dev = device;
+	} else {
+		dprintk(VIDC_ERR, "invalid device");
+		return -ENODEV;
+	}
+
+	rc = create_pkt_cmd_sys_pc_prep(&pkt);
+	if (rc) {
+		dprintk(VIDC_ERR, "Failed to create sys pc prep pkt");
+		goto err_create_pkt;
+	}
+
+	if (venus_hfi_iface_cmdq_write(dev, &pkt))
+		rc = -ENOTEMPTY;
+
+err_create_pkt:
+	return rc;
+}
+
+
+static void venus_hfi_pm_hndlr(struct work_struct *work)
+{
+	int rc = 0;
+	struct venus_hfi_device *device = list_first_entry(
+			&hal_ctxt.dev_head, struct venus_hfi_device, list);
+	mutex_lock(&device->clk_pwr_lock);
+	if (device->clocks_enabled || !device->power_enabled) {
+		dprintk(VIDC_DBG,
+				"Clocks status: %d, Power status: %d, ignore power off\n",
+				device->clocks_enabled, device->power_enabled);
+		goto clks_enabled;
+	}
+	mutex_unlock(&device->clk_pwr_lock);
+	init_completion(&pc_prep_done);
+	rc = venus_hfi_core_pc_prep(device);
+	if (rc) {
+		dprintk(VIDC_ERR, "Failed to prepare venus for power off");
+		return;
+	}
+	rc = wait_for_completion_timeout(&pc_prep_done,
+			msecs_to_jiffies(msm_vidc_hw_rsp_timeout));
+	if (!rc) {
+		dprintk(VIDC_ERR, "Wait interrupted or timeout: %d", rc);
+		return;
+	}
+
+	mutex_lock(&device->clk_pwr_lock);
+	if (device->clocks_enabled) {
+		dprintk(VIDC_ERR,
+				"Clocks are still enabled after PC_PREP_DONE, ignore power off");
+		goto clks_enabled;
+	}
+
+	rc = venus_hfi_power_off(device);
+	if (rc)
+		dprintk(VIDC_ERR, "Failed venus power off");
+clks_enabled:
+	mutex_unlock(&device->clk_pwr_lock);
+}
+
+static inline void venus_hfi_clk_gating_on(struct venus_hfi_device *device)
+{
+	if (!device) {
+		dprintk(VIDC_ERR, "Invalid params: %p\n", device);
+		return;
+	}
+	if (!device->clocks_enabled) {
+		dprintk(VIDC_DBG, "Clocks are already disabled");
+		goto already_disabled;
+	}
+	venus_hfi_clk_disable(device);
+	if (!queue_delayed_work(device->venus_pm_workq, &venus_hfi_pm_work,
+			msecs_to_jiffies(msm_vidc_pwr_collapse_delay)))
+		dprintk(VIDC_DBG, "PM work already scheduled\n");
+already_disabled:
+	device->clocks_enabled = 0;
+}
+
 static int venus_hfi_try_clk_gating(struct venus_hfi_device *device)
 {
 	int rc = 0;
@@ -1939,15 +2430,21 @@
 		return -ENODEV;
 	}
 	mutex_lock(&device->write_lock);
-	mutex_lock(&device->clock_lock);
+	mutex_lock(&device->clk_pwr_lock);
 	rc = venus_hfi_is_cmd_pending(device);
 	ctrl_status = venus_hfi_read_register(
 		device,
 		VIDC_CPU_CS_SCIACMDARG0);
+	dprintk(VIDC_DBG,
+			"venus_hfi_try_clk_gating - rc %d, ctrl_status 0x%x",
+			rc, ctrl_status);
 	if (((ctrl_status & VIDC_CPU_CS_SCIACMDARG0_HFI_CTRL_INIT_IDLE_MSG_BMSK)
-		!= 0) && !rc)
+		|| (ctrl_status & VIDC_CPU_CS_SCIACMDARG0_HFI_CTRL_PC_READY))
+			&& !rc)
 		venus_hfi_clk_gating_on(device);
-	mutex_unlock(&device->clock_lock);
+	else
+		dprintk(VIDC_DBG, "Ignore clock gating");
+	mutex_unlock(&device->clk_pwr_lock);
 	mutex_unlock(&device->write_lock);
 	return rc;
 }
@@ -2006,6 +2503,14 @@
 		}
 		if (rc == HFI_MSG_SYS_IDLE)
 			rc = venus_hfi_try_clk_gating(device);
+		else if (rc == HFI_MSG_SYS_PC_PREP_DONE) {
+			dprintk(VIDC_DBG, "Received HFI_MSG_SYS_PC_PREP_DONE");
+			rc = venus_hfi_try_clk_gating(device);
+			if (rc)
+				dprintk(VIDC_ERR,
+					"Failed clk gating after PC_PREP_DONE");
+			complete(&pc_prep_done);
+		}
 	} else {
 		dprintk(VIDC_ERR, "SPURIOUS_INTERRUPT");
 	}
@@ -2380,118 +2885,6 @@
 	return -EINVAL;
 }
 
-
-static const u32 venus_hfi_bus_table[] = {
-	36000,
-	110400,
-	244800,
-	489000,
-	783360,
-	979200,
-};
-
-static int venus_hfi_get_bus_vector(struct venus_hfi_device *device, int load,
-			enum session_type type, enum mem_type mtype)
-{
-	int num_rows = sizeof(venus_hfi_bus_table)/(sizeof(u32));
-	int i, j;
-	int idx = 0;
-
-	if (!device || (mtype != DDR_MEM && mtype != OCMEM_MEM) ||
-		(type != MSM_VIDC_ENCODER && type != MSM_VIDC_DECODER)) {
-		dprintk(VIDC_ERR, "%s invalid params", __func__);
-		return -EINVAL;
-	}
-
-	for (i = 0; i < num_rows; i++) {
-		if (load <= venus_hfi_bus_table[i])
-			break;
-	}
-
-	if (type == MSM_VIDC_ENCODER)
-		idx = (mtype == DDR_MEM) ? BUS_IDX_ENC_DDR : BUS_IDX_ENC_OCMEM;
-	else
-		idx = (mtype == DDR_MEM) ? BUS_IDX_DEC_DDR : BUS_IDX_DEC_OCMEM;
-
-	j = clamp(i, 0, num_rows-1) + 1;
-
-	/* Ensure bus index remains within the supported range,
-	* as specified in the device dtsi file */
-	j = clamp(j, 0, device->res->bus_pdata[idx].num_usecases - 1);
-
-	dprintk(VIDC_DBG, "Required bus = %d\n", j);
-	return j;
-}
-
-static int venus_hfi_scale_bus(void *dev, int load,
-				enum session_type type, enum mem_type mtype)
-{
-	int rc = 0;
-	u32 handle = 0;
-	struct venus_hfi_device *device = dev;
-	int bus_vector = 0;
-
-	if (!device) {
-		dprintk(VIDC_ERR, "%s invalid device handle %p",
-			__func__, device);
-		return -EINVAL;
-	}
-
-	if (mtype & DDR_MEM)
-		handle = device->resources.bus_info.ddr_handle[type];
-	if (mtype & OCMEM_MEM)
-		handle = device->resources.bus_info.ocmem_handle[type];
-
-	if (handle) {
-		bus_vector = venus_hfi_get_bus_vector(device, load,
-				type, mtype);
-		if (bus_vector < 0) {
-			dprintk(VIDC_ERR, "Failed to get bus vector\n");
-			return -EINVAL;
-		}
-		rc = msm_bus_scale_client_update_request(handle, bus_vector);
-		if (rc)
-			dprintk(VIDC_ERR, "Failed to scale bus: %d\n", rc);
-	} else {
-		dprintk(VIDC_ERR, "Failed to scale bus, mtype: %d\n",
-				mtype);
-		rc = -EINVAL;
-	}
-
-	return rc;
-}
-
-static int venus_hfi_unvote_bus(void *dev,
-				enum session_type type, enum mem_type mtype)
-{
-	int rc = 0;
-	u32 handle = 0;
-	struct venus_hfi_device *device = dev;
-
-	if (!device) {
-		dprintk(VIDC_ERR, "%s invalid device handle %p",
-			__func__, device);
-		return -EINVAL;
-	}
-
-	if (mtype & DDR_MEM)
-		handle = device->resources.bus_info.ddr_handle[type];
-	if (mtype & OCMEM_MEM)
-		handle = device->resources.bus_info.ocmem_handle[type];
-
-	if (handle) {
-		rc = msm_bus_scale_client_update_request(
-				handle, 0);
-		if (rc)
-			dprintk(VIDC_ERR, "Failed to unvote bus: %d\n", rc);
-	} else {
-		dprintk(VIDC_ERR, "Failed to unvote bus, mtype: %d\n",
-				mtype);
-		rc = -EINVAL;
-	}
-	return rc;
-}
-
 static int venus_hfi_set_ocmem(void *dev, struct ocmem_buf *ocmem)
 {
 	struct vidc_resource_hdr rhdr;
@@ -2657,6 +3050,15 @@
 	int rc = 0;
 
 	device->res = res;
+	if (!res) {
+		dprintk(VIDC_ERR, "Invalid params: %p\n", res);
+		return -ENODEV;
+	}
+	device->gdsc = devm_regulator_get(&res->pdev->dev, "vdd");
+	if (IS_ERR(device->gdsc)) {
+		dprintk(VIDC_ERR, "Failed to get Venus GDSC\n");
+		return -ENODEV;
+	}
 	rc = venus_hfi_init_clocks(res, device);
 	if (rc) {
 		dprintk(VIDC_ERR, "Failed to init clocks\n");
@@ -2686,6 +3088,7 @@
 err_init_bus:
 	venus_hfi_deinit_clocks(device);
 err_init_clocks:
+	device->gdsc = NULL;
 	return rc;
 }
 
@@ -2696,72 +3099,7 @@
 	venus_hfi_deregister_iommu_domains(device);
 	venus_hfi_deinit_bus(device);
 	venus_hfi_deinit_clocks(device);
-}
-
-static int venus_hfi_iommu_attach(struct venus_hfi_device *device)
-{
-	int rc = 0;
-	struct iommu_domain *domain;
-	int i;
-	struct iommu_set *iommu_group_set;
-	struct iommu_group *group;
-	struct iommu_info *iommu_map;
-
-	if (!device || !device->res)
-		return -EINVAL;
-
-	iommu_group_set = &device->res->iommu_group_set;
-	for (i = 0; i < iommu_group_set->count; i++) {
-		iommu_map = &iommu_group_set->iommu_maps[i];
-		group = iommu_map->group;
-		domain = msm_get_iommu_domain(iommu_map->domain);
-		if (IS_ERR_OR_NULL(domain)) {
-			dprintk(VIDC_ERR,
-				"Failed to get domain: %s\n", iommu_map->name);
-			rc = PTR_ERR(domain);
-			break;
-		}
-		rc = iommu_attach_group(domain, group);
-		if (rc) {
-			dprintk(VIDC_ERR,
-				"IOMMU attach failed: %s\n", iommu_map->name);
-			break;
-		}
-	}
-	if (i < iommu_group_set->count) {
-		i--;
-		for (; i >= 0; i--) {
-			iommu_map = &iommu_group_set->iommu_maps[i];
-			group = iommu_map->group;
-			domain = msm_get_iommu_domain(iommu_map->domain);
-			if (group && domain)
-				iommu_detach_group(domain, group);
-		}
-	}
-	return rc;
-}
-
-static void venus_hfi_iommu_detach(struct venus_hfi_device *device)
-{
-	struct iommu_group *group;
-	struct iommu_domain *domain;
-	struct iommu_set *iommu_group_set;
-	struct iommu_info *iommu_map;
-	int i;
-
-	if (!device || !device->res) {
-		dprintk(VIDC_ERR, "Invalid paramter: %p\n", device);
-		return;
-	}
-
-	iommu_group_set = &device->res->iommu_group_set;
-	for (i = 0; i < iommu_group_set->count; i++) {
-		iommu_map = &iommu_group_set->iommu_maps[i];
-		group = iommu_map->group;
-		domain = msm_get_iommu_domain(iommu_map->domain);
-		if (group && domain)
-			iommu_detach_group(domain, group);
-	}
+	device->gdsc = NULL;
 }
 
 static int venus_hfi_iommu_get_domain_partition(void *dev, u32 flags,
@@ -2833,12 +3171,12 @@
 	int rc = 0;
 	struct venus_hfi_device *device = dev;
 
-	if (!device) {
+	if (!device || !device->gdsc) {
 		dprintk(VIDC_ERR, "%s Invalid paramter: %p\n",
 			__func__, device);
 		return -EINVAL;
 	}
-	mutex_init(&device->clock_lock);
+	mutex_init(&device->clk_pwr_lock);
 	device->clk_gating_level = VCODEC_CLK;
 	rc = venus_hfi_iommu_attach(device);
 	if (rc) {
@@ -2846,14 +3184,21 @@
 		goto fail_iommu_attach;
 	}
 
-	if (!device->resources.fw.cookie)
+	if (!device->resources.fw.cookie) {
+		rc = regulator_enable(device->gdsc);
+		if (rc) {
+			dprintk(VIDC_ERR, "Failed to enable GDSC %d", rc);
+			goto fail_enable_gdsc;
+		}
 		device->resources.fw.cookie = subsystem_get("venus");
+	}
 
 	if (IS_ERR_OR_NULL(device->resources.fw.cookie)) {
 		dprintk(VIDC_ERR, "Failed to download firmware\n");
 		rc = -ENOMEM;
 		goto fail_load_fw;
 	}
+	device->power_enabled = 1;
 	/*Clocks can be enabled only after pil_get since
 	 * gdsc is turned-on in pil_get*/
 	rc = venus_hfi_enable_clks(device);
@@ -2875,6 +3220,8 @@
 	subsystem_put(device->resources.fw.cookie);
 fail_load_fw:
 	device->resources.fw.cookie = NULL;
+	regulator_disable(device->gdsc);
+fail_enable_gdsc:
 	venus_hfi_iommu_detach(device);
 fail_iommu_attach:
 	return rc;
@@ -2890,8 +3237,10 @@
 	}
 	if (device->resources.fw.cookie) {
 		flush_workqueue(device->vidc_workq);
+		flush_workqueue(device->venus_pm_workq);
 		venus_hfi_disable_clks(device);
 		subsystem_put(device->resources.fw.cookie);
+		regulator_disable(device->gdsc);
 		venus_hfi_interface_queues_release(dev);
 		venus_hfi_iommu_detach(device);
 		device->resources.fw.cookie = NULL;
@@ -2992,9 +3341,15 @@
 	hdevice->vidc_workq = create_singlethread_workqueue(
 		"msm_vidc_workerq_venus");
 	if (!hdevice->vidc_workq) {
-		dprintk(VIDC_ERR, ": create workq failed\n");
+		dprintk(VIDC_ERR, ": create vidc workq failed\n");
 		goto error_createq;
 	}
+	hdevice->venus_pm_workq = create_singlethread_workqueue(
+			"pm_workerq_venus");
+	if (!hdevice->venus_pm_workq) {
+		dprintk(VIDC_ERR, ": create pm workq failed\n");
+		goto error_createq_pm;
+	}
 
 	if (hal_ctxt.dev_count == 0)
 		INIT_LIST_HEAD(&hal_ctxt.dev_head);
@@ -3004,6 +3359,8 @@
 	hal_ctxt.dev_count++;
 
 	return (void *) hdevice;
+error_createq_pm:
+	destroy_workqueue(hdevice->vidc_workq);
 error_createq:
 err_init_regs:
 	kfree(hdevice);
@@ -3054,6 +3411,7 @@
 				free_irq(dev->hal_data->irq, close);
 				list_del(&close->list);
 				destroy_workqueue(close->vidc_workq);
+				destroy_workqueue(close->venus_pm_workq);
 				kfree(close->hal_data);
 				kfree(close);
 				break;
diff --git a/drivers/media/platform/msm/vidc/venus_hfi.h b/drivers/media/platform/msm/vidc/venus_hfi.h
index 44cdf31..f1d8694 100644
--- a/drivers/media/platform/msm/vidc/venus_hfi.h
+++ b/drivers/media/platform/msm/vidc/venus_hfi.h
@@ -182,12 +182,14 @@
 	struct list_head sess_head;
 	u32 intr_status;
 	u32 device_id;
-	u32 load;
+	u32 clk_load;
+	u32 bus_load[MSM_VIDC_MAX_DEVICES];
 	u32 clocks_enabled;
+	u32 power_enabled;
 	enum vidc_clocks clk_gating_level;
 	struct mutex read_lock;
 	struct mutex write_lock;
-	struct mutex clock_lock;
+	struct mutex clk_pwr_lock;
 	struct mutex session_lock;
 	msm_vidc_callback callback;
 	struct vidc_mem_addr iface_q_table;
@@ -198,6 +200,7 @@
 	struct smem_client *hal_client;
 	struct hal_data *hal_data;
 	struct workqueue_struct *vidc_workq;
+	struct workqueue_struct *venus_pm_workq;
 	int spur_count;
 	int reg_count;
 	u32 base_addr;
@@ -206,6 +209,7 @@
 	u32 irq;
 	struct venus_resources resources;
 	struct msm_vidc_platform_resources *res;
+	struct regulator *gdsc;
 };
 
 void venus_hfi_delete_device(void *device);
diff --git a/drivers/media/platform/msm/vidc/vidc_hfi_io.h b/drivers/media/platform/msm/vidc/vidc_hfi_io.h
index eeffe35..6377fbf 100644
--- a/drivers/media/platform/msm/vidc/vidc_hfi_io.h
+++ b/drivers/media/platform/msm/vidc/vidc_hfi_io.h
@@ -49,6 +49,7 @@
 #define VIDC_CPU_CS_SCIACMDARG0_HFI_CTRL_ERROR_STATUS_SHFT	0x1
 #define VIDC_CPU_CS_SCIACMDARG0_HFI_CTRL_INIT_STATUS_BMSK	0x1
 #define VIDC_CPU_CS_SCIACMDARG0_HFI_CTRL_INIT_STATUS_SHFT	0x0
+#define VIDC_CPU_CS_SCIACMDARG0_HFI_CTRL_PC_READY           0x100
 #define VIDC_CPU_CS_SCIACMDARG0_HFI_CTRL_INIT_IDLE_MSG_BMSK     0x40000000
 
 /* HFI_QTBL_INFO */
diff --git a/drivers/platform/msm/usb_bam.c b/drivers/platform/msm/usb_bam.c
index 8bb4f90..4be727f 100644
--- a/drivers/platform/msm/usb_bam.c
+++ b/drivers/platform/msm/usb_bam.c
@@ -356,7 +356,7 @@
 		/*
 		 * Enable USB PRIVATE RAM to be used for BAM FIFOs
 		 * HSUSB: Only RAM13 is used for BAM FIFOs
-		 * SSUSB: RAM11, 12, 13 are used for BAM FIFOs
+		 * SSUSB: RAM12, 13 are used for BAM FIFOs
 		 */
 		bam = pipe_connect->bam_type;
 		if (bam < 0)
@@ -365,7 +365,7 @@
 		if (bam == HSUSB_BAM)
 			ram1_value = 0x4;
 		else
-			ram1_value = 0x7;
+			ram1_value = 0x6;
 
 		pr_debug("Writing 0x%x to QSCRATCH_RAM1\n", ram1_value);
 		writel_relaxed(ram1_value, ctx.qscratch_ram1_reg);
diff --git a/drivers/power/qpnp-bms.c b/drivers/power/qpnp-bms.c
index ae13a06..6706e0d 100644
--- a/drivers/power/qpnp-bms.c
+++ b/drivers/power/qpnp-bms.c
@@ -83,7 +83,7 @@
 #define IAVG_STEP_SIZE_MA		50
 #define IAVG_START			600
 #define IAVG_INVALID			0xFF
-#define SOC_INVALID			0xFF
+#define SOC_INVALID			0x7E
 
 #define IAVG_SAMPLES 16
 
@@ -147,6 +147,8 @@
 	wait_queue_head_t		bms_wait_queue;
 	u16				base;
 	u16				iadc_base;
+	u16				batt_pres_addr;
+	u16				soc_storage_addr;
 
 	u8				revision1;
 	u8				revision2;
@@ -1510,24 +1512,6 @@
 	pr_debug("UUC = %uuAh\n", params->uuc_uah);
 }
 
-static bool is_shutdown_soc_within_limits(struct qpnp_bms_chip *chip, int soc)
-{
-	if (chip->shutdown_soc_invalid) {
-		pr_debug("NOT forcing shutdown soc = %d\n", chip->shutdown_soc);
-		return 0;
-	}
-
-	if (abs(chip->shutdown_soc - soc) > chip->shutdown_soc_valid_limit) {
-		pr_debug("rejecting shutdown soc = %d, soc = %d limit = %d\n",
-			chip->shutdown_soc, soc,
-			chip->shutdown_soc_valid_limit);
-		chip->shutdown_soc_invalid = true;
-		return 0;
-	}
-
-	return 1;
-}
-
 static int bound_soc(int soc)
 {
 	soc = max(0, soc);
@@ -1614,6 +1598,7 @@
 
 module_param_cb(bms_reset, &bms_reset_ops, &bms_reset, 0644);
 
+#define SOC_STORAGE_MASK	0xFE
 static void backup_soc_and_iavg(struct qpnp_bms_chip *chip, int batt_temp,
 				int soc)
 {
@@ -1626,15 +1611,12 @@
 	else
 		temp = 0;
 
-	rc = qpnp_write_wrapper(chip, &temp,
-			chip->base + IAVG_STORAGE_REG, 1);
-
-	temp = soc;
+	rc = qpnp_write_wrapper(chip, &temp, chip->base + IAVG_STORAGE_REG, 1);
 
 	/* don't store soc if temperature is below 5degC */
 	if (batt_temp > IGNORE_SOC_TEMP_DECIDEG)
-		rc = qpnp_write_wrapper(chip, &temp,
-				chip->base + SOC_STORAGE_REG, 1);
+		qpnp_masked_write_base(chip, chip->soc_storage_addr,
+				SOC_STORAGE_MASK, (soc + 1) << 1);
 }
 
 static int scale_soc_while_chg(struct qpnp_bms_chip *chip, int chg_time_sec,
@@ -1822,6 +1804,7 @@
 				int vbat_uv, int ibat_ua, int batt_temp)
 {
 	int chg_soc, soc_ibat, batt_terminal_uv, weight_ibat, weight_cc;
+	int new_ocv_uv;
 
 	batt_terminal_uv = vbat_uv + (ibat_ua * chip->r_conn_mohm) / 1000;
 
@@ -1873,8 +1856,6 @@
 
 	/* always report a higher soc */
 	if (chg_soc > chip->prev_chg_soc) {
-		int new_ocv_uv;
-
 		chip->prev_chg_soc = chg_soc;
 
 		find_ocv_for_soc(chip, params, batt_temp, chg_soc, &new_ocv_uv);
@@ -2186,37 +2167,22 @@
 			(uint16_t)ocv_raw);
 }
 
-#define SLEEP_RECALC_INTERVAL	3
-static int calculate_state_of_charge(struct qpnp_bms_chip *chip,
+static int calculate_raw_soc(struct qpnp_bms_chip *chip,
 					struct raw_soc_params *raw,
+					struct soc_params *params,
 					int batt_temp)
 {
-	int soc, new_ocv_uv, previous_soc;
-	int shutdown_soc, new_calculated_soc, remaining_usable_charge_uah;
-	struct soc_params params;
+	int soc, new_ocv_uv;
+	int remaining_usable_charge_uah;
 
-	if (!is_battery_present(chip)) {
-		pr_debug("battery gone, reporting 100\n");
-		new_calculated_soc = 100;
-		goto done_calculating;
-	}
-	calculate_soc_params(chip, raw, &params, batt_temp);
 	/* calculate remaining usable charge */
-	remaining_usable_charge_uah = params.ocv_charge_uah
-					- params.cc_uah
-					- params.uuc_uah;
-
+	remaining_usable_charge_uah = params->ocv_charge_uah
+					- params->cc_uah
+					- params->uuc_uah;
 	pr_debug("RUC = %duAh\n", remaining_usable_charge_uah);
-	if (params.fcc_uah - params.uuc_uah <= 0) {
-		pr_debug("FCC = %duAh, UUC = %duAh forcing soc = 0\n",
-						params.fcc_uah,
-						params.uuc_uah);
-		new_calculated_soc = 0;
-		goto done_calculating;
-	}
 
 	soc = DIV_ROUND_CLOSEST((remaining_usable_charge_uah * 100),
-				(params.fcc_uah - params.uuc_uah));
+				(params->fcc_uah - params->uuc_uah));
 
 	if (chip->first_time_calc_soc && soc < 0) {
 		/*
@@ -2224,16 +2190,16 @@
 		 * in a bad soc. Adjust ocv to get 0 soc
 		 */
 		pr_debug("soc is %d, adjusting pon ocv to make it 0\n", soc);
-		find_ocv_for_soc(chip, &params, batt_temp, 0, &new_ocv_uv);
+		find_ocv_for_soc(chip, params, batt_temp, 0, &new_ocv_uv);
 		chip->last_ocv_uv = new_ocv_uv;
 
-		remaining_usable_charge_uah = params.ocv_charge_uah
-					- params.cc_uah
-					- params.uuc_uah;
+		remaining_usable_charge_uah = params->ocv_charge_uah
+					- params->cc_uah
+					- params->uuc_uah;
 
 		soc = DIV_ROUND_CLOSEST((remaining_usable_charge_uah * 100),
-					(params.fcc_uah
-						- params.uuc_uah));
+					(params->fcc_uah
+						- params->uuc_uah));
 		pr_debug("DONE for O soc is %d, pon ocv adjusted to %duV\n",
 				soc, chip->last_ocv_uv);
 	}
@@ -2244,20 +2210,49 @@
 	if (soc < 0) {
 		pr_debug("bad rem_usb_chg = %d rem_chg %d, cc_uah %d, unusb_chg %d\n",
 				remaining_usable_charge_uah,
-				params.ocv_charge_uah,
-				params.cc_uah, params.uuc_uah);
+				params->ocv_charge_uah,
+				params->cc_uah, params->uuc_uah);
 
 		pr_debug("for bad rem_usb_chg last_ocv_uv = %d batt_temp = %d fcc = %d soc =%d\n",
 				chip->last_ocv_uv, batt_temp,
-				params.fcc_uah, soc);
+				params->fcc_uah, soc);
 		soc = 0;
 	}
 
+	return soc;
+}
+
+#define SLEEP_RECALC_INTERVAL	3
+static int calculate_state_of_charge(struct qpnp_bms_chip *chip,
+					struct raw_soc_params *raw,
+					int batt_temp)
+{
+	struct soc_params params;
+	int soc, previous_soc, shutdown_soc, new_calculated_soc;
+	int remaining_usable_charge_uah, new_ocv_uv;
+
+	calculate_soc_params(chip, raw, &params, batt_temp);
+	if (!is_battery_present(chip)) {
+		pr_debug("battery gone, reporting 100\n");
+		new_calculated_soc = 100;
+		goto done_calculating;
+	}
+
+	if (params.fcc_uah - params.uuc_uah <= 0) {
+		pr_debug("FCC = %duAh, UUC = %duAh forcing soc = 0\n",
+						params.fcc_uah,
+						params.uuc_uah);
+		new_calculated_soc = 0;
+		goto done_calculating;
+	}
+
+	soc = calculate_raw_soc(chip, raw, &params, batt_temp);
+
 	mutex_lock(&chip->soc_invalidation_mutex);
 	shutdown_soc = chip->shutdown_soc;
 
 	if (chip->first_time_calc_soc && soc != shutdown_soc
-			&& is_shutdown_soc_within_limits(chip, soc)) {
+			&& !chip->shutdown_soc_invalid) {
 		/*
 		 * soc for the first time - use shutdown soc
 		 * to adjust pon ocv since it is a small percent away from
@@ -2367,6 +2362,53 @@
 	return voltage_based_soc;
 }
 
+static int recalculate_raw_soc(struct qpnp_bms_chip *chip)
+{
+	int batt_temp, rc, soc;
+	struct qpnp_vadc_result result;
+	struct raw_soc_params raw;
+	struct soc_params params;
+
+	bms_stay_awake(&chip->soc_wake_source);
+	if (chip->use_voltage_soc) {
+		soc = calculate_soc_from_voltage(chip);
+	} else {
+		if (!chip->batfet_closed)
+			qpnp_iadc_calibrate_for_trim(chip->iadc_dev, true);
+		rc = qpnp_vadc_read(chip->vadc_dev, LR_MUX1_BATT_THERM,
+								&result);
+		if (rc) {
+			pr_err("error reading vadc LR_MUX1_BATT_THERM = %d, rc = %d\n",
+						LR_MUX1_BATT_THERM, rc);
+			soc = chip->calculated_soc;
+		} else {
+			pr_debug("batt_temp phy = %lld meas = 0x%llx\n",
+							result.physical,
+							result.measurement);
+			batt_temp = (int)result.physical;
+
+			mutex_lock(&chip->last_ocv_uv_mutex);
+			read_soc_params_raw(chip, &raw, batt_temp);
+			calculate_soc_params(chip, &raw, &params, batt_temp);
+			if (!is_battery_present(chip)) {
+				pr_debug("battery gone\n");
+				soc = 0;
+			} else if (params.fcc_uah - params.uuc_uah <= 0) {
+				pr_debug("FCC = %duAh, UUC = %duAh forcing soc = 0\n",
+							params.fcc_uah,
+							params.uuc_uah);
+				soc = 0;
+			} else {
+				soc = calculate_raw_soc(chip, &raw,
+							&params, batt_temp);
+			}
+			mutex_unlock(&chip->last_ocv_uv_mutex);
+		}
+	}
+	bms_relax(&chip->soc_wake_source);
+	return soc;
+}
+
 static int recalculate_soc(struct qpnp_bms_chip *chip)
 {
 	int batt_temp, rc, soc;
@@ -3234,61 +3276,120 @@
 	return 0;
 }
 
-static void read_shutdown_soc_and_iavg(struct qpnp_bms_chip *chip)
+static int read_shutdown_iavg_ma(struct qpnp_bms_chip *chip)
 {
+	u8 iavg;
 	int rc;
-	u8 temp;
 
-	if (chip->ignore_shutdown_soc) {
-		chip->shutdown_soc_invalid = true;
-		chip->shutdown_soc = 0;
-		chip->shutdown_iavg_ma = 0;
+	rc = qpnp_read_wrapper(chip, &iavg, chip->base + IAVG_STORAGE_REG, 1);
+	if (rc) {
+		pr_err("failed to read addr = %d %d assuming %d\n",
+				chip->base + IAVG_STORAGE_REG, rc,
+				IAVG_START);
+		return IAVG_START;
+	} else if (iavg == IAVG_INVALID) {
+		pr_err("invalid iavg read from BMS1_DATA_REG_1, using %d\n",
+				IAVG_START);
+		return IAVG_START;
 	} else {
-		rc = qpnp_read_wrapper(chip, &temp,
-				chip->base + IAVG_STORAGE_REG, 1);
-		if (rc) {
-			pr_err("failed to read addr = %d %d assuming %d\n",
-					chip->base + IAVG_STORAGE_REG, rc,
-					IAVG_START);
-			chip->shutdown_iavg_ma = IAVG_START;
-		} else if (temp == IAVG_INVALID) {
-			pr_err("invalid iavg read from BMS1_DATA_REG_1, using %d\n",
-					IAVG_START);
-			chip->shutdown_iavg_ma = IAVG_START;
-		} else {
-			if (temp == 0) {
-				chip->shutdown_iavg_ma = IAVG_START;
-			} else {
-				chip->shutdown_iavg_ma = IAVG_START
-					+ IAVG_STEP_SIZE_MA * (temp + 1);
-			}
-		}
+		if (iavg == 0)
+			return IAVG_START;
+		else
+			return IAVG_START + IAVG_STEP_SIZE_MA * (iavg + 1);
+	}
+}
 
-		rc = qpnp_read_wrapper(chip, &temp,
-				chip->base + SOC_STORAGE_REG, 1);
-		if (rc) {
-			pr_err("failed to read addr = %d %d\n",
-					chip->base + SOC_STORAGE_REG, rc);
-		} else {
-			chip->shutdown_soc = temp;
+static int read_shutdown_soc(struct qpnp_bms_chip *chip)
+{
+	u8 stored_soc;
+	int rc, shutdown_soc;
 
-			if (chip->shutdown_soc == SOC_INVALID) {
-				pr_debug("No shutdown soc available\n");
-				chip->shutdown_soc_invalid = true;
-				chip->shutdown_iavg_ma = 0;
-			}
-		}
+	/*
+	 * The previous SOC is stored in the first 7 bits of the register as
+	 * (Shutdown SOC + 1). This allows for register reset values of both
+	 * 0x00 and 0x7F.
+	 */
+	rc = qpnp_read_wrapper(chip, &stored_soc, chip->soc_storage_addr, 1);
+	if (rc) {
+		pr_err("failed to read addr = %d %d\n",
+				chip->soc_storage_addr, rc);
+		return SOC_INVALID;
 	}
 
-	/* read the SOC storage to determine if there was a battery removal */
-	rc = qpnp_read_wrapper(chip, &temp, chip->base + SOC_STORAGE_REG, 1);
-	if (!rc) {
-		if (temp == SOC_INVALID)
-			chip->battery_removed = true;
+	if ((stored_soc >> 1) > 0)
+		shutdown_soc = (stored_soc >> 1) - 1;
+	else
+		shutdown_soc = SOC_INVALID;
+
+	pr_debug("stored soc = 0x%02x, shutdown_soc = %d\n",
+			stored_soc, shutdown_soc);
+	return shutdown_soc;
+}
+
+#define BAT_REMOVED_OFFMODE_BIT		BIT(6)
+static bool is_battery_replaced_in_offmode(struct qpnp_bms_chip *chip)
+{
+	u8 batt_pres;
+	int rc;
+
+	if (chip->batt_pres_addr) {
+		rc = qpnp_read_wrapper(chip, &batt_pres,
+				chip->batt_pres_addr, 1);
+		pr_debug("offmode removed: %02x\n", batt_pres);
+		if (!rc && (batt_pres & BAT_REMOVED_OFFMODE_BIT))
+			return true;
+	}
+	return false;
+}
+
+static void load_shutdown_data(struct qpnp_bms_chip *chip)
+{
+	int calculated_soc, shutdown_soc;
+	bool invalid_stored_soc;
+	bool offmode_battery_replaced;
+	bool shutdown_soc_out_of_limit;
+
+	/*
+	 * Read the saved shutdown SoC from the configured register and
+	 * check if the value has been reset
+	 */
+	shutdown_soc = read_shutdown_soc(chip);
+	invalid_stored_soc = (shutdown_soc == SOC_INVALID);
+
+	/*
+	 * Do a quick run of SoC calculation to find whether the shutdown soc
+	 * is close enough.
+	 */
+	calculated_soc = recalculate_raw_soc(chip);
+	shutdown_soc_out_of_limit = (abs(shutdown_soc - calculated_soc)
+			> chip->shutdown_soc_valid_limit);
+	pr_debug("calculated_soc = %d, valid_limit = %d\n",
+			calculated_soc, chip->shutdown_soc_valid_limit);
+
+	/*
+	 * Check if the battery has been replaced while the system was powered
+	 * down.
+	 */
+	offmode_battery_replaced = is_battery_replaced_in_offmode(chip);
+
+	/* Invalidate the shutdown SoC if any of these conditions hold true */
+	if (chip->ignore_shutdown_soc
+			|| invalid_stored_soc
+			|| offmode_battery_replaced
+			|| shutdown_soc_out_of_limit) {
+		chip->battery_removed = true;
+		chip->shutdown_soc_invalid = true;
+		chip->shutdown_iavg_ma = 0;
+		pr_debug("Ignoring shutdown SoC: invalid = %d, offmode = %d, out_of_limit = %d\n",
+				invalid_stored_soc, offmode_battery_replaced,
+				shutdown_soc_out_of_limit);
+	} else {
+		chip->shutdown_iavg_ma = read_shutdown_iavg_ma(chip);
+		chip->shutdown_soc = shutdown_soc;
 	}
 
-
-	pr_debug("shutdown_soc = %d shutdown_iavg = %d shutdown_soc_invalid = %d, battery_removed = %d\n",
+	pr_debug("raw_soc = %d shutdown_soc = %d shutdown_iavg = %d shutdown_soc_invalid = %d, battery_removed = %d\n",
+			calculated_soc,
 			chip->shutdown_soc,
 			chip->shutdown_iavg_ma,
 			chip->shutdown_soc_invalid,
@@ -3410,6 +3511,9 @@
 	if (batt_data->iterm_ua >= 0 && dt_data)
 		chip->chg_term_ua = batt_data->iterm_ua;
 
+	if (dt_data)
+		kfree(batt_data);
+
 	if (chip->pc_temp_ocv_lut == NULL) {
 		pr_err("temp ocv lut table is NULL\n");
 		return -EINVAL;
@@ -3643,6 +3747,18 @@
 			return -ENXIO;
 		}
 
+		pr_debug("Node name = %s\n", spmi_resource->of_node->name);
+
+		if (strcmp("qcom,batt-pres-status",
+					spmi_resource->of_node->name) == 0) {
+			chip->batt_pres_addr = resource->start;
+			continue;
+		} else if (strcmp("qcom,soc-storage-reg",
+					spmi_resource->of_node->name) == 0) {
+			chip->soc_storage_addr = resource->start;
+			continue;
+		}
+
 		rc = qpnp_read_wrapper(chip, &type,
 				resource->start + REG_OFFSET_PERP_TYPE, 1);
 		if (rc) {
@@ -3681,7 +3797,14 @@
 		dev_err(&spmi->dev, "BMS_IADC peripheral was not registered\n");
 		return -EINVAL;
 	}
+	if (chip->soc_storage_addr == 0) {
+		/* default to dvdd backed BMS data reg0 */
+		chip->soc_storage_addr = chip->base + SOC_STORAGE_REG;
+	}
 
+	pr_debug("bms-base = 0x%04x, iadc-base = 0x%04x, bat-pres-reg = 0x%04x, soc-storage-reg = 0x%04x\n",
+			chip->base, chip->iadc_base,
+			chip->batt_pres_addr, chip->soc_storage_addr);
 	return 0;
 }
 
@@ -3951,7 +4074,10 @@
 	INIT_WORK(&chip->recalc_work, recalculate_work);
 	INIT_WORK(&chip->batfet_open_work, batfet_open_work);
 
-	read_shutdown_soc_and_iavg(chip);
+	dev_set_drvdata(&spmi->dev, chip);
+	device_init_wakeup(&spmi->dev, 1);
+
+	load_shutdown_data(chip);
 
 	if (chip->enable_fcc_learning) {
 		if (chip->battery_removed) {
@@ -3971,9 +4097,6 @@
 		}
 	}
 
-	dev_set_drvdata(&spmi->dev, chip);
-	device_init_wakeup(&spmi->dev, 1);
-
 	rc = setup_vbat_monitoring(chip);
 	if (rc < 0) {
 		pr_err("failed to set up voltage notifications: %d\n", rc);
diff --git a/drivers/power/qpnp-charger.c b/drivers/power/qpnp-charger.c
index 1a79ad5..f9e05fc 100644
--- a/drivers/power/qpnp-charger.c
+++ b/drivers/power/qpnp-charger.c
@@ -293,6 +293,7 @@
 	bool				bat_is_cool;
 	bool				bat_is_warm;
 	bool				chg_done;
+	bool				charger_monitor_checked;
 	bool				usb_present;
 	bool				dc_present;
 	bool				batt_present;
@@ -341,6 +342,7 @@
 	struct delayed_work		arb_stop_work;
 	struct delayed_work		eoc_work;
 	struct work_struct		soc_check_work;
+	struct delayed_work		aicl_check_work;
 	struct qpnp_chg_regulator	otg_vreg;
 	struct qpnp_chg_regulator	boost_vreg;
 	struct qpnp_chg_regulator	batfet_vreg;
@@ -1503,6 +1505,28 @@
 	return 0;
 }
 
+static void
+qpnp_aicl_check_work(struct work_struct *work)
+{
+	struct delayed_work *dwork = to_delayed_work(work);
+	struct qpnp_chg_chip *chip = container_of(dwork,
+				struct qpnp_chg_chip, aicl_check_work);
+	union power_supply_propval ret = {0,};
+
+	if (!charger_monitor && qpnp_chg_is_usb_chg_plugged_in(chip)) {
+		chip->usb_psy->get_property(chip->usb_psy,
+			  POWER_SUPPLY_PROP_CURRENT_MAX, &ret);
+		if ((ret.intval / 1000) > USB_WALL_THRESHOLD_MA) {
+			pr_debug("no charger_monitor present set iusbmax %d\n",
+					ret.intval / 1000);
+			qpnp_chg_iusbmax_set(chip, ret.intval / 1000);
+		}
+	} else {
+		pr_debug("charger_monitor is present\n");
+	}
+	chip->charger_monitor_checked = true;
+}
+
 static int
 get_prop_battery_voltage_now(struct qpnp_chg_chip *chip)
 {
@@ -1790,7 +1814,8 @@
 		} else {
 			qpnp_chg_usb_suspend_enable(chip, 0);
 			if (((ret.intval / 1000) > USB_WALL_THRESHOLD_MA)
-					&& (charger_monitor)) {
+					&& (charger_monitor ||
+					!chip->charger_monitor_checked)) {
 				qpnp_chg_iusbmax_set(chip,
 						USB_WALL_THRESHOLD_MA);
 			} else {
@@ -3931,6 +3956,7 @@
 	INIT_DELAYED_WORK(&chip->eoc_work, qpnp_eoc_work);
 	INIT_DELAYED_WORK(&chip->arb_stop_work, qpnp_arb_stop_work);
 	INIT_WORK(&chip->soc_check_work, qpnp_chg_soc_check_work);
+	INIT_DELAYED_WORK(&chip->aicl_check_work, qpnp_aicl_check_work);
 
 	if (chip->dc_chgpth_base) {
 		chip->dc_psy.name = "qpnp-dc";
@@ -4012,6 +4038,8 @@
 	if (qpnp_chg_is_usb_chg_plugged_in(chip))
 		power_supply_set_online(chip->usb_psy, 1);
 
+	schedule_delayed_work(&chip->aicl_check_work,
+		msecs_to_jiffies(EOC_CHECK_PERIOD_MS));
 	pr_info("success chg_dis = %d, bpd = %d, usb = %d, dc = %d b_health = %d batt_present = %d\n",
 			chip->charging_disabled,
 			chip->bpd_detection,
diff --git a/drivers/thermal/qpnp-adc-tm.c b/drivers/thermal/qpnp-adc-tm.c
index 467d89d..7dcd45f 100644
--- a/drivers/thermal/qpnp-adc-tm.c
+++ b/drivers/thermal/qpnp-adc-tm.c
@@ -1611,26 +1611,6 @@
 		goto fail;
 	}
 
-	rc = devm_request_irq(&spmi->dev, chip->adc->adc_high_thr_irq,
-				qpnp_adc_tm_high_thr_isr,
-		IRQF_TRIGGER_RISING, "qpnp_adc_tm_high_interrupt", chip);
-	if (rc) {
-		dev_err(&spmi->dev, "failed to request adc irq\n");
-		goto fail;
-	} else {
-		enable_irq_wake(chip->adc->adc_high_thr_irq);
-	}
-
-	rc = devm_request_irq(&spmi->dev, chip->adc->adc_low_thr_irq,
-				qpnp_adc_tm_low_thr_isr,
-		IRQF_TRIGGER_RISING, "qpnp_adc_tm_low_interrupt", chip);
-	if (rc) {
-		dev_err(&spmi->dev, "failed to request adc irq\n");
-		goto fail;
-	} else {
-		enable_irq_wake(chip->adc->adc_low_thr_irq);
-	}
-
 	for_each_child_of_node(node, child) {
 		char name[25];
 		int btm_channel_num;
@@ -1677,8 +1657,6 @@
 	chip->max_channels_available = count_adc_channel_list;
 	INIT_WORK(&chip->trigger_high_thr_work, qpnp_adc_tm_high_thr_work);
 	INIT_WORK(&chip->trigger_low_thr_work, qpnp_adc_tm_low_thr_work);
-	dev_set_drvdata(&spmi->dev, chip);
-	list_add(&chip->list, &qpnp_adc_tm_device_list);
 
 	rc = qpnp_adc_tm_write_reg(chip, QPNP_ADC_TM_HIGH_THR_INT_EN,
 								thr_init);
@@ -1701,6 +1679,29 @@
 		goto fail;
 	}
 
+	rc = devm_request_irq(&spmi->dev, chip->adc->adc_high_thr_irq,
+				qpnp_adc_tm_high_thr_isr,
+		IRQF_TRIGGER_RISING, "qpnp_adc_tm_high_interrupt", chip);
+	if (rc) {
+		dev_err(&spmi->dev, "failed to request adc irq\n");
+		goto fail;
+	} else {
+		enable_irq_wake(chip->adc->adc_high_thr_irq);
+	}
+
+	rc = devm_request_irq(&spmi->dev, chip->adc->adc_low_thr_irq,
+				qpnp_adc_tm_low_thr_isr,
+		IRQF_TRIGGER_RISING, "qpnp_adc_tm_low_interrupt", chip);
+	if (rc) {
+		dev_err(&spmi->dev, "failed to request adc irq\n");
+		goto fail;
+	} else {
+		enable_irq_wake(chip->adc->adc_low_thr_irq);
+	}
+
+	dev_set_drvdata(&spmi->dev, chip);
+	list_add(&chip->list, &qpnp_adc_tm_device_list);
+
 	pr_debug("OK\n");
 	return 0;
 fail:
diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h
index 328f6f4..674efb3 100644
--- a/drivers/usb/dwc3/core.h
+++ b/drivers/usb/dwc3/core.h
@@ -693,6 +693,7 @@
  * @mem: points to start of memory which is used for this struct.
  * @hwparams: copy of hwparams registers
  * @root: debugfs root folder pointer
+ * @tx_fifo_size: Available RAM size for TX fifo allocation
  */
 struct dwc3 {
 	struct usb_ctrlrequest	*ctrl_req;
@@ -778,6 +779,7 @@
 	/* Indicate if software connect was issued by the usb_gadget_driver */
 	bool			softconnect;
 	void (*notify_event) (struct dwc3 *, unsigned);
+	int			tx_fifo_size;
 };
 
 /* -------------------------------------------------------------------------- */
diff --git a/drivers/usb/dwc3/dwc3-msm.c b/drivers/usb/dwc3/dwc3-msm.c
index d7721dc..f43affb 100644
--- a/drivers/usb/dwc3/dwc3-msm.c
+++ b/drivers/usb/dwc3/dwc3-msm.c
@@ -223,6 +223,8 @@
 	unsigned int		vdd_no_vol_level;
 	unsigned int		vdd_low_vol_level;
 	unsigned int		vdd_high_vol_level;
+	unsigned int		tx_fifo_size;
+	unsigned int		qdss_tx_fifo_size;
 	bool			vbus_active;
 	bool			ext_inuse;
 	enum dwc3_id_state	id_state;
@@ -1028,6 +1030,19 @@
 }
 EXPORT_SYMBOL(msm_ep_unconfig);
 
+void dwc3_tx_fifo_resize_request(struct usb_ep *ep, bool qdss_enabled)
+{
+	struct dwc3_ep *dep = to_dwc3_ep(ep);
+	struct dwc3 *dwc = dep->dwc;
+	struct dwc3_msm *mdwc = dev_get_drvdata(dwc->dev->parent);
+
+	if (qdss_enabled)
+		dwc->tx_fifo_size = mdwc->qdss_tx_fifo_size;
+	else
+		dwc->tx_fifo_size = mdwc->tx_fifo_size;
+}
+EXPORT_SYMBOL(dwc3_tx_fifo_resize_request);
+
 static void dwc3_restart_usb_work(struct work_struct *w)
 {
 	struct dwc3_msm *mdwc = container_of(w, struct dwc3_msm,
@@ -1490,6 +1505,7 @@
 				"DWC3_CONTROLLER_POST_RESET_EVENT received\n");
 		dwc3_msm_qscratch_reg_init(mdwc,
 					DWC3_CONTROLLER_POST_RESET_EVENT);
+		dwc->tx_fifo_size = mdwc->tx_fifo_size;
 		break;
 	default:
 		dev_dbg(mdwc->dev, "unknown dwc3 event\n");
@@ -2963,6 +2979,17 @@
 		ret = -ENODEV;
 		goto disable_hs_ldo;
 	}
+
+	if (of_property_read_u32(node, "qcom,dwc-usb3-msm-tx-fifo-size",
+				 &mdwc->tx_fifo_size))
+		dev_err(&pdev->dev,
+			"unable to read platform data tx fifo size\n");
+
+	if (of_property_read_u32(node, "qcom,dwc-usb3-msm-qdss-tx-fifo-size",
+				 &mdwc->qdss_tx_fifo_size))
+		dev_err(&pdev->dev,
+			"unable to read platform data qdss tx fifo size\n");
+
 	dwc3_set_notifier(&dwc3_msm_notify_event);
 	/* usb_psy required only for vbus_notifications or charging support */
 	if (mdwc->ext_xceiv.otg_capability ||
diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
index 8cf8a6d..aaa22f3 100644
--- a/drivers/usb/dwc3/gadget.c
+++ b/drivers/usb/dwc3/gadget.c
@@ -36,7 +36,6 @@
  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-#include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/delay.h>
 #include <linux/slab.h>
@@ -58,11 +57,6 @@
 #include "debug.h"
 #include "io.h"
 
-static bool tx_fifo_resize_enable;
-module_param(tx_fifo_resize_enable, bool, S_IRUGO|S_IWUSR);
-MODULE_PARM_DESC(tx_fifo_resize_enable,
-			"Enable allocating Tx fifo for endpoints");
-
 static void dwc3_gadget_usb2_phy_suspend(struct dwc3 *dwc, int suspend);
 static void dwc3_gadget_usb3_phy_suspend(struct dwc3 *dwc, int suspend);
 
@@ -188,7 +182,7 @@
 	int		mdwidth;
 	int		num;
 
-	if (!dwc->needs_fifo_resize && !tx_fifo_resize_enable)
+	if (!dwc->needs_fifo_resize)
 		return 0;
 
 	ram1_depth = DWC3_RAM1_DEPTH(dwc->hwparams.hwparams7);
@@ -233,6 +227,17 @@
 		 * packets
 		 */
 		tmp = mult * (dep->endpoint.maxpacket + mdwidth);
+
+		if (dwc->tx_fifo_size &&
+				(usb_endpoint_xfer_bulk(dep->endpoint.desc)
+				|| usb_endpoint_xfer_isoc(dep->endpoint.desc)))
+			/*
+			 * Allocate 3KB fifo size for bulk and isochronous TX
+			 * endpoints irrespective of speed. For interrupt
+			 * endpoint, allocate fifo size of endpoint maxpacket.
+			 */
+			tmp = 3 * (1024 + mdwidth);
+
 		tmp += mdwidth;
 
 		fifo_size = DIV_ROUND_UP(tmp, mdwidth);
@@ -242,10 +247,21 @@
 		dev_vdbg(dwc->dev, "%s: Fifo Addr %04x Size %d\n",
 				dep->name, last_fifo_depth, fifo_size & 0xffff);
 
+		last_fifo_depth += (fifo_size & 0xffff);
+		if (dwc->tx_fifo_size &&
+				(last_fifo_depth >= dwc->tx_fifo_size)) {
+			/*
+			 * Fifo size allocated exceeded available RAM size.
+			 * Hence return error.
+			 */
+			dev_err(dwc->dev, "Fifosize(%d) > available RAM(%d)\n",
+					last_fifo_depth, dwc->tx_fifo_size);
+			return -ENOMEM;
+		}
+
 		dwc3_writel(dwc->regs, DWC3_GTXFIFOSIZ(fifo_number),
 				fifo_size);
 
-		last_fifo_depth += (fifo_size & 0xffff);
 	}
 
 	return 0;
diff --git a/drivers/usb/gadget/android.c b/drivers/usb/gadget/android.c
index 9b38ed3..bbb206d 100644
--- a/drivers/usb/gadget/android.c
+++ b/drivers/usb/gadget/android.c
@@ -1776,11 +1776,18 @@
 	config->fsg.nluns = 1;
 	name[0] = "lun";
 	if (dev->pdata && dev->pdata->cdrom) {
-		config->fsg.nluns = 2;
-		config->fsg.luns[1].cdrom = 1;
-		config->fsg.luns[1].ro = 1;
-		config->fsg.luns[1].removable = 0;
-		name[1] = "lun0";
+		config->fsg.luns[config->fsg.nluns].cdrom = 1;
+		config->fsg.luns[config->fsg.nluns].ro = 1;
+		config->fsg.luns[config->fsg.nluns].removable = 0;
+		name[config->fsg.nluns] = "lun0";
+		config->fsg.nluns++;
+	}
+	if (dev->pdata && dev->pdata->internal_ums) {
+		config->fsg.luns[config->fsg.nluns].cdrom = 0;
+		config->fsg.luns[config->fsg.nluns].ro = 0;
+		config->fsg.luns[config->fsg.nluns].removable = 1;
+		name[config->fsg.nluns] = "lun1";
+		config->fsg.nluns++;
 	}
 
 	config->fsg.luns[0].removable = 1;
@@ -2899,6 +2906,8 @@
 				&pdata->swfi_latency);
 		pdata->cdrom = of_property_read_bool(pdev->dev.of_node,
 				"qcom,android-usb-cdrom");
+		pdata->internal_ums = of_property_read_bool(pdev->dev.of_node,
+				"qcom,android-usb-internal-ums");
 	} else {
 		pdata = pdev->dev.platform_data;
 	}
diff --git a/drivers/usb/gadget/f_mtp.c b/drivers/usb/gadget/f_mtp.c
index a4192ca..6d7dd3d 100644
--- a/drivers/usb/gadget/f_mtp.c
+++ b/drivers/usb/gadget/f_mtp.c
@@ -151,7 +151,7 @@
 	.bDescriptorType =	USB_DT_SS_ENDPOINT_COMP,
 
 	/* the following 2 values can be tweaked if necessary */
-	/* .bMaxBurst =		0, */
+	.bMaxBurst =		2,
 	/* .bmAttributes =	0, */
 };
 
@@ -168,7 +168,7 @@
 	.bDescriptorType =	USB_DT_SS_ENDPOINT_COMP,
 
 	/* the following 2 values can be tweaked if necessary */
-	/* .bMaxBurst =		0, */
+	 .bMaxBurst =		2,
 	/* .bmAttributes =	0, */
 };
 
diff --git a/drivers/usb/gadget/f_qdss.c b/drivers/usb/gadget/f_qdss.c
index 3b94dd5..f649248 100644
--- a/drivers/usb/gadget/f_qdss.c
+++ b/drivers/usb/gadget/f_qdss.c
@@ -395,6 +395,7 @@
 			goto fail;
 		}
 	}
+	dwc3_tx_fifo_resize_request(qdss->data, true);
 
 	return 0;
 fail:
@@ -406,8 +407,11 @@
 
 static void qdss_unbind(struct usb_configuration *c, struct usb_function *f)
 {
+	struct f_qdss  *qdss = func_to_qdss(f);
+
 	pr_debug("qdss_unbind\n");
 
+	dwc3_tx_fifo_resize_request(qdss->data, false);
 	clear_eps(f);
 	clear_desc(c->cdev->gadget, f);
 }
diff --git a/drivers/video/msm/mdss/Makefile b/drivers/video/msm/mdss/Makefile
index 017fa8e..ba14d67 100644
--- a/drivers/video/msm/mdss/Makefile
+++ b/drivers/video/msm/mdss/Makefile
@@ -16,7 +16,7 @@
 obj-$(CONFIG_DEBUG_FS) += mdss_debug.o
 endif
 
-dsi-v2-objs = dsi_v2.o dsi_host_v2.o dsi_io_v2.o dsi_panel_v2.o
+dsi-v2-objs = dsi_v2.o dsi_host_v2.o dsi_io_v2.o
 obj-$(CONFIG_FB_MSM_MDSS) += dsi-v2.o
 
 mdss-dsi-objs := mdss_dsi.o mdss_dsi_host.o
diff --git a/drivers/video/msm/mdss/dsi_host_v2.c b/drivers/video/msm/mdss/dsi_host_v2.c
index 5554085..1f2f6f9 100644
--- a/drivers/video/msm/mdss/dsi_host_v2.c
+++ b/drivers/video/msm/mdss/dsi_host_v2.c
@@ -546,8 +546,8 @@
 		dsi_buf_init(tp);
 		dsi_cmd_dma_add(tp, cm);
 		msm_dsi_cmd_dma_tx(tp);
-		if (cm->wait)
-			msleep(cm->wait);
+		if (cm->dchdr.wait)
+			msleep(cm->dchdr.wait);
 		cm++;
 	}
 
@@ -562,8 +562,8 @@
 static char max_pktsize[2] = {0x00, 0x00}; /* LSB tx first, 10 bytes */
 
 static struct dsi_cmd_desc pkt_size_cmd[] = {
-	{DTYPE_MAX_PKTSIZE, 1, 0, 0, 0,
-		sizeof(max_pktsize), max_pktsize}
+	{{DTYPE_MAX_PKTSIZE, 1, 0, 0, 0,
+		sizeof(max_pktsize)}, max_pktsize}
 };
 
 /*
@@ -594,8 +594,8 @@
 	if (len <= 2) {
 		cnt = 4;	/* short read */
 	} else {
-		if (len > DSI_LEN)
-			len = DSI_LEN;	/* 8 bytes at most */
+		if (len > MDSS_DSI_LEN)
+			len = MDSS_DSI_LEN;	/* 8 bytes at most */
 
 		len = ALIGN(len, 4); /* len 4 bytes align */
 		diff = len - rlen;
@@ -743,12 +743,18 @@
 	u32 dummy_xres, dummy_yres;
 	u32 bitclk_rate = 0, byteclk_rate = 0, pclk_rate = 0, dsiclk_rate = 0;
 	unsigned char *ctrl_base = dsi_host_private->dsi_base;
+	struct mdss_dsi_ctrl_pdata *ctrl_pdata = NULL;
 
 	pr_debug("msm_dsi_on\n");
 
 	pinfo = &pdata->panel_info;
 
-	ret = msm_dsi_regulator_enable();
+	ctrl_pdata = container_of(pdata, struct mdss_dsi_ctrl_pdata,
+				panel_data);
+
+	ret = msm_dss_enable_vreg(
+		ctrl_pdata->power_data.vreg_config,
+		ctrl_pdata->power_data.num_vreg, 1);
 	if (ret) {
 		pr_err("%s: DSI power on failed\n", __func__);
 		return ret;
@@ -843,6 +849,16 @@
 static int msm_dsi_off(struct mdss_panel_data *pdata)
 {
 	int ret = 0;
+	struct mdss_dsi_ctrl_pdata *ctrl_pdata = NULL;
+
+	if (pdata == NULL) {
+		pr_err("%s: Invalid input data\n", __func__);
+		ret = -EINVAL;
+		return ret;
+	}
+
+	ctrl_pdata = container_of(pdata, struct mdss_dsi_ctrl_pdata,
+				panel_data);
 
 	pr_debug("msm_dsi_off\n");
 	msm_dsi_controller_cfg(0);
@@ -852,7 +868,9 @@
 	msm_dsi_phy_off(dsi_host_private->dsi_base);
 	msm_dsi_ahb_ctrl(0);
 
-	ret = msm_dsi_regulator_disable();
+	ret = msm_dss_enable_vreg(
+		ctrl_pdata->power_data.vreg_config,
+		ctrl_pdata->power_data.num_vreg, 0);
 	if (ret) {
 		pr_err("%s: Panel power off failed\n", __func__);
 		return ret;
@@ -865,11 +883,24 @@
 {
 	struct mdss_panel_info *pinfo;
 	int ret = 0;
+	struct mdss_dsi_ctrl_pdata *ctrl_pdata = NULL;
+
+	if (pdata == NULL) {
+		pr_err("%s: Invalid input data\n", __func__);
+		ret = -EINVAL;
+		return ret;
+	}
+
 
 	pr_debug("%s:\n", __func__);
 
+	ctrl_pdata = container_of(pdata, struct mdss_dsi_ctrl_pdata,
+				panel_data);
+
 	pinfo = &pdata->panel_info;
-	ret = msm_dsi_regulator_enable();
+	ret = msm_dss_enable_vreg(
+		ctrl_pdata->power_data.vreg_config,
+		ctrl_pdata->power_data.num_vreg, 1);
 	if (ret) {
 		pr_err("%s: DSI power on failed\n", __func__);
 		return ret;
@@ -912,11 +943,109 @@
 	return rc;
 }
 
+static int dsi_get_panel_cfg(char *panel_cfg)
+{
+	int rc;
+	struct mdss_panel_cfg *pan_cfg = NULL;
+
+	if (!panel_cfg)
+		return MDSS_PANEL_INTF_INVALID;
+
+	pan_cfg = mdp3_panel_intf_type(MDSS_PANEL_INTF_DSI);
+	if (IS_ERR(pan_cfg)) {
+		panel_cfg[0] = 0;
+		return PTR_ERR(pan_cfg);
+	} else if (!pan_cfg) {
+		panel_cfg[0] = 0;
+		return 0;
+	}
+
+	pr_debug("%s:%d: cfg:[%s]\n", __func__, __LINE__,
+		 pan_cfg->arg_cfg);
+	rc = strlcpy(panel_cfg, pan_cfg->arg_cfg,
+				MDSS_MAX_PANEL_LEN);
+	return rc;
+}
+
+/**
+ * dsi_find_panel_of_node(): find device node of dsi panel
+ * @pdev: platform_device of the dsi ctrl node
+ * @panel_cfg: string containing intf specific config data
+ *
+ * Function finds the panel device node using the interface
+ * specific configuration data. This configuration data is
+ * could be derived from the result of bootloader's GCDB
+ * panel detection mechanism. If such config data doesn't
+ * exist then this panel returns the default panel configured
+ * in the device tree.
+ *
+ * returns pointer to panel node on success, NULL on error.
+ */
+static struct device_node *dsi_find_panel_of_node(
+		struct platform_device *pdev, char *panel_cfg)
+{
+	int l;
+	char *panel_name;
+	struct device_node *dsi_pan_node = NULL, *mdss_node = NULL;
+
+	if (!panel_cfg)
+		return NULL;
+
+	l = strlen(panel_cfg);
+	if (!l) {
+		/* no panel cfg chg, parse dt */
+		pr_debug("%s:%d: no cmd line cfg present\n",
+			 __func__, __LINE__);
+		dsi_pan_node = of_parse_phandle(
+			pdev->dev.of_node,
+			"qcom,dsi-pref-prim-pan", 0);
+		if (!dsi_pan_node) {
+			pr_err("%s:can't find panel phandle\n",
+			       __func__);
+			return NULL;
+		}
+	} else {
+		if (panel_cfg[0] != '0') {
+			pr_err("%s:%d:ctrl id=[%d] not supported\n",
+			       __func__, __LINE__, panel_cfg[0]);
+			return NULL;
+		}
+		/*
+		 * skip first two chars '<dsi_ctrl_id>' and
+		 * ':' to get to the panel name
+		 */
+		panel_name = panel_cfg + 2;
+		pr_debug("%s:%d:%s:%s\n", __func__, __LINE__,
+			 panel_cfg, panel_name);
+
+		mdss_node = of_parse_phandle(pdev->dev.of_node,
+					     "qcom,mdss-mdp", 0);
+
+		if (!mdss_node) {
+			pr_err("%s: %d: mdss_node null\n",
+			       __func__, __LINE__);
+			return NULL;
+		}
+		dsi_pan_node = of_find_node_by_name(mdss_node,
+						    panel_name);
+		if (!dsi_pan_node) {
+			pr_err("%s: invalid pan node\n",
+			       __func__);
+			return NULL;
+		}
+	}
+	return dsi_pan_node;
+}
 
 static int __devinit msm_dsi_probe(struct platform_device *pdev)
 {
 	struct dsi_interface intf;
+	char panel_cfg[MDSS_MAX_PANEL_LEN];
+	struct mdss_dsi_ctrl_pdata *ctrl_pdata = NULL;
 	int rc = 0;
+	struct device_node *dsi_pan_node = NULL;
+	bool cmd_cfg_cont_splash = false;
+	struct resource *mdss_dsi_mres;
 
 	pr_debug("%s\n", __func__);
 
@@ -924,61 +1053,103 @@
 	if (rc)
 		return rc;
 
-	if (pdev->dev.of_node) {
-		struct resource *mdss_dsi_mres;
-		pdev->id = 0;
-		mdss_dsi_mres = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-		if (!mdss_dsi_mres) {
-			pr_err("%s:%d unable to get the MDSS reg resources",
-				__func__, __LINE__);
-			return -ENOMEM;
-		} else {
-			dsi_host_private->dsi_reg_size =
-						resource_size(mdss_dsi_mres);
-			dsi_host_private->dsi_base = ioremap(
-						mdss_dsi_mres->start,
-						dsi_host_private->dsi_reg_size);
-			if (!dsi_host_private->dsi_base) {
-				pr_err("%s:%d unable to remap dsi resources",
-					__func__, __LINE__);
-				return -ENOMEM;
-			}
-		}
-
-		mdss_dsi_mres = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
-		if (!mdss_dsi_mres || mdss_dsi_mres->start == 0) {
-			pr_err("%s:%d unable to get the MDSS irq resources",
-				__func__, __LINE__);
-			rc = -ENODEV;
-			goto dsi_probe_error;
-		} else {
-			rc = msm_dsi_irq_init(&pdev->dev, mdss_dsi_mres->start);
-			if (rc) {
-				dev_err(&pdev->dev,
-					"%s: failed to init irq, rc=%d\n",
-							__func__, rc);
-				goto dsi_probe_error;
-			}
-		}
-
-		rc = msm_dsi_io_init(pdev);
-		if (rc) {
-			dev_err(&pdev->dev,
-				"%s: failed to init DSI IO, rc=%d\n",
-							__func__, rc);
-			goto dsi_probe_error;
-		}
-
-		rc = of_platform_populate(pdev->dev.of_node,
-					NULL, NULL, &pdev->dev);
-		if (rc) {
-			dev_err(&pdev->dev,
-				"%s: failed to add child nodes, rc=%d\n",
-							__func__, rc);
-			goto dsi_probe_error;
-		}
-
+	if (!pdev->dev.of_node) {
+		pr_err("%s: Device node is not accessible\n", __func__);
+		rc = -ENODEV;
+		goto error_no_mem;
 	}
+	pdev->id = 0;
+
+	ctrl_pdata = platform_get_drvdata(pdev);
+	if (!ctrl_pdata) {
+		ctrl_pdata = devm_kzalloc(&pdev->dev,
+			sizeof(struct mdss_dsi_ctrl_pdata), GFP_KERNEL);
+		if (!ctrl_pdata) {
+			pr_err("%s: FAILED: cannot alloc dsi ctrl\n", __func__);
+			rc = -ENOMEM;
+			goto error_no_mem;
+		}
+		platform_set_drvdata(pdev, ctrl_pdata);
+	}
+
+	mdss_dsi_mres = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!mdss_dsi_mres) {
+		pr_err("%s:%d unable to get the MDSS reg resources",
+							__func__, __LINE__);
+		rc = -ENOMEM;
+		goto error_io_resource;
+	} else {
+		dsi_host_private->dsi_reg_size = resource_size(mdss_dsi_mres);
+		dsi_host_private->dsi_base = ioremap(mdss_dsi_mres->start,
+						dsi_host_private->dsi_reg_size);
+		if (!dsi_host_private->dsi_base) {
+			pr_err("%s:%d unable to remap dsi resources",
+							__func__, __LINE__);
+			rc = -ENOMEM;
+			goto error_io_resource;
+		}
+	}
+
+	mdss_dsi_mres = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+	if (!mdss_dsi_mres || mdss_dsi_mres->start == 0) {
+		pr_err("%s:%d unable to get the MDSS irq resources",
+							__func__, __LINE__);
+		rc = -ENODEV;
+		goto error_irq_resource;
+	} else {
+		rc = msm_dsi_irq_init(&pdev->dev, mdss_dsi_mres->start);
+		if (rc) {
+			dev_err(&pdev->dev, "%s: failed to init irq, rc=%d\n",
+								__func__, rc);
+			goto error_irq_resource;
+		}
+	}
+
+	rc = of_platform_populate(pdev->dev.of_node, NULL, NULL, &pdev->dev);
+	if (rc) {
+		dev_err(&pdev->dev, "%s: failed to add child nodes, rc=%d\n",
+								__func__, rc);
+		goto error_platform_pop;
+	}
+
+	/* DSI panels can be different between controllers */
+	rc = dsi_get_panel_cfg(panel_cfg);
+	if (!rc)
+		/* dsi panel cfg not present */
+		pr_warn("%s:%d:dsi specific cfg not present\n",
+							 __func__, __LINE__);
+
+	/* find panel device node */
+	dsi_pan_node = dsi_find_panel_of_node(pdev, panel_cfg);
+	if (!dsi_pan_node) {
+		pr_err("%s: can't find panel node %s\n", __func__,
+								panel_cfg);
+		goto error_pan_node;
+	}
+
+	cmd_cfg_cont_splash = mdp3_panel_get_boot_cfg() ? true : false;
+
+	rc = mdss_dsi_panel_init(dsi_pan_node, ctrl_pdata, cmd_cfg_cont_splash);
+	if (rc) {
+		pr_err("%s: dsi panel init failed\n", __func__);
+		goto error_pan_node;
+	}
+
+	rc = dsi_ctrl_config_init(pdev, ctrl_pdata);
+	if (rc) {
+		dev_err(&pdev->dev, "%s: failed to parse mdss dtsi rc=%d\n",
+								__func__, rc);
+		goto error_pan_node;
+	}
+
+	rc = msm_dsi_io_init(pdev, &(ctrl_pdata->power_data));
+	if (rc) {
+		dev_err(&pdev->dev, "%s: failed to init DSI IO, rc=%d\n",
+								__func__, rc);
+		goto error_io_init;
+	}
+
+	pr_debug("%s: Dsi Ctrl->0 initialized\n", __func__);
 
 	dsi_host_private->dis_dev = pdev->dev;
 	intf.on = msm_dsi_on;
@@ -992,25 +1163,51 @@
 	dsi_register_interface(&intf);
 
 	msm_dsi_debug_init();
+
+	rc = dsi_panel_device_register_v2(pdev, ctrl_pdata);
+	if (rc) {
+		pr_err("%s: dsi panel dev reg failed\n", __func__);
+		goto error_device_register;
+	}
 	pr_debug("%s success\n", __func__);
 	return 0;
-dsi_probe_error:
+error_device_register:
+	msm_dsi_io_deinit(pdev, &(ctrl_pdata->power_data));
+error_io_init:
+	dsi_ctrl_config_deinit(pdev, ctrl_pdata);
+error_pan_node:
+	of_node_put(dsi_pan_node);
+error_platform_pop:
+	msm_dsi_disable_irq();
+error_irq_resource:
 	if (dsi_host_private->dsi_base) {
 		iounmap(dsi_host_private->dsi_base);
 		dsi_host_private->dsi_base = NULL;
 	}
-	msm_dsi_io_deinit();
+error_io_resource:
+	devm_kfree(&pdev->dev, ctrl_pdata);
+error_no_mem:
 	msm_dsi_deinit();
+
 	return rc;
 }
 
 static int __devexit msm_dsi_remove(struct platform_device *pdev)
 {
+	struct mdss_dsi_ctrl_pdata *ctrl_pdata = platform_get_drvdata(pdev);
+	if (!ctrl_pdata) {
+		pr_err("%s: no driver data\n", __func__);
+		return -ENODEV;
+	}
+
 	msm_dsi_disable_irq();
-	msm_dsi_io_deinit();
+	msm_dsi_io_deinit(pdev, &(ctrl_pdata->power_data));
+	dsi_ctrl_config_deinit(pdev, ctrl_pdata);
 	iounmap(dsi_host_private->dsi_base);
 	dsi_host_private->dsi_base = NULL;
 	msm_dsi_deinit();
+	devm_kfree(&pdev->dev, ctrl_pdata);
+
 	return 0;
 }
 
diff --git a/drivers/video/msm/mdss/dsi_io_v2.c b/drivers/video/msm/mdss/dsi_io_v2.c
index 365c32f..2c2b3d1 100644
--- a/drivers/video/msm/mdss/dsi_io_v2.c
+++ b/drivers/video/msm/mdss/dsi_io_v2.c
@@ -24,7 +24,6 @@
 #include "dsi_host_v2.h"
 
 struct msm_dsi_io_private {
-	struct regulator *vdda_vreg;
 	struct clk *dsi_byte_clk;
 	struct clk *dsi_esc_clk;
 	struct clk *dsi_pixel_clk;
@@ -51,7 +50,7 @@
 	}
 }
 
-int msm_dsi_io_init(struct platform_device *dev)
+int msm_dsi_io_init(struct platform_device *pdev, struct dss_module_power *mp)
 {
 	int rc;
 
@@ -64,25 +63,29 @@
 		}
 	}
 
-	rc = msm_dsi_clk_init(dev);
+	rc = msm_dsi_clk_init(pdev);
 	if (rc) {
 		pr_err("fail to initialize DSI clock\n");
 		return rc;
 	}
 
-	rc = msm_dsi_regulator_init(dev);
+	rc = msm_dss_config_vreg(&pdev->dev, mp->vreg_config,
+						mp->num_vreg, 1);
 	if (rc) {
 		pr_err("fail to initialize DSI regulator\n");
 		return rc;
 	}
+
 	return 0;
 }
 
-void msm_dsi_io_deinit(void)
+void msm_dsi_io_deinit(struct platform_device *pdev,
+				 struct dss_module_power *mp)
 {
 	if (dsi_io_private) {
 		msm_dsi_clk_deinit();
-		msm_dsi_regulator_deinit();
+		msm_dss_config_vreg(&pdev->dev, mp->vreg_config,
+					mp->num_vreg, 0);
 		kfree(dsi_io_private);
 		dsi_io_private = NULL;
 	}
@@ -242,61 +245,6 @@
 	return 0;
 }
 
-int msm_dsi_regulator_init(struct platform_device *dev)
-{
-	int ret = 0;
-
-	dsi_io_private->vdda_vreg = devm_regulator_get(&dev->dev, "vdda");
-	if (IS_ERR(dsi_io_private->vdda_vreg)) {
-		ret = PTR_ERR(dsi_io_private->vdda_vreg);
-		pr_err("could not get vdda 8110_l4, ret=%d\n", ret);
-		return ret;
-	}
-
-	ret = regulator_set_voltage(dsi_io_private->vdda_vreg, DSI_VDDA_VOLTAGE,
-					DSI_VDDA_VOLTAGE);
-	if (ret)
-		pr_err("vdd_io_vreg->set_voltage failed, ret=%d\n", ret);
-
-	return ret;
-}
-
-void msm_dsi_regulator_deinit(void)
-{
-	if (!IS_ERR(dsi_io_private->vdda_vreg)) {
-		devm_regulator_put(dsi_io_private->vdda_vreg);
-		dsi_io_private->vdda_vreg = NULL;
-	}
-}
-
-int msm_dsi_regulator_enable(void)
-{
-	int ret;
-
-	ret = regulator_enable(dsi_io_private->vdda_vreg);
-	if (ret) {
-		pr_err("%s: Failed to enable regulator.\n", __func__);
-		return ret;
-	}
-	msleep(20); /*per DSI controller spec*/
-	return ret;
-}
-
-int msm_dsi_regulator_disable(void)
-{
-	int ret;
-
-	ret = regulator_disable(dsi_io_private->vdda_vreg);
-	if (ret) {
-		pr_err("%s: Failed to disable regulator.\n", __func__);
-		return ret;
-	}
-	wmb();
-	msleep(20); /*per DSI controller spec*/
-
-	return ret;
-}
-
 static void msm_dsi_phy_strength_init(unsigned char *ctrl_base,
 					struct mdss_dsi_phy_ctrl *pd)
 {
@@ -362,12 +310,12 @@
 	for (ln = 0; ln < 5; ln++) {
 		unsigned char *off = ctrl_base + 0x0300 + (ln * 0x40);
 		index = ln * 6;
-		MIPI_OUTP(off, pd->laneCfg[index]);
-		MIPI_OUTP(off + 4, pd->laneCfg[index + 1]);
-		MIPI_OUTP(off + 8, pd->laneCfg[index + 2]);
-		MIPI_OUTP(off + 12, pd->laneCfg[index + 3]);
-		MIPI_OUTP(off + 20, pd->laneCfg[index + 4]);
-		MIPI_OUTP(off + 24, pd->laneCfg[index + 5]);
+		MIPI_OUTP(off, pd->lanecfg[index]);
+		MIPI_OUTP(off + 4, pd->lanecfg[index + 1]);
+		MIPI_OUTP(off + 8, pd->lanecfg[index + 2]);
+		MIPI_OUTP(off + 12, pd->lanecfg[index + 3]);
+		MIPI_OUTP(off + 20, pd->lanecfg[index + 4]);
+		MIPI_OUTP(off + 24, pd->lanecfg[index + 5]);
 	}
 	wmb();
 }
@@ -386,9 +334,9 @@
 static void msm_dsi_phy_bist_init(unsigned char *ctrl_base,
 			struct mdss_dsi_phy_ctrl *pd)
 {
-	MIPI_OUTP(ctrl_base + DSI_DSIPHY_BIST_CTRL4, pd->bistCtrl[4]);
-	MIPI_OUTP(ctrl_base + DSI_DSIPHY_BIST_CTRL1, pd->bistCtrl[1]);
-	MIPI_OUTP(ctrl_base + DSI_DSIPHY_BIST_CTRL0, pd->bistCtrl[0]);
+	MIPI_OUTP(ctrl_base + DSI_DSIPHY_BIST_CTRL4, pd->bistctrl[4]);
+	MIPI_OUTP(ctrl_base + DSI_DSIPHY_BIST_CTRL1, pd->bistctrl[1]);
+	MIPI_OUTP(ctrl_base + DSI_DSIPHY_BIST_CTRL0, pd->bistctrl[0]);
 	MIPI_OUTP(ctrl_base + DSI_DSIPHY_BIST_CTRL4, 0);
 	wmb();
 }
@@ -398,7 +346,7 @@
 {
 	struct mdss_dsi_phy_ctrl *pd;
 
-	pd = pdata->panel_info.mipi.dsi_phy_db;
+	pd = &(pdata->panel_info.mipi.dsi_phy_db);
 
 	msm_dsi_phy_strength_init(ctrl_base, pd);
 
diff --git a/drivers/video/msm/mdss/dsi_io_v2.h b/drivers/video/msm/mdss/dsi_io_v2.h
index a7d43a0..fd1c41e 100644
--- a/drivers/video/msm/mdss/dsi_io_v2.h
+++ b/drivers/video/msm/mdss/dsi_io_v2.h
@@ -17,9 +17,11 @@
 
 void msm_dsi_ahb_ctrl(int enable);
 
-int msm_dsi_io_init(struct platform_device *dev);
+int msm_dsi_io_init(struct platform_device *dev,
+				struct dss_module_power *mp);
 
-void msm_dsi_io_deinit(void);
+void msm_dsi_io_deinit(struct platform_device *dev,
+				struct dss_module_power *mp);
 
 int msm_dsi_clk_init(struct platform_device *dev);
 
@@ -38,14 +40,6 @@
 
 int msm_dsi_clk_disable(void);
 
-int msm_dsi_regulator_init(struct platform_device *dev);
-
-void msm_dsi_regulator_deinit(void);
-
-int msm_dsi_regulator_enable(void);
-
-int msm_dsi_regulator_disable(void);
-
 int msm_dsi_phy_init(unsigned char *ctrl_base,
 			struct mdss_panel_data *pdata);
 
diff --git a/drivers/video/msm/mdss/dsi_panel_v2.c b/drivers/video/msm/mdss/dsi_panel_v2.c
deleted file mode 100644
index b1a4293..0000000
--- a/drivers/video/msm/mdss/dsi_panel_v2.c
+++ /dev/null
@@ -1,923 +0,0 @@
-/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- */
-
-#include <linux/module.h>
-#include <linux/interrupt.h>
-#include <linux/of.h>
-#include <linux/of_gpio.h>
-#include <linux/of_device.h>
-#include <linux/qpnp/pin.h>
-#include <linux/gpio.h>
-#include <linux/delay.h>
-#include <linux/slab.h>
-#include <linux/leds.h>
-#include <linux/err.h>
-#include <linux/regulator/consumer.h>
-
-#include "dsi_v2.h"
-
-#define DT_CMD_HDR 6
-
-struct dsi_panel_private {
-	struct dsi_buf dsi_panel_tx_buf;
-	struct dsi_buf dsi_panel_rx_buf;
-
-	int rst_gpio;
-	int disp_en_gpio;
-	int video_mode_gpio;
-	int te_gpio;
-	char bl_ctrl;
-
-	struct regulator *vddio_vreg;
-	struct regulator *vdda_vreg;
-
-	struct dsi_panel_cmds_list *on_cmds_list;
-	struct dsi_panel_cmds_list *off_cmds_list;
-	struct mdss_dsi_phy_ctrl phy_params;
-
-	char *on_cmds;
-	char *off_cmds;
-};
-
-static struct dsi_panel_private *panel_private;
-
-DEFINE_LED_TRIGGER(bl_led_trigger);
-
-int dsi_panel_init(void)
-{
-	int rc;
-
-	if (!panel_private) {
-		panel_private = kzalloc(sizeof(struct dsi_panel_private),
-					GFP_KERNEL);
-		if (!panel_private) {
-			pr_err("fail to alloc dsi panel private data\n");
-			return -ENOMEM;
-		}
-	}
-
-	rc = dsi_buf_alloc(&panel_private->dsi_panel_tx_buf,
-				ALIGN(DSI_BUF_SIZE,
-				SZ_4K));
-	if (rc)
-		return rc;
-
-	rc = dsi_buf_alloc(&panel_private->dsi_panel_rx_buf,
-				ALIGN(DSI_BUF_SIZE,
-				SZ_4K));
-	if (rc)
-		return rc;
-
-	return 0;
-}
-
-void dsi_panel_deinit(void)
-{
-	if (!panel_private)
-		return;
-
-	kfree(panel_private->dsi_panel_tx_buf.start);
-	kfree(panel_private->dsi_panel_rx_buf.start);
-
-	if (!IS_ERR(panel_private->vddio_vreg))
-		devm_regulator_put(panel_private->vddio_vreg);
-
-	if (!IS_ERR(panel_private->vdda_vreg))
-		devm_regulator_put(panel_private->vdda_vreg);
-
-	if (panel_private->on_cmds_list) {
-		kfree(panel_private->on_cmds_list->buf);
-		kfree(panel_private->on_cmds_list);
-	}
-	if (panel_private->off_cmds_list) {
-		kfree(panel_private->off_cmds_list->buf);
-		kfree(panel_private->off_cmds_list);
-	}
-
-	kfree(panel_private->on_cmds);
-	kfree(panel_private->off_cmds);
-
-	kfree(panel_private);
-	panel_private = NULL;
-
-	if (bl_led_trigger) {
-		led_trigger_unregister_simple(bl_led_trigger);
-		bl_led_trigger = NULL;
-	}
-}
-int dsi_panel_power(int enable)
-{
-	int ret;
-	if (enable) {
-		ret = regulator_enable(panel_private->vddio_vreg);
-		if (ret) {
-			pr_err("dsi_panel_power regulator enable vddio fail\n");
-			return ret;
-		}
-		ret = regulator_enable(panel_private->vdda_vreg);
-		if (ret) {
-			pr_err("dsi_panel_power regulator enable vdda fail\n");
-			return ret;
-		}
-	} else {
-		ret = regulator_disable(panel_private->vddio_vreg);
-		if (ret) {
-			pr_err("dsi_panel_power regulator disable vddio fail\n");
-			return ret;
-		}
-		ret = regulator_disable(panel_private->vdda_vreg);
-		if (ret) {
-			pr_err("dsi_panel_power regulator dsiable vdda fail\n");
-			return ret;
-		}
-	}
-	return 0;
-}
-
-static char led_pwm1[2] = {0x51, 0x0};	/* DTYPE_DCS_WRITE1 */
-static struct dsi_cmd_desc backlight_cmd = {
-	DTYPE_DCS_WRITE1, 1, 0, 0, 1, sizeof(led_pwm1), led_pwm1};
-
-static void dsi_panel_bklt_dcs(struct mdss_panel_data *pdata, int level)
-{
-	struct mipi_panel_info *mipi;
-
-	mipi  = &pdata->panel_info.mipi;
-
-	pr_debug("%s: dcs level=%d\n", __func__, level);
-
-	led_pwm1[1] = (unsigned char)level;
-
-	if (DSI_VIDEO_MODE == mipi->mode) {
-		dsi_set_tx_power_mode(0);
-		dsi_cmds_tx_v2(pdata, &panel_private->dsi_panel_tx_buf,
-					&backlight_cmd,
-					1);
-		dsi_set_tx_power_mode(1);
-	}
-}
-
-void dsi_panel_reset(struct mdss_panel_data *pdata, int enable)
-{
-	if (pdata == NULL) {
-		pr_err("%s: Invalid input data\n", __func__);
-		return;
-	}
-
-	if (!gpio_is_valid(panel_private->disp_en_gpio)) {
-		pr_debug("%s:%d, reset line not configured\n",
-			   __func__, __LINE__);
-	}
-
-	if (!gpio_is_valid(panel_private->rst_gpio)) {
-		pr_debug("%s:%d, reset line not configured\n",
-			   __func__, __LINE__);
-		return;
-	}
-
-	pr_debug("%s: enable = %d\n", __func__, enable);
-
-	if (enable == 2) {
-		dsi_panel_power(1);
-		gpio_request(panel_private->rst_gpio, "panel_reset");
-		gpio_set_value(panel_private->rst_gpio, 1);
-		if (gpio_is_valid(panel_private->disp_en_gpio)) {
-			gpio_request(panel_private->disp_en_gpio,
-					"panel_enable");
-			gpio_set_value(panel_private->disp_en_gpio, 1);
-		}
-		if (gpio_is_valid(panel_private->video_mode_gpio)) {
-			gpio_request(panel_private->video_mode_gpio,
-					"panel_video_mdoe");
-			if (pdata->panel_info.mipi.mode == DSI_VIDEO_MODE)
-				gpio_set_value(panel_private->video_mode_gpio,
-						1);
-			else
-				gpio_set_value(panel_private->video_mode_gpio,
-						0);
-		}
-		if (gpio_is_valid(panel_private->te_gpio))
-			gpio_request(panel_private->te_gpio, "panel_te");
-	} else if (enable == 1) {
-		dsi_panel_power(1);
-		gpio_request(panel_private->rst_gpio, "panel_reset");
-		gpio_set_value(panel_private->rst_gpio, 1);
-		/*
-		 * these delay values are by experiments currently, will need
-		 * to move to device tree late
-		 */
-		msleep(20);
-		gpio_set_value(panel_private->rst_gpio, 0);
-		udelay(200);
-		gpio_set_value(panel_private->rst_gpio, 1);
-		msleep(20);
-		if (gpio_is_valid(panel_private->disp_en_gpio)) {
-			gpio_request(panel_private->disp_en_gpio,
-					"panel_enable");
-			gpio_set_value(panel_private->disp_en_gpio, 1);
-		}
-		if (gpio_is_valid(panel_private->video_mode_gpio)) {
-			gpio_request(panel_private->video_mode_gpio,
-					"panel_video_mdoe");
-			if (pdata->panel_info.mipi.mode == DSI_VIDEO_MODE)
-				gpio_set_value(panel_private->video_mode_gpio,
-						1);
-			else
-				gpio_set_value(panel_private->video_mode_gpio,
-						0);
-		}
-		if (gpio_is_valid(panel_private->te_gpio))
-			gpio_request(panel_private->te_gpio, "panel_te");
-	} else {
-		gpio_set_value(panel_private->rst_gpio, 0);
-		gpio_free(panel_private->rst_gpio);
-
-		if (gpio_is_valid(panel_private->disp_en_gpio)) {
-			gpio_set_value(panel_private->disp_en_gpio, 0);
-			gpio_free(panel_private->disp_en_gpio);
-		}
-
-		if (gpio_is_valid(panel_private->video_mode_gpio))
-			gpio_free(panel_private->video_mode_gpio);
-
-		if (gpio_is_valid(panel_private->te_gpio))
-			gpio_free(panel_private->te_gpio);
-		dsi_panel_power(0);
-	}
-}
-
-static void dsi_panel_bl_ctrl(struct mdss_panel_data *pdata,
-				u32 bl_level)
-{
-	if (panel_private->bl_ctrl) {
-		switch (panel_private->bl_ctrl) {
-		case BL_WLED:
-			led_trigger_event(bl_led_trigger, bl_level);
-			break;
-
-		case BL_DCS_CMD:
-			dsi_panel_bklt_dcs(pdata, bl_level);
-			break;
-
-		default:
-			pr_err("%s: Unknown bl_ctrl configuration\n",
-				__func__);
-			break;
-		}
-	} else
-		pr_err("%s:%d, bl_ctrl not configured", __func__, __LINE__);
-}
-
-static int dsi_panel_on(struct mdss_panel_data *pdata)
-{
-	struct mipi_panel_info *mipi;
-
-	mipi  = &pdata->panel_info.mipi;
-
-	pr_debug("%s:%d, debug info (mode) : %d\n", __func__, __LINE__,
-		 mipi->mode);
-
-
-	return dsi_cmds_tx_v2(pdata, &panel_private->dsi_panel_tx_buf,
-					panel_private->on_cmds_list->buf,
-					panel_private->on_cmds_list->size);
-}
-
-static int dsi_panel_off(struct mdss_panel_data *pdata)
-{
-	struct mipi_panel_info *mipi;
-	mipi  = &pdata->panel_info.mipi;
-
-	pr_debug("%s:%d, debug info\n", __func__, __LINE__);
-
-
-	return dsi_cmds_tx_v2(pdata, &panel_private->dsi_panel_tx_buf,
-					panel_private->off_cmds_list->buf,
-					panel_private->off_cmds_list->size);
-}
-
-static int dsi_panel_parse_gpio(struct platform_device *pdev)
-{
-	struct device_node *np = pdev->dev.of_node;
-	panel_private->disp_en_gpio = of_get_named_gpio(np,
-						"qcom,enable-gpio", 0);
-	panel_private->rst_gpio = of_get_named_gpio(np, "qcom,rst-gpio", 0);
-	panel_private->video_mode_gpio = of_get_named_gpio(np,
-						"qcom,mode-selection-gpio", 0);
-	panel_private->te_gpio = of_get_named_gpio(np,
-						"qcom,te-gpio", 0);
-	return 0;
-}
-
-static int dsi_panel_parse_regulator(struct platform_device *pdev)
-{
-	int ret;
-	panel_private->vddio_vreg = devm_regulator_get(&pdev->dev, "vddio");
-	if (IS_ERR(panel_private->vddio_vreg)) {
-		pr_err("%s: could not get vddio vreg, rc=%ld\n",
-			__func__, PTR_ERR(panel_private->vddio_vreg));
-		return PTR_ERR(panel_private->vddio_vreg);
-	}
-	ret = regulator_set_voltage(panel_private->vddio_vreg,
-					1800000,
-					1800000);
-	if (ret) {
-		pr_err("%s: set voltage failed on vddio_vreg, rc=%d\n",
-			__func__, ret);
-		return ret;
-	}
-	panel_private->vdda_vreg = devm_regulator_get(&pdev->dev, "vdda");
-	if (IS_ERR(panel_private->vdda_vreg)) {
-		pr_err("%s: could not get vdda_vreg , rc=%ld\n",
-			__func__, PTR_ERR(panel_private->vdda_vreg));
-		return PTR_ERR(panel_private->vdda_vreg);
-	}
-	ret = regulator_set_voltage(panel_private->vdda_vreg,
-					2850000,
-					2850000);
-	if (ret) {
-		pr_err("%s: set voltage failed on vdda_vreg, rc=%d\n",
-			__func__, ret);
-		return ret;
-	}
-	return 0;
-}
-
-static int dsi_panel_parse_timing(struct platform_device *pdev,
-				struct dsi_panel_common_pdata *panel_data)
-{
-	struct device_node *np = pdev->dev.of_node;
-	u32 res[6], tmp;
-	int rc;
-
-	rc = of_property_read_u32_array(np, "qcom,mdss-pan-res", res, 2);
-	if (rc) {
-		pr_err("%s:%d, panel resolution not specified\n",
-						__func__, __LINE__);
-		return -EINVAL;
-	}
-
-	panel_data->panel_info.xres = (!rc ? res[0] : 480);
-	panel_data->panel_info.yres = (!rc ? res[1] : 800);
-
-	rc = of_property_read_u32_array(np, "qcom,mdss-pan-active-res", res, 2);
-	if (rc == 0) {
-		panel_data->panel_info.lcdc.xres_pad =
-			panel_data->panel_info.xres - res[0];
-		panel_data->panel_info.lcdc.yres_pad =
-			panel_data->panel_info.yres - res[1];
-	}
-
-	rc = of_property_read_u32(np, "qcom,mdss-pan-bpp", &tmp);
-	if (rc) {
-		pr_err("%s:%d, panel bpp not specified\n",
-						__func__, __LINE__);
-		return -EINVAL;
-	}
-	panel_data->panel_info.bpp = (!rc ? tmp : 24);
-
-	rc = of_property_read_u32_array(np,
-		"qcom,mdss-pan-porch-values", res, 6);
-	if (rc) {
-		pr_err("%s:%d, panel porch not specified\n",
-						__func__, __LINE__);
-		return -EINVAL;
-	}
-
-	panel_data->panel_info.lcdc.h_back_porch = (!rc ? res[0] : 6);
-	panel_data->panel_info.lcdc.h_pulse_width = (!rc ? res[1] : 2);
-	panel_data->panel_info.lcdc.h_front_porch = (!rc ? res[2] : 6);
-	panel_data->panel_info.lcdc.v_back_porch = (!rc ? res[3] : 6);
-	panel_data->panel_info.lcdc.v_pulse_width = (!rc ? res[4] : 2);
-	panel_data->panel_info.lcdc.v_front_porch = (!rc ? res[5] : 6);
-
-	return 0;
-}
-
-static int dsi_panel_parse_phy(struct platform_device *pdev,
-				struct dsi_panel_common_pdata *panel_data)
-{
-	struct device_node *np = pdev->dev.of_node;
-	int i, len;
-	const char *data;
-
-	data = of_get_property(np, "qcom,panel-phy-regulatorSettings", &len);
-	if ((!data) || (len != 6)) {
-		pr_err("%s:%d, Unable to read Phy regulator settings",
-			__func__, __LINE__);
-		return -EINVAL;
-	}
-	for (i = 0; i < len; i++)
-		panel_private->phy_params.regulator[i] = data[i];
-
-	data = of_get_property(np, "qcom,panel-phy-timingSettings", &len);
-	if ((!data) || (len != 12)) {
-		pr_err("%s:%d, Unable to read Phy timing settings",
-			__func__, __LINE__);
-		return -EINVAL;
-	}
-	for (i = 0; i < len; i++)
-		panel_private->phy_params.timing[i] = data[i];
-
-	data = of_get_property(np, "qcom,panel-phy-strengthCtrl", &len);
-	if ((!data) || (len != 2)) {
-		pr_err("%s:%d, Unable to read Phy Strength ctrl settings",
-			__func__, __LINE__);
-		return -EINVAL;
-	}
-	panel_private->phy_params.strength[0] = data[0];
-	panel_private->phy_params.strength[1] = data[1];
-
-	data = of_get_property(np, "qcom,panel-phy-bistCtrl", &len);
-	if ((!data) || (len != 6)) {
-		pr_err("%s:%d, Unable to read Phy Bist Ctrl settings",
-			__func__, __LINE__);
-		return -EINVAL;
-	}
-	for (i = 0; i < len; i++)
-		panel_private->phy_params.bistCtrl[i] = data[i];
-
-	data = of_get_property(np, "qcom,panel-phy-laneConfig", &len);
-	if ((!data) || (len != 30)) {
-		pr_err("%s:%d, Unable to read Phy lane configure settings",
-			__func__, __LINE__);
-		return -EINVAL;
-	}
-	for (i = 0; i < len; i++)
-		panel_private->phy_params.laneCfg[i] = data[i];
-
-	panel_data->panel_info.mipi.dsi_phy_db = &panel_private->phy_params;
-	return 0;
-}
-
-static int dsi_panel_parse_init_cmds(struct platform_device *pdev,
-				struct dsi_panel_common_pdata *panel_data)
-{
-	struct device_node *np = pdev->dev.of_node;
-	int i, len;
-	int cmd_plen, data_offset;
-	const char *data;
-	const char *on_cmds_state, *off_cmds_state;
-	int num_of_on_cmds = 0, num_of_off_cmds = 0;
-
-	data = of_get_property(np, "qcom,panel-on-cmds", &len);
-	if (!data) {
-		pr_err("%s:%d, Unable to read ON cmds", __func__, __LINE__);
-		return -EINVAL;
-	}
-
-	panel_private->on_cmds = kzalloc(sizeof(char) * len, GFP_KERNEL);
-	if (!panel_private->on_cmds)
-		return -ENOMEM;
-
-	memcpy(panel_private->on_cmds, data, len);
-
-	data_offset = 0;
-	cmd_plen = 0;
-	while ((len - data_offset) >= DT_CMD_HDR) {
-		data_offset += (DT_CMD_HDR - 1);
-		cmd_plen = panel_private->on_cmds[data_offset++];
-		data_offset += cmd_plen;
-		num_of_on_cmds++;
-	}
-	if (!num_of_on_cmds) {
-		pr_err("%s:%d, No ON cmds specified", __func__, __LINE__);
-		return -EINVAL;
-	}
-
-	panel_private->on_cmds_list =
-		kzalloc(sizeof(struct dsi_panel_cmds_list), GFP_KERNEL);
-	if (!panel_private->on_cmds_list)
-		return -ENOMEM;
-
-	panel_private->on_cmds_list->buf =
-		kzalloc((num_of_on_cmds * sizeof(struct dsi_cmd_desc)),
-			GFP_KERNEL);
-	if (!panel_private->on_cmds_list->buf)
-		return -ENOMEM;
-
-	data_offset = 0;
-	for (i = 0; i < num_of_on_cmds; i++) {
-		panel_private->on_cmds_list->buf[i].dtype =
-					panel_private->on_cmds[data_offset++];
-		panel_private->on_cmds_list->buf[i].last =
-					panel_private->on_cmds[data_offset++];
-		panel_private->on_cmds_list->buf[i].vc =
-					panel_private->on_cmds[data_offset++];
-		panel_private->on_cmds_list->buf[i].ack =
-					panel_private->on_cmds[data_offset++];
-		panel_private->on_cmds_list->buf[i].wait =
-					panel_private->on_cmds[data_offset++];
-		panel_private->on_cmds_list->buf[i].dlen =
-					panel_private->on_cmds[data_offset++];
-		panel_private->on_cmds_list->buf[i].payload =
-					&panel_private->on_cmds[data_offset];
-		data_offset += (panel_private->on_cmds_list->buf[i].dlen);
-	}
-
-	if (data_offset != len) {
-		pr_err("%s:%d, Incorrect ON command entries",
-						__func__, __LINE__);
-		return -EINVAL;
-	}
-
-	panel_private->on_cmds_list->size = num_of_on_cmds;
-
-	on_cmds_state = of_get_property(pdev->dev.of_node,
-					"qcom,on-cmds-dsi-state", NULL);
-	if (!strncmp(on_cmds_state, "DSI_LP_MODE", 11)) {
-		panel_private->on_cmds_list->ctrl_state = DSI_LP_MODE;
-	} else if (!strncmp(on_cmds_state, "DSI_HS_MODE", 11)) {
-		panel_private->on_cmds_list->ctrl_state = DSI_HS_MODE;
-	} else {
-		pr_debug("%s: ON cmds state not specified. Set Default\n",
-							__func__);
-		panel_private->on_cmds_list->ctrl_state = DSI_LP_MODE;
-	}
-
-	panel_data->dsi_panel_on_cmds = panel_private->on_cmds_list;
-
-	data = of_get_property(np, "qcom,panel-off-cmds", &len);
-	if (!data) {
-		pr_err("%s:%d, Unable to read OFF cmds", __func__, __LINE__);
-		return -EINVAL;
-	}
-
-	panel_private->off_cmds = kzalloc(sizeof(char) * len, GFP_KERNEL);
-	if (!panel_private->off_cmds)
-		return -ENOMEM;
-
-	memcpy(panel_private->off_cmds, data, len);
-
-	data_offset = 0;
-	cmd_plen = 0;
-	while ((len - data_offset) >= DT_CMD_HDR) {
-		data_offset += (DT_CMD_HDR - 1);
-		cmd_plen = panel_private->off_cmds[data_offset++];
-		data_offset += cmd_plen;
-		num_of_off_cmds++;
-	}
-	if (!num_of_off_cmds) {
-		pr_err("%s:%d, No OFF cmds specified", __func__, __LINE__);
-		return -ENOMEM;
-	}
-
-	panel_private->off_cmds_list =
-		kzalloc(sizeof(struct dsi_panel_cmds_list), GFP_KERNEL);
-	if (!panel_private->off_cmds_list)
-		return -ENOMEM;
-
-	panel_private->off_cmds_list->buf = kzalloc(num_of_off_cmds
-					* sizeof(struct dsi_cmd_desc),
-						GFP_KERNEL);
-	if (!panel_private->off_cmds_list->buf)
-		return -ENOMEM;
-
-	data_offset = 0;
-	for (i = 0; i < num_of_off_cmds; i++) {
-		panel_private->off_cmds_list->buf[i].dtype =
-					panel_private->off_cmds[data_offset++];
-		panel_private->off_cmds_list->buf[i].last =
-					panel_private->off_cmds[data_offset++];
-		panel_private->off_cmds_list->buf[i].vc =
-					panel_private->off_cmds[data_offset++];
-		panel_private->off_cmds_list->buf[i].ack =
-					panel_private->off_cmds[data_offset++];
-		panel_private->off_cmds_list->buf[i].wait =
-					panel_private->off_cmds[data_offset++];
-		panel_private->off_cmds_list->buf[i].dlen =
-					panel_private->off_cmds[data_offset++];
-		panel_private->off_cmds_list->buf[i].payload =
-					&panel_private->off_cmds[data_offset];
-		data_offset += (panel_private->off_cmds_list->buf[i].dlen);
-	}
-
-	if (data_offset != len) {
-		pr_err("%s:%d, Incorrect OFF command entries",
-						__func__, __LINE__);
-		return -EINVAL;
-	}
-
-	panel_private->off_cmds_list->size = num_of_off_cmds;
-	off_cmds_state = of_get_property(pdev->dev.of_node,
-				"qcom,off-cmds-dsi-state", NULL);
-	if (!strncmp(off_cmds_state, "DSI_LP_MODE", 11)) {
-		panel_private->off_cmds_list->ctrl_state =
-						DSI_LP_MODE;
-	} else if (!strncmp(off_cmds_state, "DSI_HS_MODE", 11)) {
-		panel_private->off_cmds_list->ctrl_state = DSI_HS_MODE;
-	} else {
-		pr_debug("%s: ON cmds state not specified. Set Default\n",
-							__func__);
-		panel_private->off_cmds_list->ctrl_state = DSI_LP_MODE;
-	}
-
-	panel_data->dsi_panel_off_cmds = panel_private->off_cmds_list;
-
-	return 0;
-}
-
-static int dsi_panel_parse_backlight(struct platform_device *pdev,
-				struct dsi_panel_common_pdata *panel_data,
-				char *bl_ctrl)
-{
-	int rc;
-	u32 res[6];
-	static const char *bl_ctrl_type;
-
-	bl_ctrl_type = of_get_property(pdev->dev.of_node,
-				  "qcom,mdss-pan-bl-ctrl", NULL);
-	if ((bl_ctrl_type) && (!strncmp(bl_ctrl_type, "bl_ctrl_wled", 12))) {
-		led_trigger_register_simple("bkl-trigger", &bl_led_trigger);
-		pr_debug("%s: SUCCESS-> WLED TRIGGER register\n", __func__);
-		*bl_ctrl = BL_WLED;
-	} else if ((bl_ctrl_type) && (!strncmp(bl_ctrl_type,
-				"bl_ctrl_dcs", 11))) {
-		pr_debug("%s: SUCCESS-> DCS COMMAND register\n", __func__);
-		*bl_ctrl = BL_DCS_CMD;
-	}
-	rc = of_property_read_u32_array(pdev->dev.of_node,
-		"qcom,mdss-pan-bl-levels", res, 2);
-	panel_data->panel_info.bl_min = (!rc ? res[0] : 0);
-	panel_data->panel_info.bl_max = (!rc ? res[1] : 255);
-	return rc;
-}
-
-static int dsi_panel_parse_other(struct platform_device *pdev,
-				struct dsi_panel_common_pdata *panel_data)
-{
-	const char *pdest;
-	u32 tmp;
-	int rc;
-	bool cont_splash_enabled = false;
-
-	pdest = of_get_property(pdev->dev.of_node,
-				"qcom,mdss-pan-dest", NULL);
-	if (strlen(pdest) != 9) {
-		pr_err("%s: Unknown pdest specified\n", __func__);
-		return -EINVAL;
-	}
-	if (!strncmp(pdest, "display_1", 9)) {
-		panel_data->panel_info.pdest = DISPLAY_1;
-	} else if (!strncmp(pdest, "display_2", 9)) {
-		panel_data->panel_info.pdest = DISPLAY_2;
-	} else {
-		pr_debug("%s: pdest not specified. Set Default\n",
-							__func__);
-		panel_data->panel_info.pdest = DISPLAY_1;
-	}
-
-	rc = of_property_read_u32(pdev->dev.of_node,
-		"qcom,mdss-pan-underflow-clr", &tmp);
-	panel_data->panel_info.lcdc.underflow_clr = (!rc ? tmp : 0xff);
-
-	cont_splash_enabled = of_property_read_bool(pdev->dev.of_node,
-		"qcom,cont-splash-enabled");
-	if (!cont_splash_enabled) {
-		pr_debug("%s:%d Continuous splash flag not found.\n",
-				__func__, __LINE__);
-		panel_data->panel_info.cont_splash_enabled = 0;
-	} else {
-		pr_debug("%s:%d Continuous splash flag enabled.\n",
-				__func__, __LINE__);
-		panel_data->panel_info.cont_splash_enabled = 1;
-	}
-	return rc;
-}
-
-static int dsi_panel_parse_host_cfg(struct platform_device *pdev,
-				struct dsi_panel_common_pdata *panel_data)
-{
-	struct device_node *np = pdev->dev.of_node;
-	u32 res[6], tmp;
-	int rc;
-
-	rc = of_property_read_u32(np, "qcom,mdss-pan-dsi-mode", &tmp);
-	panel_data->panel_info.mipi.mode = (!rc ? tmp : DSI_VIDEO_MODE);
-
-	rc = of_property_read_u32(np,
-		"qcom,mdss-pan-dsi-h-pulse-mode", &tmp);
-	panel_data->panel_info.mipi.pulse_mode_hsa_he = (!rc ? tmp : false);
-
-	rc = of_property_read_u32_array(np,
-		"qcom,mdss-pan-dsi-h-power-stop", res, 3);
-	panel_data->panel_info.mipi.hbp_power_stop = (!rc ? res[0] : false);
-	panel_data->panel_info.mipi.hsa_power_stop = (!rc ? res[1] : false);
-	panel_data->panel_info.mipi.hfp_power_stop = (!rc ? res[2] : false);
-
-	rc = of_property_read_u32_array(np,
-		"qcom,mdss-pan-dsi-bllp-power-stop", res, 2);
-	panel_data->panel_info.mipi.bllp_power_stop =
-					(!rc ? res[0] : false);
-	panel_data->panel_info.mipi.eof_bllp_power_stop =
-					(!rc ? res[1] : false);
-
-	rc = of_property_read_u32(np,
-		"qcom,mdss-pan-dsi-traffic-mode", &tmp);
-	panel_data->panel_info.mipi.traffic_mode =
-			(!rc ? tmp : DSI_NON_BURST_SYNCH_PULSE);
-
-	rc = of_property_read_u32(np,
-		"qcom,mdss-pan-dsi-dst-format", &tmp);
-	panel_data->panel_info.mipi.dst_format =
-			(!rc ? tmp : DSI_VIDEO_DST_FORMAT_RGB888);
-
-	rc = of_property_read_u32(np, "qcom,mdss-pan-dsi-vc", &tmp);
-	panel_data->panel_info.mipi.vc = (!rc ? tmp : 0);
-
-	rc = of_property_read_u32(np, "qcom,mdss-pan-dsi-rgb-swap", &tmp);
-	panel_data->panel_info.mipi.rgb_swap = (!rc ? tmp : DSI_RGB_SWAP_RGB);
-
-	rc = of_property_read_u32_array(np,
-		"qcom,mdss-pan-dsi-data-lanes", res, 4);
-	panel_data->panel_info.mipi.data_lane0 = (!rc ? res[0] : true);
-	panel_data->panel_info.mipi.data_lane1 = (!rc ? res[1] : false);
-	panel_data->panel_info.mipi.data_lane2 = (!rc ? res[2] : false);
-	panel_data->panel_info.mipi.data_lane3 = (!rc ? res[3] : false);
-
-	rc = of_property_read_u32(np, "qcom,mdss-pan-dsi-dlane-swap", &tmp);
-	panel_data->panel_info.mipi.dlane_swap = (!rc ? tmp : 0);
-
-	rc = of_property_read_u32_array(np, "qcom,mdss-pan-dsi-t-clk", res, 2);
-	panel_data->panel_info.mipi.t_clk_pre = (!rc ? res[0] : 0x24);
-	panel_data->panel_info.mipi.t_clk_post = (!rc ? res[1] : 0x03);
-
-	rc = of_property_read_u32(np, "qcom,mdss-pan-dsi-stream", &tmp);
-	panel_data->panel_info.mipi.stream = (!rc ? tmp : 0);
-
-	rc = of_property_read_u32(np, "qcom,mdss-pan-te-sel", &tmp);
-	panel_data->panel_info.mipi.te_sel = (!rc ? tmp : 1);
-
-	rc = of_property_read_u32(np, "qcom,mdss-pan-insert-dcs-cmd", &tmp);
-	panel_data->panel_info.mipi.insert_dcs_cmd = (!rc ? tmp : 1);
-
-	rc = of_property_read_u32(np, "qcom,mdss-pan-wr-mem-continue", &tmp);
-	panel_data->panel_info.mipi.wr_mem_continue = (!rc ? tmp : 0x3c);
-	rc = of_property_read_u32(np, "qcom,mdss-pan-wr-mem-start", &tmp);
-	panel_data->panel_info.mipi.wr_mem_start = (!rc ? tmp : 0x2c);
-
-	rc = of_property_read_u32(np, "qcom,mdss-pan-dsi-mdp-tr", &tmp);
-	panel_data->panel_info.mipi.mdp_trigger =
-			(!rc ? tmp : DSI_CMD_TRIGGER_SW);
-	if (panel_data->panel_info.mipi.mdp_trigger > 6) {
-		pr_err("%s:%d, Invalid mdp trigger. Forcing to sw trigger",
-						 __func__, __LINE__);
-		panel_data->panel_info.mipi.mdp_trigger =
-					DSI_CMD_TRIGGER_SW;
-	}
-
-	rc = of_property_read_u32(np, "qcom,mdss-pan-dsi-dma-tr", &tmp);
-	panel_data->panel_info.mipi.dma_trigger =
-			(!rc ? tmp : DSI_CMD_TRIGGER_SW);
-	if (panel_data->panel_info.mipi.dma_trigger > 6) {
-		pr_err("%s:%d, Invalid dma trigger. Forcing to sw trigger",
-						 __func__, __LINE__);
-		panel_data->panel_info.mipi.dma_trigger =
-					DSI_CMD_TRIGGER_SW;
-	}
-
-	rc = of_property_read_u32(np, "qcom,mdss-pan-dsi-frame-rate", &tmp);
-	panel_data->panel_info.mipi.frame_rate = (!rc ? tmp : 60);
-	return rc;
-}
-
-static int dsi_panel_parse_dt(struct platform_device *pdev,
-				struct dsi_panel_common_pdata *panel_data,
-				char *bl_ctrl)
-{
-	int rc;
-
-	rc = dsi_panel_parse_gpio(pdev);
-	if (rc) {
-		pr_err("fail to parse panel GPIOs\n");
-		return rc;
-	}
-
-	rc = dsi_panel_parse_regulator(pdev);
-	if (rc) {
-		pr_err("fail to parse panel regulators\n");
-		return rc;
-	}
-
-	rc = dsi_panel_parse_timing(pdev, panel_data);
-	if (rc) {
-		pr_err("fail to parse panel timing\n");
-		return rc;
-	}
-
-	rc = dsi_panel_parse_phy(pdev, panel_data);
-	if (rc) {
-		pr_err("fail to parse DSI PHY settings\n");
-		return rc;
-	}
-
-	rc = dsi_panel_parse_backlight(pdev, panel_data, bl_ctrl);
-	if (rc) {
-		pr_err("fail to parse DSI backlight\n");
-		return rc;
-	}
-
-	rc = dsi_panel_parse_other(pdev, panel_data);
-	if (rc) {
-		pr_err("fail to parse DSI panel destination\n");
-		return rc;
-	}
-
-	rc = dsi_panel_parse_host_cfg(pdev, panel_data);
-	if (rc) {
-		pr_err("fail to parse DSI host configs\n");
-		return rc;
-	}
-
-	rc = dsi_panel_parse_init_cmds(pdev, panel_data);
-	if (rc) {
-		pr_err("fail to parse DSI init commands\n");
-		return rc;
-	}
-
-	return 0;
-}
-
-static int __devinit dsi_panel_probe(struct platform_device *pdev)
-{
-	int rc = 0;
-	static struct dsi_panel_common_pdata vendor_pdata;
-	static const char *panel_name;
-
-	pr_debug("%s:%d, debug info id=%d", __func__, __LINE__, pdev->id);
-	if (!pdev->dev.of_node)
-		return -ENODEV;
-
-	panel_name = of_get_property(pdev->dev.of_node, "label", NULL);
-	if (!panel_name)
-		pr_debug("%s:%d, panel name not specified\n",
-						__func__, __LINE__);
-	else
-		pr_debug("%s: Panel Name = %s\n", __func__, panel_name);
-
-	rc = dsi_panel_init();
-	if (rc) {
-		pr_err("dsi_panel_init failed %d\n", rc);
-		goto dsi_panel_probe_error;
-
-	}
-	rc = dsi_panel_parse_dt(pdev, &vendor_pdata, &panel_private->bl_ctrl);
-	if (rc) {
-		pr_err("dsi_panel_parse_dt failed %d\n", rc);
-		goto dsi_panel_probe_error;
-	}
-
-	vendor_pdata.on = dsi_panel_on;
-	vendor_pdata.off = dsi_panel_off;
-	vendor_pdata.reset = dsi_panel_reset;
-	vendor_pdata.bl_fnc = dsi_panel_bl_ctrl;
-
-	rc = dsi_panel_device_register_v2(pdev, &vendor_pdata,
-					panel_private->bl_ctrl);
-
-	if (rc) {
-		pr_err("dsi_panel_device_register_v2 failed %d\n", rc);
-		goto dsi_panel_probe_error;
-	}
-
-	return 0;
-dsi_panel_probe_error:
-	dsi_panel_deinit();
-	return rc;
-}
-
-static int __devexit dsi_panel_remove(struct platform_device *pdev)
-{
-	dsi_panel_deinit();
-	return 0;
-}
-
-
-static const struct of_device_id dsi_panel_match[] = {
-	{.compatible = "qcom,dsi-panel-v2"},
-	{}
-};
-
-static struct platform_driver this_driver = {
-	.probe  = dsi_panel_probe,
-	.remove = __devexit_p(dsi_panel_remove),
-	.driver = {
-		.name = "dsi_v2_panel",
-		.of_match_table = dsi_panel_match,
-	},
-};
-
-static int __init dsi_panel_module_init(void)
-{
-	return platform_driver_register(&this_driver);
-}
-module_init(dsi_panel_module_init);
diff --git a/drivers/video/msm/mdss/dsi_v2.c b/drivers/video/msm/mdss/dsi_v2.c
index 686ec01..9ca3461 100644
--- a/drivers/video/msm/mdss/dsi_v2.c
+++ b/drivers/video/msm/mdss/dsi_v2.c
@@ -16,12 +16,12 @@
 #include <linux/slab.h>
 #include <linux/iopoll.h>
 #include <linux/of_device.h>
+#include <linux/of_gpio.h>
 
-#include "mdss_panel.h"
 #include "dsi_v2.h"
 
-static struct dsi_panel_common_pdata *panel_common_data;
 static struct dsi_interface dsi_intf;
+static struct dsi_buf dsi_panel_tx_buf;
 
 static int dsi_off(struct mdss_panel_data *pdata)
 {
@@ -52,20 +52,24 @@
 	}
 	return rc;
 }
+
 static int dsi_panel_handler(struct mdss_panel_data *pdata, int enable)
 {
 	int rc = 0;
+	struct mdss_dsi_ctrl_pdata *ctrl_pdata = NULL;
 
 	pr_debug("dsi_panel_handler enable=%d\n", enable);
-	if (!panel_common_data || !pdata)
+	if (!pdata)
 		return -ENODEV;
+	ctrl_pdata = container_of(pdata, struct mdss_dsi_ctrl_pdata,
+				panel_data);
 
 	if (enable) {
-		if (panel_common_data->reset)
-			panel_common_data->reset(pdata, 1);
+		mdss_dsi_panel_reset(pdata, 1);
 
-		if (panel_common_data->on)
-			rc = panel_common_data->on(pdata);
+		rc = dsi_cmds_tx_v2(pdata, &dsi_panel_tx_buf,
+					ctrl_pdata->on_cmds.cmds,
+					ctrl_pdata->on_cmds.cmd_cnt);
 
 		if (rc)
 			pr_err("dsi_panel_handler panel on failed %d\n", rc);
@@ -73,11 +77,11 @@
 		if (dsi_intf.op_mode_config)
 			dsi_intf.op_mode_config(DSI_CMD_MODE, pdata);
 
-		if (panel_common_data->off)
-			panel_common_data->off(pdata);
+		dsi_cmds_tx_v2(pdata, &dsi_panel_tx_buf,
+					ctrl_pdata->off_cmds.cmds,
+					ctrl_pdata->off_cmds.cmd_cnt);
 
-		if (panel_common_data->reset)
-			panel_common_data->reset(pdata, 0);
+		mdss_dsi_panel_reset(pdata, 0);
 	}
 	return rc;
 }
@@ -88,9 +92,6 @@
 
 	pr_debug("%s:\n", __func__);
 
-	if (panel_common_data->reset)
-		panel_common_data->reset(pdata, 2);
-
 	if (dsi_intf.cont_on)
 		rc = dsi_intf.cont_on(pdata);
 
@@ -106,7 +107,7 @@
 {
 	int rc = 0;
 
-	if (!pdata || !panel_common_data) {
+	if (!pdata) {
 		pr_err("%s: Invalid input data\n", __func__);
 		return -ENODEV;
 	}
@@ -134,49 +135,399 @@
 	return rc;
 }
 
-static struct platform_device *get_dsi_platform_device(
-			struct platform_device *dev)
+static int dsi_parse_gpio(struct platform_device *pdev,
+				struct mdss_dsi_ctrl_pdata *ctrl_pdata)
 {
-	struct device_node *dsi_ctrl_np;
-	struct platform_device *ctrl_pdev;
+	struct device_node *np = pdev->dev.of_node;
+	int rc = 0, i = 0;
+	u32 tmp[9];
 
-	dsi_ctrl_np = of_parse_phandle(dev->dev.of_node,
-					"qcom,dsi-ctrl-phandle", 0);
+	ctrl_pdata->disp_en_gpio = of_get_named_gpio(np,
+		"qcom,platform-enable-gpio", 0);
 
-	if (!dsi_ctrl_np)
-		return NULL;
+	if (!gpio_is_valid(ctrl_pdata->disp_en_gpio)) {
+		pr_err("%s:%d, Disp_en gpio not specified\n",
+						__func__, __LINE__);
+	} else {
+		rc = gpio_request(ctrl_pdata->disp_en_gpio, "disp_enable");
+		if (rc) {
+			pr_err("request reset gpio failed, rc=%d\n",
+			       rc);
+			gpio_free(ctrl_pdata->disp_en_gpio);
+			return -ENODEV;
+		}
+	}
 
-	ctrl_pdev = of_find_device_by_node(dsi_ctrl_np);
-	if (!ctrl_pdev)
-		return NULL;
+	if (ctrl_pdata->panel_data.panel_info.mipi.mode == DSI_CMD_MODE) {
+		ctrl_pdata->disp_te_gpio = of_get_named_gpio(np,
+						"qcom,platform-te-gpio", 0);
+		if (!gpio_is_valid(ctrl_pdata->disp_te_gpio)) {
+			pr_err("%s:%d, Disp_te gpio not specified\n",
+							__func__, __LINE__);
+		} else {
+			rc = gpio_request(ctrl_pdata->disp_te_gpio, "disp_te");
+			if (rc) {
+				pr_err("request TE gpio failed, rc=%d\n",
+								       rc);
+				gpio_free(ctrl_pdata->disp_te_gpio);
+				return -ENODEV;
+			}
+			rc = gpio_tlmm_config(GPIO_CFG(
+					ctrl_pdata->disp_te_gpio, 1,
+					GPIO_CFG_INPUT,
+					GPIO_CFG_PULL_DOWN,
+					GPIO_CFG_2MA),
+					GPIO_CFG_ENABLE);
 
-	return ctrl_pdev;
+			if (rc) {
+				pr_err("%s: unable to config tlmm = %d\n",
+					__func__, ctrl_pdata->disp_te_gpio);
+				gpio_free(ctrl_pdata->disp_te_gpio);
+				return -ENODEV;
+			}
+
+			rc = gpio_direction_input(ctrl_pdata->disp_te_gpio);
+			if (rc) {
+				pr_err("set_direction for disp_en gpio failed, rc=%d\n",
+								       rc);
+				gpio_free(ctrl_pdata->disp_te_gpio);
+				if (gpio_is_valid(ctrl_pdata->disp_en_gpio))
+					gpio_free(ctrl_pdata->disp_en_gpio);
+				return -ENODEV;
+			}
+			pr_debug("%s: te_gpio=%d\n", __func__,
+					ctrl_pdata->disp_te_gpio);
+		}
+	}
+
+	rc = of_property_read_u32_array(np,
+		"qcom,platform-reset-sequence", tmp, MDSS_DSI_RST_SEQ_LEN);
+	if (rc)
+		pr_err("%s:%d, unable to read gpio reset sequence\n",
+						__func__, __LINE__);
+	else
+		for (i = 0; i < MDSS_DSI_RST_SEQ_LEN; ++i)
+			ctrl_pdata->rst_seq[i] = tmp[i];
+
+	ctrl_pdata->rst_gpio = of_get_named_gpio(np,
+					"qcom,platform-reset-gpio", 0);
+	if (!gpio_is_valid(ctrl_pdata->rst_gpio)) {
+		pr_err("%s:%d, reset gpio not specified\n",
+						__func__, __LINE__);
+	} else {
+		rc = gpio_request(ctrl_pdata->rst_gpio, "disp_rst_n");
+		if (rc) {
+			pr_err("request reset gpio failed, rc=%d\n",
+				rc);
+			gpio_free(ctrl_pdata->rst_gpio);
+			if (gpio_is_valid(ctrl_pdata->disp_en_gpio))
+				gpio_free(ctrl_pdata->disp_en_gpio);
+			if (gpio_is_valid(ctrl_pdata->disp_te_gpio))
+				gpio_free(ctrl_pdata->disp_te_gpio);
+			return -ENODEV;
+		}
+	}
+
+	if (ctrl_pdata->panel_data.panel_info.mode_gpio_state !=
+						MODE_GPIO_NOT_VALID) {
+		ctrl_pdata->mode_gpio = of_get_named_gpio(np,
+						"qcom,platform-mode-gpio", 0);
+		if (!gpio_is_valid(ctrl_pdata->mode_gpio)) {
+			pr_info("%s:%d, reset gpio not specified\n",
+							__func__, __LINE__);
+		} else {
+			rc = gpio_request(ctrl_pdata->mode_gpio, "panel_mode");
+			if (rc) {
+				pr_err("request panel mode gpio failed,rc=%d\n",
+									rc);
+				gpio_free(ctrl_pdata->mode_gpio);
+				if (gpio_is_valid(ctrl_pdata->disp_en_gpio))
+					gpio_free(ctrl_pdata->disp_en_gpio);
+				if (gpio_is_valid(ctrl_pdata->rst_gpio))
+					gpio_free(ctrl_pdata->rst_gpio);
+				if (gpio_is_valid(ctrl_pdata->disp_te_gpio))
+					gpio_free(ctrl_pdata->disp_te_gpio);
+				return -ENODEV;
+			}
+		}
+	}
+	return 0;
 }
 
+void dsi_ctrl_config_deinit(struct platform_device *pdev,
+				struct mdss_dsi_ctrl_pdata *ctrl_pdata)
+{
+	struct dss_module_power *module_power = &(ctrl_pdata->power_data);
+	if (!module_power) {
+		pr_err("%s: invalid input\n", __func__);
+		return;
+	}
+
+	if (module_power->vreg_config) {
+		devm_kfree(&(pdev->dev), module_power->vreg_config);
+		module_power->vreg_config = NULL;
+	}
+	module_power->num_vreg = 0;
+
+	if (gpio_is_valid(ctrl_pdata->disp_en_gpio))
+		gpio_free(ctrl_pdata->disp_en_gpio);
+	if (gpio_is_valid(ctrl_pdata->rst_gpio))
+		gpio_free(ctrl_pdata->rst_gpio);
+	if (gpio_is_valid(ctrl_pdata->disp_te_gpio))
+		gpio_free(ctrl_pdata->disp_te_gpio);
+	if (gpio_is_valid(ctrl_pdata->mode_gpio))
+		gpio_free(ctrl_pdata->mode_gpio);
+}
+
+static int dsi_parse_vreg(struct device *dev, struct dss_module_power *mp)
+{
+	int i = 0, rc = 0;
+	u32 tmp = 0;
+	struct device_node *supply_node = NULL;
+	struct device_node *np = NULL;
+
+	if (!dev || !mp) {
+		pr_err("%s: invalid input\n", __func__);
+		rc = -EINVAL;
+		goto error;
+	}
+
+	np = dev->of_node;
+
+	mp->num_vreg = 0;
+	for_each_child_of_node(np, supply_node) {
+		if (!strncmp(supply_node->name, "qcom,platform-supply-entry",
+					strlen("qcom,platform-supply-entry")))
+			++mp->num_vreg;
+	}
+	if (mp->num_vreg == 0) {
+		pr_err("%s: no vreg\n", __func__);
+		goto novreg;
+	} else {
+		pr_debug("%s: vreg found. count=%d\n", __func__, mp->num_vreg);
+	}
+
+	mp->vreg_config = devm_kzalloc(dev, sizeof(struct dss_vreg) *
+		mp->num_vreg, GFP_KERNEL);
+	if (!mp->vreg_config) {
+		pr_err("%s: can't alloc vreg mem\n", __func__);
+		rc = -ENOMEM;
+		goto error;
+	}
+
+	for_each_child_of_node(np, supply_node) {
+		if (!strncmp(supply_node->name, "qcom,platform-supply-entry",
+					strlen("qcom,platform-supply-entry"))) {
+			const char *st = NULL;
+			/* vreg-name */
+			rc = of_property_read_string(supply_node,
+				"qcom,supply-name", &st);
+			if (rc) {
+				pr_err("%s: error reading name. rc=%d\n",
+					__func__, rc);
+				goto error;
+			}
+			strlcpy(mp->vreg_config[i].vreg_name, st,
+				sizeof(mp->vreg_config[i].vreg_name));
+			/* vreg-min-voltage */
+			rc = of_property_read_u32(supply_node,
+				"qcom,supply-min-voltage", &tmp);
+			if (rc) {
+				pr_err("%s: error reading min volt. rc=%d\n",
+					__func__, rc);
+				goto error;
+			}
+			mp->vreg_config[i].min_voltage = tmp;
+
+			/* vreg-max-voltage */
+			rc = of_property_read_u32(supply_node,
+				"qcom,supply-max-voltage", &tmp);
+			if (rc) {
+				pr_err("%s: error reading max volt. rc=%d\n",
+					__func__, rc);
+				goto error;
+			}
+			mp->vreg_config[i].max_voltage = tmp;
+
+			/* enable-load */
+			rc = of_property_read_u32(supply_node,
+				"qcom,supply-enable-load", &tmp);
+			if (rc) {
+				pr_err("%s: error reading enable load. rc=%d\n",
+					__func__, rc);
+				goto error;
+			}
+			mp->vreg_config[i].enable_load = tmp;
+
+			/* disable-load */
+			rc = of_property_read_u32(supply_node,
+				"qcom,supply-disable-load", &tmp);
+			if (rc) {
+				pr_err("%s: error reading disable load. rc=%d\n",
+					__func__, rc);
+				goto error;
+			}
+			mp->vreg_config[i].disable_load = tmp;
+
+			/* pre-sleep */
+			rc = of_property_read_u32(supply_node,
+				"qcom,supply-pre-on-sleep", &tmp);
+			if (rc) {
+				pr_debug("%s: error reading supply pre sleep value. rc=%d\n",
+					__func__, rc);
+			}
+			mp->vreg_config[i].pre_on_sleep = (!rc ? tmp : 0);
+
+			rc = of_property_read_u32(supply_node,
+				"qcom,supply-pre-off-sleep", &tmp);
+			if (rc) {
+				pr_debug("%s: error reading supply pre sleep value. rc=%d\n",
+					__func__, rc);
+			}
+			mp->vreg_config[i].pre_off_sleep = (!rc ? tmp : 0);
+
+			/* post-sleep */
+			rc = of_property_read_u32(supply_node,
+				"qcom,supply-post-on-sleep", &tmp);
+			if (rc) {
+				pr_debug("%s: error reading supply post sleep value. rc=%d\n",
+					__func__, rc);
+			}
+			mp->vreg_config[i].post_on_sleep = (!rc ? tmp : 0);
+
+			rc = of_property_read_u32(supply_node,
+				"qcom,supply-post-off-sleep", &tmp);
+			if (rc) {
+				pr_debug("%s: error reading supply post sleep value. rc=%d\n",
+					__func__, rc);
+			}
+			mp->vreg_config[i].post_off_sleep = (!rc ? tmp : 0);
+
+			pr_debug("%s: %s min=%d, max=%d, enable=%d, disable=%d, preonsleep=%d, postonsleep=%d, preoffsleep=%d, postoffsleep=%d\n",
+				__func__,
+				mp->vreg_config[i].vreg_name,
+				mp->vreg_config[i].min_voltage,
+				mp->vreg_config[i].max_voltage,
+				mp->vreg_config[i].enable_load,
+				mp->vreg_config[i].disable_load,
+				mp->vreg_config[i].pre_on_sleep,
+				mp->vreg_config[i].post_on_sleep,
+				mp->vreg_config[i].pre_off_sleep,
+				mp->vreg_config[i].post_off_sleep
+				);
+			++i;
+		}
+	}
+
+	return 0;
+
+error:
+	if (mp->vreg_config) {
+		devm_kfree(dev, mp->vreg_config);
+		mp->vreg_config = NULL;
+	}
+novreg:
+	mp->num_vreg = 0;
+
+	return rc;
+}
+
+static int dsi_parse_phy(struct platform_device *pdev,
+				struct mdss_dsi_ctrl_pdata *ctrl_pdata)
+{
+	struct device_node *np = pdev->dev.of_node;
+	int i, len;
+	const char *data;
+	struct mdss_dsi_phy_ctrl *phy_db
+		= &(ctrl_pdata->panel_data.panel_info.mipi.dsi_phy_db);
+
+	data = of_get_property(np, "qcom,platform-regulator-settings", &len);
+	if ((!data) || (len != 6)) {
+		pr_err("%s:%d, Unable to read Phy regulator settings",
+			__func__, __LINE__);
+		return -EINVAL;
+	}
+	for (i = 0; i < len; i++)
+		phy_db->regulator[i] = data[i];
+
+	data = of_get_property(np, "qcom,platform-strength-ctrl", &len);
+	if ((!data) || (len != 2)) {
+		pr_err("%s:%d, Unable to read Phy Strength ctrl settings",
+			__func__, __LINE__);
+		return -EINVAL;
+	}
+	phy_db->strength[0] = data[0];
+	phy_db->strength[1] = data[1];
+
+	data = of_get_property(np, "qcom,platform-bist-ctrl", &len);
+	if ((!data) || (len != 6)) {
+		pr_err("%s:%d, Unable to read Phy Bist Ctrl settings",
+			__func__, __LINE__);
+		return -EINVAL;
+	}
+	for (i = 0; i < len; i++)
+		phy_db->bistctrl[i] = data[i];
+
+	data = of_get_property(np, "qcom,platform-lane-config", &len);
+	if ((!data) || (len != 30)) {
+		pr_err("%s:%d, Unable to read Phy lane configure settings",
+			__func__, __LINE__);
+		return -EINVAL;
+	}
+	for (i = 0; i < len; i++)
+		phy_db->lanecfg[i] = data[i];
+
+	return 0;
+}
+
+int dsi_ctrl_config_init(struct platform_device *pdev,
+				struct mdss_dsi_ctrl_pdata *ctrl_pdata)
+{
+	int rc;
+
+	rc = dsi_parse_vreg(&pdev->dev, &ctrl_pdata->power_data);
+	if (rc) {
+		pr_err("%s:%d unable to get the regulator resources",
+			__func__, __LINE__);
+		return rc;
+	}
+
+	rc = dsi_parse_gpio(pdev, ctrl_pdata);
+	if (rc) {
+		pr_err("fail to parse panel GPIOs\n");
+		return rc;
+	}
+
+	rc = dsi_parse_phy(pdev, ctrl_pdata);
+	if (rc) {
+		pr_err("fail to parse DSI PHY settings\n");
+		return rc;
+	}
+
+	return 0;
+}
 int dsi_panel_device_register_v2(struct platform_device *dev,
-				struct dsi_panel_common_pdata *panel_data,
-				char backlight_ctrl)
+				struct mdss_dsi_ctrl_pdata *ctrl_pdata)
 {
 	struct mipi_panel_info *mipi;
-	struct platform_device *ctrl_pdev;
 	int rc;
 	u8 lanes = 0, bpp;
 	u32 h_period, v_period;
-	static struct mdss_panel_data dsi_panel_data;
+	struct mdss_panel_info *pinfo = &(ctrl_pdata->panel_data.panel_info);
 
-	h_period = ((panel_data->panel_info.lcdc.h_pulse_width)
-			+ (panel_data->panel_info.lcdc.h_back_porch)
-			+ (panel_data->panel_info.xres)
-			+ (panel_data->panel_info.lcdc.h_front_porch));
+	h_period = ((pinfo->lcdc.h_pulse_width)
+			+ (pinfo->lcdc.h_back_porch)
+			+ (pinfo->xres)
+			+ (pinfo->lcdc.h_front_porch));
 
-	v_period = ((panel_data->panel_info.lcdc.v_pulse_width)
-			+ (panel_data->panel_info.lcdc.v_back_porch)
-			+ (panel_data->panel_info.yres)
-			+ (panel_data->panel_info.lcdc.v_front_porch));
+	v_period = ((pinfo->lcdc.v_pulse_width)
+			+ (pinfo->lcdc.v_back_porch)
+			+ (pinfo->yres)
+			+ (pinfo->lcdc.v_front_porch));
 
-	mipi  = &panel_data->panel_info.mipi;
+	mipi  = &pinfo->mipi;
 
-	panel_data->panel_info.type =
+	pinfo->type =
 		((mipi->mode == DSI_VIDEO_MODE)
 			? MIPI_VIDEO_PANEL : MIPI_CMD_PANEL);
 
@@ -189,7 +540,6 @@
 	if (mipi->data_lane0)
 		lanes += 1;
 
-
 	if ((mipi->dst_format == DSI_CMD_DST_FORMAT_RGB888)
 		|| (mipi->dst_format == DSI_VIDEO_DST_FORMAT_RGB888)
 		|| (mipi->dst_format == DSI_VIDEO_DST_FORMAT_RGB666_LOOSE))
@@ -200,39 +550,38 @@
 	else
 		bpp = 3; /* Default format set to RGB888 */
 
-	if (panel_data->panel_info.type == MIPI_VIDEO_PANEL &&
-		!panel_data->panel_info.clk_rate) {
-		h_period += panel_data->panel_info.lcdc.xres_pad;
-		v_period += panel_data->panel_info.lcdc.yres_pad;
+	if (pinfo->type == MIPI_VIDEO_PANEL &&
+		!pinfo->clk_rate) {
+		h_period += pinfo->lcdc.xres_pad;
+		v_period += pinfo->lcdc.yres_pad;
 
 		if (lanes > 0) {
-			panel_data->panel_info.clk_rate =
+			pinfo->clk_rate =
 			((h_period * v_period * (mipi->frame_rate) * bpp * 8)
 			   / lanes);
 		} else {
 			pr_err("%s: forcing mdss_dsi lanes to 1\n", __func__);
-			panel_data->panel_info.clk_rate =
+			pinfo->clk_rate =
 				(h_period * v_period
 					 * (mipi->frame_rate) * bpp * 8);
 		}
 	}
 
-	ctrl_pdev = get_dsi_platform_device(dev);
-	if (!ctrl_pdev)
-		return -EPROBE_DEFER;
+	ctrl_pdata->panel_data.event_handler = dsi_event_handler;
 
-	dsi_panel_data.event_handler = dsi_event_handler;
+	rc = dsi_buf_alloc(&dsi_panel_tx_buf,
+				ALIGN(DSI_BUF_SIZE,
+				SZ_4K));
+	if (rc)
+		return rc;
 
-	dsi_panel_data.panel_info = panel_data->panel_info;
-
-	dsi_panel_data.set_backlight = panel_data->bl_fnc;
-	panel_common_data = panel_data;
 	/*
 	 * register in mdp driver
 	 */
-	rc = mdss_register_panel(ctrl_pdev, &dsi_panel_data);
+	rc = mdss_register_panel(dev, &(ctrl_pdata->panel_data));
 	if (rc) {
 		dev_err(&dev->dev, "unable to register MIPI DSI panel\n");
+		kfree(dsi_panel_tx_buf.start);
 		return rc;
 	}
 
@@ -340,15 +689,16 @@
 	char *bp;
 	u32 *hp;
 	int i, len;
+	struct dsi_ctrl_hdr *dchdr = &cm->dchdr;
 
 	bp = dsi_buf_reserve_hdr(dp, DSI_HOST_HDR_SIZE);
 
 	/* fill up payload */
 	if (cm->payload) {
-		len = cm->dlen;
+		len = dchdr->dlen;
 		len += 3;
 		len &= ~0x03; /* multipled by 4 */
-		for (i = 0; i < cm->dlen; i++)
+		for (i = 0; i < dchdr->dlen; i++)
 			*bp++ = cm->payload[i];
 
 		/* append 0xff to the end */
@@ -361,11 +711,11 @@
 	/* fill up header */
 	hp = dp->hdr;
 	*hp = 0;
-	*hp = DSI_HDR_WC(cm->dlen);
-	*hp |= DSI_HDR_VC(cm->vc);
+	*hp = DSI_HDR_WC(dchdr->dlen);
+	*hp |= DSI_HDR_VC(dchdr->vc);
 	*hp |= DSI_HDR_LONG_PKT;
 	*hp |= DSI_HDR_DTYPE(DTYPE_GEN_LWRITE);
-	if (cm->last)
+	if (dchdr->last)
 		*hp |= DSI_HDR_LAST;
 
 	dsi_buf_push(dp, DSI_HOST_HDR_SIZE);
@@ -380,8 +730,9 @@
 {
 	u32 *hp;
 	int len;
+	struct dsi_ctrl_hdr *dchdr = &cm->dchdr;
 
-	if (cm->dlen && cm->payload == 0) {
+	if (dchdr->dlen && cm->payload == 0) {
 		pr_err("%s: NO payload error\n", __func__);
 		return 0;
 	}
@@ -389,11 +740,11 @@
 	dsi_buf_reserve_hdr(dp, DSI_HOST_HDR_SIZE);
 	hp = dp->hdr;
 	*hp = 0;
-	*hp |= DSI_HDR_VC(cm->vc);
-	if (cm->last)
+	*hp |= DSI_HDR_VC(dchdr->vc);
+	if (dchdr->last)
 		*hp |= DSI_HDR_LAST;
 
-	len = (cm->dlen > 2) ? 2 : cm->dlen;
+	len = (dchdr->dlen > 2) ? 2 : dchdr->dlen;
 
 	if (len == 1) {
 		*hp |= DSI_HDR_DTYPE(DTYPE_GEN_WRITE1);
@@ -421,8 +772,9 @@
 {
 	u32 *hp;
 	int len;
+	struct dsi_ctrl_hdr *dchdr = &cm->dchdr;
 
-	if (cm->dlen && cm->payload == 0) {
+	if (dchdr->dlen && cm->payload == 0) {
 		pr_err("%s: NO payload error\n", __func__);
 		return 0;
 	}
@@ -430,12 +782,12 @@
 	dsi_buf_reserve_hdr(dp, DSI_HOST_HDR_SIZE);
 	hp = dp->hdr;
 	*hp = 0;
-	*hp |= DSI_HDR_VC(cm->vc);
+	*hp |= DSI_HDR_VC(dchdr->vc);
 	*hp |= DSI_HDR_BTA;
-	if (cm->last)
+	if (dchdr->last)
 		*hp |= DSI_HDR_LAST;
 
-	len = (cm->dlen > 2) ? 2 : cm->dlen;
+	len = (dchdr->dlen > 2) ? 2 : dchdr->dlen;
 
 	if (len == 1) {
 		*hp |= DSI_HDR_DTYPE(DTYPE_GEN_READ1);
@@ -463,6 +815,7 @@
 	char *bp;
 	u32 *hp;
 	int i, len;
+	struct dsi_ctrl_hdr *dchdr = &cm->dchdr;
 
 	bp = dsi_buf_reserve_hdr(dp, DSI_HOST_HDR_SIZE);
 
@@ -471,10 +824,10 @@
 	 * dcs command byte (first byte) followed by payload
 	 */
 	if (cm->payload) {
-		len = cm->dlen;
+		len = dchdr->dlen;
 		len += 3;
 		len &= ~0x03; /* multipled by 4 */
-		for (i = 0; i < cm->dlen; i++)
+		for (i = 0; i < dchdr->dlen; i++)
 			*bp++ = cm->payload[i];
 
 		/* append 0xff to the end */
@@ -487,11 +840,11 @@
 	/* fill up header */
 	hp = dp->hdr;
 	*hp = 0;
-	*hp = DSI_HDR_WC(cm->dlen);
-	*hp |= DSI_HDR_VC(cm->vc);
+	*hp = DSI_HDR_WC(dchdr->dlen);
+	*hp |= DSI_HDR_VC(dchdr->vc);
 	*hp |= DSI_HDR_LONG_PKT;
 	*hp |= DSI_HDR_DTYPE(DTYPE_DCS_LWRITE);
-	if (cm->last)
+	if (dchdr->last)
 		*hp |= DSI_HDR_LAST;
 
 	dsi_buf_push(dp, DSI_HOST_HDR_SIZE);
@@ -506,6 +859,7 @@
 {
 	u32 *hp;
 	int len;
+	struct dsi_ctrl_hdr *dchdr = &cm->dchdr;
 
 	if (cm->payload == 0) {
 		pr_err("%s: NO payload error\n", __func__);
@@ -515,13 +869,13 @@
 	dsi_buf_reserve_hdr(dp, DSI_HOST_HDR_SIZE);
 	hp = dp->hdr;
 	*hp = 0;
-	*hp |= DSI_HDR_VC(cm->vc);
-	if (cm->ack)
+	*hp |= DSI_HDR_VC(dchdr->vc);
+	if (dchdr->ack)
 		*hp |= DSI_HDR_BTA;
-	if (cm->last)
+	if (dchdr->last)
 		*hp |= DSI_HDR_LAST;
 
-	len = (cm->dlen > 1) ? 1 : cm->dlen;
+	len = (dchdr->dlen > 1) ? 1 : dchdr->dlen;
 
 	*hp |= DSI_HDR_DTYPE(DTYPE_DCS_WRITE);
 	*hp |= DSI_HDR_DATA1(cm->payload[0]); /* dcs command byte */
@@ -537,8 +891,9 @@
 static int dsi_dcs_swrite1(struct dsi_buf *dp, struct dsi_cmd_desc *cm)
 {
 	u32 *hp;
+	struct dsi_ctrl_hdr *dchdr = &cm->dchdr;
 
-	if (cm->dlen < 2 || cm->payload == 0) {
+	if (dchdr->dlen < 2 || cm->payload == 0) {
 		pr_err("%s: NO payload error\n", __func__);
 		return -EINVAL;
 	}
@@ -546,10 +901,10 @@
 	dsi_buf_reserve_hdr(dp, DSI_HOST_HDR_SIZE);
 	hp = dp->hdr;
 	*hp = 0;
-	*hp |= DSI_HDR_VC(cm->vc);
-	if (cm->ack)
+	*hp |= DSI_HDR_VC(dchdr->vc);
+	if (dchdr->ack)
 		*hp |= DSI_HDR_BTA;
-	if (cm->last)
+	if (dchdr->last)
 		*hp |= DSI_HDR_LAST;
 
 	*hp |= DSI_HDR_DTYPE(DTYPE_DCS_WRITE1);
@@ -567,6 +922,7 @@
 static int dsi_dcs_read(struct dsi_buf *dp, struct dsi_cmd_desc *cm)
 {
 	u32 *hp;
+	struct dsi_ctrl_hdr *dchdr = &cm->dchdr;
 
 	if (cm->payload == 0) {
 		pr_err("%s: NO payload error\n", __func__);
@@ -576,10 +932,10 @@
 	dsi_buf_reserve_hdr(dp, DSI_HOST_HDR_SIZE);
 	hp = dp->hdr;
 	*hp = 0;
-	*hp |= DSI_HDR_VC(cm->vc);
+	*hp |= DSI_HDR_VC(dchdr->vc);
 	*hp |= DSI_HDR_BTA;
 	*hp |= DSI_HDR_DTYPE(DTYPE_DCS_READ);
-	if (cm->last)
+	if (dchdr->last)
 		*hp |= DSI_HDR_LAST;
 
 	*hp |= DSI_HDR_DATA1(cm->payload[0]); /* dcs command byte */
@@ -593,13 +949,14 @@
 static int dsi_cm_on(struct dsi_buf *dp, struct dsi_cmd_desc *cm)
 {
 	u32 *hp;
+	struct dsi_ctrl_hdr *dchdr = &cm->dchdr;
 
 	dsi_buf_reserve_hdr(dp, DSI_HOST_HDR_SIZE);
 	hp = dp->hdr;
 	*hp = 0;
-	*hp |= DSI_HDR_VC(cm->vc);
+	*hp |= DSI_HDR_VC(dchdr->vc);
 	*hp |= DSI_HDR_DTYPE(DTYPE_CM_ON);
-	if (cm->last)
+	if (dchdr->last)
 		*hp |= DSI_HDR_LAST;
 
 	dsi_buf_push(dp, DSI_HOST_HDR_SIZE);
@@ -610,13 +967,14 @@
 static int dsi_cm_off(struct dsi_buf *dp, struct dsi_cmd_desc *cm)
 {
 	u32 *hp;
+	struct dsi_ctrl_hdr *dchdr = &cm->dchdr;
 
 	dsi_buf_reserve_hdr(dp, DSI_HOST_HDR_SIZE);
 	hp = dp->hdr;
 	*hp = 0;
-	*hp |= DSI_HDR_VC(cm->vc);
+	*hp |= DSI_HDR_VC(dchdr->vc);
 	*hp |= DSI_HDR_DTYPE(DTYPE_CM_OFF);
-	if (cm->last)
+	if (dchdr->last)
 		*hp |= DSI_HDR_LAST;
 
 	dsi_buf_push(dp, DSI_HOST_HDR_SIZE);
@@ -627,13 +985,14 @@
 static int dsi_peripheral_on(struct dsi_buf *dp, struct dsi_cmd_desc *cm)
 {
 	u32 *hp;
+	struct dsi_ctrl_hdr *dchdr = &cm->dchdr;
 
 	dsi_buf_reserve_hdr(dp, DSI_HOST_HDR_SIZE);
 	hp = dp->hdr;
 	*hp = 0;
-	*hp |= DSI_HDR_VC(cm->vc);
+	*hp |= DSI_HDR_VC(dchdr->vc);
 	*hp |= DSI_HDR_DTYPE(DTYPE_PERIPHERAL_ON);
-	if (cm->last)
+	if (dchdr->last)
 		*hp |= DSI_HDR_LAST;
 
 	dsi_buf_push(dp, DSI_HOST_HDR_SIZE);
@@ -644,13 +1003,14 @@
 static int dsi_peripheral_off(struct dsi_buf *dp, struct dsi_cmd_desc *cm)
 {
 	u32 *hp;
+	struct dsi_ctrl_hdr *dchdr = &cm->dchdr;
 
 	dsi_buf_reserve_hdr(dp, DSI_HOST_HDR_SIZE);
 	hp = dp->hdr;
 	*hp = 0;
-	*hp |= DSI_HDR_VC(cm->vc);
+	*hp |= DSI_HDR_VC(dchdr->vc);
 	*hp |= DSI_HDR_DTYPE(DTYPE_PERIPHERAL_OFF);
-	if (cm->last)
+	if (dchdr->last)
 		*hp |= DSI_HDR_LAST;
 
 	dsi_buf_push(dp, DSI_HOST_HDR_SIZE);
@@ -661,6 +1021,7 @@
 static int dsi_set_max_pktsize(struct dsi_buf *dp, struct dsi_cmd_desc *cm)
 {
 	u32 *hp;
+	struct dsi_ctrl_hdr *dchdr = &cm->dchdr;
 
 	if (cm->payload == 0) {
 		pr_err("%s: NO payload error\n", __func__);
@@ -670,9 +1031,9 @@
 	dsi_buf_reserve_hdr(dp, DSI_HOST_HDR_SIZE);
 	hp = dp->hdr;
 	*hp = 0;
-	*hp |= DSI_HDR_VC(cm->vc);
+	*hp |= DSI_HDR_VC(dchdr->vc);
 	*hp |= DSI_HDR_DTYPE(DTYPE_MAX_PKTSIZE);
-	if (cm->last)
+	if (dchdr->last)
 		*hp |= DSI_HDR_LAST;
 
 	*hp |= DSI_HDR_DATA1(cm->payload[0]);
@@ -686,15 +1047,16 @@
 static int dsi_null_pkt(struct dsi_buf *dp, struct dsi_cmd_desc *cm)
 {
 	u32 *hp;
+	struct dsi_ctrl_hdr *dchdr = &cm->dchdr;
 
 	dsi_buf_reserve_hdr(dp, DSI_HOST_HDR_SIZE);
 	hp = dp->hdr;
 	*hp = 0;
-	*hp = DSI_HDR_WC(cm->dlen);
+	*hp = DSI_HDR_WC(dchdr->dlen);
 	*hp |= DSI_HDR_LONG_PKT;
-	*hp |= DSI_HDR_VC(cm->vc);
+	*hp |= DSI_HDR_VC(dchdr->vc);
 	*hp |= DSI_HDR_DTYPE(DTYPE_NULL_PKT);
-	if (cm->last)
+	if (dchdr->last)
 		*hp |= DSI_HDR_LAST;
 
 	dsi_buf_push(dp, DSI_HOST_HDR_SIZE);
@@ -705,15 +1067,16 @@
 static int dsi_blank_pkt(struct dsi_buf *dp, struct dsi_cmd_desc *cm)
 {
 	u32 *hp;
+	struct dsi_ctrl_hdr *dchdr = &cm->dchdr;
 
 	dsi_buf_reserve_hdr(dp, DSI_HOST_HDR_SIZE);
 	hp = dp->hdr;
 	*hp = 0;
-	*hp = DSI_HDR_WC(cm->dlen);
+	*hp = DSI_HDR_WC(dchdr->dlen);
 	*hp |= DSI_HDR_LONG_PKT;
-	*hp |= DSI_HDR_VC(cm->vc);
+	*hp |= DSI_HDR_VC(dchdr->vc);
 	*hp |= DSI_HDR_DTYPE(DTYPE_BLANK_PKT);
-	if (cm->last)
+	if (dchdr->last)
 		*hp |= DSI_HDR_LAST;
 
 	dsi_buf_push(dp, DSI_HOST_HDR_SIZE);
@@ -727,8 +1090,9 @@
 int dsi_cmd_dma_add(struct dsi_buf *dp, struct dsi_cmd_desc *cm)
 {
 	int len = 0;
+	struct dsi_ctrl_hdr *dchdr = &cm->dchdr;
 
-	switch (cm->dtype) {
+	switch (dchdr->dtype) {
 	case DTYPE_GEN_WRITE:
 	case DTYPE_GEN_WRITE1:
 	case DTYPE_GEN_WRITE2:
@@ -777,7 +1141,7 @@
 		break;
 	default:
 		pr_debug("%s: dtype=%x NOT supported\n",
-					__func__, cm->dtype);
+					__func__, dchdr->dtype);
 		break;
 
 	}
diff --git a/drivers/video/msm/mdss/dsi_v2.h b/drivers/video/msm/mdss/dsi_v2.h
index 73df790..a554856 100644
--- a/drivers/video/msm/mdss/dsi_v2.h
+++ b/drivers/video/msm/mdss/dsi_v2.h
@@ -11,190 +11,18 @@
  *
  */
 
-#ifndef MDSS_DSI_H
-#define MDSS_DSI_H
+#ifndef DSI_V2_H
+#define DSI_V2_H
 
 #include <linux/list.h>
 #include <mach/scm-io.h>
 
+#include "mdss_dsi.h"
 #include "mdss_panel.h"
 
-#define MIPI_OUTP(addr, data) writel_relaxed((data), (addr))
-#define MIPI_INP(addr) readl_relaxed(addr)
-
-#define MIPI_DSI_PRIM 1
-#define MIPI_DSI_SECD 2
-
-#define MIPI_DSI_PANEL_VGA	0
-#define MIPI_DSI_PANEL_WVGA	1
-#define MIPI_DSI_PANEL_WVGA_PT	2
-#define MIPI_DSI_PANEL_FWVGA_PT	3
-#define MIPI_DSI_PANEL_WSVGA_PT	4
-#define MIPI_DSI_PANEL_QHD_PT 5
-#define MIPI_DSI_PANEL_WXGA	6
-#define MIPI_DSI_PANEL_WUXGA	7
-#define MIPI_DSI_PANEL_720P_PT	8
-#define DSI_PANEL_MAX	8
-
-enum {
-	DSI_VIDEO_MODE,
-	DSI_CMD_MODE,
-};
-
-enum {
-	ST_DSI_CLK_OFF,
-	ST_DSI_SUSPEND,
-	ST_DSI_RESUME,
-	ST_DSI_PLAYING,
-	ST_DSI_NUM
-};
-
-enum {
-	EV_DSI_UPDATE,
-	EV_DSI_DONE,
-	EV_DSI_TOUT,
-	EV_DSI_NUM
-};
-
-enum {
-	LANDSCAPE = 1,
-	PORTRAIT = 2,
-};
-
-enum {
-	DSI_CMD_MODE_DMA,
-	DSI_CMD_MODE_MDP,
-};
-
-enum {
-	BL_PWM,
-	BL_WLED,
-	BL_DCS_CMD,
-	UNKNOWN_CTRL,
-};
-
-enum {
-	DSI_LP_MODE,
-	DSI_HS_MODE,
-};
-
-#define DSI_NON_BURST_SYNCH_PULSE	0
-#define DSI_NON_BURST_SYNCH_EVENT	1
-#define DSI_BURST_MODE			2
-
-#define DSI_RGB_SWAP_RGB	0
-#define DSI_RGB_SWAP_RBG	1
-#define DSI_RGB_SWAP_BGR	2
-#define DSI_RGB_SWAP_BRG	3
-#define DSI_RGB_SWAP_GRB	4
-#define DSI_RGB_SWAP_GBR	5
-
-#define DSI_VIDEO_DST_FORMAT_RGB565		0
-#define DSI_VIDEO_DST_FORMAT_RGB666		1
-#define DSI_VIDEO_DST_FORMAT_RGB666_LOOSE	2
-#define DSI_VIDEO_DST_FORMAT_RGB888		3
-
-#define DSI_CMD_DST_FORMAT_RGB111	0
-#define DSI_CMD_DST_FORMAT_RGB332	3
-#define DSI_CMD_DST_FORMAT_RGB444	4
-#define DSI_CMD_DST_FORMAT_RGB565	6
-#define DSI_CMD_DST_FORMAT_RGB666	7
-#define DSI_CMD_DST_FORMAT_RGB888	8
-
-#define DSI_CMD_TRIGGER_NONE		0x0	/* mdp trigger */
-#define DSI_CMD_TRIGGER_TE		0x02
-#define DSI_CMD_TRIGGER_SW		0x04
-#define DSI_CMD_TRIGGER_SW_SEOF		0x05	/* cmd dma only */
-#define DSI_CMD_TRIGGER_SW_TE		0x06
-
-#define DSI_HOST_HDR_SIZE	4
-#define DSI_HDR_LAST		BIT(31)
-#define DSI_HDR_LONG_PKT	BIT(30)
-#define DSI_HDR_BTA		BIT(29)
-#define DSI_HDR_VC(vc)		(((vc) & 0x03) << 22)
-#define DSI_HDR_DTYPE(dtype)	(((dtype) & 0x03f) << 16)
-#define DSI_HDR_DATA2(data)	(((data) & 0x0ff) << 8)
-#define DSI_HDR_DATA1(data)	((data) & 0x0ff)
-#define DSI_HDR_WC(wc)		((wc) & 0x0ffff)
-
 #define DSI_BUF_SIZE	1024
 #define DSI_MRPS	0x04  /* Maximum Return Packet Size */
 
-#define DSI_LEN 8 /* 4 x 4 - 6 - 2, bytes dcs header+crc-align  */
-
-struct dsi_buf {
-	u32 *hdr;	/* dsi host header */
-	char *start;	/* buffer start addr */
-	char *end;	/* buffer end addr */
-	int size;	/* size of buffer */
-	char *data;	/* buffer */
-	int len;	/* data length */
-	dma_addr_t dmap; /* mapped dma addr */
-};
-
-/* dcs read/write */
-#define DTYPE_DCS_WRITE		0x05	/* short write, 0 parameter */
-#define DTYPE_DCS_WRITE1	0x15	/* short write, 1 parameter */
-#define DTYPE_DCS_READ		0x06	/* read */
-#define DTYPE_DCS_LWRITE	0x39	/* long write */
-
-/* generic read/write */
-#define DTYPE_GEN_WRITE		0x03	/* short write, 0 parameter */
-#define DTYPE_GEN_WRITE1	0x13	/* short write, 1 parameter */
-#define DTYPE_GEN_WRITE2	0x23	/* short write, 2 parameter */
-#define DTYPE_GEN_LWRITE	0x29	/* long write */
-#define DTYPE_GEN_READ		0x04	/* long read, 0 parameter */
-#define DTYPE_GEN_READ1		0x14	/* long read, 1 parameter */
-#define DTYPE_GEN_READ2		0x24	/* long read, 2 parameter */
-
-#define DTYPE_TEAR_ON		0x35	/* set tear on */
-#define DTYPE_MAX_PKTSIZE	0x37	/* set max packet size */
-#define DTYPE_NULL_PKT		0x09	/* null packet, no data */
-#define DTYPE_BLANK_PKT		0x19	/* blankiing packet, no data */
-
-#define DTYPE_CM_ON		0x02	/* color mode off */
-#define DTYPE_CM_OFF		0x12	/* color mode on */
-#define DTYPE_PERIPHERAL_OFF	0x22
-#define DTYPE_PERIPHERAL_ON	0x32
-
-/*
- * dcs response
- */
-#define DTYPE_ACK_ERR_RESP      0x02
-#define DTYPE_EOT_RESP          0x08    /* end of tx */
-#define DTYPE_GEN_READ1_RESP    0x11    /* 1 parameter, short */
-#define DTYPE_GEN_READ2_RESP    0x12    /* 2 parameter, short */
-#define DTYPE_GEN_LREAD_RESP    0x1a
-#define DTYPE_DCS_LREAD_RESP    0x1c
-#define DTYPE_DCS_READ1_RESP    0x21    /* 1 parameter, short */
-#define DTYPE_DCS_READ2_RESP    0x22    /* 2 parameter, short */
-
-struct dsi_cmd_desc {
-	int dtype;
-	int last;
-	int vc;
-	int ack;	/* ask ACK from peripheral */
-	int wait;
-	int dlen;
-	char *payload;
-};
-
-struct dsi_panel_cmds_list {
-	struct dsi_cmd_desc *buf;
-	int size;
-	char ctrl_state;
-};
-
-struct dsi_panel_common_pdata {
-	struct mdss_panel_info panel_info;
-	int (*on) (struct mdss_panel_data *pdata);
-	int (*off) (struct mdss_panel_data *pdata);
-	void (*reset)(struct mdss_panel_data *pdata, int enable);
-	void (*bl_fnc) (struct mdss_panel_data *pdata, u32 bl_level);
-	struct dsi_panel_cmds_list *dsi_panel_on_cmds;
-	struct dsi_panel_cmds_list *dsi_panel_off_cmds;
-};
-
 struct dsi_interface {
 	int (*on)(struct mdss_panel_data *pdata);
 	int (*off)(struct mdss_panel_data *pdata);
@@ -210,8 +38,7 @@
 };
 
 int dsi_panel_device_register_v2(struct platform_device *pdev,
-				struct dsi_panel_common_pdata *panel_data,
-				char bl_ctrl);
+				struct mdss_dsi_ctrl_pdata *ctrl_pdata);
 
 void dsi_register_interface(struct dsi_interface *intf);
 
@@ -237,4 +64,14 @@
 
 void dsi_set_tx_power_mode(int mode);
 
-#endif /* MDSS_DSI_H */
+void dsi_ctrl_config_deinit(struct platform_device *pdev,
+				struct mdss_dsi_ctrl_pdata *ctrl_pdata);
+
+int dsi_ctrl_config_init(struct platform_device *pdev,
+				struct mdss_dsi_ctrl_pdata *ctrl_pdata);
+
+struct mdss_panel_cfg *mdp3_panel_intf_type(int intf_val);
+
+int mdp3_panel_get_boot_cfg(void);
+
+#endif /* DSI_V2_H */
diff --git a/drivers/video/msm/mdss/mdp3.c b/drivers/video/msm/mdss/mdp3.c
index 66ad706..f6c90f5 100644
--- a/drivers/video/msm/mdss/mdp3.c
+++ b/drivers/video/msm/mdss/mdp3.c
@@ -92,6 +92,10 @@
 static struct msm_bus_paths
 	mdp_bus_ppp_usecases[ARRAY_SIZE(mdp_bus_ppp_vectors)];
 
+static struct mdss_panel_intf pan_types[] = {
+	{"dsi", MDSS_PANEL_INTF_DSI},
+};
+
 static struct msm_bus_scale_pdata mdp_bus_ppp_scale_table = {
 	.usecase = mdp_bus_ppp_usecases,
 	.num_usecases = ARRAY_SIZE(mdp_bus_ppp_usecases),
@@ -379,7 +383,7 @@
 
 static int mdp3_clk_update(u32 clk_idx, u32 enable)
 {
-	int ret = -EINVAL;
+	int ret = 0;
 	struct clk *clk;
 	int count = 0;
 
@@ -807,9 +811,191 @@
 		devm_free_irq(&mdp3_res->pdev->dev, mdp3_res->irq, mdp3_res);
 }
 
+static int mdp3_get_pan_intf(const char *pan_intf)
+{
+	int i, rc = MDSS_PANEL_INTF_INVALID;
+
+	if (!pan_intf)
+		return rc;
+
+	for (i = 0; i < ARRAY_SIZE(pan_types); i++) {
+		if (!strncmp(pan_intf, pan_types[i].name,
+				strlen(pan_types[i].name))) {
+			rc = pan_types[i].type;
+			break;
+		}
+	}
+
+	return rc;
+}
+
+static int mdp3_parse_dt_pan_intf(struct platform_device *pdev)
+{
+	int rc;
+	struct mdp3_hw_resource *mdata = platform_get_drvdata(pdev);
+	const char *prim_intf = NULL;
+
+	rc = of_property_read_string(pdev->dev.of_node,
+				"qcom,mdss-pref-prim-intf", &prim_intf);
+	if (rc)
+		return -ENODEV;
+
+	rc = mdp3_get_pan_intf(prim_intf);
+	if (rc < 0) {
+		mdata->pan_cfg.pan_intf = MDSS_PANEL_INTF_INVALID;
+	} else {
+		mdata->pan_cfg.pan_intf = rc;
+		rc = 0;
+	}
+	return rc;
+}
+
+static int mdp3_get_pan_cfg(struct mdss_panel_cfg *pan_cfg)
+{
+	char *t = NULL;
+	char pan_intf_str[MDSS_MAX_PANEL_LEN];
+	int rc, i;
+	char pan_name[MDSS_MAX_PANEL_LEN];
+
+	if (!pan_cfg)
+		return -EINVAL;
+
+	strlcpy(pan_name, &pan_cfg->arg_cfg[0], sizeof(pan_cfg->arg_cfg));
+	if (pan_name[0] == '0') {
+		pan_cfg->lk_cfg = false;
+	} else if (pan_name[0] == '1') {
+		pan_cfg->lk_cfg = true;
+	} else {
+		/* read from dt */
+		pan_cfg->lk_cfg = true;
+		pan_cfg->pan_intf = MDSS_PANEL_INTF_INVALID;
+		return -EINVAL;
+	}
+
+	/* skip lk cfg and delimiter; ex: "0:" */
+	strlcpy(pan_name, &pan_name[2], MDSS_MAX_PANEL_LEN);
+	t = strnstr(pan_name, ":", MDSS_MAX_PANEL_LEN);
+	if (!t) {
+		pr_err("%s: pan_name=[%s] invalid\n",
+			__func__, pan_name);
+		pan_cfg->pan_intf = MDSS_PANEL_INTF_INVALID;
+		return -EINVAL;
+	}
+
+	for (i = 0; ((pan_name + i) < t) && (i < 4); i++)
+		pan_intf_str[i] = *(pan_name + i);
+	pan_intf_str[i] = 0;
+	pr_debug("%s:%d panel intf %s\n", __func__, __LINE__, pan_intf_str);
+	/* point to the start of panel name */
+	t = t + 1;
+	strlcpy(&pan_cfg->arg_cfg[0], t, sizeof(pan_cfg->arg_cfg));
+	pr_debug("%s:%d: t=[%s] panel name=[%s]\n", __func__, __LINE__,
+		t, pan_cfg->arg_cfg);
+	rc = mdp3_get_pan_intf(pan_intf_str);
+	pan_cfg->pan_intf = (rc < 0) ?  MDSS_PANEL_INTF_INVALID : rc;
+	return 0;
+}
+
+static int mdp3_parse_bootarg(struct platform_device *pdev)
+{
+	struct device_node *chosen_node;
+	static const char *cmd_line;
+	char *disp_idx, *end_idx;
+	int rc, len = 0, name_len, cmd_len;
+	int *intf_type;
+	char *panel_name;
+	struct mdss_panel_cfg *pan_cfg;
+	struct mdp3_hw_resource *mdata = platform_get_drvdata(pdev);
+
+	mdata->pan_cfg.arg_cfg[MDSS_MAX_PANEL_LEN] = 0;
+	pan_cfg = &mdata->pan_cfg;
+	panel_name = &pan_cfg->arg_cfg[0];
+	intf_type = &pan_cfg->pan_intf;
+
+	/* reads from dt by default */
+	pan_cfg->lk_cfg = true;
+
+	chosen_node = of_find_node_by_name(NULL, "chosen");
+	if (!chosen_node) {
+		pr_err("%s: get chosen node failed\n", __func__);
+		rc = -ENODEV;
+		goto get_dt_pan;
+	}
+
+	cmd_line = of_get_property(chosen_node, "bootargs", &len);
+	if (!cmd_line || len <= 0) {
+		pr_err("%s: get bootargs failed\n", __func__);
+		rc = -ENODEV;
+		goto get_dt_pan;
+	}
+
+	name_len = strlen("mdss_mdp.panel=");
+	cmd_len = strlen(cmd_line);
+	disp_idx = strnstr(cmd_line, "mdss_mdp.panel=", cmd_len);
+	if (!disp_idx) {
+		pr_err("%s:%d:cmdline panel not set disp_idx=[%p]\n",
+				__func__, __LINE__, disp_idx);
+		memset(panel_name, 0x00, MDSS_MAX_PANEL_LEN);
+		*intf_type = MDSS_PANEL_INTF_INVALID;
+		rc = MDSS_PANEL_INTF_INVALID;
+		goto get_dt_pan;
+	}
+
+	disp_idx += name_len;
+
+	end_idx = strnstr(disp_idx, " ", MDSS_MAX_PANEL_LEN);
+	pr_debug("%s:%d: pan_name=[%s] end=[%s]\n", __func__, __LINE__,
+		 disp_idx, end_idx);
+	if (!end_idx) {
+		end_idx = disp_idx + strlen(disp_idx) + 1;
+		pr_warn("%s:%d: pan_name=[%s] end=[%s]\n", __func__,
+		       __LINE__, disp_idx, end_idx);
+	}
+
+	if (end_idx <= disp_idx) {
+		pr_err("%s:%d:cmdline pan incorrect end=[%p] disp=[%p]\n",
+			__func__, __LINE__, end_idx, disp_idx);
+		memset(panel_name, 0x00, MDSS_MAX_PANEL_LEN);
+		*intf_type = MDSS_PANEL_INTF_INVALID;
+		rc = MDSS_PANEL_INTF_INVALID;
+		goto get_dt_pan;
+	}
+
+	*end_idx = 0;
+	len = end_idx - disp_idx + 1;
+	if (len <= 0) {
+		pr_warn("%s: panel name not rx", __func__);
+		rc = -EINVAL;
+		goto get_dt_pan;
+	}
+
+	strlcpy(panel_name, disp_idx, min(++len, MDSS_MAX_PANEL_LEN));
+	pr_debug("%s:%d panel:[%s]", __func__, __LINE__, panel_name);
+	of_node_put(chosen_node);
+
+	rc = mdp3_get_pan_cfg(pan_cfg);
+	if (!rc)
+		pan_cfg->init_done = true;
+
+	return rc;
+
+get_dt_pan:
+	rc = mdp3_parse_dt_pan_intf(pdev);
+	/* if pref pan intf is not present */
+	if (rc)
+		pr_err("%s:unable to parse device tree for pan intf\n",
+			__func__);
+	else
+		pan_cfg->init_done = true;
+
+	of_node_put(chosen_node);
+	return rc;
+}
+
 static int mdp3_parse_dt(struct platform_device *pdev)
 {
 	struct resource *res;
+	int rc;
 
 	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "mdp_phys");
 	if (!res) {
@@ -836,6 +1022,13 @@
 	}
 	mdp3_res->irq = res->start;
 
+	rc = mdp3_parse_bootarg(pdev);
+	if (rc) {
+		pr_err("%s: Error in panel override:rc=[%d]\n",
+		       __func__, rc);
+		return rc;
+	}
+
 	return 0;
 }
 
@@ -1350,6 +1543,31 @@
 	return rc;
 }
 
+struct mdss_panel_cfg *mdp3_panel_intf_type(int intf_val)
+{
+	if (!mdp3_res || !mdp3_res->pan_cfg.init_done)
+		return ERR_PTR(-EPROBE_DEFER);
+
+	if (mdp3_res->pan_cfg.pan_intf == intf_val)
+		return &mdp3_res->pan_cfg;
+	else
+		return NULL;
+}
+EXPORT_SYMBOL(mdp3_panel_intf_type);
+
+int mdp3_panel_get_boot_cfg(void)
+{
+	int rc;
+
+	if (!mdp3_res || !mdp3_res->pan_cfg.init_done)
+		rc = -EPROBE_DEFER;
+	if (mdp3_res->pan_cfg.lk_cfg)
+		rc = 1;
+	else
+		rc = 0;
+	return rc;
+}
+
 static  int mdp3_suspend_sub(struct mdp3_hw_resource *mdata)
 {
 	return 0;
diff --git a/drivers/video/msm/mdss/mdp3.h b/drivers/video/msm/mdss/mdp3.h
index bd1c03d..3f081ba 100644
--- a/drivers/video/msm/mdss/mdp3.h
+++ b/drivers/video/msm/mdss/mdp3.h
@@ -126,6 +126,7 @@
 	int irq_registered;
 
 	struct early_suspend suspend_handler;
+	struct mdss_panel_cfg pan_cfg;
 };
 
 struct mdp3_img_data {
diff --git a/drivers/video/msm/mdss/mdp3_ctrl.c b/drivers/video/msm/mdss/mdp3_ctrl.c
index bb53f33..167f3b6 100644
--- a/drivers/video/msm/mdss/mdp3_ctrl.c
+++ b/drivers/video/msm/mdss/mdp3_ctrl.c
@@ -583,15 +583,15 @@
 
 	mutex_lock(&mdp3_session->lock);
 
-	if (mdp3_session->overlay.id == req->id) {
-		mdp3_session->overlay = *req;
-		if (req->id == MSMFB_NEW_REQUEST) {
-			mdp3_session->overlay.id = 1;
-			req->id = 1;
-		}
-	} else {
-		rc = -EINVAL;
+	if (mdp3_session->overlay.id != req->id)
+		pr_err("overlay was not released, continue to recover\n");
+
+	mdp3_session->overlay = *req;
+	if (req->id == MSMFB_NEW_REQUEST) {
+		mdp3_session->overlay.id = 1;
+		req->id = 1;
 	}
+
 	mutex_unlock(&mdp3_session->lock);
 
 	return rc;
@@ -673,11 +673,6 @@
 	if (!mdp3_session || !mdp3_session->dma)
 		return -EINVAL;
 
-	if (!mdp3_session->status) {
-		pr_err("%s, display off!\n", __func__);
-		return -EPERM;
-	}
-
 	if (!mdp3_iommu_is_attached(MDP3_CLIENT_DMA_P)) {
 		pr_debug("continuous splash screen, IOMMU not attached\n");
 		mdp3_ctrl_off(mfd);
@@ -687,6 +682,12 @@
 
 	mutex_lock(&mdp3_session->lock);
 
+	if (!mdp3_session->status) {
+		pr_err("%s, display off!\n", __func__);
+		mutex_unlock(&mdp3_session->lock);
+		return -EPERM;
+	}
+
 	data = mdp3_bufq_pop(&mdp3_session->bufq_in);
 	if (data) {
 		mdp3_session->dma->update(mdp3_session->dma,
@@ -721,11 +722,6 @@
 	if (!mdp3_session || !mdp3_session->dma)
 		return;
 
-	if (!mdp3_session->status) {
-		pr_err("mdp3_ctrl_pan_display, display off!\n");
-		return;
-	}
-
 	if (!mdp3_iommu_is_attached(MDP3_CLIENT_DMA_P)) {
 		pr_debug("continuous splash screen, IOMMU not attached\n");
 		mdp3_ctrl_off(mfd);
@@ -733,6 +729,12 @@
 	}
 
 	mutex_lock(&mdp3_session->lock);
+
+	if (!mdp3_session->status) {
+		pr_err("mdp3_ctrl_pan_display, display off!\n");
+		goto pan_error;
+	}
+
 	fbi = mfd->fbi;
 
 	bpp = fbi->var.bits_per_pixel / 8;
diff --git a/drivers/video/msm/mdss/mdss.h b/drivers/video/msm/mdss/mdss.h
index 88baa44..ecc07cf 100644
--- a/drivers/video/msm/mdss/mdss.h
+++ b/drivers/video/msm/mdss/mdss.h
@@ -23,6 +23,8 @@
 
 #include <mach/iommu_domains.h>
 
+#include "mdss_panel.h"
+
 #define MDSS_REG_WRITE(addr, val) writel_relaxed(val, mdss_res->mdp_base + addr)
 #define MDSS_REG_READ(addr) readl_relaxed(mdss_res->mdp_base + addr)
 
@@ -131,6 +133,7 @@
 	struct mdss_debug_inf debug_inf;
 	int current_bus_idx;
 	bool mixer_switched;
+	struct mdss_panel_cfg pan_cfg;
 };
 extern struct mdss_data_type *mdss_res;
 
diff --git a/drivers/video/msm/mdss/mdss_dsi.c b/drivers/video/msm/mdss/mdss_dsi.c
index a575d6d..e156116 100644
--- a/drivers/video/msm/mdss/mdss_dsi.c
+++ b/drivers/video/msm/mdss/mdss_dsi.c
@@ -262,6 +262,29 @@
 	return rc;
 }
 
+static int mdss_dsi_get_panel_cfg(char *panel_cfg)
+{
+	int rc;
+	struct mdss_panel_cfg *pan_cfg = NULL;
+
+	if (!panel_cfg)
+		return MDSS_PANEL_INTF_INVALID;
+
+	pan_cfg = mdss_panel_intf_type(MDSS_PANEL_INTF_DSI);
+	if (IS_ERR(pan_cfg)) {
+		return PTR_ERR(pan_cfg);
+	} else if (!pan_cfg) {
+		panel_cfg[0] = 0;
+		return 0;
+	}
+
+	pr_debug("%s:%d: cfg:[%s]\n", __func__, __LINE__,
+		 pan_cfg->arg_cfg);
+	rc = strlcpy(panel_cfg, pan_cfg->arg_cfg,
+		     sizeof(pan_cfg->arg_cfg));
+	return rc;
+}
+
 static int mdss_dsi_off(struct mdss_panel_data *pdata)
 {
 	int ret = 0;
@@ -636,98 +659,212 @@
 	return rc;
 }
 
+/**
+ * mdss_dsi_find_panel_of_node(): find device node of dsi panel
+ * @pdev: platform_device of the dsi ctrl node
+ * @panel_cfg: string containing intf specific config data
+ *
+ * Function finds the panel device node using the interface
+ * specific configuration data. This configuration data is
+ * could be derived from the result of bootloader's GCDB
+ * panel detection mechanism. If such config data doesn't
+ * exist then this panel returns the default panel configured
+ * in the device tree.
+ *
+ * returns pointer to panel node on success, NULL on error.
+ */
+static struct device_node *mdss_dsi_find_panel_of_node(
+		struct platform_device *pdev, char *panel_cfg)
+{
+	int l;
+	int ctrl_id = -1;
+	char *panel_name;
+	struct device_node *dsi_pan_node = NULL, *mdss_node = NULL;
+
+	l = strlen(panel_cfg);
+	if (!l) {
+		/* no panel cfg chg, parse dt */
+		pr_debug("%s:%d: no cmd line cfg present\n",
+			 __func__, __LINE__);
+		dsi_pan_node = of_parse_phandle(
+			pdev->dev.of_node,
+			"qcom,dsi-pref-prim-pan", 0);
+		if (!dsi_pan_node) {
+			pr_err("%s:can't find panel phandle\n",
+			       __func__);
+			return NULL;
+		}
+	} else {
+		if (panel_cfg[0] == '0') {
+			pr_debug("%s:%d: DSI ctrl 1\n", __func__, __LINE__);
+			ctrl_id = 0;
+		} else if (panel_cfg[0] == '1') {
+			pr_debug("%s:%d: DSI ctrl 2\n", __func__, __LINE__);
+			ctrl_id = 1;
+		}
+		if ((pdev->id - 1) != ctrl_id) {
+			pr_err("%s:%d:pdev_ID=[%d]\n",
+			       __func__, __LINE__, pdev->id);
+			return NULL;
+		}
+		/*
+		 * skip first two chars '<dsi_ctrl_id>' and
+		 * ':' to get to the panel name
+		 */
+		panel_name = panel_cfg + 2;
+		pr_debug("%s:%d:%s:%s\n", __func__, __LINE__,
+			 panel_cfg, panel_name);
+
+		mdss_node = of_parse_phandle(pdev->dev.of_node,
+					     "qcom,mdss-mdp", 0);
+
+		if (!mdss_node) {
+			pr_err("%s: %d: mdss_node null\n",
+			       __func__, __LINE__);
+			return NULL;
+		}
+		dsi_pan_node = of_find_node_by_name(mdss_node,
+						    panel_name);
+		if (!dsi_pan_node) {
+			pr_err("%s: invalid pan node\n",
+			       __func__);
+			return NULL;
+		}
+	}
+	return dsi_pan_node;
+}
+
 static int __devinit mdss_dsi_ctrl_probe(struct platform_device *pdev)
 {
 	int rc = 0;
 	u32 index;
 	struct mdss_dsi_ctrl_pdata *ctrl_pdata = NULL;
+	struct device_node *dsi_pan_node = NULL;
+	char panel_cfg[MDSS_MAX_PANEL_LEN];
+	struct resource *mdss_dsi_mres;
+	const char *ctrl_name;
+	bool cmd_cfg_cont_splash = true;
 
-	if (pdev->dev.of_node) {
-		struct resource *mdss_dsi_mres;
-		const char *ctrl_name;
+	if (!mdss_is_ready()) {
+		pr_err("%s: MDP not probed yet!\n", __func__);
+		return -EPROBE_DEFER;
+	}
 
-		ctrl_pdata = platform_get_drvdata(pdev);
+	if (!pdev->dev.of_node) {
+		pr_err("DSI driver only supports device tree probe\n");
+		return -ENOTSUPP;
+	}
+
+	ctrl_pdata = platform_get_drvdata(pdev);
+	if (!ctrl_pdata) {
+		ctrl_pdata = devm_kzalloc(&pdev->dev,
+					  sizeof(struct mdss_dsi_ctrl_pdata),
+					  GFP_KERNEL);
 		if (!ctrl_pdata) {
-			ctrl_pdata = devm_kzalloc(&pdev->dev,
-				sizeof(struct mdss_dsi_ctrl_pdata), GFP_KERNEL);
-			if (!ctrl_pdata) {
-				pr_err("%s: FAILED: cannot alloc dsi ctrl\n",
-					__func__);
-				rc = -ENOMEM;
-				goto error_no_mem;
-			}
-			platform_set_drvdata(pdev, ctrl_pdata);
-		}
-
-		ctrl_name = of_get_property(pdev->dev.of_node, "label", NULL);
-		if (!ctrl_name)
-			pr_info("%s:%d, DSI Ctrl name not specified\n",
-						__func__, __LINE__);
-		else
-			pr_info("%s: DSI Ctrl name = %s\n",
-				__func__, ctrl_name);
-
-		rc = of_property_read_u32(pdev->dev.of_node,
-					  "cell-index", &index);
-		if (rc) {
-			dev_err(&pdev->dev,
-				"%s: Cell-index not specified, rc=%d\n",
-							__func__, rc);
-			goto error_no_mem;
-		}
-
-		if (index == 0)
-			pdev->id = 1;
-		else
-			pdev->id = 2;
-
-		mdss_dsi_mres = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-		if (!mdss_dsi_mres) {
-			pr_err("%s:%d unable to get the MDSS resources",
-				       __func__, __LINE__);
+			pr_err("%s: FAILED: cannot alloc dsi ctrl\n",
+			       __func__);
 			rc = -ENOMEM;
 			goto error_no_mem;
 		}
-		if (mdss_dsi_mres) {
-			mdss_dsi_base = ioremap(mdss_dsi_mres->start,
-				resource_size(mdss_dsi_mres));
-			if (!mdss_dsi_base) {
-				pr_err("%s:%d unable to remap dsi resources",
-					       __func__, __LINE__);
-				rc = -ENOMEM;
-				goto error_no_mem;
-			}
-		}
-
-		rc = of_platform_populate(pdev->dev.of_node,
-					NULL, NULL, &pdev->dev);
-		if (rc) {
-			dev_err(&pdev->dev,
-				"%s: failed to add child nodes, rc=%d\n",
-							__func__, rc);
-			goto error_ioremap;
-		}
-
-		/* Parse the regulator information */
-		rc = mdss_dsi_get_dt_vreg_data(&pdev->dev,
-			&ctrl_pdata->power_data);
-		if (rc) {
-			pr_err("%s: failed to get vreg data from dt. rc=%d\n",
-				__func__, rc);
-			goto error_vreg;
-		}
-
-		pr_debug("%s: Dsi Ctrl->%d initialized\n", __func__, index);
+		platform_set_drvdata(pdev, ctrl_pdata);
 	}
 
+	ctrl_name = of_get_property(pdev->dev.of_node, "label", NULL);
+	if (!ctrl_name)
+		pr_info("%s:%d, DSI Ctrl name not specified\n",
+			__func__, __LINE__);
+	else
+		pr_info("%s: DSI Ctrl name = %s\n",
+			__func__, ctrl_name);
+
+	rc = of_property_read_u32(pdev->dev.of_node,
+				  "cell-index", &index);
+	if (rc) {
+		dev_err(&pdev->dev,
+			"%s: Cell-index not specified, rc=%d\n",
+			__func__, rc);
+		goto error_no_mem;
+	}
+
+	if (index == 0)
+		pdev->id = 1;
+	else
+		pdev->id = 2;
+
+	mdss_dsi_mres = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!mdss_dsi_mres) {
+		pr_err("%s:%d unable to get the MDSS resources",
+		       __func__, __LINE__);
+		rc = -ENOMEM;
+		goto error_no_mem;
+	}
+
+	mdss_dsi_base = ioremap(mdss_dsi_mres->start,
+				resource_size(mdss_dsi_mres));
+	if (!mdss_dsi_base) {
+		pr_err("%s:%d unable to remap dsi resources",
+		       __func__, __LINE__);
+		rc = -ENOMEM;
+		goto error_no_mem;
+	}
+
+	rc = of_platform_populate(pdev->dev.of_node,
+				  NULL, NULL, &pdev->dev);
+	if (rc) {
+		dev_err(&pdev->dev,
+			"%s: failed to add child nodes, rc=%d\n",
+			__func__, rc);
+		goto error_ioremap;
+	}
+
+	/* Parse the regulator information */
+	rc = mdss_dsi_get_dt_vreg_data(&pdev->dev,
+				       &ctrl_pdata->power_data);
+	if (rc) {
+		pr_err("%s: failed to get vreg data from dt. rc=%d\n",
+		       __func__, rc);
+		goto error_vreg;
+	}
+
+	/* DSI panels can be different between controllers */
+	rc = mdss_dsi_get_panel_cfg(panel_cfg);
+	if (!rc)
+		/* dsi panel cfg not present */
+		pr_warn("%s:%d:dsi specific cfg not present\n",
+			__func__, __LINE__);
+
+	/* find panel device node */
+	dsi_pan_node = mdss_dsi_find_panel_of_node(pdev, panel_cfg);
+	if (!dsi_pan_node) {
+		pr_err("%s: can't find panel node %s\n", __func__, panel_cfg);
+		goto error_pan_node;
+	}
+
+	cmd_cfg_cont_splash = mdss_panel_get_boot_cfg() ? true : false;
+
+	rc = mdss_dsi_panel_init(dsi_pan_node, ctrl_pdata, cmd_cfg_cont_splash);
+	if (rc) {
+		pr_err("%s: dsi panel init failed\n", __func__);
+		goto error_pan_node;
+	}
+
+	rc = dsi_panel_device_register(dsi_pan_node, ctrl_pdata);
+	if (rc) {
+		pr_err("%s: dsi panel dev reg failed\n", __func__);
+		goto error_pan_node;
+	}
+
+	pr_debug("%s: Dsi Ctrl->%d initialized\n", __func__, index);
 	return 0;
 
+error_pan_node:
+	of_node_put(dsi_pan_node);
+error_vreg:
+	mdss_dsi_put_dt_vreg_data(&pdev->dev, &ctrl_pdata->power_data);
 error_ioremap:
 	iounmap(mdss_dsi_base);
 error_no_mem:
 	devm_kfree(&pdev->dev, ctrl_pdata);
-error_vreg:
-	mdss_dsi_put_dt_vreg_data(&pdev->dev, &ctrl_pdata->power_data);
 
 	return rc;
 }
@@ -810,33 +947,32 @@
 	return 0;
 }
 
-
-int dsi_panel_device_register(struct platform_device *pdev,
-			      struct mdss_panel_common_pdata *panel_data)
+int dsi_panel_device_register(struct device_node *pan_node,
+				struct mdss_dsi_ctrl_pdata *ctrl_pdata)
 {
 	struct mipi_panel_info *mipi;
 	int rc, i, len;
 	u8 lanes = 0, bpp;
 	u32 h_period, v_period, dsi_pclk_rate, tmp[9];
-	struct mdss_dsi_ctrl_pdata *ctrl_pdata;
 	struct device_node *dsi_ctrl_np = NULL;
 	struct platform_device *ctrl_pdev = NULL;
-	bool cont_splash_enabled = false;
 	const char *data;
+	struct mdss_panel_info *pinfo = &(ctrl_pdata->panel_data.panel_info);
 
-	h_period = ((panel_data->panel_info.lcdc.h_pulse_width)
-			+ (panel_data->panel_info.lcdc.h_back_porch)
-			+ (panel_data->panel_info.xres)
-			+ (panel_data->panel_info.lcdc.h_front_porch));
+	h_period = ((pinfo->lcdc.h_pulse_width)
+			+ (pinfo->lcdc.h_back_porch)
+			+ (pinfo->xres)
+			+ (pinfo->lcdc.h_front_porch));
 
-	v_period = ((panel_data->panel_info.lcdc.v_pulse_width)
-			+ (panel_data->panel_info.lcdc.v_back_porch)
-			+ (panel_data->panel_info.yres)
-			+ (panel_data->panel_info.lcdc.v_front_porch));
+	v_period = ((pinfo->lcdc.v_pulse_width)
+			+ (pinfo->lcdc.v_back_porch)
+			+ (pinfo->yres)
+			+ (pinfo->lcdc.v_front_porch));
 
-	mipi  = &panel_data->panel_info.mipi;
+	mipi  = &pinfo->mipi;
+	mipi  = &(pinfo->mipi);
 
-	panel_data->panel_info.type =
+	pinfo->type =
 		((mipi->mode == DSI_VIDEO_MODE)
 			? MIPI_VIDEO_PANEL : MIPI_CMD_PANEL);
 
@@ -860,22 +996,22 @@
 	else
 		bpp = 3;		/* Default format set to RGB888 */
 
-	if (!panel_data->panel_info.clk_rate) {
-		h_period += panel_data->panel_info.lcdc.xres_pad;
-		v_period += panel_data->panel_info.lcdc.yres_pad;
+	if (!pinfo->clk_rate) {
+		h_period += pinfo->lcdc.xres_pad;
+		v_period += pinfo->lcdc.yres_pad;
 
 		if (lanes > 0) {
-			panel_data->panel_info.clk_rate =
+			pinfo->clk_rate =
 			((h_period * v_period * (mipi->frame_rate) * bpp * 8)
 			   / lanes);
 		} else {
 			pr_err("%s: forcing mdss_dsi lanes to 1\n", __func__);
-			panel_data->panel_info.clk_rate =
+			pinfo->clk_rate =
 				(h_period * v_period
 					 * (mipi->frame_rate) * bpp * 8);
 		}
 	}
-	pll_divider_config.clk_rate = panel_data->panel_info.clk_rate;
+	pll_divider_config.clk_rate = pinfo->clk_rate;
 
 	rc = mdss_dsi_clk_div_config(bpp, lanes, &dsi_pclk_rate);
 	if (rc) {
@@ -887,7 +1023,7 @@
 		dsi_pclk_rate = 35000000;
 	mipi->dsi_pclk_rate = dsi_pclk_rate;
 
-	dsi_ctrl_np = of_parse_phandle(pdev->dev.of_node,
+	dsi_ctrl_np = of_parse_phandle(pan_node,
 				"qcom,mdss-dsi-panel-controller", 0);
 	if (!dsi_ctrl_np) {
 		pr_err("%s: Dsi controller node not initialized\n", __func__);
@@ -895,16 +1031,10 @@
 	}
 
 	ctrl_pdev = of_find_device_by_node(dsi_ctrl_np);
-	ctrl_pdata = platform_get_drvdata(ctrl_pdev);
-	if (!ctrl_pdata) {
-		pr_err("%s: no dsi ctrl driver data\n", __func__);
-		return -EINVAL;
-	}
 
 	rc = mdss_dsi_regulator_init(ctrl_pdev);
 	if (rc) {
-		dev_err(&pdev->dev,
-			"%s: failed to init regulator, rc=%d\n",
+		pr_err("%s: failed to init regulator, rc=%d\n",
 						__func__, rc);
 		return rc;
 	}
@@ -916,8 +1046,8 @@
 			__func__, __LINE__);
 		return -EINVAL;
 	}
-	(panel_data->panel_info.mipi.dsi_phy_db)->strength[0] = data[0];
-	(panel_data->panel_info.mipi.dsi_phy_db)->strength[1] = data[1];
+	pinfo->mipi.dsi_phy_db.strength[0] = data[0];
+	pinfo->mipi.dsi_phy_db.strength[1] = data[1];
 
 	data = of_get_property(ctrl_pdev->dev.of_node,
 		"qcom,platform-regulator-settings", &len);
@@ -927,7 +1057,7 @@
 		return -EINVAL;
 	}
 	for (i = 0; i < len; i++) {
-		(panel_data->panel_info.mipi.dsi_phy_db)->regulator[i]
+		pinfo->mipi.dsi_phy_db.regulator[i]
 			= data[i];
 	}
 
@@ -939,7 +1069,7 @@
 		return -EINVAL;
 	}
 	for (i = 0; i < len; i++) {
-		(panel_data->panel_info.mipi.dsi_phy_db)->bistCtrl[i]
+		pinfo->mipi.dsi_phy_db.bistctrl[i]
 			= data[i];
 	}
 
@@ -951,15 +1081,16 @@
 		return -EINVAL;
 	}
 	for (i = 0; i < len; i++) {
-		(panel_data->panel_info.mipi.dsi_phy_db)->laneCfg[i] =
+		pinfo->mipi.dsi_phy_db.lanecfg[i] =
 			data[i];
 	}
 
 	ctrl_pdata->shared_pdata.broadcast_enable = of_property_read_bool(
-		pdev->dev.of_node, "qcom,mdss-dsi-panel-broadcast-mode");
+		pan_node, "qcom,mdss-dsi-panel-broadcast-mode");
 
 	ctrl_pdata->disp_en_gpio = of_get_named_gpio(ctrl_pdev->dev.of_node,
 		"qcom,platform-enable-gpio", 0);
+
 	if (!gpio_is_valid(ctrl_pdata->disp_en_gpio)) {
 		pr_err("%s:%d, Disp_en gpio not specified\n",
 						__func__, __LINE__);
@@ -973,12 +1104,16 @@
 		}
 	}
 
-	ctrl_pdata->disp_te_gpio = of_get_named_gpio(ctrl_pdev->dev.of_node,
+	if (pinfo->type == MIPI_CMD_PANEL) {
+		ctrl_pdata->disp_te_gpio = of_get_named_gpio(ctrl_pdev->dev.of_node,
 						"qcom,platform-te-gpio", 0);
-	if (!gpio_is_valid(ctrl_pdata->disp_te_gpio)) {
-		pr_err("%s:%d, Disp_te gpio not specified\n",
+		if (!gpio_is_valid(ctrl_pdata->disp_te_gpio)) {
+			pr_err("%s:%d, Disp_te gpio not specified\n",
 						__func__, __LINE__);
-	} else {
+		}
+	}
+
+	if (gpio_is_valid(ctrl_pdata->disp_te_gpio)) {
 		rc = gpio_request(ctrl_pdata->disp_te_gpio, "disp_te");
 		if (rc) {
 			pr_err("request TE gpio failed, rc=%d\n",
@@ -1037,13 +1172,38 @@
 		}
 	}
 
+	if (pinfo->mode_gpio_state != MODE_GPIO_NOT_VALID) {
+
+		ctrl_pdata->mode_gpio = of_get_named_gpio(
+					ctrl_pdev->dev.of_node,
+					"qcom,platform-mode-gpio", 0);
+		if (!gpio_is_valid(ctrl_pdata->mode_gpio)) {
+			pr_info("%s:%d, mode gpio not specified\n",
+							__func__, __LINE__);
+		} else {
+			rc = gpio_request(ctrl_pdata->mode_gpio, "panel_mode");
+			if (rc) {
+				pr_err("request panel mode gpio failed,rc=%d\n",
+									rc);
+				gpio_free(ctrl_pdata->mode_gpio);
+				if (gpio_is_valid(ctrl_pdata->disp_en_gpio))
+					gpio_free(ctrl_pdata->disp_en_gpio);
+				if (gpio_is_valid(ctrl_pdata->rst_gpio))
+					gpio_free(ctrl_pdata->rst_gpio);
+				if (gpio_is_valid(ctrl_pdata->disp_te_gpio))
+					gpio_free(ctrl_pdata->disp_te_gpio);
+				return -ENODEV;
+			}
+		}
+	}
+
 	if (mdss_dsi_clk_init(ctrl_pdev, ctrl_pdata)) {
 		pr_err("%s: unable to initialize Dsi ctrl clks\n", __func__);
 		return -EPERM;
 	}
 
 	if (mdss_dsi_retrieve_ctrl_resources(ctrl_pdev,
-					     panel_data->panel_info.pdest,
+					     pinfo->pdest,
 					     ctrl_pdata)) {
 		pr_err("%s: unable to get Dsi controller res\n", __func__);
 		return -EPERM;
@@ -1051,20 +1211,6 @@
 
 	ctrl_pdata->panel_data.event_handler = mdss_dsi_event_handler;
 
-	ctrl_pdata->on_cmds = panel_data->on_cmds;
-	ctrl_pdata->off_cmds = panel_data->off_cmds;
-
-	memcpy(&((ctrl_pdata->panel_data).panel_info),
-				&(panel_data->panel_info),
-				       sizeof(struct mdss_panel_info));
-
-	ctrl_pdata->panel_data.set_backlight = panel_data->bl_fnc;
-	ctrl_pdata->bklt_ctrl = panel_data->panel_info.bklt_ctrl;
-	ctrl_pdata->pwm_pmic_gpio = panel_data->panel_info.pwm_pmic_gpio;
-	ctrl_pdata->pwm_period = panel_data->panel_info.pwm_period;
-	ctrl_pdata->pwm_lpg_chan = panel_data->panel_info.pwm_lpg_chan;
-	ctrl_pdata->bklt_max = panel_data->panel_info.bl_max;
-
 	if (ctrl_pdata->bklt_ctrl == BL_PWM)
 		mdss_dsi_panel_pwm_cfg(ctrl_pdata);
 
@@ -1074,24 +1220,14 @@
 	 */
 
 	ctrl_pdata->pclk_rate = dsi_pclk_rate;
-	ctrl_pdata->byte_clk_rate = panel_data->panel_info.clk_rate / 8;
+	ctrl_pdata->byte_clk_rate = pinfo->clk_rate / 8;
 	pr_debug("%s: pclk=%d, bclk=%d\n", __func__,
 			ctrl_pdata->pclk_rate, ctrl_pdata->byte_clk_rate);
 
 	ctrl_pdata->ctrl_state = CTRL_STATE_UNKNOWN;
-	cont_splash_enabled = of_property_read_bool(pdev->dev.of_node,
-			"qcom,cont-splash-enabled");
-	if (!cont_splash_enabled) {
-		pr_info("%s:%d Continuous splash flag not found.\n",
-				__func__, __LINE__);
-		ctrl_pdata->panel_data.panel_info.cont_splash_enabled = 0;
-		ctrl_pdata->panel_data.panel_info.panel_power_on = 0;
-	} else {
-		pr_info("%s:%d Continuous splash flag enabled.\n",
-				__func__, __LINE__);
 
-		ctrl_pdata->panel_data.panel_info.cont_splash_enabled = 1;
-		ctrl_pdata->panel_data.panel_info.panel_power_on = 1;
+	if (pinfo->cont_splash_enabled) {
+		pinfo->panel_power_on = 1;
 		rc = mdss_dsi_panel_power_on(&(ctrl_pdata->panel_data), 1);
 		if (rc) {
 			pr_err("%s: Panel power on failed\n", __func__);
@@ -1101,11 +1237,13 @@
 		mdss_dsi_clk_ctrl(ctrl_pdata, 1);
 		ctrl_pdata->ctrl_state |=
 			(CTRL_STATE_PANEL_INIT | CTRL_STATE_MDP_ACTIVE);
+	} else {
+		pinfo->panel_power_on = 0;
 	}
 
 	rc = mdss_register_panel(ctrl_pdev, &(ctrl_pdata->panel_data));
 	if (rc) {
-		dev_err(&pdev->dev, "unable to register MIPI DSI panel\n");
+		pr_err("%s: unable to register MIPI DSI panel\n", __func__);
 		if (ctrl_pdata->rst_gpio)
 			gpio_free(ctrl_pdata->rst_gpio);
 		if (gpio_is_valid(ctrl_pdata->disp_en_gpio))
@@ -1113,10 +1251,7 @@
 		return rc;
 	}
 
-	ctrl_pdata->on = panel_data->on;
-	ctrl_pdata->off = panel_data->off;
-
-	if (panel_data->panel_info.pdest == DISPLAY_1) {
+	if (pinfo->pdest == DISPLAY_1) {
 		mdss_debug_register_base("dsi0",
 			ctrl_pdata->ctrl_base, ctrl_pdata->reg_size);
 		ctrl_pdata->ndx = 0;
@@ -1126,7 +1261,7 @@
 		ctrl_pdata->ndx = 1;
 	}
 
-	pr_debug("%s: Panal data initialized\n", __func__);
+	pr_debug("%s: Panel data initialized\n", __func__);
 	return 0;
 }
 
diff --git a/drivers/video/msm/mdss/mdss_dsi.h b/drivers/video/msm/mdss/mdss_dsi.h
index a8c34f3..ec21db2 100644
--- a/drivers/video/msm/mdss/mdss_dsi.h
+++ b/drivers/video/msm/mdss/mdss_dsi.h
@@ -296,16 +296,6 @@
 	void *data;
 };
 
-struct mdss_panel_common_pdata {
-	struct mdss_panel_info panel_info;
-	int (*on) (struct mdss_panel_data *pdata);
-	int (*off) (struct mdss_panel_data *pdata);
-	void (*bl_fnc) (struct mdss_panel_data *pdata, u32 bl_level);
-
-	struct dsi_panel_cmds on_cmds;
-	struct dsi_panel_cmds off_cmds;
-};
-
 struct dsi_drv_cm_data {
 	struct regulator *vdd_vreg;
 	struct regulator *vdd_io_vreg;
@@ -338,6 +328,7 @@
 	int rst_gpio;
 	int disp_en_gpio;
 	int disp_te_gpio;
+	int mode_gpio;
 	int bklt_ctrl;	/* backlight ctrl */
 	int pwm_period;
 	int pwm_pmic_gpio;
@@ -369,8 +360,8 @@
 	struct dsi_buf rx_buf;
 };
 
-int dsi_panel_device_register(struct platform_device *pdev,
-			      struct mdss_panel_common_pdata *panel_data);
+int dsi_panel_device_register(struct device_node *pan_node,
+				struct mdss_dsi_ctrl_pdata *ctrl_pdata);
 
 char *mdss_dsi_buf_reserve_hdr(struct dsi_buf *dp, int hlen);
 char *mdss_dsi_buf_init(struct dsi_buf *dp);
@@ -428,4 +419,7 @@
 struct dcs_cmd_req *mdss_dsi_cmdlist_get(struct mdss_dsi_ctrl_pdata *ctrl);
 void mdss_dsi_cmdlist_kickoff(int intf);
 
+int mdss_dsi_panel_init(struct device_node *node,
+		struct mdss_dsi_ctrl_pdata *ctrl_pdata,
+		bool cmd_cfg_cont_splash);
 #endif /* MDSS_DSI_H */
diff --git a/drivers/video/msm/mdss/mdss_dsi_panel.c b/drivers/video/msm/mdss/mdss_dsi_panel.c
index 9a9a227..203900c 100644
--- a/drivers/video/msm/mdss/mdss_dsi_panel.c
+++ b/drivers/video/msm/mdss/mdss_dsi_panel.c
@@ -28,8 +28,6 @@
 
 DEFINE_LED_TRIGGER(bl_led_trigger);
 
-static struct mdss_dsi_phy_ctrl phy_params;
-
 void mdss_dsi_panel_pwm_cfg(struct mdss_dsi_ctrl_pdata *ctrl)
 {
 	int ret;
@@ -158,6 +156,7 @@
 void mdss_dsi_panel_reset(struct mdss_panel_data *pdata, int enable)
 {
 	struct mdss_dsi_ctrl_pdata *ctrl_pdata = NULL;
+	struct mdss_panel_info *pinfo = NULL;
 	int i;
 
 	if (pdata == NULL) {
@@ -180,6 +179,7 @@
 	}
 
 	pr_debug("%s: enable = %d\n", __func__, enable);
+	pinfo = &(ctrl_pdata->panel_data.panel_info);
 
 	if (enable) {
 		for (i = 0; i < MDSS_DSI_RST_SEQ_LEN; ++i) {
@@ -189,6 +189,13 @@
 		}
 		if (gpio_is_valid(ctrl_pdata->disp_en_gpio))
 			gpio_set_value((ctrl_pdata->disp_en_gpio), 1);
+
+		if (gpio_is_valid(ctrl_pdata->mode_gpio)) {
+			if (pinfo->mode_gpio_state == MODE_GPIO_HIGH)
+				gpio_set_value((ctrl_pdata->mode_gpio), 1);
+			else if (pinfo->mode_gpio_state == MODE_GPIO_LOW)
+				gpio_set_value((ctrl_pdata->mode_gpio), 0);
+		}
 		if (ctrl_pdata->ctrl_state & CTRL_STATE_PANEL_INIT) {
 			pr_debug("%s: Panel Not properly turned OFF\n",
 						__func__);
@@ -485,14 +492,14 @@
 }
 
 
-static int mdss_panel_parse_dt(struct platform_device *pdev,
-			      struct mdss_panel_common_pdata *panel_data)
+static int mdss_panel_parse_dt(struct device_node *np,
+			struct mdss_dsi_ctrl_pdata *ctrl_pdata)
 {
-	struct device_node *np = pdev->dev.of_node;
 	u32 tmp;
 	int rc, i, len;
 	const char *data;
 	static const char *pdest;
+	struct mdss_panel_info *pinfo = &(ctrl_pdata->panel_data.panel_info);
 
 	rc = of_property_read_u32(np, "qcom,mdss-dsi-panel-width", &tmp);
 	if (rc) {
@@ -500,7 +507,7 @@
 						__func__, __LINE__);
 		return -EINVAL;
 	}
-	panel_data->panel_info.xres = (!rc ? tmp : 640);
+	pinfo->xres = (!rc ? tmp : 640);
 
 	rc = of_property_read_u32(np, "qcom,mdss-dsi-panel-height", &tmp);
 	if (rc) {
@@ -508,81 +515,82 @@
 						__func__, __LINE__);
 		return -EINVAL;
 	}
-	panel_data->panel_info.yres = (!rc ? tmp : 480);
+	pinfo->yres = (!rc ? tmp : 480);
 
 	rc = of_property_read_u32(np,
 		"qcom,mdss-pan-physical-width-dimension", &tmp);
-	panel_data->panel_info.physical_width = (!rc ? tmp : 0);
+	pinfo->physical_width = (!rc ? tmp : 0);
 	rc = of_property_read_u32(np,
 		"qcom,mdss-pan-physical-height-dimension", &tmp);
-	panel_data->panel_info.physical_height = (!rc ? tmp : 0);
+	pinfo->physical_height = (!rc ? tmp : 0);
 	rc = of_property_read_u32(np, "qcom,mdss-dsi-h-left-border", &tmp);
-	panel_data->panel_info.lcdc.xres_pad = (!rc ? tmp : 0);
+	pinfo->lcdc.xres_pad = (!rc ? tmp : 0);
 	rc = of_property_read_u32(np, "qcom,mdss-dsi-h-right-border", &tmp);
 	if (!rc)
-		panel_data->panel_info.lcdc.xres_pad += tmp;
+		pinfo->lcdc.xres_pad += tmp;
 	rc = of_property_read_u32(np, "qcom,mdss-dsi-v-top-border", &tmp);
-	panel_data->panel_info.lcdc.yres_pad = (!rc ? tmp : 0);
+	pinfo->lcdc.yres_pad = (!rc ? tmp : 0);
 	rc = of_property_read_u32(np, "qcom,mdss-dsi-v-bottom-border", &tmp);
 	if (!rc)
-		panel_data->panel_info.lcdc.yres_pad += tmp;
+		pinfo->lcdc.yres_pad += tmp;
 	rc = of_property_read_u32(np, "qcom,mdss-dsi-bpp", &tmp);
 	if (rc) {
 		pr_err("%s:%d, bpp not specified\n", __func__, __LINE__);
 		return -EINVAL;
 	}
-	panel_data->panel_info.bpp = (!rc ? tmp : 24);
-	panel_data->panel_info.mipi.mode = DSI_VIDEO_MODE;
+	pinfo->bpp = (!rc ? tmp : 24);
+	pinfo->mipi.mode = DSI_VIDEO_MODE;
 	data = of_get_property(np, "qcom,mdss-dsi-panel-type", NULL);
 	if (data && !strncmp(data, "dsi_cmd_mode", 12))
-		panel_data->panel_info.mipi.mode = DSI_CMD_MODE;
+		pinfo->mipi.mode = DSI_CMD_MODE;
 	rc = of_property_read_u32(np, "qcom,mdss-dsi-pixel-packing", &tmp);
 	tmp = (!rc ? tmp : 0);
-	rc = mdss_panel_dt_get_dst_fmt(panel_data->panel_info.bpp,
-		panel_data->panel_info.mipi.mode, tmp,
-		&(panel_data->panel_info.mipi.dst_format));
+	rc = mdss_panel_dt_get_dst_fmt(pinfo->bpp,
+		pinfo->mipi.mode, tmp,
+		&(pinfo->mipi.dst_format));
 	if (rc) {
 		pr_debug("%s: problem determining dst format. Set Default\n",
 			__func__);
-		panel_data->panel_info.mipi.dst_format =
+		pinfo->mipi.dst_format =
 			DSI_VIDEO_DST_FORMAT_RGB888;
 	}
-	pdest = of_get_property(pdev->dev.of_node,
+	pdest = of_get_property(np,
 		"qcom,mdss-dsi-panel-destination", NULL);
+
 	if (strlen(pdest) != 9) {
 		pr_err("%s: Unknown pdest specified\n", __func__);
 		return -EINVAL;
 	}
 	if (!strncmp(pdest, "display_1", 9))
-		panel_data->panel_info.pdest = DISPLAY_1;
+		pinfo->pdest = DISPLAY_1;
 	else if (!strncmp(pdest, "display_2", 9))
-		panel_data->panel_info.pdest = DISPLAY_2;
+		pinfo->pdest = DISPLAY_2;
 	else {
 		pr_debug("%s: pdest not specified. Set Default\n",
 							__func__);
-		panel_data->panel_info.pdest = DISPLAY_1;
+		pinfo->pdest = DISPLAY_1;
 	}
 	rc = of_property_read_u32(np, "qcom,mdss-dsi-h-front-porch", &tmp);
-	panel_data->panel_info.lcdc.h_front_porch = (!rc ? tmp : 6);
+	pinfo->lcdc.h_front_porch = (!rc ? tmp : 6);
 	rc = of_property_read_u32(np, "qcom,mdss-dsi-h-back-porch", &tmp);
-	panel_data->panel_info.lcdc.h_back_porch = (!rc ? tmp : 6);
+	pinfo->lcdc.h_back_porch = (!rc ? tmp : 6);
 	rc = of_property_read_u32(np, "qcom,mdss-dsi-h-pulse-width", &tmp);
-	panel_data->panel_info.lcdc.h_pulse_width = (!rc ? tmp : 2);
+	pinfo->lcdc.h_pulse_width = (!rc ? tmp : 2);
 	rc = of_property_read_u32(np, "qcom,mdss-dsi-h-sync-skew", &tmp);
-	panel_data->panel_info.lcdc.hsync_skew = (!rc ? tmp : 0);
+	pinfo->lcdc.hsync_skew = (!rc ? tmp : 0);
 	rc = of_property_read_u32(np, "qcom,mdss-dsi-v-back-porch", &tmp);
-	panel_data->panel_info.lcdc.v_back_porch = (!rc ? tmp : 6);
+	pinfo->lcdc.v_back_porch = (!rc ? tmp : 6);
 	rc = of_property_read_u32(np, "qcom,mdss-dsi-v-front-porch", &tmp);
-	panel_data->panel_info.lcdc.v_front_porch = (!rc ? tmp : 6);
+	pinfo->lcdc.v_front_porch = (!rc ? tmp : 6);
 	rc = of_property_read_u32(np, "qcom,mdss-dsi-v-pulse-width", &tmp);
-	panel_data->panel_info.lcdc.v_pulse_width = (!rc ? tmp : 2);
+	pinfo->lcdc.v_pulse_width = (!rc ? tmp : 2);
 	rc = of_property_read_u32(np,
 		"qcom,mdss-dsi-underflow-color", &tmp);
-	panel_data->panel_info.lcdc.underflow_clr = (!rc ? tmp : 0xff);
+	pinfo->lcdc.underflow_clr = (!rc ? tmp : 0xff);
 	rc = of_property_read_u32(np,
 		"qcom,mdss-dsi-border-color", &tmp);
-	panel_data->panel_info.lcdc.border_clr = (!rc ? tmp : 0);
-	panel_data->panel_info.bklt_ctrl = UNKNOWN_CTRL;
+	pinfo->lcdc.border_clr = (!rc ? tmp : 0);
+	pinfo->bklt_ctrl = UNKNOWN_CTRL;
 	data = of_get_property(np, "qcom,mdss-dsi-bl-pmic-control-type", NULL);
 	if (data) {
 		if (!strncmp(data, "bl_ctrl_wled", 12)) {
@@ -590,9 +598,9 @@
 				&bl_led_trigger);
 			pr_debug("%s: SUCCESS-> WLED TRIGGER register\n",
 				__func__);
-			panel_data->panel_info.bklt_ctrl = BL_WLED;
+			ctrl_pdata->bklt_ctrl = BL_WLED;
 		} else if (!strncmp(data, "bl_ctrl_pwm", 11)) {
-			panel_data->panel_info.bklt_ctrl = BL_PWM;
+			ctrl_pdata->bklt_ctrl = BL_PWM;
 			rc = of_property_read_u32(np,
 				"qcom,mdss-dsi-bl-pmic-pwm-frequency", &tmp);
 			if (rc) {
@@ -600,7 +608,7 @@
 						__func__, __LINE__);
 				return -EINVAL;
 			}
-			panel_data->panel_info.pwm_period = tmp;
+			ctrl_pdata->pwm_period = tmp;
 			rc = of_property_read_u32(np,
 				"qcom,mdss-dsi-bl-pmic-bank-select", &tmp);
 			if (rc) {
@@ -608,108 +616,119 @@
 						__func__, __LINE__);
 				return -EINVAL;
 			}
-			panel_data->panel_info.pwm_lpg_chan = tmp;
+			ctrl_pdata->pwm_lpg_chan = tmp;
 			tmp = of_get_named_gpio(np,
 				"qcom,mdss-dsi-pwm-gpio", 0);
-			panel_data->panel_info.pwm_pmic_gpio = tmp;
+			ctrl_pdata->pwm_pmic_gpio = tmp;
 		} else if (!strncmp(data, "bl_ctrl_dcs", 11)) {
-			panel_data->panel_info.bklt_ctrl = BL_DCS_CMD;
+			ctrl_pdata->bklt_ctrl = BL_DCS_CMD;
 		}
 	}
 	rc = of_property_read_u32(np, "qcom,mdss-dsi-bl-min-level", &tmp);
-	panel_data->panel_info.bl_min = (!rc ? tmp : 0);
+	pinfo->bl_min = (!rc ? tmp : 0);
 	rc = of_property_read_u32(np, "qcom,mdss-dsi-bl-max-level", &tmp);
-	panel_data->panel_info.bl_max = (!rc ? tmp : 255);
+	pinfo->bl_max = (!rc ? tmp : 255);
+	ctrl_pdata->bklt_max = pinfo->bl_max;
 
 	rc = of_property_read_u32(np, "qcom,mdss-dsi-interleave-mode", &tmp);
-	panel_data->panel_info.mipi.interleave_mode = (!rc ? tmp : 0);
+	pinfo->mipi.interleave_mode = (!rc ? tmp : 0);
 
-	panel_data->panel_info.mipi.vsync_enable = of_property_read_bool(np,
+	pinfo->mipi.vsync_enable = of_property_read_bool(np,
 		"qcom,mdss-dsi-te-check-enable");
-	panel_data->panel_info.mipi.hw_vsync_mode = of_property_read_bool(np,
+	pinfo->mipi.hw_vsync_mode = of_property_read_bool(np,
 		"qcom,mdss-dsi-te-using-te-pin");
 
 	rc = of_property_read_u32(np,
 		"qcom,mdss-dsi-h-sync-pulse", &tmp);
-	panel_data->panel_info.mipi.pulse_mode_hsa_he = (!rc ? tmp : false);
+	pinfo->mipi.pulse_mode_hsa_he = (!rc ? tmp : false);
 
-	panel_data->panel_info.mipi.hfp_power_stop = of_property_read_bool(np,
+	pinfo->mipi.hfp_power_stop = of_property_read_bool(np,
 		"qcom,mdss-dsi-hfp-power-mode");
-	panel_data->panel_info.mipi.hsa_power_stop = of_property_read_bool(np,
+	pinfo->mipi.hsa_power_stop = of_property_read_bool(np,
 		"qcom,mdss-dsi-hsa-power-mode");
-	panel_data->panel_info.mipi.hbp_power_stop = of_property_read_bool(np,
+	pinfo->mipi.hbp_power_stop = of_property_read_bool(np,
 		"qcom,mdss-dsi-hbp-power-mode");
-	panel_data->panel_info.mipi.bllp_power_stop = of_property_read_bool(np,
+	pinfo->mipi.bllp_power_stop = of_property_read_bool(np,
 		"qcom,mdss-dsi-bllp-power-mode");
-	panel_data->panel_info.mipi.eof_bllp_power_stop = of_property_read_bool(
+	pinfo->mipi.eof_bllp_power_stop = of_property_read_bool(
 		np, "qcom,mdss-dsi-bllp-eof-power-mode");
 	rc = of_property_read_u32(np,
 		"qcom,mdss-dsi-traffic-mode", &tmp);
-	panel_data->panel_info.mipi.traffic_mode =
+	pinfo->mipi.traffic_mode =
 			(!rc ? tmp : DSI_NON_BURST_SYNCH_PULSE);
 	rc = of_property_read_u32(np,
 		"qcom,mdss-dsi-te-dcs-command", &tmp);
-	panel_data->panel_info.mipi.insert_dcs_cmd =
+	pinfo->mipi.insert_dcs_cmd =
 			(!rc ? tmp : 1);
 	rc = of_property_read_u32(np,
 		"qcom,mdss-dsi-te-v-sync-continue-lines", &tmp);
-	panel_data->panel_info.mipi.wr_mem_continue =
+	pinfo->mipi.wr_mem_continue =
 			(!rc ? tmp : 0x3c);
 	rc = of_property_read_u32(np,
 		"qcom,mdss-dsi-te-v-sync-rd-ptr-irq-line", &tmp);
-	panel_data->panel_info.mipi.wr_mem_start =
+	pinfo->mipi.wr_mem_start =
 			(!rc ? tmp : 0x2c);
 	rc = of_property_read_u32(np,
 		"qcom,mdss-dsi-te-pin-select", &tmp);
-	panel_data->panel_info.mipi.te_sel =
+	pinfo->mipi.te_sel =
 			(!rc ? tmp : 1);
 	rc = of_property_read_u32(np, "qcom,mdss-dsi-virtual-channel-id", &tmp);
-	panel_data->panel_info.mipi.vc = (!rc ? tmp : 0);
+	pinfo->mipi.vc = (!rc ? tmp : 0);
 	rc = of_property_read_u32(np, "qcom,mdss-dsi-color-order", &tmp);
-	panel_data->panel_info.mipi.rgb_swap = (!rc ? tmp : DSI_RGB_SWAP_RGB);
-	panel_data->panel_info.mipi.data_lane0 = of_property_read_bool(np,
+	pinfo->mipi.rgb_swap = (!rc ? tmp : DSI_RGB_SWAP_RGB);
+	pinfo->mipi.data_lane0 = of_property_read_bool(np,
 		"qcom,mdss-dsi-lane-0-state");
-	panel_data->panel_info.mipi.data_lane1 = of_property_read_bool(np,
+	pinfo->mipi.data_lane1 = of_property_read_bool(np,
 		"qcom,mdss-dsi-lane-1-state");
-	panel_data->panel_info.mipi.data_lane2 = of_property_read_bool(np,
+	pinfo->mipi.data_lane2 = of_property_read_bool(np,
 		"qcom,mdss-dsi-lane-2-state");
-	panel_data->panel_info.mipi.data_lane3 = of_property_read_bool(np,
+	pinfo->mipi.data_lane3 = of_property_read_bool(np,
 		"qcom,mdss-dsi-lane-3-state");
 
 	rc = of_property_read_u32(np, "qcom,mdss-dsi-lane-map", &tmp);
-	panel_data->panel_info.mipi.dlane_swap = (!rc ? tmp : 0);
+	pinfo->mipi.dlane_swap = (!rc ? tmp : 0);
 
 	rc = of_property_read_u32(np, "qcom,mdss-dsi-t-clk-pre", &tmp);
-	panel_data->panel_info.mipi.t_clk_pre = (!rc ? tmp : 0x24);
+	pinfo->mipi.t_clk_pre = (!rc ? tmp : 0x24);
 	rc = of_property_read_u32(np, "qcom,mdss-dsi-t-clk-post", &tmp);
-	panel_data->panel_info.mipi.t_clk_post = (!rc ? tmp : 0x03);
+	pinfo->mipi.t_clk_post = (!rc ? tmp : 0x03);
 
 	rc = of_property_read_u32(np, "qcom,mdss-dsi-stream", &tmp);
-	panel_data->panel_info.mipi.stream = (!rc ? tmp : 0);
+	pinfo->mipi.stream = (!rc ? tmp : 0);
 
 	rc = of_property_read_u32(np, "qcom,mdss-dsi-mdp-trigger", &tmp);
-	panel_data->panel_info.mipi.mdp_trigger =
+	pinfo->mipi.mdp_trigger =
 			(!rc ? tmp : DSI_CMD_TRIGGER_SW);
-	if (panel_data->panel_info.mipi.mdp_trigger > 6) {
+	if (pinfo->mipi.mdp_trigger > 6) {
 		pr_err("%s:%d, Invalid mdp trigger. Forcing to sw trigger",
 						 __func__, __LINE__);
-		panel_data->panel_info.mipi.mdp_trigger =
+		pinfo->mipi.mdp_trigger =
 					DSI_CMD_TRIGGER_SW;
 	}
 
 	rc = of_property_read_u32(np, "qcom,mdss-dsi-dma-trigger", &tmp);
-	panel_data->panel_info.mipi.dma_trigger =
+	pinfo->mipi.dma_trigger =
 			(!rc ? tmp : DSI_CMD_TRIGGER_SW);
-	if (panel_data->panel_info.mipi.dma_trigger > 6) {
+	if (pinfo->mipi.dma_trigger > 6) {
 		pr_err("%s:%d, Invalid dma trigger. Forcing to sw trigger",
 						 __func__, __LINE__);
-		panel_data->panel_info.mipi.dma_trigger =
+		pinfo->mipi.dma_trigger =
 					DSI_CMD_TRIGGER_SW;
 	}
+	data = of_get_property(np, "qcom,mdss-dsi-panel-mode-gpio-state", &tmp);
+	if (data) {
+		if (!strcmp(data, "high"))
+			pinfo->mode_gpio_state = MODE_GPIO_HIGH;
+		else if (!strcmp(data, "low"))
+			pinfo->mode_gpio_state = MODE_GPIO_LOW;
+	} else {
+		pinfo->mode_gpio_state = MODE_GPIO_NOT_VALID;
+	}
+
 	rc = of_property_read_u32(np, "qcom,mdss-dsi-panel-frame-rate", &tmp);
-	panel_data->panel_info.mipi.frame_rate = (!rc ? tmp : 60);
+	pinfo->mipi.frame_rate = (!rc ? tmp : 60);
 	rc = of_property_read_u32(np, "qcom,mdss-dsi-panel-clock-rate", &tmp);
-	panel_data->panel_info.clk_rate = (!rc ? tmp : 0);
+	pinfo->clk_rate = (!rc ? tmp : 0);
 	data = of_get_property(np, "qcom,mdss-dsi-panel-timings", &len);
 	if ((!data) || (len != 12)) {
 		pr_err("%s:%d, Unable to read Phy timing settings",
@@ -717,16 +736,14 @@
 		goto error;
 	}
 	for (i = 0; i < len; i++)
-		phy_params.timing[i] = data[i];
+		pinfo->mipi.dsi_phy_db.timing[i] = data[i];
 
-	panel_data->panel_info.mipi.dsi_phy_db = &phy_params;
+	mdss_dsi_parse_fbc_params(np, pinfo);
 
-	mdss_dsi_parse_fbc_params(np, &panel_data->panel_info);
-
-	mdss_dsi_parse_dcs_cmds(np, &panel_data->on_cmds,
+	mdss_dsi_parse_dcs_cmds(np, &ctrl_pdata->on_cmds,
 		"qcom,mdss-dsi-on-command", "qcom,mdss-dsi-on-command-state");
 
-	mdss_dsi_parse_dcs_cmds(np, &panel_data->off_cmds,
+	mdss_dsi_parse_dcs_cmds(np, &ctrl_pdata->off_cmds,
 		"qcom,mdss-dsi-off-command", "qcom,mdss-dsi-off-command-state");
 
 	return 0;
@@ -735,53 +752,52 @@
 	return -EINVAL;
 }
 
-static int __devinit mdss_dsi_panel_probe(struct platform_device *pdev)
+int mdss_dsi_panel_init(struct device_node *node,
+	struct mdss_dsi_ctrl_pdata *ctrl_pdata,
+	bool cmd_cfg_cont_splash)
 {
 	int rc = 0;
-	static struct mdss_panel_common_pdata vendor_pdata;
 	static const char *panel_name;
-	pr_debug("%s:%d, debug info id=%d", __func__, __LINE__, pdev->id);
-	if (!pdev->dev.of_node)
-		return -ENODEV;
+	bool cont_splash_enabled;
 
-	panel_name = of_get_property(pdev->dev.of_node,
-		"qcom,mdss-dsi-panel-name", NULL);
+	if (!node) {
+		pr_err("%s: no panel node\n", __func__);
+		return -ENODEV;
+	}
+
+	pr_debug("%s:%d\n", __func__, __LINE__);
+	panel_name = of_get_property(node, "qcom,mdss-dsi-panel-name", NULL);
 	if (!panel_name)
-		pr_info("%s:%d, panel name not specified\n",
+		pr_info("%s:%d, Panel name not specified\n",
 						__func__, __LINE__);
 	else
 		pr_info("%s: Panel Name = %s\n", __func__, panel_name);
 
-	rc = mdss_panel_parse_dt(pdev, &vendor_pdata);
-	if (rc)
+	rc = mdss_panel_parse_dt(node, ctrl_pdata);
+	if (rc) {
+		pr_err("%s:%d panel dt parse failed\n", __func__, __LINE__);
 		return rc;
+	}
 
-	vendor_pdata.on = mdss_dsi_panel_on;
-	vendor_pdata.off = mdss_dsi_panel_off;
-	vendor_pdata.bl_fnc = mdss_dsi_panel_bl_ctrl;
+	if (cmd_cfg_cont_splash)
+		cont_splash_enabled = of_property_read_bool(node,
+				"qcom,cont-splash-enabled");
+	else
+		cont_splash_enabled = false;
+	if (!cont_splash_enabled) {
+		pr_info("%s:%d Continuous splash flag not found.\n",
+				__func__, __LINE__);
+		ctrl_pdata->panel_data.panel_info.cont_splash_enabled = 0;
+	} else {
+		pr_info("%s:%d Continuous splash flag enabled.\n",
+				__func__, __LINE__);
 
-	rc = dsi_panel_device_register(pdev, &vendor_pdata);
-	if (rc)
-		return rc;
+		ctrl_pdata->panel_data.panel_info.cont_splash_enabled = 1;
+	}
+
+	ctrl_pdata->on = mdss_dsi_panel_on;
+	ctrl_pdata->off = mdss_dsi_panel_off;
+	ctrl_pdata->panel_data.set_backlight = mdss_dsi_panel_bl_ctrl;
 
 	return 0;
 }
-
-static const struct of_device_id mdss_dsi_panel_match[] = {
-	{.compatible = "qcom,mdss-dsi-panel"},
-	{}
-};
-
-static struct platform_driver this_driver = {
-	.probe  = mdss_dsi_panel_probe,
-	.driver = {
-		.name   = "dsi_panel",
-		.of_match_table = mdss_dsi_panel_match,
-	},
-};
-
-static int __init mdss_dsi_panel_init(void)
-{
-	return platform_driver_register(&this_driver);
-}
-module_init(mdss_dsi_panel_init);
diff --git a/drivers/video/msm/mdss/mdss_edp.c b/drivers/video/msm/mdss/mdss_edp.c
index 3e0bc6d..64caaf5 100644
--- a/drivers/video/msm/mdss/mdss_edp.c
+++ b/drivers/video/msm/mdss/mdss_edp.c
@@ -753,6 +753,20 @@
 {
 	int ret;
 	struct mdss_edp_drv_pdata *edp_drv;
+	struct mdss_panel_cfg *pan_cfg = NULL;
+
+	if (!mdss_is_ready()) {
+		pr_err("%s: MDP not probed yet!\n", __func__);
+		return -EPROBE_DEFER;
+	}
+
+	pan_cfg = mdss_panel_intf_type(MDSS_PANEL_INTF_EDP);
+	if (IS_ERR(pan_cfg)) {
+		return PTR_ERR(pan_cfg);
+	} else if (!pan_cfg) {
+		pr_debug("%s: not configured as prim\n", __func__);
+		return -ENODEV;
+	}
 
 	if (!pdev->dev.of_node) {
 		pr_err("%s: Failed\n", __func__);
diff --git a/drivers/video/msm/mdss/mdss_mdp.c b/drivers/video/msm/mdss/mdss_mdp.c
index 5597c03..6a12b6b 100644
--- a/drivers/video/msm/mdss/mdss_mdp.c
+++ b/drivers/video/msm/mdss/mdss_mdp.c
@@ -52,6 +52,7 @@
 #include "mdss.h"
 #include "mdss_fb.h"
 #include "mdss_mdp.h"
+#include "mdss_panel.h"
 #include "mdss_debug.h"
 
 struct mdss_data_type *mdss_res;
@@ -92,6 +93,13 @@
 	MDP_BUS_VECTOR_ENTRY(SZ_256M, SZ_512M),
 };
 static struct msm_bus_paths mdp_bus_usecases[ARRAY_SIZE(mdp_bus_vectors)];
+
+static struct mdss_panel_intf pan_types[] = {
+	{"dsi", MDSS_PANEL_INTF_DSI},
+	{"edp", MDSS_PANEL_INTF_EDP},
+	{"hdmi", MDSS_PANEL_INTF_HDMI},
+};
+
 static struct msm_bus_scale_pdata mdp_bus_scale_table = {
 	.usecase = mdp_bus_usecases,
 	.num_usecases = ARRAY_SIZE(mdp_bus_usecases),
@@ -1162,6 +1170,185 @@
 	return 0;
 }
 
+static int mdss_mdp_get_pan_intf(const char *pan_intf)
+{
+	int i, rc = MDSS_PANEL_INTF_INVALID;
+
+	if (!pan_intf)
+		return rc;
+
+	for (i = 0; i < ARRAY_SIZE(pan_types); i++) {
+		if (!strncmp(pan_intf, pan_types[i].name, MDSS_MAX_PANEL_LEN)) {
+			rc = pan_types[i].type;
+			break;
+		}
+	}
+	return rc;
+}
+
+static int mdss_mdp_get_pan_cfg(struct mdss_panel_cfg *pan_cfg)
+{
+	char *t = NULL;
+	char pan_intf_str[MDSS_MAX_PANEL_LEN];
+	int rc, i;
+	char pan_name[MDSS_MAX_PANEL_LEN];
+
+	if (!pan_cfg)
+		return -EINVAL;
+
+	strlcpy(pan_name, &pan_cfg->arg_cfg[0], sizeof(pan_cfg->arg_cfg));
+	if (pan_name[0] == '0') {
+		pan_cfg->lk_cfg = false;
+	} else if (pan_name[0] == '1') {
+		pan_cfg->lk_cfg = true;
+	} else {
+		/* read from dt */
+		pan_cfg->lk_cfg = true;
+		pan_cfg->pan_intf = MDSS_PANEL_INTF_INVALID;
+		return -EINVAL;
+	}
+
+	/* skip lk cfg and delimiter; ex: "0:" */
+	strlcpy(pan_name, &pan_name[2], MDSS_MAX_PANEL_LEN);
+	t = strnstr(pan_name, ":", MDSS_MAX_PANEL_LEN);
+	if (!t) {
+		pr_err("%s: pan_name=[%s] invalid\n",
+			__func__, pan_name);
+		pan_cfg->pan_intf = MDSS_PANEL_INTF_INVALID;
+		return -EINVAL;
+	}
+
+	for (i = 0; ((pan_name + i) < t) && (i < 4); i++)
+		pan_intf_str[i] = *(pan_name + i);
+	pan_intf_str[i] = 0;
+	pr_debug("%s:%d panel intf %s\n", __func__, __LINE__, pan_intf_str);
+	/* point to the start of panel name */
+	t = t + 1;
+	strlcpy(&pan_cfg->arg_cfg[0], t, sizeof(pan_cfg->arg_cfg));
+	pr_debug("%s:%d: t=[%s] panel name=[%s]\n", __func__, __LINE__,
+		t, pan_cfg->arg_cfg);
+	rc = mdss_mdp_get_pan_intf(pan_intf_str);
+	pan_cfg->pan_intf = (rc < 0) ?  MDSS_PANEL_INTF_INVALID : rc;
+	return 0;
+}
+
+static int mdss_mdp_parse_dt_pan_intf(struct platform_device *pdev)
+{
+	int rc;
+	struct mdss_data_type *mdata = platform_get_drvdata(pdev);
+	const char *prim_intf = NULL;
+
+	rc = of_property_read_string(pdev->dev.of_node,
+				"qcom,mdss-pref-prim-intf", &prim_intf);
+	if (rc)
+		return -ENODEV;
+
+	rc = mdss_mdp_get_pan_intf(prim_intf);
+	if (rc < 0) {
+		mdata->pan_cfg.pan_intf = MDSS_PANEL_INTF_INVALID;
+	} else {
+		mdata->pan_cfg.pan_intf = rc;
+		rc = 0;
+	}
+	return rc;
+}
+
+static int mdss_mdp_parse_bootarg(struct platform_device *pdev)
+{
+	struct device_node *chosen_node;
+	static const char *cmd_line;
+	char *disp_idx, *end_idx;
+	int rc, len = 0, name_len, cmd_len;
+	int *intf_type;
+	char *panel_name;
+	struct mdss_panel_cfg *pan_cfg;
+	struct mdss_data_type *mdata = platform_get_drvdata(pdev);
+
+	mdata->pan_cfg.arg_cfg[MDSS_MAX_PANEL_LEN] = 0;
+	pan_cfg = &mdata->pan_cfg;
+	panel_name = &pan_cfg->arg_cfg[0];
+	intf_type = &pan_cfg->pan_intf;
+
+	/* reads from dt by default */
+	pan_cfg->lk_cfg = true;
+
+	chosen_node = of_find_node_by_name(NULL, "chosen");
+	if (!chosen_node) {
+		pr_err("%s: get chosen node failed\n", __func__);
+		rc = -ENODEV;
+		goto get_dt_pan;
+	}
+
+	cmd_line = of_get_property(chosen_node, "bootargs", &len);
+	if (!cmd_line || len <= 0) {
+		pr_err("%s: get bootargs failed\n", __func__);
+		rc = -ENODEV;
+		goto get_dt_pan;
+	}
+
+	name_len = strlen("mdss_mdp.panel=");
+	cmd_len = strlen(cmd_line);
+	disp_idx = strnstr(cmd_line, "mdss_mdp.panel=", cmd_len);
+	if (!disp_idx) {
+		pr_err("%s:%d:cmdline panel not set disp_idx=[%p]\n",
+				__func__, __LINE__, disp_idx);
+		memset(panel_name, 0x00, MDSS_MAX_PANEL_LEN);
+		*intf_type = MDSS_PANEL_INTF_INVALID;
+		rc = MDSS_PANEL_INTF_INVALID;
+		goto get_dt_pan;
+	}
+
+	disp_idx += name_len;
+
+	end_idx = strnstr(disp_idx, " ", MDSS_MAX_PANEL_LEN);
+	pr_debug("%s:%d: pan_name=[%s] end=[%s]\n", __func__, __LINE__,
+		 disp_idx, end_idx);
+	if (!end_idx) {
+		end_idx = disp_idx + strlen(disp_idx) + 1;
+		pr_warn("%s:%d: pan_name=[%s] end=[%s]\n", __func__,
+		       __LINE__, disp_idx, end_idx);
+	}
+
+	if (end_idx <= disp_idx) {
+		pr_err("%s:%d:cmdline pan incorrect end=[%p] disp=[%p]\n",
+			__func__, __LINE__, end_idx, disp_idx);
+		memset(panel_name, 0x00, MDSS_MAX_PANEL_LEN);
+		*intf_type = MDSS_PANEL_INTF_INVALID;
+		rc = MDSS_PANEL_INTF_INVALID;
+		goto get_dt_pan;
+	}
+
+	*end_idx = 0;
+	len = end_idx - disp_idx + 1;
+	if (len <= 0) {
+		pr_warn("%s: panel name not rx", __func__);
+		rc = -EINVAL;
+		goto get_dt_pan;
+	}
+
+	strlcpy(panel_name, disp_idx, min(++len, MDSS_MAX_PANEL_LEN));
+	pr_debug("%s:%d panel:[%s]", __func__, __LINE__, panel_name);
+	of_node_put(chosen_node);
+
+	rc = mdss_mdp_get_pan_cfg(pan_cfg);
+	if (!rc)
+		pan_cfg->init_done = true;
+
+	return rc;
+
+get_dt_pan:
+	rc = mdss_mdp_parse_dt_pan_intf(pdev);
+	/* if pref pan intf is not present */
+	if (rc)
+		pr_err("%s:unable to parse device tree for pan intf\n",
+			__func__);
+	else
+		pan_cfg->init_done = true;
+
+	of_node_put(chosen_node);
+	return rc;
+}
+
 static int mdss_mdp_parse_dt(struct platform_device *pdev)
 {
 	int rc;
@@ -1214,6 +1401,13 @@
 		return rc;
 	}
 
+	rc = mdss_mdp_parse_bootarg(pdev);
+	if (rc) {
+		pr_err("%s: Error in panel override:rc=[%d]\n",
+		       __func__, rc);
+		return rc;
+	}
+
 	return 0;
 }
 
@@ -1679,11 +1873,61 @@
 	return len;
 }
 
-struct mdss_data_type *mdss_mdp_get_mdata()
+struct mdss_data_type *mdss_mdp_get_mdata(void)
 {
 	return mdss_res;
 }
 
+/**
+ * mdss_is_ready() - checks if mdss is probed and ready
+ *
+ * Checks if mdss resources have been initialized
+ *
+ * returns true if mdss is ready, else returns false
+ */
+bool mdss_is_ready(void)
+{
+	return mdss_mdp_get_mdata() ? true : false;
+}
+EXPORT_SYMBOL(mdss_mdp_get_mdata);
+
+/**
+ * mdss_panel_intf_type() - checks if a given intf type is primary
+ * @intf_val: panel interface type of the individual controller
+ *
+ * Individual controller queries with MDP to check if it is
+ * configured as the primary interface.
+ *
+ * returns a pointer to the configured structure mdss_panel_cfg
+ * to the controller that's configured as the primary panel interface.
+ * returns NULL on error or if @intf_val is not the configured
+ * controller.
+ */
+struct mdss_panel_cfg *mdss_panel_intf_type(int intf_val)
+{
+	if (!mdss_res || !mdss_res->pan_cfg.init_done)
+		return ERR_PTR(-EPROBE_DEFER);
+
+	if (mdss_res->pan_cfg.pan_intf == intf_val)
+		return &mdss_res->pan_cfg;
+	else
+		return NULL;
+}
+EXPORT_SYMBOL(mdss_panel_intf_type);
+
+int mdss_panel_get_boot_cfg(void)
+{
+	int rc;
+
+	if (!mdss_res || !mdss_res->pan_cfg.init_done)
+		rc = -EPROBE_DEFER;
+	if (mdss_res->pan_cfg.lk_cfg)
+		rc = 1;
+	else
+		rc = 0;
+	return rc;
+}
+
 static void mdss_mdp_footswitch_ctrl(struct mdss_data_type *mdata, int on)
 {
 	if (!mdata->fs)
diff --git a/drivers/video/msm/mdss/mdss_panel.h b/drivers/video/msm/mdss/mdss_panel.h
index becf455..a01ae09 100644
--- a/drivers/video/msm/mdss/mdss_panel.h
+++ b/drivers/video/msm/mdss/mdss_panel.h
@@ -57,6 +57,34 @@
 	MAX_PHYS_TARGET_NUM,
 };
 
+enum {
+	MDSS_PANEL_INTF_INVALID = -1,
+	MDSS_PANEL_INTF_DSI,
+	MDSS_PANEL_INTF_EDP,
+	MDSS_PANEL_INTF_HDMI,
+};
+
+enum {
+	MODE_GPIO_NOT_VALID = 0,
+	MODE_GPIO_HIGH,
+	MODE_GPIO_LOW,
+};
+
+#define MDSS_MAX_PANEL_LEN      256
+#define MDSS_INTF_MAX_NAME_LEN 5
+struct mdss_panel_intf {
+	char name[MDSS_INTF_MAX_NAME_LEN];
+	u8   len;
+	int  type;
+};
+
+struct mdss_panel_cfg {
+	char arg_cfg[MDSS_MAX_PANEL_LEN + 1];
+	int  pan_intf;
+	bool lk_cfg;
+	bool init_done;
+};
+
 /**
  * enum mdss_intf_events - Different events generated by MDP core
  *
@@ -133,9 +161,9 @@
 	uint32_t timing[12];
 	uint32_t ctrl[4];
 	uint32_t strength[2];
-	char bistCtrl[6];
+	char bistctrl[6];
 	uint32_t pll[21];
-	char laneCfg[45];
+	char lanecfg[45];
 };
 
 struct mipi_panel_info {
@@ -158,7 +186,7 @@
 	char t_clk_post; /* 0xc0, DSI_CLKOUT_TIMING_CTRL */
 	char t_clk_pre;  /* 0xc0, DSI_CLKOUT_TIMING_CTRL */
 	char vc;	/* virtual channel */
-	struct mdss_dsi_phy_ctrl *dsi_phy_db;
+	struct mdss_dsi_phy_ctrl dsi_phy_db;
 	/* video mode */
 	char pulse_mode_hsa_he;
 	char hfp_power_stop;
@@ -241,6 +269,7 @@
 	int pwm_pmic_gpio;
 	int pwm_lpg_chan;
 	int pwm_period;
+	u32 mode_gpio_state;
 
 	u32 cont_splash_enabled;
 	struct ion_handle *splash_ihdl;
@@ -328,4 +357,37 @@
 
 int mdss_register_panel(struct platform_device *pdev,
 	struct mdss_panel_data *pdata);
+
+/**
+ * mdss_panel_intf_type: - checks if a given intf type is primary
+ * @intf_val: panel interface type of the individual controller
+ *
+ * Individual controller queries with MDP to check if it is
+ * configured as the primary interface.
+ *
+ * returns a pointer to the configured structure mdss_panel_cfg
+ * to the controller that's configured as the primary panel interface.
+ * returns NULL on error or if @intf_val is not the configured
+ * controller.
+ */
+struct mdss_panel_cfg *mdss_panel_intf_type(int intf_val);
+
+/**
+ * mdss_panel_get_boot_cfg() - checks if bootloader config present
+ *
+ * Function returns true if bootloader has configured the parameters
+ * for primary controller and panel config data.
+ *
+ * returns true if bootloader configured, else false
+ */
+int mdss_panel_get_boot_cfg(void);
+
+/**
+ * mdss_is_ready() - checks if mdss is probed and ready
+ *
+ * Checks if mdss resources have been initialized
+ *
+ * returns true if mdss is ready, else returns false.
+ */
+bool mdss_is_ready(void);
 #endif /* MDSS_PANEL_H */
diff --git a/drivers/video/msm/mdss/msm_mdss_io_8974.c b/drivers/video/msm/mdss/msm_mdss_io_8974.c
index 7b89eff..d24daab 100644
--- a/drivers/video/msm/mdss/msm_mdss_io_8974.c
+++ b/drivers/video/msm/mdss/msm_mdss_io_8974.c
@@ -504,7 +504,7 @@
 		return;
 	}
 
-	pd = ((ctrl_pdata->panel_data).panel_info.mipi).dsi_phy_db;
+	pd = &(((ctrl_pdata->panel_data).panel_info.mipi).dsi_phy_db);
 
 	/* Strength ctrl 0 */
 	MIPI_OUTP((ctrl_pdata->ctrl_base) + 0x0484, pd->strength[0]);
@@ -564,7 +564,7 @@
 		for (i = 0; i < 9; i++) {
 			offset = i + (ln * 9);
 			MIPI_OUTP((ctrl_pdata->ctrl_base) + off,
-							pd->laneCfg[offset]);
+							pd->lanecfg[offset]);
 			wmb();
 			off += 4;
 		}
@@ -583,7 +583,7 @@
 
 	off = 0x04b4;	/* phy BIST ctrl 0 - 5 */
 	for (i = 0; i < 6; i++) {
-		MIPI_OUTP((ctrl_pdata->ctrl_base) + off, pd->bistCtrl[i]);
+		MIPI_OUTP((ctrl_pdata->ctrl_base) + off, pd->bistctrl[i]);
 		wmb();
 		off += 4;
 	}
diff --git a/include/linux/coresight-cti.h b/include/linux/coresight-cti.h
index 7f2da3f..c3dce9f 100644
--- a/include/linux/coresight-cti.h
+++ b/include/linux/coresight-cti.h
@@ -34,6 +34,7 @@
 			struct coresight_cti *cti, int trig, int ch);
 extern void coresight_cti_unmap_trigout(
 			struct coresight_cti *cti, int trig, int ch);
+extern void coresight_cti_reset(struct coresight_cti *cti);
 #else
 static inline struct coresight_cti *coresight_cti_get(const char *name)
 {
@@ -54,6 +55,7 @@
 			struct coresight_cti *cti, int trig, int ch) {}
 static inline void coresight_cti_unmap_trigout(
 			struct coresight_cti *cti, int trig, int ch) {}
+static inline void coresight_cti_reset(struct coresight_cti *cti) {}
 #endif
 
 #endif
diff --git a/include/linux/coresight.h b/include/linux/coresight.h
index 5b69884..fbd5fb0 100644
--- a/include/linux/coresight.h
+++ b/include/linux/coresight.h
@@ -41,6 +41,7 @@
 	CORESIGHT_CLK_RATE_OFF,
 	CORESIGHT_CLK_RATE_TRACE = 1000,
 	CORESIGHT_CLK_RATE_HSTRACE = 2000,
+	CORESIGHT_CLK_RATE_FIXED = 3000,
 };
 
 enum coresight_dev_type {
diff --git a/include/linux/stk3x1x.h b/include/linux/stk3x1x.h
index d9d2cf6..6dd446c 100644
--- a/include/linux/stk3x1x.h
+++ b/include/linux/stk3x1x.h
@@ -24,6 +24,7 @@
 	int int_pin;
 	uint32_t transmittance;
 	uint32_t int_flags;
+	bool use_fir;
 };
 
 #endif /* __STK3X1X_H__ */
diff --git a/include/linux/usb/android.h b/include/linux/usb/android.h
index 0b11fdaf..e17e978 100644
--- a/include/linux/usb/android.h
+++ b/include/linux/usb/android.h
@@ -24,6 +24,7 @@
 	u32 swfi_latency;
 	u8 usb_core_id;
 	bool cdrom;
+	bool internal_ums;
 };
 
 #ifndef CONFIG_TARGET_CORE
diff --git a/include/linux/usb/msm_hsusb.h b/include/linux/usb/msm_hsusb.h
index ac8d7f8..f462b64 100644
--- a/include/linux/usb/msm_hsusb.h
+++ b/include/linux/usb/msm_hsusb.h
@@ -563,6 +563,7 @@
 #ifdef CONFIG_USB_DWC3_MSM
 int msm_ep_config(struct usb_ep *ep);
 int msm_ep_unconfig(struct usb_ep *ep);
+void dwc3_tx_fifo_resize_request(struct usb_ep *ep, bool qdss_enable);
 int msm_data_fifo_config(struct usb_ep *ep, u32 addr, u32 size,
 	u8 dst_pipe_idx);
 
@@ -586,6 +587,12 @@
 	return -ENODEV;
 }
 
+static inline void dwc3_tx_fifo_resize_request(
+					struct usb_ep *ep, bool qdss_enable)
+{
+	return;
+}
+
 static inline void msm_dwc3_restart_usb_session(struct usb_gadget *gadget)
 {
 	return;
diff --git a/include/sound/q6adm-v2.h b/include/sound/q6adm-v2.h
index e07f634..6f121b3 100644
--- a/include/sound/q6adm-v2.h
+++ b/include/sound/q6adm-v2.h
@@ -16,6 +16,7 @@
 #define ADM_PATH_PLAYBACK 0x1
 #define ADM_PATH_LIVE_REC 0x2
 #define ADM_PATH_NONLIVE_REC 0x3
+#include <mach/qdsp6v2/rtac.h>
 #include <sound/q6afe-v2.h>
 #include <sound/q6audio-v2.h>
 
@@ -41,11 +42,16 @@
 int adm_multi_ch_copp_open(int port, int path, int rate, int mode,
 			int topology, bool perf_mode, uint16_t bits_per_sample);
 
+int adm_unmap_cal_blocks(void);
+
+int adm_map_rtac_block(struct rtac_cal_block_data *cal_block);
+
+int adm_unmap_rtac_block(uint32_t *mem_map_handle);
+
 int adm_memory_map_regions(int port_id, uint32_t *buf_add, uint32_t mempool_id,
 				uint32_t *bufsz, uint32_t bufcnt);
 
-int adm_memory_unmap_regions(int port_id, uint32_t *buf_add, uint32_t *bufsz,
-						uint32_t bufcnt);
+int adm_memory_unmap_regions(int port_id);
 
 int adm_close(int port, bool perf_mode);
 
diff --git a/include/sound/q6afe-v2.h b/include/sound/q6afe-v2.h
index 12934aa..594d750 100644
--- a/include/sound/q6afe-v2.h
+++ b/include/sound/q6afe-v2.h
@@ -148,6 +148,7 @@
 int afe_start_pseudo_port(u16 port_id);
 int afe_stop_pseudo_port(u16 port_id);
 uint32_t afe_req_mmap_handle(struct afe_audio_client *ac);
+int afe_unmap_cal_blocks(void);
 int afe_memory_map(u32 dma_addr_p, u32 dma_buf_sz, struct afe_audio_client *ac);
 int afe_cmd_memory_map(u32 dma_addr_p, u32 dma_buf_sz);
 int afe_cmd_memory_map_nowait(int port_id, u32 dma_addr_p, u32 dma_buf_sz);
diff --git a/include/sound/q6asm-v2.h b/include/sound/q6asm-v2.h
index bd4cddf..0dd1f1c 100644
--- a/include/sound/q6asm-v2.h
+++ b/include/sound/q6asm-v2.h
@@ -13,6 +13,7 @@
 #define __Q6_ASM_V2_H__
 
 #include <mach/qdsp6v2/apr.h>
+#include <mach/qdsp6v2/rtac.h>
 #include <sound/apr_audio-v2.h>
 #include <linux/list.h>
 #include <linux/msm_ion.h>
@@ -76,7 +77,8 @@
 #define SOFT_PAUSE_ENABLE	1
 #define SOFT_PAUSE_DISABLE	0
 
-#define SESSION_MAX	0x08
+#define SESSION_MAX		0x08
+#define ASM_CONTROL_SESSION	0x0F
 
 /* payload structure bytes */
 #define READDONE_IDX_STATUS 0
@@ -224,6 +226,12 @@
 int q6asm_memory_unmap(struct audio_client *ac, uint32_t buf_add,
 							int dir);
 
+int q6asm_unmap_cal_blocks(void);
+
+int q6asm_map_rtac_block(struct rtac_cal_block_data *cal_block);
+
+int q6asm_unmap_rtac_block(uint32_t *mem_map_handle);
+
 int q6asm_run(struct audio_client *ac, uint32_t flags,
 		uint32_t msw_ts, uint32_t lsw_ts);
 
diff --git a/include/sound/q6lsm.h b/include/sound/q6lsm.h
index d7a01a0..34eba81 100644
--- a/include/sound/q6lsm.h
+++ b/include/sound/q6lsm.h
@@ -19,7 +19,7 @@
 #include <sound/lsm_params.h>
 #include <mach/qdsp6v2/apr.h>
 
-typedef void (*app_cb)(uint32_t opcode, uint32_t token,
+typedef void (*lsm_app_cb)(uint32_t opcode, uint32_t token,
 		       uint32_t *payload, void *priv);
 
 struct lsm_sound_model {
@@ -34,7 +34,7 @@
 
 struct lsm_client {
 	int		session;
-	app_cb		cb;
+	lsm_app_cb	cb;
 	atomic_t	cmd_state;
 	void		*priv;
 	struct apr_svc  *apr;
@@ -118,7 +118,7 @@
 	uint32_t	mem_map_handle;
 } __packed;
 
-struct lsm_client *q6lsm_client_alloc(app_cb cb, void *priv);
+struct lsm_client *q6lsm_client_alloc(lsm_app_cb cb, void *priv);
 void q6lsm_client_free(struct lsm_client *client);
 int q6lsm_open(struct lsm_client *client);
 int q6lsm_start(struct lsm_client *client, bool wait);
@@ -126,6 +126,7 @@
 int q6lsm_snd_model_buf_alloc(struct lsm_client *client, uint32_t len);
 int q6lsm_snd_model_buf_free(struct lsm_client *client);
 int q6lsm_close(struct lsm_client *client);
+int q6lsm_unmap_cal_blocks(void);
 int q6lsm_register_sound_model(struct lsm_client *client,
 			       enum lsm_detection_mode mode, u16 minkeyword,
 			       u16 minuser, bool detectfailure);
diff --git a/sound/soc/codecs/wcd9306.c b/sound/soc/codecs/wcd9306.c
index c509b08..a6ef992 100644
--- a/sound/soc/codecs/wcd9306.c
+++ b/sound/soc/codecs/wcd9306.c
@@ -45,6 +45,9 @@
 #define TAPAN_VDD_CX_OPTIMAL_UA 10000
 #define TAPAN_VDD_CX_SLEEP_UA 2000
 
+/* RX_HPH_CNP_WG_TIME increases by 0.24ms */
+#define TAPAN_WG_TIME_FACTOR_US  240
+
 static struct regulator *tapan_codec_find_regulator(
 	struct snd_soc_codec *codec,
 	const char *name);
@@ -97,6 +100,12 @@
 
 static enum tapan_codec_type codec_ver;
 
+/*
+ * Multiplication factor to compute impedance on Tapan
+ * This is computed from (Vx / (m*Ical)) = (10mV/(180*30uA))
+ */
+#define TAPAN_ZDET_MUL_FACTOR 1852
+
 enum {
 	AIF1_PB = 0,
 	AIF1_CAP,
@@ -251,6 +260,12 @@
 
 	/* pointers to regulators required for chargepump */
 	struct regulator *cp_regulators[CP_REG_MAX];
+
+	/*
+	 * list used to save/restore registers at start and
+	 * end of impedance measurement
+	 */
+	struct list_head reg_save_restore;
 };
 
 static const u32 comp_shift[] = {
@@ -4917,6 +4932,255 @@
 	return WCD9XXX_CDC_TYPE_TAPAN;
 }
 
+static void wcd9xxx_prepare_hph_pa(struct wcd9xxx_mbhc *mbhc,
+				   struct list_head *lh)
+{
+	int i;
+	struct snd_soc_codec *codec = mbhc->codec;
+	u32 delay;
+
+	const struct wcd9xxx_reg_mask_val reg_set_paon[] = {
+		{WCD9XXX_A_CDC_CLSH_B1_CTL, 0x0F, 0x00},
+		{WCD9XXX_A_RX_HPH_CHOP_CTL, 0xFF, 0xA4},
+		{WCD9XXX_A_RX_HPH_OCP_CTL, 0xFF, 0x67},
+		{WCD9XXX_A_RX_HPH_L_TEST, 0x1, 0x0},
+		{WCD9XXX_A_RX_HPH_R_TEST, 0x1, 0x0},
+		{WCD9XXX_A_RX_HPH_BIAS_WG_OCP, 0xFF, 0x1A},
+		{WCD9XXX_A_RX_HPH_CNP_WG_CTL, 0xFF, 0xDB},
+		{WCD9XXX_A_RX_HPH_CNP_WG_TIME, 0xFF, 0x2A},
+		{TAPAN_A_CDC_CONN_RX2_B2_CTL, 0xFF, 0x10},
+		{WCD9XXX_A_CDC_CLK_OTHR_CTL, 0xFF, 0x05},
+		{WCD9XXX_A_CDC_RX1_B6_CTL, 0xFF, 0x81},
+		{WCD9XXX_A_CDC_CLK_RX_B1_CTL, 0x03, 0x03},
+		{WCD9XXX_A_RX_HPH_L_GAIN, 0xFF, 0x2C},
+		{WCD9XXX_A_CDC_RX2_B6_CTL, 0xFF, 0x81},
+		{WCD9XXX_A_RX_HPH_R_GAIN, 0xFF, 0x2C},
+		{WCD9XXX_A_BUCK_CTRL_CCL_4, 0xFF, 0x50},
+		{WCD9XXX_A_BUCK_CTRL_VCL_1, 0xFF, 0x08},
+		{WCD9XXX_A_BUCK_CTRL_CCL_1, 0xFF, 0x5B},
+		{WCD9XXX_A_NCP_CLK, 0xFF, 0x9C},
+		{WCD9XXX_A_NCP_CLK, 0xFF, 0xFC},
+		{WCD9XXX_A_BUCK_MODE_3, 0xFF, 0xCE},
+		{WCD9XXX_A_BUCK_CTRL_CCL_3, 0xFF, 0x6B},
+		{WCD9XXX_A_BUCK_CTRL_CCL_3, 0xFF, 0x6F},
+		{TAPAN_A_RX_BUCK_BIAS1, 0xFF, 0x62},
+		{TAPAN_A_RX_HPH_BIAS_PA, 0xFF, 0x7A},
+		{TAPAN_A_CDC_CLK_RDAC_CLK_EN_CTL, 0xFF, 0x02},
+		{TAPAN_A_CDC_CLK_RDAC_CLK_EN_CTL, 0xFF, 0x06},
+		{WCD9XXX_A_RX_COM_BIAS, 0xFF, 0x80},
+		{WCD9XXX_A_BUCK_MODE_3, 0xFF, 0xC6},
+		{WCD9XXX_A_BUCK_MODE_4, 0xFF, 0xE6},
+		{WCD9XXX_A_BUCK_MODE_5, 0xFF, 0x02},
+		{WCD9XXX_A_BUCK_MODE_1, 0xFF, 0xA1},
+		/* Delay 1ms */
+		{WCD9XXX_A_NCP_EN, 0xFF, 0xFF},
+		/* Delay 1ms */
+		{WCD9XXX_A_BUCK_MODE_5, 0xFF, 0x03},
+		{WCD9XXX_A_BUCK_MODE_5, 0xFF, 0x7B},
+		{WCD9XXX_A_CDC_CLSH_B1_CTL, 0xFF, 0xE6},
+		{WCD9XXX_A_RX_HPH_L_DAC_CTL, 0xFF, 0x40},
+		{WCD9XXX_A_RX_HPH_L_DAC_CTL, 0xFF, 0xC0},
+		{WCD9XXX_A_RX_HPH_R_DAC_CTL, 0xFF, 0x40},
+		{WCD9XXX_A_RX_HPH_R_DAC_CTL, 0xFF, 0xC0},
+		{WCD9XXX_A_NCP_STATIC, 0xFF, 0x08},
+		{WCD9XXX_A_RX_HPH_L_DAC_CTL, 0x03, 0x01},
+		{WCD9XXX_A_RX_HPH_R_DAC_CTL, 0x03, 0x01},
+	};
+
+	/*
+	 * Configure PA in class-AB, -18dB gain,
+	 * companding off, OCP off, Chopping ON
+	 */
+	for (i = 0; i < ARRAY_SIZE(reg_set_paon); i++) {
+		/*
+		 * Some of the codec registers like BUCK_MODE_1
+		 * and NCP_EN requires 1ms wait time for them
+		 * to take effect. Other register writes for
+		 * PA configuration do not require any wait time.
+		 */
+		if (reg_set_paon[i].reg == WCD9XXX_A_BUCK_MODE_1 ||
+		    reg_set_paon[i].reg == WCD9XXX_A_NCP_EN)
+			delay = 1000;
+		else
+			delay = 0;
+		wcd9xxx_soc_update_bits_push(codec, lh,
+					     reg_set_paon[i].reg,
+					     reg_set_paon[i].mask,
+					     reg_set_paon[i].val, delay);
+	}
+	pr_debug("%s: PAs are prepared\n", __func__);
+	return;
+}
+
+static int wcd9xxx_enable_static_pa(struct wcd9xxx_mbhc *mbhc, bool enable)
+{
+	struct snd_soc_codec *codec = mbhc->codec;
+	int wg_time = snd_soc_read(codec, WCD9XXX_A_RX_HPH_CNP_WG_TIME) *
+				   TAPAN_WG_TIME_FACTOR_US;
+	/*
+	 * Tapan requires additional time to enable PA.
+	 * It is observed during experiments that we need
+	 * an additional wait time about 0.35 times of
+	 * the WG_TIME
+	 */
+	wg_time += (int) (wg_time * 35) / 100;
+
+	snd_soc_update_bits(codec, WCD9XXX_A_RX_HPH_CNP_EN, 0x30,
+			    enable ? 0x30 : 0x0);
+	/* Wait for wave gen time to avoid pop noise */
+	usleep_range(wg_time, wg_time + WCD9XXX_USLEEP_RANGE_MARGIN_US);
+	pr_debug("%s: PAs are %s as static mode (wg_time %d)\n", __func__,
+		 enable ? "enabled" : "disabled", wg_time);
+	return 0;
+}
+
+static int tapan_setup_zdet(struct wcd9xxx_mbhc *mbhc,
+			    enum mbhc_impedance_detect_stages stage)
+{
+
+	int ret = 0;
+	struct snd_soc_codec *codec = mbhc->codec;
+	struct tapan_priv *tapan = snd_soc_codec_get_drvdata(codec);
+	const int mux_wait_us = 25;
+
+	switch (stage) {
+
+	case PRE_MEAS:
+		INIT_LIST_HEAD(&tapan->reg_save_restore);
+		/* Configure PA */
+		wcd9xxx_prepare_hph_pa(mbhc, &tapan->reg_save_restore);
+
+#define __wr(reg, mask, value)						  \
+	do {								  \
+		ret = wcd9xxx_soc_update_bits_push(codec,		  \
+						   &tapan->reg_save_restore, \
+						   reg, mask, value, 0);  \
+		if (ret < 0)						  \
+			return ret;					  \
+	} while (0)
+
+		/* Setup MBHC */
+		__wr(WCD9XXX_A_MBHC_SCALING_MUX_1, 0x7F, 0x40);
+		__wr(WCD9XXX_A_MBHC_SCALING_MUX_2, 0xFF, 0xF0);
+		__wr(WCD9XXX_A_TX_7_MBHC_TEST_CTL, 0xFF, 0x78);
+		__wr(WCD9XXX_A_TX_7_MBHC_EN, 0xFF, 0xEC);
+		__wr(WCD9XXX_A_CDC_MBHC_TIMER_B4_CTL, 0xFF, 0x45);
+		__wr(WCD9XXX_A_CDC_MBHC_TIMER_B5_CTL, 0xFF, 0x80);
+
+		__wr(WCD9XXX_A_CDC_MBHC_CLK_CTL, 0xFF, 0x0A);
+		snd_soc_write(codec, WCD9XXX_A_CDC_MBHC_EN_CTL, 0x2);
+		__wr(WCD9XXX_A_CDC_MBHC_CLK_CTL, 0xFF, 0x02);
+
+		/* Enable Impedance Detection */
+		__wr(WCD9XXX_A_MBHC_HPH, 0xFF, 0xC8);
+
+		/*
+		 * CnP setup for 0mV
+		 * Route static data as input to noise shaper
+		 */
+		__wr(TAPAN_A_CDC_RX1_B3_CTL, 0xFF, 0x02);
+		__wr(TAPAN_A_CDC_RX2_B3_CTL, 0xFF, 0x02);
+
+		snd_soc_update_bits(codec, WCD9XXX_A_RX_HPH_L_TEST,
+				    0x02, 0x00);
+		snd_soc_update_bits(codec, WCD9XXX_A_RX_HPH_R_TEST,
+				    0x02, 0x00);
+
+		/* Reset the HPHL static data pointer */
+		__wr(TAPAN_A_CDC_RX1_B2_CTL, 0xFF, 0x00);
+		/* Four consecutive writes to set 0V as static data input */
+		snd_soc_write(codec, TAPAN_A_CDC_RX1_B1_CTL, 0x00);
+		snd_soc_write(codec, TAPAN_A_CDC_RX1_B1_CTL, 0x00);
+		snd_soc_write(codec, TAPAN_A_CDC_RX1_B1_CTL, 0x00);
+		snd_soc_write(codec, TAPAN_A_CDC_RX1_B1_CTL, 0x00);
+
+		/* Reset the HPHR static data pointer */
+		__wr(TAPAN_A_CDC_RX2_B2_CTL, 0xFF, 0x00);
+		/* Four consecutive writes to set 0V as static data input */
+		snd_soc_write(codec, TAPAN_A_CDC_RX2_B1_CTL, 0x00);
+		snd_soc_write(codec, TAPAN_A_CDC_RX2_B1_CTL, 0x00);
+		snd_soc_write(codec, TAPAN_A_CDC_RX2_B1_CTL, 0x00);
+		snd_soc_write(codec, TAPAN_A_CDC_RX2_B1_CTL, 0x00);
+
+		/* Enable the HPHL and HPHR PA */
+		wcd9xxx_enable_static_pa(mbhc, true);
+		break;
+	case POST_MEAS:
+		/* Turn off ICAL */
+		snd_soc_write(codec, WCD9XXX_A_MBHC_SCALING_MUX_2, 0xF0);
+
+		wcd9xxx_enable_static_pa(mbhc, false);
+
+		/*
+		 * Setup CnP wavegen to ramp to the desired
+		 * output using a 40ms ramp
+		 */
+
+		/* CnP wavegen current to 0.5uA */
+		snd_soc_write(codec, WCD9XXX_A_RX_HPH_BIAS_WG_OCP, 0x1A);
+		/* Set the current division ratio to 2000 */
+		snd_soc_write(codec, WCD9XXX_A_RX_HPH_CNP_WG_CTL, 0xDF);
+		/* Set the wavegen timer to max (60msec) */
+		snd_soc_write(codec, WCD9XXX_A_RX_HPH_CNP_WG_TIME, 0xA0);
+		/* Set the CnP reference current to sc_bias */
+		snd_soc_write(codec, WCD9XXX_A_RX_HPH_OCP_CTL, 0x6D);
+
+		snd_soc_write(codec, TAPAN_A_CDC_RX1_B2_CTL, 0x00);
+		/* Four consecutive writes to set -10mV as static data input */
+		snd_soc_write(codec, TAPAN_A_CDC_RX1_B1_CTL, 0x00);
+		snd_soc_write(codec, TAPAN_A_CDC_RX1_B1_CTL, 0x1F);
+		snd_soc_write(codec, TAPAN_A_CDC_RX1_B1_CTL, 0x19);
+		snd_soc_write(codec, TAPAN_A_CDC_RX1_B1_CTL, 0xAA);
+
+		snd_soc_write(codec, TAPAN_A_CDC_RX2_B2_CTL, 0x00);
+		/* Four consecutive writes to set -10mV as static data input */
+		snd_soc_write(codec, TAPAN_A_CDC_RX2_B1_CTL, 0x00);
+		snd_soc_write(codec, TAPAN_A_CDC_RX2_B1_CTL, 0x1F);
+		snd_soc_write(codec, TAPAN_A_CDC_RX2_B1_CTL, 0x19);
+		snd_soc_write(codec, TAPAN_A_CDC_RX2_B1_CTL, 0xAA);
+
+		snd_soc_update_bits(codec, WCD9XXX_A_RX_HPH_L_TEST,
+				    0x02, 0x02);
+		snd_soc_update_bits(codec, WCD9XXX_A_RX_HPH_R_TEST,
+				    0x02, 0x02);
+		/* Enable the HPHL and HPHR PA and wait for 60mS */
+		wcd9xxx_enable_static_pa(mbhc, true);
+
+		snd_soc_update_bits(codec, WCD9XXX_A_MBHC_SCALING_MUX_1,
+				    0x7F, 0x40);
+		usleep_range(mux_wait_us,
+				mux_wait_us + WCD9XXX_USLEEP_RANGE_MARGIN_US);
+		break;
+	case PA_DISABLE:
+		wcd9xxx_enable_static_pa(mbhc, false);
+		wcd9xxx_restore_registers(codec, &tapan->reg_save_restore);
+		break;
+	}
+#undef __wr
+
+	return ret;
+}
+
+static void tapan_compute_impedance(s16 *l, s16 *r, uint32_t *zl, uint32_t *zr)
+{
+	int zln, zld;
+	int zrn, zrd;
+	int rl = 0, rr = 0;
+
+	zln = (l[1] - l[0]) * TAPAN_ZDET_MUL_FACTOR;
+	zld = (l[2] - l[0]);
+	if (zld)
+		rl = zln / zld;
+
+	zrn = (r[1] - r[0]) * TAPAN_ZDET_MUL_FACTOR;
+	zrd = (r[2] - r[0]);
+	if (zrd)
+		rr = zrn / zrd;
+
+	*zl = rl;
+	*zr = rr;
+}
+
 static const struct wcd9xxx_mbhc_cb mbhc_cb = {
 	.enable_mux_bias_block = tapan_enable_mux_bias_block,
 	.cfilt_fast_mode = tapan_put_cfilt_fast_mode,
@@ -4926,6 +5190,8 @@
 	.select_cfilt = tapan_select_cfilt,
 	.free_irq = tapan_free_irq,
 	.get_cdc_type = tapan_get_cdc_type,
+	.setup_zdet = tapan_setup_zdet,
+	.compute_impedance = tapan_compute_impedance,
 };
 
 int tapan_hs_detect(struct snd_soc_codec *codec,
@@ -5000,7 +5266,8 @@
 		rco_clk_rate = TAPAN_MCLK_CLK_9P6MHZ;
 
 	ret = wcd9xxx_mbhc_init(&tapan->mbhc, &tapan->resmgr, codec, NULL,
-				&mbhc_cb, rco_clk_rate, false);
+				&mbhc_cb, rco_clk_rate,
+				TAPAN_CDC_ZDET_SUPPORTED);
 	if (ret)
 		pr_err("%s: mbhc init failed %d\n", __func__, ret);
 	else
@@ -5203,7 +5470,8 @@
 		rco_clk_rate = TAPAN_MCLK_CLK_9P6MHZ;
 
 	ret = wcd9xxx_mbhc_init(&tapan->mbhc, &tapan->resmgr, codec, NULL,
-				&mbhc_cb, rco_clk_rate, false);
+				&mbhc_cb, rco_clk_rate,
+				TAPAN_CDC_ZDET_SUPPORTED);
 
 	if (ret) {
 		pr_err("%s: mbhc init failed %d\n", __func__, ret);
diff --git a/sound/soc/codecs/wcd9306.h b/sound/soc/codecs/wcd9306.h
index fdd62d1..c4788cc 100644
--- a/sound/soc/codecs/wcd9306.h
+++ b/sound/soc/codecs/wcd9306.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -24,6 +24,8 @@
 
 #define TAPAN_REG_VAL(reg, val)		{reg, 0, val}
 
+#define TAPAN_CDC_ZDET_SUPPORTED  true
+
 extern const u8 tapan_reg_readable[TAPAN_CACHE_SIZE];
 extern const u8 tapan_reset_reg_defaults[TAPAN_CACHE_SIZE];
 struct tapan_codec_dai_data {
diff --git a/sound/soc/codecs/wcd9320.c b/sound/soc/codecs/wcd9320.c
index 3621879..e52eb9d 100644
--- a/sound/soc/codecs/wcd9320.c
+++ b/sound/soc/codecs/wcd9320.c
@@ -49,6 +49,9 @@
 
 #define DAPM_MICBIAS2_EXTERNAL_STANDALONE "MIC BIAS2 External Standalone"
 
+/* RX_HPH_CNP_WG_TIME increases by 0.24ms */
+#define TAIKO_WG_TIME_FACTOR_US	240
+
 static atomic_t kp_taiko_priv;
 static int spkr_drv_wrnd_param_set(const char *val,
 				   const struct kernel_param *kp);
@@ -509,6 +512,12 @@
 
 	int (*machine_codec_event_cb)(struct snd_soc_codec *codec,
 			enum wcd9xxx_codec_event);
+
+	/*
+	 * list used to save/restore registers at start and
+	 * end of impedance measurement
+	 */
+	struct list_head reg_save_restore;
 };
 
 static const u32 comp_shift[] = {
@@ -6239,6 +6248,198 @@
 	return 0;
 }
 
+static int wcd9xxx_prepare_static_pa(struct wcd9xxx_mbhc *mbhc,
+				     struct list_head *lh)
+{
+	int i;
+	struct snd_soc_codec *codec = mbhc->codec;
+
+	const struct wcd9xxx_reg_mask_val reg_set_paon[] = {
+		{WCD9XXX_A_RX_HPH_OCP_CTL, 0x18, 0x00},
+		{WCD9XXX_A_RX_HPH_L_TEST, 0x1, 0x0},
+		{WCD9XXX_A_RX_HPH_R_TEST, 0x1, 0x0},
+		{WCD9XXX_A_RX_HPH_BIAS_WG_OCP, 0xff, 0x1A},
+		{WCD9XXX_A_RX_HPH_CNP_WG_CTL, 0xff, 0xDB},
+		{WCD9XXX_A_RX_HPH_CNP_WG_TIME, 0xff, 0x15},
+		{WCD9XXX_A_CDC_RX1_B6_CTL, 0xff, 0x81},
+		{WCD9XXX_A_CDC_CLK_RX_B1_CTL, 0x01, 0x01},
+		{WCD9XXX_A_RX_HPH_CHOP_CTL, 0xff, 0xA4},
+		{WCD9XXX_A_RX_HPH_L_GAIN, 0xff, 0x2C},
+		{WCD9XXX_A_CDC_RX2_B6_CTL, 0xff, 0x81},
+		{WCD9XXX_A_CDC_CLK_RX_B1_CTL, 0x02, 0x02},
+		{WCD9XXX_A_RX_HPH_R_GAIN, 0xff, 0x2C},
+		{WCD9XXX_A_NCP_CLK, 0xff, 0xFC},
+		{WCD9XXX_A_BUCK_CTRL_CCL_3, 0xff, 0x60},
+		{WCD9XXX_A_RX_COM_BIAS, 0xff, 0x80},
+		{WCD9XXX_A_BUCK_MODE_3, 0xff, 0xC6},
+		{WCD9XXX_A_BUCK_MODE_4, 0xff, 0xE6},
+		{WCD9XXX_A_BUCK_MODE_5, 0xff, 0x02},
+		{WCD9XXX_A_BUCK_MODE_1, 0xff, 0xA1},
+		{WCD9XXX_A_NCP_EN, 0xff, 0xFF},
+		{WCD9XXX_A_BUCK_MODE_5, 0xff, 0x7B},
+		{WCD9XXX_A_CDC_CLSH_B1_CTL, 0xff, 0xE6},
+		{WCD9XXX_A_RX_HPH_L_DAC_CTL, 0xff, 0xC0},
+		{WCD9XXX_A_RX_HPH_R_DAC_CTL, 0xff, 0xC0},
+	};
+
+	for (i = 0; i < ARRAY_SIZE(reg_set_paon); i++)
+		wcd9xxx_soc_update_bits_push(codec, lh,
+					     reg_set_paon[i].reg,
+					     reg_set_paon[i].mask,
+					     reg_set_paon[i].val, 0);
+	pr_debug("%s: PAs are prepared\n", __func__);
+
+	return 0;
+}
+
+static int wcd9xxx_enable_static_pa(struct wcd9xxx_mbhc *mbhc, bool enable)
+{
+	struct snd_soc_codec *codec = mbhc->codec;
+	const int wg_time = snd_soc_read(codec, WCD9XXX_A_RX_HPH_CNP_WG_TIME) *
+			    TAIKO_WG_TIME_FACTOR_US;
+
+	snd_soc_update_bits(codec, WCD9XXX_A_RX_HPH_CNP_EN, 0x30,
+			    enable ? 0x30 : 0x0);
+	/* Wait for wave gen time to avoid pop noise */
+	usleep_range(wg_time, wg_time + WCD9XXX_USLEEP_RANGE_MARGIN_US);
+	pr_debug("%s: PAs are %s as static mode (wg_time %d)\n", __func__,
+		 enable ? "enabled" : "disabled", wg_time);
+	return 0;
+}
+
+static int taiko_setup_zdet(struct wcd9xxx_mbhc *mbhc,
+			    enum mbhc_impedance_detect_stages stage)
+{
+	int ret = 0;
+	struct snd_soc_codec *codec = mbhc->codec;
+	struct taiko_priv *taiko = snd_soc_codec_get_drvdata(codec);
+	const int ramp_wait_us = 18 * 1000;
+
+#define __wr(reg, mask, value)						  \
+	do {								  \
+		ret = wcd9xxx_soc_update_bits_push(codec,		  \
+						   &taiko->reg_save_restore, \
+						   reg, mask, value, 0);  \
+		if (ret < 0)						  \
+			return ret;					  \
+	} while (0)
+
+	switch (stage) {
+
+	case PRE_MEAS:
+		INIT_LIST_HEAD(&taiko->reg_save_restore);
+		wcd9xxx_prepare_static_pa(mbhc, &taiko->reg_save_restore);
+		wcd9xxx_enable_static_pa(mbhc, true);
+
+		/*
+		 * save old value of registers and write the new value to
+		 * restore old value back, WCD9XXX_A_CDC_PA_RAMP_B{1,2,3,4}_CTL
+		 * registers don't need to be restored as those are solely used
+		 * by impedance detection.
+		 */
+		/* Phase 1 */
+		/* Reset the PA Ramp */
+		snd_soc_write(codec, WCD9XXX_A_CDC_PA_RAMP_B1_CTL, 0x1C);
+		/*
+		 * Connect the PA Ramp to PA chain and release reset with
+		 * keep it connected.
+		 */
+		snd_soc_write(codec, WCD9XXX_A_CDC_PA_RAMP_B1_CTL, 0x1F);
+		snd_soc_write(codec, WCD9XXX_A_CDC_PA_RAMP_B1_CTL, 0x03);
+		/*
+		 * Program the PA Ramp to FS_48K, L shift 1 and sample
+		 * num to 24
+		 */
+		snd_soc_write(codec, WCD9XXX_A_CDC_PA_RAMP_B3_CTL,
+			      0x3 << 4 | 0x6);
+		/* 0x56 for 10mv.  0xC0 is for 50mv */
+		snd_soc_write(codec, WCD9XXX_A_CDC_PA_RAMP_B4_CTL, 0xC0);
+		/* Enable MBHC MUX, Set MUX current to 37.5uA and ADC7 */
+		__wr(WCD9XXX_A_MBHC_SCALING_MUX_1, 0xFF, 0xC0);
+		__wr(WCD9XXX_A_MBHC_SCALING_MUX_2, 0xFF, 0xF0);
+		__wr(WCD9XXX_A_TX_7_MBHC_TEST_CTL, 0xFF, 0x78);
+		__wr(WCD9XXX_A_TX_7_MBHC_EN, 0xFF, 0x8C);
+		/* Change NSA and NAVG */
+		__wr(WCD9XXX_A_CDC_MBHC_TIMER_B4_CTL, 0x4 << 4, 0x4 << 4);
+		__wr(WCD9XXX_A_CDC_MBHC_TIMER_B5_CTL, 0xFF, 0x10);
+		/* Reset MBHC and set it up for STA */
+		__wr(WCD9XXX_A_CDC_MBHC_CLK_CTL, 0xFF, 0x0A);
+		__wr(WCD9XXX_A_CDC_MBHC_EN_CTL, 0xFF, 0x02);
+		__wr(WCD9XXX_A_CDC_MBHC_CLK_CTL, 0xFF, 0x02);
+
+		/* Set HPH_MBHC for zdet */
+		__wr(WCD9XXX_A_MBHC_HPH, 0xB3, 0x80);
+		break;
+	case POST_MEAS:
+		/* Phase 2 */
+		/* Start the PA ramp on HPH L and R */
+		snd_soc_write(codec, WCD9XXX_A_CDC_PA_RAMP_B2_CTL, 0x05);
+		/* Ramp generator takes ~17ms */
+		usleep_range(ramp_wait_us,
+				ramp_wait_us + WCD9XXX_USLEEP_RANGE_MARGIN_US);
+
+		/* Disable Ical */
+		snd_soc_write(codec, WCD9XXX_A_CDC_PA_RAMP_B2_CTL, 0x00);
+		/* Ramp generator takes ~17ms */
+		usleep_range(ramp_wait_us,
+				ramp_wait_us + WCD9XXX_USLEEP_RANGE_MARGIN_US);
+		break;
+	case PA_DISABLE:
+		/* Ramp HPH L & R back to Zero */
+		snd_soc_write(codec, WCD9XXX_A_CDC_PA_RAMP_B2_CTL, 0x0A);
+		/* Ramp generator takes ~17ms */
+		usleep_range(ramp_wait_us,
+				ramp_wait_us + WCD9XXX_USLEEP_RANGE_MARGIN_US);
+		snd_soc_write(codec, WCD9XXX_A_CDC_PA_RAMP_B2_CTL, 0x00);
+
+		/* Clean up starts */
+		/* Turn off PA ramp generator */
+		snd_soc_write(codec, WCD9XXX_A_CDC_PA_RAMP_B1_CTL, 0x0);
+		wcd9xxx_enable_static_pa(mbhc, false);
+		wcd9xxx_restore_registers(codec, &taiko->reg_save_restore);
+		break;
+	}
+#undef __wr
+
+	return ret;
+}
+
+static void taiko_compute_impedance(s16 *l, s16 *r, uint32_t *zl, uint32_t *zr)
+{
+
+	int64_t rl, rr = 0; /* milliohm */
+	const int alphal = 364; /* 0.005555 * 65536 = 364.05 */
+	const int alphar = 364; /* 0.005555 * 65536 = 364.05 */
+	const int beta = 3855; /* 0.011765 * 5 * 65536 = 3855.15 */
+	const int rref = 11333; /* not scaled up */
+	const int shift = 16;
+
+	rl = (int)(l[0] - l[1]) * 1000 / (l[0] - l[2]);
+	rl = rl * rref * alphal;
+	rl = rl >> shift;
+	rl = rl * beta;
+	rl = rl >> shift;
+	*zl = rl;
+
+	rr = (int)(r[0] - r[1]) * 1000 / (r[0] - r[2]);
+	rr = rr * rref  * alphar;
+	rr = rr >> shift;
+	rr = rr * beta;
+	rr = rr >> shift;
+	*zr = rr;
+}
+
+static enum wcd9xxx_cdc_type taiko_get_cdc_type(void)
+{
+	return WCD9XXX_CDC_TYPE_TAIKO;
+}
+
+static const struct wcd9xxx_mbhc_cb mbhc_cb = {
+	.get_cdc_type = taiko_get_cdc_type,
+	.setup_zdet = taiko_setup_zdet,
+	.compute_impedance = taiko_compute_impedance,
+};
+
 static int taiko_post_reset_cb(struct wcd9xxx *wcd9xxx)
 {
 	int ret = 0;
@@ -6284,7 +6485,7 @@
 
 		ret = wcd9xxx_mbhc_init(&taiko->mbhc, &taiko->resmgr, codec,
 					taiko_enable_mbhc_micbias,
-					NULL, rco_clk_rate, true);
+					&mbhc_cb, rco_clk_rate, true);
 		if (ret)
 			pr_err("%s: mbhc init failed %d\n", __func__, ret);
 		else
@@ -6473,7 +6674,7 @@
 	/* init and start mbhc */
 	ret = wcd9xxx_mbhc_init(&taiko->mbhc, &taiko->resmgr, codec,
 				taiko_enable_mbhc_micbias,
-				NULL, rco_clk_rate, true);
+				&mbhc_cb, rco_clk_rate, true);
 	if (ret) {
 		pr_err("%s: mbhc init failed %d\n", __func__, ret);
 		goto err_init;
diff --git a/sound/soc/codecs/wcd9xxx-common.c b/sound/soc/codecs/wcd9xxx-common.c
index d00b843..05f2191 100644
--- a/sound/soc/codecs/wcd9xxx-common.c
+++ b/sound/soc/codecs/wcd9xxx-common.c
@@ -11,6 +11,7 @@
  */
 
 #include <linux/module.h>
+#include <linux/slab.h>
 #include <sound/soc.h>
 #include <linux/kernel.h>
 #include <linux/delay.h>
@@ -32,6 +33,8 @@
 
 #define MAX_IMPED_PARAMS 13
 
+#define USLEEP_RANGE_MARGIN_US 100
+
 struct wcd9xxx_imped_val {
 	u32 imped_val;
 	u8 index;
@@ -614,6 +617,46 @@
 	}
 }
 
+
+int wcd9xxx_soc_update_bits_push(struct snd_soc_codec *codec,
+					struct list_head *list,
+					uint16_t reg, uint8_t mask,
+					uint8_t value, int delay)
+{
+	int rc;
+	struct wcd9xxx_register_save_node *node;
+
+	node = kmalloc(sizeof(*node), GFP_KERNEL);
+	if (unlikely(!node)) {
+		pr_err("%s: Not enough memory\n", __func__);
+		return -ENOMEM;
+	}
+	node->reg = reg;
+	node->value = snd_soc_read(codec, reg);
+	list_add(&node->lh, list);
+	if (mask == 0xFF)
+		rc = snd_soc_write(codec, reg, value);
+	else
+		rc = snd_soc_update_bits(codec, reg, mask, value);
+	if (delay)
+		usleep_range(delay, delay + USLEEP_RANGE_MARGIN_US);
+	return rc;
+}
+EXPORT_SYMBOL(wcd9xxx_soc_update_bits_push);
+
+void wcd9xxx_restore_registers(struct snd_soc_codec *codec,
+			       struct list_head *lh)
+{
+	struct wcd9xxx_register_save_node *node, *nodetmp;
+
+	list_for_each_entry_safe(node, nodetmp, lh, lh) {
+		snd_soc_write(codec, node->reg, node->value);
+		list_del(&node->lh);
+		kfree(node);
+	}
+}
+EXPORT_SYMBOL(wcd9xxx_restore_registers);
+
 static void wcd9xxx_enable_buck_mode(struct snd_soc_codec *codec,
 		u8 buck_vref)
 {
diff --git a/sound/soc/codecs/wcd9xxx-common.h b/sound/soc/codecs/wcd9xxx-common.h
index 654964e..9fba8e3 100644
--- a/sound/soc/codecs/wcd9xxx-common.h
+++ b/sound/soc/codecs/wcd9xxx-common.h
@@ -81,4 +81,16 @@
 	WCD9XXX_CODEC_EVENT_CODEC_UP = 0,
 };
 
+struct wcd9xxx_register_save_node {
+	struct list_head lh;
+	u16 reg;
+	u16 value;
+};
+
+extern int wcd9xxx_soc_update_bits_push(struct snd_soc_codec *codec,
+					struct list_head *lh,
+					uint16_t reg, uint8_t mask,
+					uint8_t value, int delay);
+extern void wcd9xxx_restore_registers(struct snd_soc_codec *codec,
+				      struct list_head *lh);
 #endif
diff --git a/sound/soc/codecs/wcd9xxx-mbhc.c b/sound/soc/codecs/wcd9xxx-mbhc.c
index acb86416..4e95fa9 100644
--- a/sound/soc/codecs/wcd9xxx-mbhc.c
+++ b/sound/soc/codecs/wcd9xxx-mbhc.c
@@ -142,12 +142,6 @@
 	enum wcd9xxx_mbhc_plug_type _type;
 };
 
-struct wcd9xxx_register_save_node {
-	struct list_head lh;
-	u16 reg;
-	u16 value;
-};
-
 enum meas_type {
 	STA = 0,
 	DCE,
@@ -182,6 +176,8 @@
 				    uint32_t *zr);
 static s16 wcd9xxx_get_current_v(struct wcd9xxx_mbhc *mbhc,
 				 const enum wcd9xxx_current_v_idx idx);
+static void wcd9xxx_get_z(struct wcd9xxx_mbhc *mbhc, s16 *dce_z, s16 *sta_z);
+static void wcd9xxx_mbhc_calc_thres(struct wcd9xxx_mbhc *mbhc);
 
 static bool wcd9xxx_mbhc_polling(struct wcd9xxx_mbhc *mbhc)
 {
@@ -973,6 +969,7 @@
 	if (noreldetection)
 		wcd9xxx_turn_onoff_rel_detection(codec, false);
 
+	snd_soc_update_bits(codec, WCD9XXX_A_CDC_MBHC_CLK_CTL, 0x2, 0x0);
 	/* Turn on the override */
 	if (!override_bypass)
 		snd_soc_update_bits(codec, WCD9XXX_A_CDC_MBHC_B1_CTL, 0x4, 0x4);
@@ -982,6 +979,8 @@
 		snd_soc_write(codec, WCD9XXX_A_CDC_MBHC_EN_CTL, 0x4);
 		snd_soc_update_bits(codec, WCD9XXX_A_CDC_MBHC_CLK_CTL, 0x8,
 				    0x0);
+		snd_soc_update_bits(codec, WCD9XXX_A_CDC_MBHC_CLK_CTL, 0x2,
+				    0x2);
 		usleep_range(mbhc->mbhc_data.t_sta_dce,
 			     mbhc->mbhc_data.t_sta_dce);
 		snd_soc_write(codec, WCD9XXX_A_CDC_MBHC_EN_CTL, 0x4);
@@ -993,6 +992,8 @@
 		snd_soc_write(codec, WCD9XXX_A_CDC_MBHC_EN_CTL, 0x2);
 		snd_soc_update_bits(codec, WCD9XXX_A_CDC_MBHC_CLK_CTL, 0x8,
 				    0x0);
+		snd_soc_update_bits(codec, WCD9XXX_A_CDC_MBHC_CLK_CTL, 0x2,
+				    0x2);
 		usleep_range(mbhc->mbhc_data.t_sta_dce,
 			     mbhc->mbhc_data.t_sta_dce);
 		snd_soc_write(codec, WCD9XXX_A_CDC_MBHC_EN_CTL, 0x2);
@@ -1055,6 +1056,10 @@
 	struct snd_soc_codec *codec = mbhc->codec;
 	short bias_value;
 	u8 cfilt_mode;
+	s16 reg;
+	int change;
+	struct wcd9xxx_mbhc_btn_detect_cfg *btn_det;
+	s16 sta_z = 0, dce_z = 0;
 
 	WCD9XXX_BCL_ASSERT_LOCKED(mbhc->resmgr);
 
@@ -1064,6 +1069,8 @@
 		return -ENODEV;
 	}
 
+	btn_det = WCD9XXX_MBHC_CAL_BTN_DET_PTR(mbhc->mbhc_cfg->calibration);
+
 	/*
 	 * Request BG and clock.
 	 * These will be released by wcd9xxx_cleanup_hs_polling
@@ -1102,14 +1109,48 @@
 	snd_soc_update_bits(codec, WCD9XXX_A_CDC_MBHC_B1_CTL, 0x2, 0x2);
 	snd_soc_update_bits(codec, WCD9XXX_A_CDC_MBHC_CLK_CTL, 0x8, 0x8);
 
-	if (!is_cs_enable)
-		wcd9xxx_calibrate_hs_polling(mbhc);
-
 	/* don't flip override */
 	bias_value = __wcd9xxx_codec_sta_dce(mbhc, 1, true, true);
 	snd_soc_write(codec, mbhc->mbhc_bias_regs.cfilt_ctl, cfilt_mode);
 	snd_soc_update_bits(codec, WCD9XXX_A_MBHC_HPH, 0x13, 0x00);
 
+	/* recalibrate dce_z and sta_z */
+	reg = snd_soc_read(codec, WCD9XXX_A_CDC_MBHC_B1_CTL);
+	change = snd_soc_update_bits(codec, WCD9XXX_A_CDC_MBHC_B1_CTL, 0x78,
+				     btn_det->mbhc_nsc << 3);
+	wcd9xxx_get_z(mbhc, &dce_z, &sta_z);
+	if (change)
+		snd_soc_write(codec, WCD9XXX_A_CDC_MBHC_B1_CTL, reg);
+	if (dce_z && sta_z) {
+		pr_debug("%s: sta_z 0x%x -> 0x%x, dce_z 0x%x -> 0x%x\n",
+			 __func__,
+			 mbhc->mbhc_data.sta_z, sta_z & 0xffff,
+			 mbhc->mbhc_data.dce_z, dce_z & 0xffff);
+		mbhc->mbhc_data.dce_z = dce_z;
+		mbhc->mbhc_data.sta_z = sta_z;
+		wcd9xxx_mbhc_calc_thres(mbhc);
+		wcd9xxx_calibrate_hs_polling(mbhc);
+	} else {
+		pr_warn("%s: failed get new dce_z/sta_z 0x%x/0x%x\n", __func__,
+			dce_z, sta_z);
+	}
+
+	if (is_cs_enable) {
+		/* recalibrate dce_nsc_cs_z */
+		reg = snd_soc_read(mbhc->codec, WCD9XXX_A_CDC_MBHC_B1_CTL);
+		snd_soc_update_bits(mbhc->codec, WCD9XXX_A_CDC_MBHC_B1_CTL,
+				    0x78, WCD9XXX_MBHC_NSC_CS << 3);
+		wcd9xxx_get_z(mbhc, &dce_z, NULL);
+		snd_soc_write(mbhc->codec, WCD9XXX_A_CDC_MBHC_B1_CTL, reg);
+		if (dce_z) {
+			pr_debug("%s: dce_nsc_cs_z 0x%x -> 0x%x\n", __func__,
+				 mbhc->mbhc_data.dce_nsc_cs_z, dce_z & 0xffff);
+			mbhc->mbhc_data.dce_nsc_cs_z = dce_z;
+		} else {
+			pr_debug("%s: failed get new dce_nsc_cs_z\n", __func__);
+		}
+	}
+
 	return bias_value;
 }
 
@@ -2946,9 +2987,10 @@
 	return mask;
 }
 
-void wcd9xxx_get_z(struct wcd9xxx_mbhc *mbhc, s16 *dce_z, s16 *sta_z)
+static void wcd9xxx_get_z(struct wcd9xxx_mbhc *mbhc, s16 *dce_z, s16 *sta_z)
 {
 	s16 reg0, reg1;
+	int change;
 	struct snd_soc_codec *codec = mbhc->codec;
 
 	WCD9XXX_BCL_ASSERT_LOCKED(mbhc->resmgr);
@@ -2959,16 +3001,21 @@
 	snd_soc_update_bits(codec, mbhc->mbhc_bias_regs.mbhc_reg, 1 << 7, 0);
 
 	/* Disconnect override from micbias */
-	snd_soc_update_bits(codec, WCD9XXX_A_MAD_ANA_CTRL, 1 << 4, 1 << 0);
+	change = snd_soc_update_bits(codec, WCD9XXX_A_MAD_ANA_CTRL, 1 << 4,
+				     1 << 0);
 	usleep_range(1000, 1000 + 1000);
-	*sta_z = wcd9xxx_codec_sta_dce(mbhc, 0, false);
-	*dce_z = wcd9xxx_codec_sta_dce(mbhc, 1, false);
+	if (sta_z)
+		*sta_z = wcd9xxx_codec_sta_dce(mbhc, 0, false);
+	if (dce_z)
+		*dce_z = wcd9xxx_codec_sta_dce(mbhc, 1, false);
 
 	pr_debug("%s: sta_z 0x%x, dce_z 0x%x\n", __func__, *sta_z & 0xFFFF,
 		 *dce_z & 0xFFFF);
 
 	/* Connect override from micbias */
-	snd_soc_update_bits(codec, WCD9XXX_A_MAD_ANA_CTRL, 1 << 4, 1 << 4);
+	if (change)
+		snd_soc_update_bits(codec, WCD9XXX_A_MAD_ANA_CTRL, 1 << 4,
+				    1 << 4);
 	/* Disable pull down micbias to ground */
 	snd_soc_write(codec, mbhc->mbhc_bias_regs.mbhc_reg, reg1);
 	snd_soc_write(codec, mbhc->mbhc_bias_regs.ctl_reg, reg0);
@@ -3740,6 +3787,11 @@
 		      p->dce_z, wcd9xxx_codec_sta_dce_v(mbhc, 1, p->dce_z));
 	n += scnprintf(buffer + n, size - n, "dce_mb = %x(%dmv)\n",
 		       p->dce_mb, wcd9xxx_codec_sta_dce_v(mbhc, 1, p->dce_mb));
+	n += scnprintf(buffer + n, size - n, "dce_nsc_cs_z = %x(%dmv)\n",
+		      p->dce_nsc_cs_z,
+		      __wcd9xxx_codec_sta_dce_v(mbhc, 1, p->dce_nsc_cs_z,
+						p->dce_nsc_cs_z,
+						VDDIO_MICBIAS_MV));
 	n += scnprintf(buffer + n, size - n, "sta_z = %x(%dmv)\n",
 		       p->sta_z, wcd9xxx_codec_sta_dce_v(mbhc, 0, p->sta_z));
 	n += scnprintf(buffer + n, size - n, "sta_mb = %x(%dmv)\n",
@@ -4158,107 +4210,6 @@
 	return ret;
 }
 
-static int wcd9xxx_soc_update_bits_push(struct snd_soc_codec *codec,
-					struct list_head *list,
-					uint16_t reg, uint8_t mask,
-					uint8_t value)
-{
-	int rc;
-	struct wcd9xxx_register_save_node *node;
-
-	node = kmalloc(sizeof(*node), GFP_KERNEL);
-	if (unlikely(!node)) {
-		pr_err("%s: Not enough memory\n", __func__);
-		return -ENOMEM;
-	}
-	node->reg = reg;
-	node->value = snd_soc_read(codec, reg);
-	list_add(&node->lh, list);
-	if (mask == 0xFF)
-		rc = snd_soc_write(codec, reg, value);
-	else
-		rc = snd_soc_update_bits(codec, reg, mask, value);
-	return rc;
-}
-
-static int wcd9xxx_prepare_static_pa(struct wcd9xxx_mbhc *mbhc,
-				     struct list_head *lh)
-{
-	int i;
-	struct snd_soc_codec *codec = mbhc->codec;
-
-	const struct wcd9xxx_reg_mask_val reg_set_paon[] = {
-		{WCD9XXX_A_RX_HPH_OCP_CTL, 0x18, 0x00},
-		{WCD9XXX_A_RX_HPH_L_TEST, 0x1, 0x0},
-		{WCD9XXX_A_RX_HPH_R_TEST, 0x1, 0x0},
-		{WCD9XXX_A_RX_HPH_BIAS_WG_OCP, 0xff, 0x1A},
-		{WCD9XXX_A_RX_HPH_CNP_WG_CTL, 0xff, 0xDB},
-		{WCD9XXX_A_RX_HPH_CNP_WG_TIME, 0xff, 0x15},
-		{WCD9XXX_A_CDC_RX1_B6_CTL, 0xff, 0x81},
-		{WCD9XXX_A_CDC_CLK_RX_B1_CTL, 0x01, 0x01},
-		{WCD9XXX_A_RX_HPH_CHOP_CTL, 0xff, 0xA4},
-		{WCD9XXX_A_RX_HPH_L_GAIN, 0xff, 0x2C},
-		{WCD9XXX_A_CDC_RX2_B6_CTL, 0xff, 0x81},
-		{WCD9XXX_A_CDC_CLK_RX_B1_CTL, 0x02, 0x02},
-		{WCD9XXX_A_RX_HPH_R_GAIN, 0xff, 0x2C},
-		{WCD9XXX_A_NCP_CLK, 0xff, 0xFC},
-		{WCD9XXX_A_BUCK_CTRL_CCL_3, 0xff, 0x60},
-		{WCD9XXX_A_RX_COM_BIAS, 0xff, 0x80},
-		{WCD9XXX_A_BUCK_MODE_3, 0xff, 0xC6},
-		{WCD9XXX_A_BUCK_MODE_4, 0xff, 0xE6},
-		{WCD9XXX_A_BUCK_MODE_5, 0xff, 0x02},
-		{WCD9XXX_A_BUCK_MODE_1, 0xff, 0xA1},
-		{WCD9XXX_A_NCP_EN, 0xff, 0xFF},
-		{WCD9XXX_A_BUCK_MODE_5, 0xff, 0x7B},
-		{WCD9XXX_A_CDC_CLSH_B1_CTL, 0xff, 0xE6},
-		{WCD9XXX_A_RX_HPH_L_DAC_CTL, 0xff, 0xC0},
-		{WCD9XXX_A_RX_HPH_R_DAC_CTL, 0xff, 0xC0},
-	};
-
-	for (i = 0; i < ARRAY_SIZE(reg_set_paon); i++)
-		wcd9xxx_soc_update_bits_push(codec, lh,
-					     reg_set_paon[i].reg,
-					     reg_set_paon[i].mask,
-					     reg_set_paon[i].val);
-	pr_debug("%s: PAs are prepared\n", __func__);
-
-	return 0;
-}
-
-static void wcd9xxx_restore_registers(struct wcd9xxx_mbhc *mbhc,
-				      struct list_head *lh)
-{
-	struct wcd9xxx_register_save_node *node, *nodetmp;
-	struct snd_soc_codec *codec = mbhc->codec;
-
-	list_for_each_entry_safe(node, nodetmp, lh, lh) {
-		snd_soc_write(codec, node->reg, node->value);
-		list_del(&node->lh);
-		kfree(node);
-	}
-}
-
-static void wcd9xxx_unprepare_static_pa(struct wcd9xxx_mbhc *mbhc,
-					struct list_head *lh)
-{
-	wcd9xxx_restore_registers(mbhc, lh);
-}
-
-static int wcd9xxx_enable_static_pa(struct wcd9xxx_mbhc *mbhc, bool enable)
-{
-	struct snd_soc_codec *codec = mbhc->codec;
-	const int wg_time = snd_soc_read(codec, WCD9XXX_A_RX_HPH_CNP_WG_TIME) *
-			    WCD9XXX_WG_TIME_FACTOR_US;
-
-	snd_soc_update_bits(codec, WCD9XXX_A_RX_HPH_CNP_EN, 0x30,
-			    enable ? 0x30 : 0x0);
-	/* Wait for wave gen time to avoid pop noise */
-	usleep_range(wg_time, wg_time + WCD9XXX_USLEEP_RANGE_MARGIN_US);
-	pr_debug("%s: PAs are %s as static mode (wg_time %d)\n", __func__,
-		 enable ? "enabled" : "disabled", wg_time);
-	return 0;
-}
-
 static int wcd9xxx_detect_impedance(struct wcd9xxx_mbhc *mbhc, uint32_t *zl,
 				    uint32_t *zr)
 {
@@ -4268,17 +4219,8 @@
 	s16 *z[] = {
 		&l[0], &r[0], &r[1], &l[1], &l[2], &r[2],
 	};
-	LIST_HEAD(lh);
-	LIST_HEAD(lhpa);
 	struct snd_soc_codec *codec = mbhc->codec;
-	const int ramp_wait_us = 18 * 1000;
 	const int mux_wait_us = 25;
-	const int alphal = 364; /* 0.005555 * 65536 = 364.05 */
-	const int alphar = 364; /* 0.005555 * 65536 = 364.05 */
-	const int beta = 3855; /* 0.011765 * 5 * 65536 = 3855.15 */
-	const int rref = 11333; /* not scaled up */
-	const int shift = 16;
-	int64_t rl, rr = 0; /* milliohm */
 	const struct wcd9xxx_reg_mask_val reg_set_mux[] = {
 		/* Phase 1 */
 		/* Set MBHC_MUX for HPHL without ical */
@@ -4299,6 +4241,11 @@
 	pr_debug("%s: enter\n", __func__);
 	WCD9XXX_BCL_ASSERT_LOCKED(mbhc->resmgr);
 
+	if (!mbhc->mbhc_cb || !mbhc->mbhc_cb->setup_zdet ||
+	    !mbhc->mbhc_cb->compute_impedance || !zl ||
+	    !zr)
+		return -EINVAL;
+
 	/*
 	 * Impedance detection is an intrusive function as it mutes RX paths,
 	 * enable PAs and etc.  Therefore codec drvier including ALSA
@@ -4317,127 +4264,66 @@
 	wcd9xxx_resmgr_get_clk_block(mbhc->resmgr, WCD9XXX_CLK_RCO);
 	WCD9XXX_BG_CLK_UNLOCK(mbhc->resmgr);
 
+	wcd9xxx_turn_onoff_override(codec, true);
 	pr_debug("%s: Setting impedance detection\n", __func__);
-	wcd9xxx_prepare_static_pa(mbhc, &lhpa);
-	wcd9xxx_enable_static_pa(mbhc, true);
 
-	/*
-	 * save old value of registers and write the new value to restore old
-	 * value back, WCD9XXX_A_CDC_PA_RAMP_B{1,2,3,4}_CTL registers don't
-	 * need to be restored as those are solely used by impedance detection.
-	 */
-#define __w(reg, mask, value)						  \
-	do {								  \
-		ret = wcd9xxx_soc_update_bits_push(codec, &lh, reg, mask, \
-						   value);		  \
-		if (ret < 0)						  \
-			return ret;					  \
-	} while (0)
-
-	/* Reset the PA Ramp */
-	snd_soc_write(codec, WCD9XXX_A_CDC_PA_RAMP_B1_CTL, 0x1C);
-	/*
-	 * Connect the PA Ramp to PA chain and release reset with keep it
-	 * connected.
-	 */
-	snd_soc_write(codec, WCD9XXX_A_CDC_PA_RAMP_B1_CTL, 0x1F);
-	snd_soc_write(codec, WCD9XXX_A_CDC_PA_RAMP_B1_CTL, 0x03);
-	/* Program the PA Ramp to FS_48K, L shift 1 and sample num to 24 */
-	snd_soc_write(codec, WCD9XXX_A_CDC_PA_RAMP_B3_CTL, 0x3 << 4 | 0x6);
-	/* 0x56 for 10mv.  0xC0 is for 50mv */
-	snd_soc_write(codec, WCD9XXX_A_CDC_PA_RAMP_B4_CTL, 0xC0);
-	/* Enable MBHC MUX, Set MUX current to 37.5uA and ADC7 */
-	__w(WCD9XXX_A_MBHC_SCALING_MUX_1, 0xFF, 0xC0);
-	__w(WCD9XXX_A_MBHC_SCALING_MUX_2, 0xFF, 0xF0);
-	__w(WCD9XXX_A_TX_7_MBHC_TEST_CTL, 0xFF, 0x78);
-	__w(WCD9XXX_A_TX_7_MBHC_EN, 0xFF, 0x8C);
-	/* Change NSA and NAVG */
-	__w(WCD9XXX_A_CDC_MBHC_TIMER_B4_CTL, 0x4 << 4, 0x4 << 4);
-	__w(WCD9XXX_A_CDC_MBHC_TIMER_B5_CTL, 0xFF, 0x10);
-	/* Reset MBHC and set it up for STA */
-	__w(WCD9XXX_A_CDC_MBHC_CLK_CTL, 0xFF, 0x0A);
-	__w(WCD9XXX_A_CDC_MBHC_EN_CTL, 0xFF, 0x02);
-	__w(WCD9XXX_A_CDC_MBHC_CLK_CTL, 0xFF, 0x02);
-
-	/* Set HPH_MBHC for zdet */
-	__w(WCD9XXX_A_MBHC_HPH, 0xB3, 0x80);
+	/* Codec specific setup for L0, R0, L1 and R1 measurements */
+	mbhc->mbhc_cb->setup_zdet(mbhc, PRE_MEAS);
 
 	pr_debug("%s: Performing impedance detection\n", __func__);
-	/* Phase 1 */
 	for (i = 0; i < ARRAY_SIZE(reg_set_mux) - 2; i++) {
-		__w(reg_set_mux[i].reg, reg_set_mux[i].mask,
-		    reg_set_mux[i].val);
+		snd_soc_update_bits(codec, reg_set_mux[i].reg,
+				    reg_set_mux[i].mask,
+				    reg_set_mux[i].val);
+		if (mbhc->mbhc_cb && mbhc->mbhc_cb->enable_mux_bias_block)
+			mbhc->mbhc_cb->enable_mux_bias_block(codec);
+		else
+			snd_soc_update_bits(codec,
+					    WCD9XXX_A_MBHC_SCALING_MUX_1,
+					    0x80, 0x80);
 		/* 25us is required after mux change to settle down */
 		usleep_range(mux_wait_us,
 			     mux_wait_us + WCD9XXX_USLEEP_RANGE_MARGIN_US);
-		*(z[i]) = __wcd9xxx_codec_sta_dce(mbhc, 0, false, false);
+		*(z[i]) = __wcd9xxx_codec_sta_dce(mbhc, 0, true, false);
 	}
 
-	/* Phase 2 */
-	/* Start the PA ramp on HPH L and R */
-	snd_soc_write(codec, WCD9XXX_A_CDC_PA_RAMP_B2_CTL, 0x05);
-	/* Ramp generator takes ~17ms */
-	usleep_range(ramp_wait_us,
-		     ramp_wait_us + WCD9XXX_USLEEP_RANGE_MARGIN_US);
+	/* Codec specific setup for L2 and R2 measurements */
+	mbhc->mbhc_cb->setup_zdet(mbhc, POST_MEAS);
 
-	/* Disable Ical */
-	snd_soc_write(codec, WCD9XXX_A_CDC_PA_RAMP_B2_CTL, 0x00);
-	/* Ramp generator takes ~17ms */
-	usleep_range(ramp_wait_us,
-		     ramp_wait_us + WCD9XXX_USLEEP_RANGE_MARGIN_US);
 	for (; i < ARRAY_SIZE(reg_set_mux); i++) {
-		__w(reg_set_mux[i].reg, reg_set_mux[i].mask,
-		    reg_set_mux[i].val);
+		snd_soc_update_bits(codec, reg_set_mux[i].reg,
+				    reg_set_mux[i].mask,
+				    reg_set_mux[i].val);
+		if (mbhc->mbhc_cb && mbhc->mbhc_cb->enable_mux_bias_block)
+			mbhc->mbhc_cb->enable_mux_bias_block(codec);
+		else
+			snd_soc_update_bits(codec,
+					    WCD9XXX_A_MBHC_SCALING_MUX_1,
+					    0x80, 0x80);
 		/* 25us is required after mux change to settle down */
 		usleep_range(mux_wait_us,
 			     mux_wait_us + WCD9XXX_USLEEP_RANGE_MARGIN_US);
-		*(z[i]) = __wcd9xxx_codec_sta_dce(mbhc, 0, false, false);
+		*(z[i]) = __wcd9xxx_codec_sta_dce(mbhc, 0, true, false);
 	}
 
-	/* Ramp HPH L & R back to Zero */
-	snd_soc_write(codec, WCD9XXX_A_CDC_PA_RAMP_B2_CTL, 0x0A);
-	/* Ramp generator takes ~17ms */
-	usleep_range(ramp_wait_us,
-		     ramp_wait_us + WCD9XXX_USLEEP_RANGE_MARGIN_US);
-	snd_soc_write(codec, WCD9XXX_A_CDC_PA_RAMP_B2_CTL, 0x00);
-#undef __w
-
-	/* Clean up starts */
-	/* Turn off PA ramp generator */
-	snd_soc_write(codec, WCD9XXX_A_CDC_PA_RAMP_B1_CTL, 0x0);
-	wcd9xxx_enable_static_pa(mbhc, false);
-	wcd9xxx_restore_registers(mbhc, &lh);
-	wcd9xxx_unprepare_static_pa(mbhc, &lhpa);
+	mbhc->mbhc_cb->setup_zdet(mbhc, PA_DISABLE);
 
 	mutex_unlock(&codec->mutex);
 
 	WCD9XXX_BG_CLK_LOCK(mbhc->resmgr);
-	wcd9xxx_resmgr_put_bandgap(mbhc->resmgr, WCD9XXX_BANDGAP_MBHC_MODE);
+	wcd9xxx_resmgr_put_bandgap(mbhc->resmgr, WCD9XXX_BANDGAP_AUDIO_MODE);
 	wcd9xxx_resmgr_put_clk_block(mbhc->resmgr, WCD9XXX_CLK_RCO);
 	WCD9XXX_BG_CLK_UNLOCK(mbhc->resmgr);
 
-	rl = (int)(l[0] - l[1]) * 1000 / (l[0] - l[2]);
-	rl = rl * rref * alphal;
-	rl = rl >> shift;
-	rl = rl * beta;
-	rl = rl >> shift;
-	*zl = rl;
+	wcd9xxx_turn_onoff_override(codec, false);
+	mbhc->mbhc_cb->compute_impedance(l, r, zl, zr);
 
-	rr = (int)(r[0] - r[1]) * 1000 / (r[0] - r[2]);
-	rr = rr * rref  * alphar;
-	rr = rr >> shift;
-	rr = rr * beta;
-	rr = rr >> shift;
-	*zr = rr;
-
-	pr_debug("%s: L0: 0x%x(%d), L1: 0x%x(%d), L2: 0x%x(%d), rl: %lld\n",
+	pr_debug("%s: L0: 0x%x(%d), L1: 0x%x(%d), L2: 0x%x(%d)\n",
 		 __func__,
-		 l[0] & 0xffff, l[0], l[1] & 0xffff, l[1], l[2] & 0xffff, l[2],
-		 rl);
-	pr_debug("%s: R0: 0x%x(%d), R1: 0x%x(%d), R2: 0x%x(%d), rr: %lld\n",
+		 l[0] & 0xffff, l[0], l[1] & 0xffff, l[1], l[2] & 0xffff, l[2]);
+	pr_debug("%s: R0: 0x%x(%d), R1: 0x%x(%d), R2: 0x%x(%d)\n",
 		 __func__,
-		 r[0] & 0xffff, r[0], r[1] & 0xffff, r[1], r[2] & 0xffff, r[2],
-		 rr);
+		 r[0] & 0xffff, r[0], r[1] & 0xffff, r[1], r[2] & 0xffff, r[2]);
 	pr_debug("%s: RL %d milliohm, RR %d milliohm\n", __func__, *zl, *zr);
 	pr_debug("%s: Impedance detection completed\n", __func__);
 
diff --git a/sound/soc/codecs/wcd9xxx-mbhc.h b/sound/soc/codecs/wcd9xxx-mbhc.h
index 3040bc4..e5259c3 100644
--- a/sound/soc/codecs/wcd9xxx-mbhc.h
+++ b/sound/soc/codecs/wcd9xxx-mbhc.h
@@ -19,6 +19,8 @@
 #define WCD9XXX_CFILT_EXT_PRCHG_EN 0x30
 #define WCD9XXX_CFILT_EXT_PRCHG_DSBL 0x00
 
+#define WCD9XXX_USLEEP_RANGE_MARGIN_US 100
+
 struct mbhc_micbias_regs {
 	u16 cfilt_val;
 	u16 cfilt_ctl;
@@ -40,6 +42,12 @@
 	MBHC_CAL_NUM,
 };
 
+enum mbhc_impedance_detect_stages {
+	PRE_MEAS,
+	POST_MEAS,
+	PA_DISABLE,
+};
+
 /* Data used by MBHC */
 struct mbhc_internal_cal_data {
 	u16 dce_z;
@@ -239,6 +247,9 @@
 	void (*free_irq) (struct wcd9xxx_mbhc *);
 	enum wcd9xxx_cdc_type (*get_cdc_type) (void);
 	void (*enable_clock_gate) (struct snd_soc_codec *, bool);
+	int (*setup_zdet) (struct wcd9xxx_mbhc *,
+			   enum mbhc_impedance_detect_stages stage);
+	void (*compute_impedance) (s16 *, s16 *, uint32_t *, uint32_t *);
 };
 
 struct wcd9xxx_mbhc {
diff --git a/sound/soc/msm/qdsp6v2/audio_acdb.c b/sound/soc/msm/qdsp6v2/audio_acdb.c
index 2836b87..3e93b6e 100644
--- a/sound/soc/msm/qdsp6v2/audio_acdb.c
+++ b/sound/soc/msm/qdsp6v2/audio_acdb.c
@@ -22,6 +22,11 @@
 #include "audio_acdb.h"
 #include "q6voice.h"
 
+#include <sound/q6adm-v2.h>
+#include <sound/q6afe-v2.h>
+#include <sound/q6asm-v2.h>
+#include <sound/q6lsm.h>
+
 
 #define MAX_NETWORKS			15
 #define MAX_IOCTL_DATA			(MAX_NETWORKS * 2)
@@ -996,12 +1001,64 @@
 	return result;
 }
 
+static int unmap_cal_tables(void)
+{
+	int	result = 0;
+	int	result2 = 0;
+
+	result2 = adm_unmap_cal_blocks();
+	if (result2 < 0) {
+		pr_err("%s: adm_unmap_cal_blocks failed, err = %d\n",
+			__func__, result2);
+		result = result2;
+	}
+
+	result2 = afe_unmap_cal_blocks();
+	if (result2 < 0) {
+		pr_err("%s: afe_unmap_cal_blocks failed, err = %d\n",
+			__func__, result2);
+		result = result2;
+	}
+
+	result2 = q6lsm_unmap_cal_blocks();
+	if (result2 < 0) {
+		pr_err("%s: lsm_unmap_cal_blocks failed, err = %d\n",
+			__func__, result2);
+		result = result2;
+	}
+
+	result2 = q6asm_unmap_cal_blocks();
+	if (result2 < 0) {
+		pr_err("%s: asm_unmap_cal_blocks failed, err = %d\n",
+			__func__, result2);
+		result = result2;
+	}
+
+	result2 = voc_unmap_cal_blocks();
+	if (result2 < 0) {
+		pr_err("%s: voice_unmap_cal_blocks failed, err = %d\n",
+			__func__, result2);
+		result = result2;
+	}
+
+	return result;
+}
+
 static int deregister_memory(void)
 {
-	int i;
+	int	result = 0;
+	int	i;
+	pr_debug("%s\n", __func__);
 
 	if (atomic64_read(&acdb_data.mem_len)) {
 		mutex_lock(&acdb_data.acdb_mutex);
+		/* unmap all cal data */
+		result = unmap_cal_tables();
+		if (result < 0)
+			pr_err("%s: unmap_cal_tables failed, err = %d\n",
+				__func__, result);
+
+
 		atomic64_set(&acdb_data.mem_len, 0);
 
 		for (i = 0; i < MAX_VOCPROC_TYPES; i++) {
@@ -1011,7 +1068,7 @@
 		msm_audio_ion_free(acdb_data.ion_client, acdb_data.ion_handle);
 		mutex_unlock(&acdb_data.acdb_mutex);
 	}
-	return 0;
+	return result;
 }
 
 static int register_memory(void)
@@ -1022,6 +1079,7 @@
 	void                    *kvptr;
 	unsigned long		kvaddr;
 	unsigned long		mem_len;
+	pr_debug("%s\n", __func__);
 
 	mutex_lock(&acdb_data.acdb_mutex);
 	for (i = 0; i < MAX_VOCPROC_TYPES; i++) {
diff --git a/sound/soc/msm/qdsp6v2/msm-lsm-client.c b/sound/soc/msm/qdsp6v2/msm-lsm-client.c
index f76d455..3f57078 100644
--- a/sound/soc/msm/qdsp6v2/msm-lsm-client.c
+++ b/sound/soc/msm/qdsp6v2/msm-lsm-client.c
@@ -252,7 +252,8 @@
 		return -ENOMEM;
 	}
 	prtd->substream = substream;
-	prtd->lsm_client = q6lsm_client_alloc((app_cb)lsm_event_handler, prtd);
+	prtd->lsm_client = q6lsm_client_alloc(
+				(lsm_app_cb)lsm_event_handler, prtd);
 	if (!prtd->lsm_client) {
 		pr_err("%s: Could not allocate memory\n", __func__);
 		kfree(prtd);
diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c b/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c
index 62fe6d2..42a24fc 100644
--- a/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c
+++ b/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c
@@ -48,7 +48,6 @@
 	unsigned int  sample_rate;
 	unsigned int  channel;
 	unsigned int  format;
-	unsigned long perf_mode;
 };
 
 #define INVALID_SESSION -1
@@ -265,6 +264,11 @@
 	{INVALID_SESSION, INVALID_SESSION},
 };
 
+/* Track performance mode of all front-end multimedia sessions.
+ * Performance mode is only valid when session is valid.
+ */
+static bool fe_dai_perf_mode[MSM_FRONTEND_DAI_MM_SIZE][2];
+
 static uint8_t is_be_dai_extproc(int be_dai)
 {
 	if (be_dai == MSM_BACKEND_DAI_EXTPROC_RX ||
@@ -366,17 +370,13 @@
 
 	payload.num_copps = 0; /* only RX needs to use payload */
 	fe_dai_map[fedai_id][session_type] = dspst_id;
+	fe_dai_perf_mode[fedai_id][session_type] = perf_mode;
+
 	/* re-enable EQ if active */
 	if (eq_data[fedai_id].enable)
 		msm_send_eq_values(fedai_id);
 	topology = get_topology(path_type);
 	for (i = 0; i < MSM_BACKEND_DAI_MAX; i++) {
-		if (test_bit(fedai_id, &msm_bedais[i].fe_sessions)) {
-			if (perf_mode)
-				set_bit(fedai_id, &msm_bedais[i].perf_mode);
-			else
-				clear_bit(fedai_id, &msm_bedais[i].perf_mode);
-		}
 		if (!is_be_dai_extproc(i) &&
 		   (afe_get_port_type(msm_bedais[i].port_id) == port_type) &&
 		   (msm_bedais[i].active) &&
@@ -399,8 +399,7 @@
 				path_type,
 				msm_bedais[i].sample_rate,
 				msm_bedais[i].channel,
-				topology,
-				test_bit(fedai_id, &msm_bedais[i].perf_mode),
+				topology, perf_mode,
 				bits_per_sample);
 			else
 				adm_open(msm_bedais[i].port_id,
@@ -457,9 +456,9 @@
 		   (msm_bedais[i].active) &&
 		   (test_bit(fedai_id, &msm_bedais[i].fe_sessions))) {
 			adm_close(msm_bedais[i].port_id,
-				test_bit(fedai_id, &msm_bedais[i].perf_mode));
+				  fe_dai_perf_mode[fedai_id][session_type]);
 			if ((DOLBY_ADM_COPP_TOPOLOGY_ID == topology) &&
-			    (!test_bit(fedai_id, &msm_bedais[i].perf_mode)))
+			    (fe_dai_perf_mode[fedai_id][session_type] == false))
 				dolby_dap_deinit(msm_bedais[i].port_id);
 		}
 	}
@@ -491,7 +490,6 @@
 	int session_type, path_type, port_id, topology;
 	u32 channels;
 	uint16_t bits_per_sample = 16;
-	bool perf_mode = false;
 
 	pr_debug("%s: reg %x val %x set %x\n", __func__, reg, val, set);
 
@@ -531,14 +529,12 @@
 
 			if ((session_type == SESSION_TYPE_RX) &&
 				(channels > 0)) {
-				perf_mode = test_bit(val,
-						&msm_bedais[reg].perf_mode);
 				adm_multi_ch_copp_open(msm_bedais[reg].port_id,
 				path_type,
 				msm_bedais[reg].sample_rate,
 				channels,
 				topology,
-				perf_mode,
+				fe_dai_perf_mode[val][session_type],
 				bits_per_sample);
 			} else
 				adm_open(msm_bedais[reg].port_id,
@@ -548,11 +544,11 @@
 
 			msm_pcm_routing_build_matrix(val,
 				fe_dai_map[val][session_type], path_type,
-				perf_mode);
+				fe_dai_perf_mode[val][session_type]);
 			port_id = srs_port_id = msm_bedais[reg].port_id;
 			srs_send_params(srs_port_id, 1, 0);
 			if ((DOLBY_ADM_COPP_TOPOLOGY_ID == topology) &&
-			    (!perf_mode))
+			    (fe_dai_perf_mode[val][session_type] == false))
 				if (dolby_dap_init(port_id, channels) < 0)
 					pr_err("%s: Err init dolby dap\n",
 						__func__);
@@ -565,14 +561,14 @@
 		clear_bit(val, &msm_bedais[reg].fe_sessions);
 		if (msm_bedais[reg].active && fe_dai_map[val][session_type] !=
 			INVALID_SESSION) {
-			perf_mode = test_bit(val, &msm_bedais[reg].perf_mode);
-			adm_close(msm_bedais[reg].port_id, perf_mode);
+			adm_close(msm_bedais[reg].port_id,
+				  fe_dai_perf_mode[val][session_type]);
 			if ((DOLBY_ADM_COPP_TOPOLOGY_ID == topology) &&
-			    (!perf_mode))
+			    (fe_dai_perf_mode[val][session_type] == false))
 				dolby_dap_deinit(msm_bedais[reg].port_id);
 			msm_pcm_routing_build_matrix(val,
 				fe_dai_map[val][session_type], path_type,
-				perf_mode);
+				fe_dai_perf_mode[val][session_type]);
 		}
 	}
 	if ((msm_bedais[reg].port_id == VOICE_RECORD_RX)
@@ -3729,12 +3725,11 @@
 	for_each_set_bit(i, &bedai->fe_sessions, MSM_FRONTEND_DAI_MM_SIZE) {
 		if (fe_dai_map[i][session_type] != INVALID_SESSION) {
 			adm_close(bedai->port_id,
-				test_bit(i, &(bedai->perf_mode)));
+				  fe_dai_perf_mode[i][session_type]);
 			srs_port_id = -1;
 			if ((DOLBY_ADM_COPP_TOPOLOGY_ID == topology) &&
-			    (!test_bit(i, &(bedai->perf_mode))))
+			    (fe_dai_perf_mode[i][session_type] == false))
 				dolby_dap_deinit(bedai->port_id);
-			clear_bit(i, &(bedai->perf_mode));
 		}
 	}
 
@@ -3755,7 +3750,6 @@
 	u32 channels;
 	bool playback, capture;
 	uint16_t bits_per_sample = 16;
-	bool perf_mode = false;
 
 	if (be_id >= MSM_BACKEND_DAI_MAX) {
 		pr_err("%s: unexpected be_id %d\n", __func__, be_id);
@@ -3798,13 +3792,12 @@
 				topology = DEFAULT_COPP_TOPOLOGY;
 
 			if ((playback) && (channels > 0)) {
-				perf_mode = test_bit(i, &(bedai->perf_mode));
 				adm_multi_ch_copp_open(bedai->port_id,
 					path_type,
 					bedai->sample_rate,
 					channels,
 					topology,
-					perf_mode,
+					fe_dai_perf_mode[i][session_type],
 					bits_per_sample);
 			} else if (capture) {
 				adm_open(bedai->port_id,
@@ -3817,11 +3810,11 @@
 
 			msm_pcm_routing_build_matrix(i,
 				fe_dai_map[i][session_type], path_type,
-				perf_mode);
+				fe_dai_perf_mode[i][session_type]);
 			port_id = srs_port_id = bedai->port_id;
 			srs_send_params(srs_port_id, 1, 0);
 			if ((DOLBY_ADM_COPP_TOPOLOGY_ID == topology) &&
-			    (!perf_mode))
+			    (fe_dai_perf_mode[i][session_type] == false))
 				if (dolby_dap_init(port_id, channels) < 0)
 					pr_err("%s: Err init dolby dap\n",
 						__func__);
diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-voip-v2.c b/sound/soc/msm/qdsp6v2/msm-pcm-voip-v2.c
index 4a829fd..158009f 100644
--- a/sound/soc/msm/qdsp6v2/msm-pcm-voip-v2.c
+++ b/sound/soc/msm/qdsp6v2/msm-pcm-voip-v2.c
@@ -79,12 +79,16 @@
 	VOIP_STARTED,
 };
 
-struct voip_frame {
+struct voip_frame_hdr {
+	uint32_t timestamp;
 	union {
-	uint32_t frame_type;
-	uint32_t packet_rate;
-	} header;
-	uint32_t len;
+		uint32_t frame_type;
+		uint32_t packet_rate;
+	};
+};
+struct voip_frame {
+	struct voip_frame_hdr frm_hdr;
+	uint32_t pktlen;
 	uint8_t voc_pkt[VOIP_MAX_VOC_PKT_SIZE];
 };
 
@@ -275,6 +279,7 @@
 /* capture path */
 static void voip_process_ul_pkt(uint8_t *voc_pkt,
 				uint32_t pkt_len,
+				uint32_t timestamp,
 				void *private_data)
 {
 	struct voip_buf_node *buf_node = NULL;
@@ -299,13 +304,15 @@
 			 * Bits 0-3: Frame rate
 			 * Bits 4-7: Frame type
 			 */
-			buf_node->frame.header.frame_type =
+			buf_node->frame.frm_hdr.timestamp = timestamp;
+			buf_node->frame.frm_hdr.frame_type =
 						((*voc_pkt) & 0xF0) >> 4;
 			voc_pkt = voc_pkt + DSP_FRAME_HDR_LEN;
-			buf_node->frame.len = pkt_len - DSP_FRAME_HDR_LEN;
+			buf_node->frame.pktlen = pkt_len - DSP_FRAME_HDR_LEN;
 			memcpy(&buf_node->frame.voc_pkt[0],
 				voc_pkt,
-				buf_node->frame.len);
+				buf_node->frame.pktlen);
+
 			list_add_tail(&buf_node->list, &prtd->out_queue);
 			break;
 		}
@@ -316,27 +323,30 @@
 			 * Header format:
 			 * Bits 0-3: frame rate
 			 */
-			buf_node->frame.header.packet_rate = (*voc_pkt) & 0x0F;
+			buf_node->frame.frm_hdr.timestamp = timestamp;
+			buf_node->frame.frm_hdr.packet_rate = (*voc_pkt) & 0x0F;
 			voc_pkt = voc_pkt + DSP_FRAME_HDR_LEN;
-			buf_node->frame.len = pkt_len - DSP_FRAME_HDR_LEN;
+			buf_node->frame.pktlen = pkt_len - DSP_FRAME_HDR_LEN;
 
 			memcpy(&buf_node->frame.voc_pkt[0],
 				voc_pkt,
-				buf_node->frame.len);
+				buf_node->frame.pktlen);
 
 			list_add_tail(&buf_node->list, &prtd->out_queue);
 			break;
 		}
 		default: {
-			buf_node->frame.len = pkt_len;
+			buf_node->frame.frm_hdr.timestamp = timestamp;
+			buf_node->frame.pktlen = pkt_len;
 			memcpy(&buf_node->frame.voc_pkt[0],
 			       voc_pkt,
-			       buf_node->frame.len);
+			       buf_node->frame.pktlen);
 			list_add_tail(&buf_node->list, &prtd->out_queue);
 		}
 		}
-		pr_debug("ul_pkt: pkt_len =%d, frame.len=%d\n", pkt_len,
-			buf_node->frame.len);
+		pr_debug("%s: pkt_len =%d, frame.pktlen=%d, timestamp=%d\n",
+			 __func__, pkt_len, buf_node->frame.pktlen, timestamp);
+
 		prtd->pcm_capture_irq_pos += prtd->pcm_capture_count;
 		spin_unlock_irqrestore(&prtd->dsp_ul_lock, dsp_flags);
 		snd_pcm_period_elapsed(prtd->capture_substream);
@@ -367,7 +377,7 @@
 		switch (prtd->mode) {
 		case MODE_AMR:
 		case MODE_AMR_WB: {
-			*((uint32_t *)voc_pkt) = buf_node->frame.len +
+			*((uint32_t *)voc_pkt) = buf_node->frame.pktlen +
 							DSP_FRAME_HDR_LEN;
 			/* Advance to the header of voip packet */
 			voc_pkt = voc_pkt + sizeof(uint32_t);
@@ -376,19 +386,19 @@
 			 * Bits 0-3: Frame rate
 			 * Bits 4-7: Frame type
 			 */
-			*voc_pkt = ((buf_node->frame.header.frame_type &
+			*voc_pkt = ((buf_node->frame.frm_hdr.frame_type &
 					0x0F) << 4) | (prtd->rate_type & 0x0F);
 			voc_pkt = voc_pkt + DSP_FRAME_HDR_LEN;
 			memcpy(voc_pkt,
 				&buf_node->frame.voc_pkt[0],
-				buf_node->frame.len);
+				buf_node->frame.pktlen);
 			list_add_tail(&buf_node->list, &prtd->free_in_queue);
 			break;
 		}
 		case MODE_IS127:
 		case MODE_4GV_NB:
 		case MODE_4GV_WB: {
-			*((uint32_t *)voc_pkt) = buf_node->frame.len +
+			*((uint32_t *)voc_pkt) = buf_node->frame.pktlen +
 							 DSP_FRAME_HDR_LEN;
 			/* Advance to the header of voip packet */
 			voc_pkt = voc_pkt + sizeof(uint32_t);
@@ -396,22 +406,22 @@
 			 * Add the DSP frame info header. Header format:
 			 * Bits 0-3 : Frame rate
 			 */
-			*voc_pkt = buf_node->frame.header.packet_rate & 0x0F;
+			*voc_pkt = buf_node->frame.frm_hdr.packet_rate & 0x0F;
 			voc_pkt = voc_pkt + DSP_FRAME_HDR_LEN;
 
 			memcpy(voc_pkt,
 				&buf_node->frame.voc_pkt[0],
-				buf_node->frame.len);
+				buf_node->frame.pktlen);
 
 			list_add_tail(&buf_node->list, &prtd->free_in_queue);
 			break;
 		}
 		default: {
-			*((uint32_t *)voc_pkt) = buf_node->frame.len;
+			*((uint32_t *)voc_pkt) = buf_node->frame.pktlen;
 			voc_pkt = voc_pkt + sizeof(uint32_t);
 			memcpy(voc_pkt,
 			       &buf_node->frame.voc_pkt[0],
-			       buf_node->frame.len);
+			       buf_node->frame.pktlen);
 			list_add_tail(&buf_node->list, &prtd->free_in_queue);
 		}
 		}
@@ -559,7 +569,7 @@
 			if (prtd->mode == MODE_PCM) {
 				ret = copy_from_user(&buf_node->frame.voc_pkt,
 							buf, count);
-				buf_node->frame.len = count;
+				buf_node->frame.pktlen = count;
 			} else
 				ret = copy_from_user(&buf_node->frame,
 							buf, count);
diff --git a/sound/soc/msm/qdsp6v2/q6adm.c b/sound/soc/msm/qdsp6v2/q6adm.c
index d99812f..297a386 100644
--- a/sound/soc/msm/qdsp6v2/q6adm.c
+++ b/sound/soc/msm/qdsp6v2/q6adm.c
@@ -18,8 +18,6 @@
 #include <linux/atomic.h>
 #include <linux/wait.h>
 
-#include <mach/qdsp6v2/rtac.h>
-
 #include <sound/apr_audio-v2.h>
 #include <mach/qdsp6v2/apr.h>
 #include <sound/q6adm-v2.h>
@@ -33,7 +31,9 @@
 
 #define RESET_COPP_ID 99
 #define INVALID_COPP_ID 0xFF
-#define ADM_GET_PARAMETER_LENGTH 350
+/* Used for inband payload copy, max size is 4k */
+/* 2 is to account for module & param ID in payload */
+#define ADM_GET_PARAMETER_LENGTH  (4096 - APR_HDR_SIZE - 2 * sizeof(uint32_t))
 
 
 enum {
@@ -42,6 +42,7 @@
 	ADM_RX_AUDVOL_CAL,
 	ADM_TX_AUDVOL_CAL,
 	ADM_CUSTOM_TOP_CAL,
+	ADM_RTAC,
 	ADM_MAX_CAL_TYPES
 };
 
@@ -469,6 +470,10 @@
 			this_adm.apr = NULL;
 			reset_custom_topology_flags();
 			this_adm.set_custom_topology = 1;
+			for (i = 0; i < ADM_MAX_CAL_TYPES; i++)
+				atomic_set(&this_adm.mem_map_cal_handles[i],
+					0);
+			rtac_clear_mapping(ADM_RTAC_CAL);
 		}
 		pr_debug("Resetting calibration blocks");
 		for (i = 0; i < MAX_AUDPROC_TYPES; i++) {
@@ -525,7 +530,8 @@
 				if (payload[1] != 0) {
 					pr_err("%s: ADM map error, resuming\n",
 						__func__);
-					atomic_set(&this_adm.copp_stat[0], 1);
+					atomic_set(&this_adm.copp_stat[index],
+							1);
 					wake_up(&this_adm.wait[index]);
 				}
 				break;
@@ -580,13 +586,18 @@
 			if (payload[0] != 0)
 				pr_err("%s: ADM_CMDRSP_GET_PP_PARAMS_V5 returned error = 0x%x\n",
 					__func__, payload[0]);
-			rtac_make_adm_callback(payload,
-				data->payload_size);
-			adm_get_parameters[0] = payload[3];
-			pr_debug("GET_PP PARAM:received parameter length: %x\n",
-					adm_get_parameters[0]);
-			for (i = 0; i < payload[3]; i++)
-				adm_get_parameters[1+i] = payload[4+i];
+			if (rtac_make_adm_callback(payload,
+					data->payload_size))
+				break;
+
+			if (data->payload_size > (4 * sizeof(uint32_t))) {
+				adm_get_parameters[0] = payload[3];
+				pr_debug("GET_PP PARAM:received parameter length: %x\n",
+						adm_get_parameters[0]);
+				/* storing param size then params */
+				for (i = 0; i < payload[3]; i++)
+					adm_get_parameters[1+i] = payload[4+i];
+			}
 			atomic_set(&this_adm.copp_stat[index], 1);
 			wake_up(&this_adm.wait[index]);
 			break;
@@ -596,7 +607,7 @@
 			atomic_set(&this_adm.mem_map_cal_handles[
 				atomic_read(&this_adm.mem_map_cal_index)],
 				*payload);
-			atomic_set(&this_adm.copp_stat[0], 1);
+			atomic_set(&this_adm.copp_stat[index], 1);
 			wake_up(&this_adm.wait[index]);
 			break;
 		default:
@@ -637,8 +648,8 @@
 		/* Only call this once */
 		this_adm.set_custom_topology = 0;
 
-		result = adm_memory_map_regions(port_id, &cal_block.cal_paddr,
-					0, &size, 1);
+		result = adm_memory_map_regions(port_id,
+				&cal_block.cal_paddr, 0, &size, 1);
 		if (result < 0) {
 			pr_err("%s: mmap did not work! addr = 0x%x, size = %d\n",
 				__func__, cal_block.cal_paddr,
@@ -760,11 +771,15 @@
 	int			result = 0;
 	s32			acdb_path;
 	struct acdb_cal_block	aud_cal;
-	int			size = 4096;
+	int			size;
 	pr_debug("%s\n", __func__);
 
 	/* Maps audio_dev_ctrl path definition to ACDB definition */
 	acdb_path = path - 1;
+	if (acdb_path == TX_CAL)
+		size = 4096 * 4;
+	else
+		size = 4096;
 
 	pr_debug("%s: Sending audproc cal\n", __func__);
 	get_audproc_cal(acdb_path, &aud_cal);
@@ -777,9 +792,7 @@
 		this_adm.mem_addr_audproc[acdb_path].cal_size)) {
 
 		if (this_adm.mem_addr_audproc[acdb_path].cal_paddr != 0)
-			adm_memory_unmap_regions(port_id,
-				&this_adm.mem_addr_audproc[acdb_path].
-				cal_paddr, &size, 1);
+			adm_memory_unmap_regions(port_id);
 
 		result = adm_memory_map_regions(port_id, &aud_cal.cal_paddr,
 						0, &size, 1);
@@ -813,9 +826,7 @@
 		this_adm.mem_addr_audvol[acdb_path].cal_size)) {
 
 		if (this_adm.mem_addr_audvol[acdb_path].cal_paddr != 0)
-			adm_memory_unmap_regions(port_id,
-				&this_adm.mem_addr_audvol[acdb_path].cal_paddr,
-				&size, 1);
+			adm_memory_unmap_regions(port_id);
 
 		result = adm_memory_map_regions(port_id, &aud_cal.cal_paddr,
 						0, &size, 1);
@@ -838,6 +849,133 @@
 			__func__, port_id, acdb_path);
 }
 
+int adm_map_rtac_block(struct rtac_cal_block_data *cal_block)
+{
+	int	result = 0;
+	pr_debug("%s\n", __func__);
+
+	if (cal_block == NULL) {
+		pr_err("%s: cal_block is NULL!\n",
+			__func__);
+		result = -EINVAL;
+		goto done;
+	}
+
+	if (cal_block->cal_data.paddr == 0) {
+		pr_debug("%s: No address to map!\n",
+			__func__);
+		result = -EINVAL;
+		goto done;
+	}
+
+	if (cal_block->map_data.map_size == 0) {
+		pr_debug("%s: map size is 0!\n",
+			__func__);
+		result = -EINVAL;
+		goto done;
+	}
+
+	/* valid port ID needed for callback use primary I2S */
+	atomic_set(&this_adm.mem_map_cal_index, ADM_RTAC);
+	result = adm_memory_map_regions(PRIMARY_I2S_RX,
+			&cal_block->cal_data.paddr, 0,
+			&cal_block->map_data.map_size, 1);
+	if (result < 0) {
+		pr_err("%s: RTAC mmap did not work! addr = 0x%x, size = %d\n",
+			__func__, cal_block->cal_data.paddr,
+			cal_block->map_data.map_size);
+		goto done;
+	}
+
+	cal_block->map_data.map_handle = atomic_read(
+		&this_adm.mem_map_cal_handles[ADM_RTAC]);
+done:
+	return result;
+}
+
+int adm_unmap_rtac_block(uint32_t *mem_map_handle)
+{
+	int	result = 0;
+	pr_debug("%s\n", __func__);
+
+	if (mem_map_handle == NULL) {
+		pr_debug("%s: Map handle is NULL, nothing to unmap\n",
+			__func__);
+		goto done;
+	}
+
+	if (*mem_map_handle == 0) {
+		pr_debug("%s: Map handle is 0, nothing to unmap\n",
+			__func__);
+		goto done;
+	}
+
+	if (*mem_map_handle != atomic_read(
+			&this_adm.mem_map_cal_handles[ADM_RTAC])) {
+		pr_err("%s: Map handles do not match! Unmapping RTAC, RTAC map 0x%x, ADM map 0x%x\n",
+			__func__, *mem_map_handle, atomic_read(
+			&this_adm.mem_map_cal_handles[ADM_RTAC]));
+
+		/* if mismatch use handle passed in to unmap */
+		atomic_set(&this_adm.mem_map_cal_handles[ADM_RTAC],
+			   *mem_map_handle);
+	}
+
+	/* valid port ID needed for callback use primary I2S */
+	atomic_set(&this_adm.mem_map_cal_index, ADM_RTAC);
+	result = adm_memory_unmap_regions(PRIMARY_I2S_RX);
+	if (result < 0) {
+		pr_debug("%s: adm_memory_unmap_regions failed, error %d\n",
+			__func__, result);
+	} else {
+		atomic_set(&this_adm.mem_map_cal_handles[ADM_RTAC], 0);
+		*mem_map_handle = 0;
+	}
+done:
+	return result;
+}
+
+int adm_unmap_cal_blocks(void)
+{
+	int	i;
+	int	result = 0;
+	int	result2 = 0;
+
+	for (i = 0; i < ADM_MAX_CAL_TYPES; i++) {
+		if (atomic_read(&this_adm.mem_map_cal_handles[i]) != 0) {
+
+			if (i <= ADM_TX_AUDPROC_CAL) {
+				this_adm.mem_addr_audproc[i].cal_paddr = 0;
+				this_adm.mem_addr_audproc[i].cal_size = 0;
+			} else if (i <= ADM_TX_AUDVOL_CAL) {
+				this_adm.mem_addr_audvol
+					[(i - ADM_RX_AUDVOL_CAL)].cal_paddr
+					= 0;
+				this_adm.mem_addr_audvol
+					[(i - ADM_RX_AUDVOL_CAL)].cal_size
+					= 0;
+			} else if (i == ADM_CUSTOM_TOP_CAL) {
+				this_adm.set_custom_topology = 1;
+			} else {
+				continue;
+			}
+
+			/* valid port ID needed for callback use primary I2S */
+			atomic_set(&this_adm.mem_map_cal_index, i);
+			result2 = adm_memory_unmap_regions(PRIMARY_I2S_RX);
+			if (result2 < 0) {
+				pr_err("%s: adm_memory_unmap_regions failed, err %d\n",
+						__func__, result2);
+				result = result2;
+			} else {
+				atomic_set(&this_adm.mem_map_cal_handles[i],
+					0);
+			}
+		}
+	}
+	return result;
+}
+
 int adm_connect_afe_port(int mode, int session_id, int port_id)
 {
 	struct adm_cmd_connect_afe_port_v5	cmd;
@@ -1294,7 +1432,7 @@
 		++mregions;
 	}
 
-	atomic_set(&this_adm.copp_stat[0], 0);
+	atomic_set(&this_adm.copp_stat[index], 0);
 	ret = apr_send_pkt(this_adm.apr, (uint32_t *) mmap_region_cmd);
 	if (ret < 0) {
 		pr_err("%s: mmap_regions op[0x%x]rc[%d]\n", __func__,
@@ -1304,7 +1442,7 @@
 	}
 
 	ret = wait_event_timeout(this_adm.wait[index],
-			atomic_read(&this_adm.copp_stat[0]), 5 * HZ);
+			atomic_read(&this_adm.copp_stat[index]), 5 * HZ);
 	if (!ret) {
 		pr_err("%s: timeout. waited for memory_map\n", __func__);
 		ret = -EINVAL;
@@ -1315,8 +1453,7 @@
 	return ret;
 }
 
-int adm_memory_unmap_regions(int32_t port_id, uint32_t *buf_add,
-			uint32_t *bufsz, uint32_t bufcnt)
+int adm_memory_unmap_regions(int32_t port_id)
 {
 	struct  avs_cmd_shared_mem_unmap_regions unmap_regions;
 	int     ret = 0;
diff --git a/sound/soc/msm/qdsp6v2/q6afe.c b/sound/soc/msm/qdsp6v2/q6afe.c
index 6dfe5b3..88ee47e 100644
--- a/sound/soc/msm/qdsp6v2/q6afe.c
+++ b/sound/soc/msm/qdsp6v2/q6afe.c
@@ -357,7 +357,8 @@
 {
 	int ret;
 
-	atomic_set(&this_afe.state, 1);
+	if (wait)
+		atomic_set(&this_afe.state, 1);
 	atomic_set(&this_afe.status, 0);
 	ret = apr_send_pkt(this_afe.apr, data);
 	if (ret > 0) {
@@ -469,6 +470,35 @@
 	return;
 }
 
+int afe_unmap_cal_blocks(void)
+{
+	int	i;
+	int	result = 0;
+	int	result2 = 0;
+
+	for (i = 0; i < MAX_AFE_CAL_TYPES; i++) {
+		if (atomic_read(&this_afe.mem_map_cal_handles[i]) != 0) {
+
+			atomic_set(&this_afe.mem_map_cal_index, i);
+			result2 = afe_cmd_memory_unmap(atomic_read(
+				&this_afe.mem_map_cal_handles[i]));
+			if (result2 < 0) {
+				pr_err("%s: unmap failed, err %d\n",
+					__func__, result2);
+				result = result2;
+			} else {
+				atomic_set(&this_afe.mem_map_cal_handles[i],
+					0);
+			}
+			atomic_set(&this_afe.mem_map_cal_index, -1);
+
+			this_afe.afe_cal_addr[i].cal_paddr = 0;
+			this_afe.afe_cal_addr[i].cal_size = 0;
+		}
+	}
+	return result;
+}
+
 static int afe_spk_prot_prepare(int port, int param_id,
 		union afe_spkr_prot_config *prot_config)
 {
@@ -2006,7 +2036,6 @@
 		goto fail_cmd;
 	}
 
-	pr_debug("%s: mmap handle 0x%x\n", __func__, this_afe.mmap_handle);
 	kfree(mmap_region_cmd);
 	return 0;
 fail_cmd:
diff --git a/sound/soc/msm/qdsp6v2/q6asm.c b/sound/soc/msm/qdsp6v2/q6asm.c
index 1abc47d..c153d10 100644
--- a/sound/soc/msm/qdsp6v2/q6asm.c
+++ b/sound/soc/msm/qdsp6v2/q6asm.c
@@ -36,7 +36,6 @@
 
 #include <mach/memory.h>
 #include <mach/debug_mm.h>
-#include <mach/qdsp6v2/rtac.h>
 
 #include <sound/apr_audio-v2.h>
 #include <sound/q6asm-v2.h>
@@ -72,11 +71,11 @@
 static int q6asm_memory_map_regions(struct audio_client *ac, int dir,
 				uint32_t bufsz, uint32_t bufcnt,
 				bool is_contiguous);
-static int q6asm_memory_unmap_regions(struct audio_client *ac, int dir,
-				uint32_t bufsz, uint32_t bufcnt);
+static int q6asm_memory_unmap_regions(struct audio_client *ac, int dir);
 static void q6asm_reset_buf_state(struct audio_client *ac);
 
 static int q6asm_map_channels(u8 *channel_mapping, uint32_t channels);
+void *q6asm_mmap_apr_reg(void);
 
 
 #ifdef CONFIG_DEBUG_FS
@@ -96,9 +95,28 @@
 static int out_cold_index;
 static char *out_buffer;
 static char *in_buffer;
+static struct audio_buffer common_buf[2];
+static struct audio_client common_client;
 static int set_custom_topology;
 static int topology_map_handle;
 
+
+int q6asm_mmap_apr_dereg(void)
+{
+	int c;
+
+	c = atomic_sub_return(1, &this_mmap.ref_cnt);
+	if (c == 0) {
+		apr_deregister(this_mmap.apr);
+		pr_debug("%s: APR De-Register common port\n", __func__);
+	} else if (c < 0) {
+		pr_err("%s: APR Common Port Already Closed\n", __func__);
+		atomic_set(&this_mmap.ref_cnt, 0);
+	}
+
+	return 0;
+}
+
 static int audio_output_latency_dbgfs_open(struct inode *inode,
 							struct file *file)
 {
@@ -340,7 +358,6 @@
 {
 	struct acdb_cal_block		cal_block;
 	struct cmd_set_topologies	asm_top;
-	struct audio_buffer		*buf;
 	struct asm_buffer_node		*buf_node = NULL;
 	struct list_head		*ptr, *next;
 	int				result;
@@ -354,20 +371,29 @@
 	}
 
 	if (set_custom_topology) {
+		if (common_client.mmap_apr == NULL) {
+			common_client.mmap_apr = q6asm_mmap_apr_reg();
+			common_client.apr = common_client.mmap_apr;
+			if (common_client.mmap_apr == NULL) {
+				pr_err("%s: q6asm_mmap_apr_reg failed\n",
+					__func__);
+				result = -EPERM;
+				goto done;
+			}
+		}
 		/* Only call this once */
 		set_custom_topology = 0;
 
 		/* Use first asm buf to map memory */
-		buf = kzalloc(sizeof(struct audio_buffer), GFP_KERNEL);
-		if (!buf) {
-			pr_debug("%s: could not allocate temp memory\n",
+		if (common_client.port[IN].buf == NULL) {
+			pr_err("%s: common buf is NULL\n",
 				__func__);
 			goto done;
 		}
-		buf[0].phys = cal_block.cal_paddr;
-		ac->port[0].buf = buf;
+		common_client.port[IN].buf->phys = cal_block.cal_paddr;
 
-		result = q6asm_memory_map_regions(ac, 0, size, 1, 1);
+		result = q6asm_memory_map_regions(&common_client,
+							IN, size, 1, 1);
 		if (result < 0) {
 			pr_err("%s: mmap did not work! addr = 0x%x, size = %d\n",
 				__func__, cal_block.cal_paddr,
@@ -375,7 +401,8 @@
 			goto done;
 		}
 
-		list_for_each_safe(ptr, next, &ac->port[IN].mem_map_handle) {
+		list_for_each_safe(ptr, next,
+				&common_client.port[IN].mem_map_handle) {
 			buf_node = list_entry(ptr, struct asm_buffer_node,
 						list);
 			if (buf_node->buf_addr_lsw == cal_block.cal_paddr) {
@@ -384,7 +411,13 @@
 			}
 		}
 
-		kfree(buf);
+		result = q6asm_mmap_apr_dereg();
+		if (result < 0) {
+			pr_err("%s: q6asm_mmap_apr_dereg failed, err %d\n",
+				__func__, result);
+		} else {
+			common_client.mmap_apr = NULL;
+		}
 	}
 
 	q6asm_add_hdr(ac, &asm_top.hdr, APR_PKT_SIZE(APR_HDR_SIZE,
@@ -415,11 +448,181 @@
 		goto done;
 	}
 
-
 done:
 	return;
 }
 
+int q6asm_map_rtac_block(struct rtac_cal_block_data *cal_block)
+{
+	int			result = 0;
+	struct asm_buffer_node	*buf_node = NULL;
+	struct list_head	*ptr, *next;
+	pr_debug("%s\n", __func__);
+
+	if (cal_block == NULL) {
+		pr_err("%s: cal_block is NULL!\n",
+			__func__);
+		result = -EINVAL;
+		goto done;
+	}
+
+	if (cal_block->cal_data.paddr == 0) {
+		pr_debug("%s: No address to map!\n",
+			__func__);
+		result = -EINVAL;
+		goto done;
+	}
+
+	if (common_client.mmap_apr == NULL) {
+		common_client.mmap_apr = q6asm_mmap_apr_reg();
+		if (common_client.mmap_apr == NULL) {
+			pr_err("%s: q6asm_mmap_apr_reg failed\n",
+				__func__);
+			result = -EPERM;
+			goto done;
+		}
+	}
+
+	if (cal_block->map_data.map_size == 0) {
+		pr_debug("%s: map size is 0!\n",
+			__func__);
+		result = -EINVAL;
+		goto done;
+	}
+
+	/* Use second asm buf to map memory */
+	if (common_client.port[OUT].buf == NULL) {
+		pr_err("%s: common buf is NULL\n",
+			__func__);
+		result = -EINVAL;
+		goto done;
+	}
+
+	common_client.port[OUT].buf->phys = cal_block->cal_data.paddr;
+
+	result = q6asm_memory_map_regions(&common_client,
+			OUT, cal_block->map_data.map_size, 1, 1);
+	if (result < 0) {
+		pr_err("%s: mmap did not work! addr = 0x%x, size = %d\n",
+			__func__, cal_block->cal_data.paddr,
+			cal_block->map_data.map_size);
+		goto done;
+	}
+
+	list_for_each_safe(ptr, next,
+		&common_client.port[OUT].mem_map_handle) {
+		buf_node = list_entry(ptr, struct asm_buffer_node,
+					list);
+		if (buf_node->buf_addr_lsw == cal_block->cal_data.paddr) {
+			cal_block->map_data.map_handle =  buf_node->mmap_hdl;
+			break;
+		}
+	}
+
+	result = q6asm_mmap_apr_dereg();
+	if (result < 0) {
+		pr_err("%s: q6asm_mmap_apr_dereg failed, err %d\n",
+			__func__, result);
+	} else {
+		common_client.mmap_apr = NULL;
+	}
+done:
+	return result;
+}
+
+int q6asm_unmap_rtac_block(uint32_t *mem_map_handle)
+{
+	int	result = 0;
+	int	result2 = 0;
+	pr_debug("%s\n", __func__);
+
+	if (mem_map_handle == NULL) {
+		pr_debug("%s: Map handle is NULL, nothing to unmap\n",
+			__func__);
+		goto done;
+	}
+
+	if (*mem_map_handle == 0) {
+		pr_debug("%s: Map handle is 0, nothing to unmap\n",
+			__func__);
+		goto done;
+	}
+
+	if (common_client.mmap_apr == NULL) {
+		common_client.mmap_apr = q6asm_mmap_apr_reg();
+		if (common_client.mmap_apr == NULL) {
+			pr_err("%s: q6asm_mmap_apr_reg failed\n",
+				__func__);
+			result = -EPERM;
+			goto done;
+		}
+	}
+
+
+	result2 = q6asm_memory_unmap_regions(&common_client, OUT);
+	if (result2 < 0) {
+		pr_err("%s: unmap failed, err %d\n",
+			__func__, result2);
+		result = result2;
+	} else {
+		mem_map_handle = 0;
+	}
+
+	result2 = q6asm_mmap_apr_dereg();
+	if (result2 < 0) {
+		pr_err("%s: q6asm_mmap_apr_dereg failed, err %d\n",
+			__func__, result2);
+		result = result2;
+	} else {
+		common_client.mmap_apr = NULL;
+	}
+done:
+	return result;
+}
+
+int q6asm_unmap_cal_blocks(void)
+{
+	int	result = 0;
+	int	result2 = 0;
+	pr_debug("%s\n", __func__);
+
+	if (topology_map_handle == 0)
+		goto done;
+
+	if (common_client.mmap_apr == NULL) {
+		common_client.mmap_apr = q6asm_mmap_apr_reg();
+		if (common_client.mmap_apr == NULL) {
+			pr_err("%s: q6asm_mmap_apr_reg failed\n",
+				__func__);
+			result = -EPERM;
+			goto done;
+		}
+	}
+
+	result2 = q6asm_memory_unmap_regions(&common_client, IN);
+	if (result2 < 0) {
+		pr_err("%s: unmap failed, err %d\n",
+			__func__, result2);
+		result = result2;
+	} else {
+		topology_map_handle = 0;
+	}
+
+	result2 = q6asm_mmap_apr_dereg();
+	if (result2 < 0) {
+		pr_err("%s: q6asm_mmap_apr_dereg failed, err %d\n",
+			__func__, result2);
+		result = result2;
+	} else {
+		common_client.mmap_apr = NULL;
+	}
+
+	set_custom_topology = 0;
+
+done:
+	return result;
+}
+
 int q6asm_audio_client_buf_free(unsigned int dir,
 			struct audio_client *ac)
 {
@@ -437,9 +640,7 @@
 		cnt = port->max_buf_cnt - 1;
 
 		if (cnt >= 0) {
-			rc = q6asm_memory_unmap_regions(ac, dir,
-							port->buf[0].size,
-							port->max_buf_cnt);
+			rc = q6asm_memory_unmap_regions(ac, dir);
 			if (rc < 0)
 				pr_err("%s CMD Memory_unmap_regions failed\n",
 								__func__);
@@ -507,23 +708,6 @@
 	return 0;
 }
 
-int q6asm_mmap_apr_dereg(void)
-{
-	int c;
-
-	c = atomic_sub_return(1, &this_mmap.ref_cnt);
-	if (c == 0) {
-		apr_deregister(this_mmap.apr);
-		pr_debug("%s: APR De-Register common port\n", __func__);
-	} else if (c < 0) {
-		pr_err("%s: APR Common Port Already Closed\n", __func__);
-		atomic_set(&this_mmap.ref_cnt, 0);
-	}
-
-	return 0;
-}
-
-
 void q6asm_audio_client_free(struct audio_client *ac)
 {
 	int loopcnt;
@@ -662,6 +846,10 @@
 
 struct audio_client *q6asm_get_audio_client(int session_id)
 {
+	if (session_id == ASM_CONTROL_SESSION) {
+		return &common_client;
+	}
+
 	if ((session_id <= 0) || (session_id > SESSION_MAX)) {
 		pr_err("%s: invalid session: %d\n", __func__, session_id);
 		goto err;
@@ -871,6 +1059,8 @@
 		this_mmap.apr = NULL;
 		reset_custom_topology_flags();
 		set_custom_topology = 1;
+		topology_map_handle = 0;
+		rtac_clear_mapping(ASM_RTAC_CAL);
 		return 0;
 	}
 	sid = (data->token >> 8) & 0x0F;
@@ -891,7 +1081,7 @@
 		case ASM_CMD_SHARED_MEM_UNMAP_REGIONS:
 			if (payload[1] != 0) {
 				pr_err("%s: cmd = 0x%x returned error = 0x%x sid:%d\n",
-				__func__, payload[0], payload[1], sid);
+					__func__, payload[0], payload[1], sid);
 			}
 
 			if (atomic_read(&ac->cmd_state)) {
@@ -1005,8 +1195,6 @@
 					(uint32_t *)data->payload, ac->priv);
 		apr_reset(ac->apr);
 		ac->apr = NULL;
-		reset_custom_topology_flags();
-		set_custom_topology = 1;
 		return 0;
 	}
 
@@ -2602,7 +2790,7 @@
 	int	rc = 0;
 	int	cmd_size = 0;
 
-	if (!ac || ac->apr == NULL || ac->mmap_apr == NULL) {
+	if (!ac || ac->mmap_apr == NULL) {
 		pr_err("APR handle NULL\n");
 		return -EINVAL;
 	}
@@ -2679,7 +2867,7 @@
 
 	int rc = 0;
 
-	if (!ac || ac->apr == NULL || this_mmap.apr == NULL) {
+	if (!ac || this_mmap.apr == NULL) {
 		pr_err("APR handle NULL\n");
 		return -EINVAL;
 	}
@@ -2749,7 +2937,7 @@
 	uint32_t bufcnt_t;
 	uint32_t bufsz_t;
 
-	if (!ac || ac->apr == NULL || ac->mmap_apr == NULL) {
+	if (!ac || ac->mmap_apr == NULL) {
 		pr_err("APR handle NULL\n");
 		return -EINVAL;
 	}
@@ -2848,8 +3036,7 @@
 	return rc;
 }
 
-static int q6asm_memory_unmap_regions(struct audio_client *ac, int dir,
-				uint32_t bufsz, uint32_t bufcnt)
+static int q6asm_memory_unmap_regions(struct audio_client *ac, int dir)
 {
 	struct avs_cmd_shared_mem_unmap_regions mem_unmap;
 	struct audio_port_data *port = NULL;
@@ -2859,7 +3046,7 @@
 	int	rc = 0;
 	int	cmd_size = 0;
 
-	if (!ac || ac->apr == NULL || ac->mmap_apr == NULL) {
+	if (!ac || ac->mmap_apr == NULL) {
 		pr_err("APR handle NULL\n");
 		return -EINVAL;
 	}
@@ -3849,7 +4036,7 @@
 {
 	pr_debug("%s\n", __func__);
 
-	if (session_id < 0 || session_id > SESSION_MAX) {
+	if (session_id <= 0 || session_id > SESSION_MAX) {
 		pr_err("%s: invalid session_id = %d\n", __func__, session_id);
 		return -EINVAL;
 	}
@@ -3860,10 +4047,29 @@
 
 static int __init q6asm_init(void)
 {
+	int lcnt;
 	pr_debug("%s\n", __func__);
+
 	memset(session, 0, sizeof(session));
 	set_custom_topology = 1;
 
+	/*setup common client used for cal mem map */
+	common_client.session = ASM_CONTROL_SESSION;
+	common_client.port[0].buf = &common_buf[0];
+	common_client.port[1].buf = &common_buf[1];
+	init_waitqueue_head(&common_client.cmd_wait);
+	init_waitqueue_head(&common_client.time_wait);
+	atomic_set(&common_client.time_flag, 1);
+	INIT_LIST_HEAD(&common_client.port[0].mem_map_handle);
+	INIT_LIST_HEAD(&common_client.port[1].mem_map_handle);
+	mutex_init(&common_client.cmd_lock);
+	for (lcnt = 0; lcnt <= OUT; lcnt++) {
+		mutex_init(&common_client.port[lcnt].lock);
+		spin_lock_init(&common_client.port[lcnt].dsp_lock);
+	}
+	atomic_set(&common_client.cmd_state, 0);
+	atomic_set(&common_client.nowait_cmd_cnt, 0);
+
 	config_debug_fs_init();
 
 	return 0;
diff --git a/sound/soc/msm/qdsp6v2/q6lsm.c b/sound/soc/msm/qdsp6v2/q6lsm.c
index aec048e..e8880d1 100644
--- a/sound/soc/msm/qdsp6v2/q6lsm.c
+++ b/sound/soc/msm/qdsp6v2/q6lsm.c
@@ -45,6 +45,7 @@
 	LSM_INVALID_SESSION_ID = 0,
 	LSM_MIN_SESSION_ID = 1,
 	LSM_MAX_SESSION_ID = 8,
+	LSM_CONTROL_SESSION = 0x0F,
 };
 
 struct lsm_common {
@@ -53,6 +54,7 @@
 	uint32_t lsm_cal_addr;
 	uint32_t lsm_cal_size;
 	uint32_t mmap_handle_for_cal;
+	struct lsm_client	common_client;
 	struct mutex apr_lock;
 };
 
@@ -191,7 +193,7 @@
 	return 0;
 }
 
-struct lsm_client *q6lsm_client_alloc(app_cb cb, void *priv)
+struct lsm_client *q6lsm_client_alloc(lsm_app_cb cb, void *priv)
 {
 	struct lsm_client *client;
 	int n;
@@ -269,7 +271,7 @@
 		mmap_handle_p = mmap_p;
 	}
 	atomic_set(&client->cmd_state, CMD_STATE_WAIT_RESP);
-	ret = apr_send_pkt(client->apr, data);
+	ret = apr_send_pkt(handle, data);
 	if (mmap_p)
 		spin_unlock_irqrestore(&mmap_lock, flags);
 
@@ -607,6 +609,7 @@
 		}
 		lsm_common.lsm_cal_addr = lsm_cal.cal_paddr;
 		lsm_common.lsm_cal_size = LSM_CAL_SIZE;
+		lsm_common.common_client.session = client->session;
 	}
 
 	q6lsm_add_hdr(client, &params.hdr, sizeof(params), true);
@@ -626,6 +629,51 @@
 	return rc;
 }
 
+int q6lsm_unmap_cal_blocks(void)
+{
+	int	result = 0;
+	int	result2 = 0;
+
+	if (lsm_common.mmap_handle_for_cal == 0)
+		goto done;
+
+	if (lsm_common.common_client.mmap_apr == NULL) {
+		lsm_common.common_client.mmap_apr = q6lsm_mmap_apr_reg();
+		if (lsm_common.common_client.mmap_apr == NULL) {
+			pr_err("%s: q6lsm_mmap_apr_reg failed\n",
+				__func__);
+			result = -EPERM;
+			goto done;
+		}
+	}
+
+	result2 = q6lsm_memory_unmap_regions(
+		&lsm_common.common_client,
+		lsm_common.mmap_handle_for_cal);
+	if (result2 < 0) {
+		pr_err("%s: unmap failed, err %d\n",
+			__func__, result2);
+		result = result2;
+	} else {
+		lsm_common.mmap_handle_for_cal = 0;
+	}
+
+	result2 = q6lsm_mmap_apr_dereg();
+	if (result2 < 0) {
+		pr_err("%s: q6lsm_mmap_apr_dereg failed, err %d\n",
+			__func__, result2);
+		result = result2;
+	} else {
+		lsm_common.common_client.mmap_apr = NULL;
+	}
+
+	lsm_common.lsm_cal_addr = 0;
+	lsm_common.lsm_cal_size = 0;
+
+done:
+	return result;
+}
+
 int q6lsm_snd_model_buf_free(struct lsm_client *client)
 {
 	int rc;
@@ -655,6 +703,11 @@
 	unsigned long flags;
 	struct lsm_client *client = NULL;
 
+	if (session_id == LSM_CONTROL_SESSION) {
+		client = &lsm_common.common_client;
+		goto done;
+	}
+
 	spin_lock_irqsave(&lsm_session_lock, flags);
 	if (session_id < LSM_MIN_SESSION_ID || session_id > LSM_MAX_SESSION_ID)
 		pr_err("%s: Invalid session %d\n", __func__, session_id);
@@ -663,7 +716,7 @@
 	else
 		client = lsm_session[session_id];
 	spin_unlock_irqrestore(&lsm_session_lock, flags);
-
+done:
 	return client;
 }
 
@@ -842,6 +895,12 @@
 	spin_lock_init(&lsm_session_lock);
 	spin_lock_init(&mmap_lock);
 	mutex_init(&lsm_common.apr_lock);
+
+	lsm_common.common_client.session = LSM_CONTROL_SESSION;
+	init_waitqueue_head(&lsm_common.common_client.cmd_wait);
+	mutex_init(&lsm_common.common_client.cmd_lock);
+	atomic_set(&lsm_common.common_client.cmd_state, CMD_STATE_CLEARED);
+
 	return 0;
 }
 
diff --git a/sound/soc/msm/qdsp6v2/q6voice.c b/sound/soc/msm/qdsp6v2/q6voice.c
index c863497..ae5bbbf 100644
--- a/sound/soc/msm/qdsp6v2/q6voice.c
+++ b/sound/soc/msm/qdsp6v2/q6voice.c
@@ -19,7 +19,6 @@
 #include <linux/msm_audio_ion.h>
 
 #include <asm/mach-types.h>
-#include <mach/qdsp6v2/rtac.h>
 #include <mach/socinfo.h>
 #include <mach/qdsp6v2/apr_tal.h>
 
@@ -45,6 +44,7 @@
 	VOC_TOKEN_NONE,
 	VOIP_MEM_MAP_TOKEN,
 	VOC_CAL_MEM_MAP_TOKEN,
+	VOC_RTAC_MEM_MAP_TOKEN
 };
 
 static struct common_data common;
@@ -88,6 +88,7 @@
 static int is_cal_memory_allocated(void);
 static int is_voip_memory_allocated(void);
 static int voice_alloc_cal_mem_map_table(void);
+static int voice_alloc_rtac_mem_map_table(void);
 static int voice_alloc_oob_shared_mem(void);
 static int voice_free_oob_shared_mem(void);
 static int voice_alloc_oob_mem_table(void);
@@ -1404,6 +1405,63 @@
 	return ret;
 }
 
+
+static int free_cal_map_table(void)
+{
+	int ret = 0;
+
+	if ((common.cal_mem_map_table.client == NULL) ||
+		(common.cal_mem_map_table.handle == NULL))
+		goto done;
+
+	ret = msm_audio_ion_free(common.cal_mem_map_table.client,
+		common.cal_mem_map_table.handle);
+	if (ret < 0) {
+		pr_err("%s: msm_audio_ion_free failed:\n", __func__);
+		ret = -EPERM;
+	}
+
+done:
+	common.cal_mem_map_table.client = NULL;
+	common.cal_mem_map_table.handle = NULL;
+	return ret;
+}
+
+static int is_rtac_memory_allocated(void)
+{
+	bool ret;
+
+	if (common.rtac_mem_map_table.client != NULL &&
+	    common.rtac_mem_map_table.handle != NULL)
+		ret = true;
+	else
+		ret = false;
+
+	return ret;
+}
+
+static int free_rtac_map_table(void)
+{
+	int ret = 0;
+
+	if ((common.rtac_mem_map_table.client == NULL) ||
+		(common.rtac_mem_map_table.handle == NULL))
+		goto done;
+
+	ret = msm_audio_ion_free(common.rtac_mem_map_table.client,
+		common.rtac_mem_map_table.handle);
+	if (ret < 0) {
+		pr_err("%s: msm_audio_ion_free failed:\n", __func__);
+		ret = -EPERM;
+	}
+
+done:
+	common.rtac_mem_map_table.client = NULL;
+	common.rtac_mem_map_table.handle = NULL;
+	return ret;
+}
+
+
 static int is_voip_memory_allocated(void)
 {
 	bool ret;
@@ -2439,72 +2497,6 @@
 	return ret;
 }
 
-int voc_register_vocproc_vol_table(void)
-{
-	int			result = 0;
-	int			result2 = 0;
-	int			i;
-	struct voice_data	*v = NULL;
-	pr_debug("%s\n", __func__);
-
-	mutex_lock(&common.common_lock);
-	for (i = 0; i < MAX_VOC_SESSIONS; i++) {
-		v = &common.voice[i];
-
-		mutex_lock(&v->lock);
-		if (is_voc_state_active(v->voc_state)) {
-			result2 = voice_send_cvp_register_vol_cal_cmd(v);
-			if (result2 < 0) {
-				pr_err("%s: Failed to register vocvol table for session 0x%x!\n",
-					__func__, v->session_id);
-				result = result2;
-				/* Still try to register other sessions */
-			}
-		}
-		mutex_unlock(&v->lock);
-	}
-
-	mutex_unlock(&common.common_lock);
-	return result;
-}
-
-int voc_deregister_vocproc_vol_table(void)
-{
-	int			result = 0;
-	int			success = 0;
-	int			i;
-	struct voice_data	*v = NULL;
-	pr_debug("%s\n", __func__);
-
-	mutex_lock(&common.common_lock);
-	for (i = 0; i < MAX_VOC_SESSIONS; i++) {
-		v = &common.voice[i];
-
-		mutex_lock(&v->lock);
-		if (is_voc_state_active(v->voc_state)) {
-			result = voice_send_cvp_deregister_vol_cal_cmd(v);
-			if (result < 0) {
-				pr_err("%s: Failed to deregister vocvol table for session 0x%x!\n",
-					__func__, v->session_id);
-				mutex_unlock(&v->lock);
-				mutex_unlock(&common.common_lock);
-				if (success) {
-					pr_err("%s: Try to re-register all deregistered sessions!\n",
-						__func__);
-					voc_register_vocproc_vol_table();
-				}
-				goto done;
-			} else {
-				success = 1;
-			}
-		}
-		mutex_unlock(&v->lock);
-	}
-	mutex_unlock(&common.common_lock);
-done:
-	return result;
-}
-
 static int voice_map_memory_physical_cmd(struct voice_data *v,
 					 struct mem_map_table *table_info,
 					 dma_addr_t phys,
@@ -2642,6 +2634,313 @@
 	return ret;
 }
 
+static int voice_pause_voice_call(struct voice_data *v)
+{
+	struct apr_hdr	mvm_pause_voice_cmd;
+	void		*apr_mvm;
+	int		ret = 0;
+
+	pr_debug("%s\n", __func__);
+
+	if (v == NULL) {
+		pr_err("%s: Voice data is NULL\n", __func__);
+
+		ret = -EINVAL;
+		goto done;
+	}
+
+	apr_mvm = common.apr_q6_mvm;
+	if (!apr_mvm) {
+		pr_err("%s: apr_mvm is NULL.\n", __func__);
+
+		ret = -EINVAL;
+		goto done;
+	}
+
+	mvm_pause_voice_cmd.hdr_field =
+		APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
+		APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
+	mvm_pause_voice_cmd.pkt_size =
+		APR_PKT_SIZE(APR_HDR_SIZE,
+		sizeof(mvm_pause_voice_cmd) - APR_HDR_SIZE);
+	mvm_pause_voice_cmd.src_port =
+			voice_get_idx_for_session(v->session_id);
+	mvm_pause_voice_cmd.dest_port = voice_get_mvm_handle(v);
+	mvm_pause_voice_cmd.token = 0;
+	mvm_pause_voice_cmd.opcode = VSS_IMVM_CMD_PAUSE_VOICE;
+	v->mvm_state = CMD_STATUS_FAIL;
+
+	pr_debug("%s: send mvm_pause_voice_cmd pkt size = %d\n",
+		__func__, mvm_pause_voice_cmd.pkt_size);
+
+	ret = apr_send_pkt(apr_mvm,
+		(uint32_t *)&mvm_pause_voice_cmd);
+	if (ret < 0) {
+		pr_err("Fail in sending VSS_IMVM_CMD_PAUSE_VOICE\n");
+
+		ret = -EINVAL;
+		goto done;
+	}
+
+	ret = wait_event_timeout(v->mvm_wait,
+		(v->mvm_state == CMD_STATUS_SUCCESS),
+		msecs_to_jiffies(TIMEOUT_MS));
+	if (!ret) {
+		pr_err("%s: Command timeout\n", __func__);
+
+		ret = -EINVAL;
+		goto done;
+	}
+
+done:
+	return ret;
+}
+
+int voc_register_vocproc_vol_table(void)
+{
+	int			result = 0;
+	int			result2 = 0;
+	int			i;
+	struct voice_data	*v = NULL;
+
+	pr_debug("%s\n", __func__);
+
+	mutex_lock(&common.common_lock);
+	for (i = 0; i < MAX_VOC_SESSIONS; i++) {
+		v = &common.voice[i];
+
+		mutex_lock(&v->lock);
+		if (is_voc_state_active(v->voc_state)) {
+			result2 = voice_send_cvp_register_vol_cal_cmd(v);
+			if (result2 < 0) {
+				pr_err("%s: Failed to register vocvol table for session 0x%x!\n",
+					__func__, v->session_id);
+
+				result = result2;
+				/* Still try to register other sessions */
+			}
+		}
+		mutex_unlock(&v->lock);
+	}
+
+	mutex_unlock(&common.common_lock);
+	return result;
+}
+
+int voc_deregister_vocproc_vol_table(void)
+{
+	int			result = 0;
+	int			success = 0;
+	int			i;
+	struct voice_data	*v = NULL;
+
+	pr_debug("%s\n", __func__);
+
+	mutex_lock(&common.common_lock);
+	for (i = 0; i < MAX_VOC_SESSIONS; i++) {
+		v = &common.voice[i];
+
+		mutex_lock(&v->lock);
+		if (is_voc_state_active(v->voc_state)) {
+			result = voice_send_cvp_deregister_vol_cal_cmd(v);
+			if (result < 0) {
+				pr_err("%s: Failed to deregister vocvol table for session 0x%x!\n",
+					__func__, v->session_id);
+
+				mutex_unlock(&v->lock);
+				mutex_unlock(&common.common_lock);
+				if (success) {
+					pr_err("%s: Try to re-register all deregistered sessions!\n",
+						__func__);
+
+					voc_register_vocproc_vol_table();
+				}
+				goto done;
+			} else {
+				success = 1;
+			}
+		}
+		mutex_unlock(&v->lock);
+	}
+	mutex_unlock(&common.common_lock);
+done:
+	return result;
+}
+
+int voc_map_rtac_block(struct rtac_cal_block_data *cal_block)
+{
+	int			result = 0;
+	struct voice_data	*v = NULL;
+
+	pr_debug("%s\n", __func__);
+
+	if (cal_block == NULL) {
+		pr_err("%s: cal_block is NULL!\n",
+			__func__);
+
+		result = -EINVAL;
+		goto done;
+	}
+
+	if (cal_block->cal_data.paddr == 0) {
+		pr_debug("%s: No address to map!\n",
+			__func__);
+
+		result = -EINVAL;
+		goto done;
+	}
+
+	if (cal_block->map_data.map_size == 0) {
+		pr_debug("%s: map size is 0!\n",
+			__func__);
+
+		result = -EINVAL;
+		goto done;
+	}
+
+	mutex_lock(&common.common_lock);
+	/* use first session */
+	v = &common.voice[0];
+	mutex_lock(&v->lock);
+
+	if (!is_rtac_memory_allocated()) {
+		result = voice_alloc_rtac_mem_map_table();
+		if (result < 0) {
+			pr_err("%s: RTAC alloc mem map table did not work! addr = 0x%x, size = %d\n",
+				__func__, cal_block->cal_data.paddr,
+				cal_block->map_data.map_size);
+
+			goto err;
+		}
+	}
+
+	result = voice_map_memory_physical_cmd(v,
+		&common.rtac_mem_map_table,
+		(dma_addr_t)cal_block->cal_data.paddr,
+		cal_block->map_data.map_size,
+		VOC_RTAC_MEM_MAP_TOKEN);
+	if (result < 0) {
+		pr_err("%s: RTAC mmap did not work! addr = 0x%x, size = %d\n",
+			__func__, cal_block->cal_data.paddr,
+			cal_block->map_data.map_size);
+
+		free_rtac_map_table();
+		goto err;
+	}
+
+	cal_block->map_data.map_handle = common.rtac_mem_handle;
+err:
+	mutex_unlock(&v->lock);
+	mutex_unlock(&common.common_lock);
+done:
+	return result;
+}
+
+int voc_unmap_rtac_block(uint32_t *mem_map_handle)
+{
+	int			result = 0;
+	struct voice_data	*v = NULL;
+
+	pr_debug("%s\n", __func__);
+
+	if (mem_map_handle == NULL) {
+		pr_debug("%s: Map handle is NULL, nothing to unmap\n",
+			__func__);
+
+		goto done;
+	}
+
+	if (*mem_map_handle == 0) {
+		pr_debug("%s: Map handle is 0, nothing to unmap\n",
+			__func__);
+
+		goto done;
+	}
+
+	mutex_lock(&common.common_lock);
+	/* use first session */
+	v = &common.voice[0];
+	mutex_lock(&v->lock);
+
+	result = voice_send_mvm_unmap_memory_physical_cmd(
+			v, *mem_map_handle);
+	if (result) {
+		pr_err("%s: voice_send_mvm_unmap_memory_physical_cmd Failed for session 0x%x!\n",
+			__func__, v->session_id);
+	} else {
+		*mem_map_handle = 0;
+		common.rtac_mem_handle = 0;
+		free_rtac_map_table();
+	}
+	mutex_unlock(&v->lock);
+	mutex_unlock(&common.common_lock);
+done:
+	return result;
+}
+
+int voc_unmap_cal_blocks(void)
+{
+	int			result = 0;
+	int			result2 = 0;
+	int			i;
+	struct voice_data	*v = NULL;
+
+	pr_debug("%s\n", __func__);
+
+	mutex_lock(&common.common_lock);
+
+	if (common.cal_mem_handle == 0)
+		goto done;
+
+	for (i = 0; i < MAX_VOC_SESSIONS; i++) {
+		v = &common.voice[i];
+
+		mutex_lock(&v->lock);
+		if (is_voc_state_active(v->voc_state)) {
+			result2 = voice_pause_voice_call(v);
+			if (result2 < 0) {
+				pr_err("%s: voice_pause_voice_call failed for session 0x%x, err %d!\n",
+					__func__, v->session_id, result2);
+
+				result = result2;
+			}
+
+			voice_send_cvp_deregister_vol_cal_cmd(v);
+			voice_send_cvp_deregister_cal_cmd(v);
+			voice_send_cvp_deregister_dev_cfg_cmd(v);
+			voice_send_cvs_deregister_cal_cmd(v);
+
+			result2 = voice_send_start_voice_cmd(v);
+			if (result2) {
+				pr_err("%s: voice_send_start_voice_cmd failed for session 0x%x, err %d!\n",
+					__func__, v->session_id, result2);
+
+				result = result2;
+			}
+		}
+
+		if ((common.cal_mem_handle != 0) &&
+			(!is_other_session_active(v->session_id))) {
+
+			result2 = voice_send_mvm_unmap_memory_physical_cmd(
+				v, common.cal_mem_handle);
+			if (result2) {
+				pr_err("%s: voice_send_mvm_unmap_memory_physical_cmd failed for session 0x%x, err %d!\n",
+					__func__, v->session_id, result2);
+
+				result = result2;
+			} else {
+				common.cal_mem_handle = 0;
+				free_cal_map_table();
+			}
+		}
+		mutex_unlock(&v->lock);
+	}
+done:
+	mutex_unlock(&common.common_lock);
+	return result;
+}
+
 static int voice_setup_vocproc(struct voice_data *v)
 {
 	struct cvp_create_full_ctl_session_cmd cvp_session_cmd;
@@ -3112,7 +3411,6 @@
 	voice_send_cvp_deregister_vol_cal_cmd(v);
 	voice_send_cvp_deregister_cal_cmd(v);
 	voice_send_cvp_deregister_dev_cfg_cmd(v);
-
 	voice_send_cvs_deregister_cal_cmd(v);
 
 	/* destrop cvp session */
@@ -4671,6 +4969,8 @@
 
 			/* clean up memory handle */
 			c->cal_mem_handle = 0;
+			c->rtac_mem_handle = 0;
+			rtac_clear_mapping(VOICE_RTAC_CAL);
 
 			/* Sub-system restart is applicable to all sessions. */
 			for (i = 0; i < MAX_VOC_SESSIONS; i++) {
@@ -4729,6 +5029,7 @@
 			case VSS_IMVM_CMD_SET_CAL_MEDIA_TYPE:
 			case VSS_IMEMORY_CMD_MAP_PHYSICAL:
 			case VSS_IMEMORY_CMD_UNMAP:
+			case VSS_IMVM_CMD_PAUSE_VOICE:
 			case VSS_IMVM_CMD_STANDBY_VOICE:
 				pr_debug("%s: cmd = 0x%x\n", __func__, ptr[0]);
 				v->mvm_state = CMD_STATUS_SUCCESS;
@@ -4764,6 +5065,18 @@
 				v->mvm_state = CMD_STATUS_SUCCESS;
 				wake_up(&v->mvm_wait);
 			}
+		} else if (data->payload_size &&
+				data->token == VOC_RTAC_MEM_MAP_TOKEN) {
+			ptr = data->payload;
+			if (ptr[0]) {
+				c->rtac_mem_handle = ptr[0];
+
+				pr_debug("%s: cal mem handle 0x%x\n",
+					 __func__, c->rtac_mem_handle);
+
+				v->mvm_state = CMD_STATUS_SUCCESS;
+				wake_up(&v->mvm_wait);
+			}
 		} else {
 			pr_err("%s: Unknown mem map token %d\n",
 			       __func__, data->token);
@@ -4921,8 +5234,10 @@
 
 		cvs_voc_pkt = v->shmem_info.sh_buf.buf[1].data;
 		if (cvs_voc_pkt != NULL &&  common.mvs_info.ul_cb != NULL) {
+			/* cvs_voc_pkt[0] contains tx timestamp */
 			common.mvs_info.ul_cb((uint8_t *)&cvs_voc_pkt[3],
 					      cvs_voc_pkt[2],
+					      cvs_voc_pkt[0],
 					      common.mvs_info.private_data);
 		} else
 			pr_err("%s: cvs_voc_pkt or ul_cb is NULL\n", __func__);
@@ -5316,6 +5631,33 @@
 	return ret;
 }
 
+static int voice_alloc_rtac_mem_map_table(void)
+{
+	int ret = 0;
+	int len;
+
+	ret = msm_audio_ion_alloc("voc_rtac_cal",
+			&(common.rtac_mem_map_table.client),
+			&(common.rtac_mem_map_table.handle),
+			sizeof(struct vss_imemory_table_t),
+			(ion_phys_addr_t *)&common.rtac_mem_map_table.phys,
+			(size_t *) &len,
+			&(common.rtac_mem_map_table.data));
+	if (ret < 0) {
+		pr_err("%s: audio ION alloc failed, rc = %d\n",
+			__func__, ret);
+		goto done;
+	}
+
+	common.rtac_mem_map_table.size = sizeof(struct vss_imemory_table_t);
+	pr_debug("%s: data 0x%x phys 0x%x\n", __func__,
+		 (unsigned int) common.rtac_mem_map_table.data,
+		 common.rtac_mem_map_table.phys);
+
+done:
+	return ret;
+}
+
 static int voice_alloc_and_map_cal_mem(struct voice_data *v)
 {
 	int ret = 0;
diff --git a/sound/soc/msm/qdsp6v2/q6voice.h b/sound/soc/msm/qdsp6v2/q6voice.h
index 20f2857..798391d 100644
--- a/sound/soc/msm/qdsp6v2/q6voice.h
+++ b/sound/soc/msm/qdsp6v2/q6voice.h
@@ -13,6 +13,7 @@
 #define __QDSP6VOICE_H__
 
 #include <mach/qdsp6v2/apr.h>
+#include <mach/qdsp6v2/rtac.h>
 #include <linux/msm_ion.h>
 #include <sound/voice_params.h>
 
@@ -186,6 +187,9 @@
 #define VSS_IMVM_CMD_STOP_VOICE				0x00011192
 /**< No payload. Wait for APRV2_IBASIC_RSP_RESULT response. */
 
+#define VSS_IMVM_CMD_PAUSE_VOICE			0x0001137D
+/* No payload. Wait for APRV2_IBASIC_RSP_RESULT response. */
+
 #define VSS_ISTREAM_CMD_ATTACH_VOCPROC			0x000110F8
 /**< Wait for APRV2_IBASIC_RSP_RESULT response. */
 
@@ -1207,6 +1211,7 @@
 /* CB for up-link packets. */
 typedef void (*ul_cb_fn)(uint8_t *voc_pkt,
 			 uint32_t pkt_len,
+			 uint32_t timestamp,
 			 void *private_data);
 
 /* CB for down-link packets. */
@@ -1328,6 +1333,10 @@
 
 	struct mem_map_table cal_mem_map_table;
 	uint32_t cal_mem_handle;
+
+	struct mem_map_table rtac_mem_map_table;
+	uint32_t rtac_mem_handle;
+
 	struct cal_mem cvp_cal;
 	struct cal_mem cvs_cal;
 
@@ -1437,6 +1446,10 @@
 int voc_register_vocproc_vol_table(void);
 int voc_deregister_vocproc_vol_table(void);
 
+int voc_unmap_cal_blocks(void);
+int voc_map_rtac_block(struct rtac_cal_block_data *cal_block);
+int voc_unmap_rtac_block(uint32_t *mem_map_handle);
+
 uint32_t voc_get_session_id(char *name);
 
 int voc_start_playback(uint32_t set, uint16_t port_id);
diff --git a/sound/soc/msm/qdsp6v2/rtac.c b/sound/soc/msm/qdsp6v2/rtac.c
index a4983d3..ee21112 100644
--- a/sound/soc/msm/qdsp6v2/rtac.c
+++ b/sound/soc/msm/qdsp6v2/rtac.c
@@ -20,6 +20,7 @@
 #include <linux/sched.h>
 #include <linux/msm_audio_acdb.h>
 #include <linux/atomic.h>
+#include <linux/msm_audio_ion.h>
 #include <mach/qdsp6v2/rtac.h>
 #include <sound/q6asm-v2.h>
 #include <sound/q6afe-v2.h>
@@ -53,10 +54,26 @@
 #define RTAC_MAX_ACTIVE_DEVICES		4
 #define RTAC_MAX_ACTIVE_VOICE_COMBOS	2
 #define RTAC_MAX_ACTIVE_POPP		8
-#define RTAC_BUF_SIZE			4096
+#define RTAC_BUF_SIZE			8192
 
 #define TIMEOUT_MS	1000
 
+struct rtac_cal_block_data	rtac_cal[MAX_RTAC_BLOCKS] = {
+/* ADM_RTAC_CAL */
+	{{RTAC_BUF_SIZE, 0, 0, 0}, {0, 0, 0} },
+/* ASM_RTAC_CAL */
+	{{RTAC_BUF_SIZE, 0, 0, 0}, {0, 0, 0} },
+/* VOICE_RTAC_CAL */
+	{{RTAC_BUF_SIZE, 0, 0, 0}, {0, 0, 0} }
+};
+
+struct rtac_common_data {
+	atomic_t			usage_count;
+	atomic_t			apr_err_code;
+};
+
+static struct rtac_common_data		rtac_common;
+
 /* APR data */
 struct rtac_apr_data {
 	void			*apr_handle;
@@ -83,15 +100,11 @@
 	struct rtac_adm_data	device[RTAC_MAX_ACTIVE_DEVICES];
 };
 static struct rtac_adm		rtac_adm_data;
-static u32			rtac_adm_payload_size;
-static u32			rtac_adm_user_buf_size;
-static u8			*rtac_adm_buffer;
+static u32			*rtac_adm_buffer;
 
 
 /* ASM APR */
-static u32			rtac_asm_payload_size;
-static u32			rtac_asm_user_buf_size;
-static u8			*rtac_asm_buffer;
+static u32			*rtac_asm_buffer;
 
 
 /* Voice info & APR */
@@ -110,9 +123,7 @@
 };
 
 static struct rtac_voice	rtac_voice_data;
-static u32			rtac_voice_payload_size;
-static u32			rtac_voice_user_buf_size;
-static u8			*rtac_voice_buffer;
+static u32			*rtac_voice_buffer;
 static u32			voice_session_id[RTAC_MAX_ACTIVE_VOICE_COMBOS];
 
 
@@ -122,16 +133,227 @@
 struct mutex			rtac_voice_mutex;
 struct mutex			rtac_voice_apr_mutex;
 
+int rtac_clear_mapping(uint32_t cal_type)
+{
+	int result = 0;
+	pr_debug("%s\n", __func__);
+
+	if (cal_type >= MAX_RTAC_BLOCKS) {
+		pr_debug("%s: invalid cal type %d\n", __func__, cal_type);
+		result = -EINVAL;
+		goto done;
+	}
+
+	rtac_cal[cal_type].map_data.map_handle = 0;
+done:
+	return result;
+}
+
+int rtac_allocate_cal_buffer(uint32_t cal_type)
+{
+	int result = 0;
+	int len;
+	pr_debug("%s\n", __func__);
+
+	if (cal_type >= MAX_RTAC_BLOCKS) {
+		pr_err("%s: cal_type %d is invalid!\n",
+		       __func__, cal_type);
+		result =  -EINVAL;
+		goto done;
+	}
+
+	if (rtac_cal[cal_type].cal_data.paddr != 0) {
+		pr_err("%s: memory already allocated! cal_type %d, paddr 0x%x\n",
+		       __func__, cal_type, rtac_cal[cal_type].cal_data.paddr);
+		result = -EPERM;
+		goto done;
+	}
+
+	result = msm_audio_ion_alloc("rtac_client",
+		&rtac_cal[cal_type].map_data.ion_client,
+		&rtac_cal[cal_type].map_data.ion_handle,
+		rtac_cal[cal_type].map_data.map_size,
+		(ion_phys_addr_t *)&rtac_cal[cal_type].cal_data.paddr,
+		(size_t *)&len,
+		(void **)&rtac_cal[cal_type].cal_data.kvaddr);
+	if (result < 0) {
+		pr_err("%s: ION create client for RTAC failed\n",
+		       __func__);
+		goto done;
+	}
+
+	pr_debug("%s: cal_type %d, paddr 0x%x, kvaddr 0x%x, map_size 0x%x\n",
+		__func__, cal_type,
+		rtac_cal[cal_type].cal_data.paddr,
+		rtac_cal[cal_type].cal_data.kvaddr,
+		rtac_cal[cal_type].map_data.map_size);
+done:
+	return result;
+}
+
+int rtac_free_cal_buffer(uint32_t cal_type)
+{
+	int result = 0;
+	pr_debug("%s\n", __func__);
+
+	if (cal_type >= MAX_RTAC_BLOCKS) {
+		pr_err("%s: cal_type %d is invalid!\n",
+		       __func__, cal_type);
+		result =  -EINVAL;
+		goto done;
+	}
+
+	if (rtac_cal[cal_type].map_data.ion_client == NULL) {
+		pr_debug("%s: cal_type %d not allocated!\n",
+		       __func__, cal_type);
+		goto done;
+	}
+
+	result = msm_audio_ion_free(rtac_cal[cal_type].map_data.ion_client,
+				rtac_cal[cal_type].map_data.ion_handle);
+	if (result < 0) {
+		pr_err("%s: ION free for RTAC failed! cal_type %d, paddr 0x%x\n",
+		       __func__, cal_type, rtac_cal[cal_type].cal_data.paddr);
+		goto done;
+	}
+
+	rtac_cal[cal_type].map_data.map_handle = 0;
+	rtac_cal[cal_type].map_data.ion_client = NULL;
+	rtac_cal[cal_type].map_data.ion_handle = NULL;
+	rtac_cal[cal_type].cal_data.size = 0;
+	rtac_cal[cal_type].cal_data.kvaddr = 0;
+	rtac_cal[cal_type].cal_data.paddr = 0;
+done:
+	return result;
+}
+
+int rtac_map_cal_buffer(uint32_t cal_type)
+{
+	int result = 0;
+	pr_debug("%s\n", __func__);
+
+	if (cal_type >= MAX_RTAC_BLOCKS) {
+		pr_err("%s: cal_type %d is invalid!\n",
+		       __func__, cal_type);
+		result =  -EINVAL;
+		goto done;
+	}
+
+	if (rtac_cal[cal_type].map_data.map_handle != 0) {
+		pr_err("%s: already mapped cal_type %d\n",
+			__func__, cal_type);
+		result =  -EPERM;
+		goto done;
+	}
+
+	if (rtac_cal[cal_type].cal_data.paddr == 0) {
+		pr_err("%s: physical address is NULL cal_type %d\n",
+			__func__, cal_type);
+		result =  -EPERM;
+		goto done;
+	}
+
+	switch (cal_type) {
+	case ADM_RTAC_CAL:
+		result = adm_map_rtac_block(&rtac_cal[cal_type]);
+		break;
+	case ASM_RTAC_CAL:
+		result = q6asm_map_rtac_block(&rtac_cal[cal_type]);
+		break;
+	case VOICE_RTAC_CAL:
+		result = voc_map_rtac_block(&rtac_cal[cal_type]);
+		break;
+	}
+	if (result < 0) {
+		pr_err("%s: map RTAC failed! cal_type %d\n",
+		       __func__, cal_type);
+		goto done;
+	}
+done:
+	return result;
+}
+
+int rtac_unmap_cal_buffer(uint32_t cal_type)
+{
+	int result = 0;
+	pr_debug("%s\n", __func__);
+
+	if (cal_type >= MAX_RTAC_BLOCKS) {
+		pr_err("%s: cal_type %d is invalid!\n",
+		       __func__, cal_type);
+		result =  -EINVAL;
+		goto done;
+	}
+
+	if (rtac_cal[cal_type].map_data.map_handle == 0) {
+		pr_debug("%s: nothing to unmap cal_type %d\n",
+			__func__, cal_type);
+		goto done;
+	}
+
+	switch (cal_type) {
+	case ADM_RTAC_CAL:
+		result = adm_unmap_rtac_block(
+			&rtac_cal[cal_type].map_data.map_handle);
+		break;
+	case ASM_RTAC_CAL:
+		result = q6asm_unmap_rtac_block(
+			&rtac_cal[cal_type].map_data.map_handle);
+		break;
+	case VOICE_RTAC_CAL:
+		result = voc_unmap_rtac_block(
+			&rtac_cal[cal_type].map_data.map_handle);
+		break;
+	}
+	if (result < 0) {
+		pr_err("%s: unmap RTAC failed! cal_type %d\n",
+		       __func__, cal_type);
+		goto done;
+	}
+done:
+	return result;
+}
+
 static int rtac_open(struct inode *inode, struct file *f)
 {
+	int	result = 0;
 	pr_debug("%s\n", __func__);
-	return 0;
+
+	atomic_inc(&rtac_common.usage_count);
+	return result;
 }
 
 static int rtac_release(struct inode *inode, struct file *f)
 {
+	int	result = 0;
+	int	result2 = 0;
+	int	i;
 	pr_debug("%s\n", __func__);
-	return 0;
+
+	atomic_dec(&rtac_common.usage_count);
+	pr_debug("%s: ref count %d!\n", __func__,
+		atomic_read(&rtac_common.usage_count));
+
+	if (atomic_read(&rtac_common.usage_count) > 0)
+		goto done;
+
+	for (i = 0; i < MAX_RTAC_BLOCKS; i++) {
+		result2 = rtac_unmap_cal_buffer(i);
+		if (result2 < 0) {
+			pr_err("%s: unmap buffer failed! error %d!\n",
+				__func__, result2);
+			result = result2;
+		}
+
+		result2 = rtac_free_cal_buffer(i);
+		if (result2 < 0) {
+			pr_err("%s: free buffer failed! error %d!\n",
+				__func__, result2);
+			result = result2;
+		}
+	}
+done:
+	return result;
 }
 
 /* ADM Info */
@@ -412,52 +634,56 @@
 	if (atomic_read(&rtac_adm_apr_data.cmd_state) != 1)
 		return false;
 
-	/* Offset data for in-band payload */
-	rtac_copy_adm_payload_to_user(payload, payload_size);
+	pr_debug("%s\n", __func__);
+	if (payload_size == sizeof(uint32_t))
+		atomic_set(&rtac_common.apr_err_code, payload[0]);
+	else if (payload_size == (2*sizeof(uint32_t)))
+		atomic_set(&rtac_common.apr_err_code, payload[1]);
+
 	atomic_set(&rtac_adm_apr_data.cmd_state, 0);
 	wake_up(&rtac_adm_apr_data.cmd_wait);
 	return true;
 }
 
-void rtac_copy_adm_payload_to_user(void *payload, u32 payload_size)
-{
-	pr_debug("%s\n", __func__);
-	rtac_adm_payload_size = payload_size;
-
-	memcpy(rtac_adm_buffer, &payload_size, sizeof(u32));
-	if (payload_size != 0) {
-		if (payload_size > rtac_adm_user_buf_size) {
-			pr_err("%s: Buffer set not big enough for returned data, buf size = %d, ret data = %d\n",
-			 __func__, rtac_adm_user_buf_size, payload_size);
-			rtac_adm_payload_size = 0;
-			goto done;
-		}
-		memcpy(rtac_adm_buffer + sizeof(u32), payload, payload_size);
-	}
-done:
-	return;
-}
-
 u32 send_adm_apr(void *buf, u32 opcode)
 {
 	s32	result;
-	u32	count = 0;
+	u32	user_buf_size = 0;
 	u32	bytes_returned = 0;
 	u32	port_index = 0;
 	u32	copp_id;
 	u32	payload_size;
+	u32	data_size = 0;
 	struct apr_hdr	adm_params;
 	pr_debug("%s\n", __func__);
 
-	if (copy_from_user(&count, (void *)buf, sizeof(count))) {
-		pr_err("%s: Copy to user failed! buf = 0x%x\n",
-		       __func__, (unsigned int)buf);
-		result = -EFAULT;
-		goto done;
+	if (rtac_cal[ADM_RTAC_CAL].map_data.ion_handle == NULL) {
+		result = rtac_allocate_cal_buffer(ADM_RTAC_CAL);
+		if (result < 0) {
+			pr_err("%s: allocate buffer failed!",
+				__func__);
+			goto done;
+		}
 	}
 
-	if (count <= 0) {
-		pr_err("%s: Invalid buffer size = %d\n", __func__, count);
+	if (rtac_cal[ADM_RTAC_CAL].map_data.map_handle == 0) {
+		result = rtac_map_cal_buffer(ADM_RTAC_CAL);
+		if (result < 0) {
+			pr_err("%s: map buffer failed!",
+				__func__);
+			goto done;
+		}
+	}
+
+	if (copy_from_user(&user_buf_size, (void *)buf,
+						sizeof(user_buf_size))) {
+		pr_err("%s: Copy from user failed! buf = 0x%x\n",
+		       __func__, (unsigned int)buf);
+		goto done;
+	}
+	if (user_buf_size <= 0) {
+		pr_err("%s: Invalid buffer size = %d\n",
+			__func__, user_buf_size);
 		goto done;
 	}
 
@@ -467,13 +693,6 @@
 		goto done;
 	}
 
-
-	if (payload_size > MAX_PAYLOAD_SIZE) {
-		pr_err("%s: Invalid payload size = %d\n",
-			__func__, payload_size);
-		goto done;
-	}
-
 	if (copy_from_user(&copp_id, buf + 2 * sizeof(u32), sizeof(u32))) {
 		pr_err("%s: Could not copy port id from user buffer\n",
 			__func__);
@@ -496,15 +715,42 @@
 		goto err;
 	}
 
-	/* Set globals for copy of returned payload */
-	rtac_adm_user_buf_size = count;
+	if (opcode == ADM_CMD_SET_PP_PARAMS_V5) {
+		/* set payload size to in-band payload */
+		/* set data size to actual out of band payload size */
+		data_size = payload_size - 4 * sizeof(u32);
+		if (data_size > rtac_cal[ADM_RTAC_CAL].map_data.map_size) {
+			pr_err("%s: Invalid data size = %d\n",
+				__func__, data_size);
+			goto done;
+		}
+		payload_size = 4 * sizeof(u32);
 
-	/* Copy buffer to in-band payload */
-	if (copy_from_user(rtac_adm_buffer + sizeof(adm_params),
-			buf + 3 * sizeof(u32), payload_size)) {
-		pr_err("%s: Could not copy payload from user buffer\n",
-			__func__);
-		goto err;
+		/* Copy buffer to out-of-band payload */
+		if (copy_from_user((void *)
+				rtac_cal[ADM_RTAC_CAL].cal_data.kvaddr,
+				buf + 7 * sizeof(u32), data_size)) {
+			pr_err("%s: Could not copy payload from user buffer\n",
+				__func__);
+			goto err;
+		}
+		/* set payload size in packet */
+		rtac_adm_buffer[8] = data_size;
+	} else {
+		if (payload_size > MAX_PAYLOAD_SIZE) {
+			pr_err("%s: Invalid payload size = %d\n",
+				__func__, payload_size);
+			goto done;
+		}
+
+		/* Copy buffer to in-band payload */
+		if (copy_from_user(rtac_adm_buffer +
+				sizeof(adm_params)/sizeof(u32),
+				buf + 3 * sizeof(u32), payload_size)) {
+			pr_err("%s: Could not copy payload from user buffer\n",
+				__func__);
+			goto err;
+		}
 	}
 
 	/* Pack header */
@@ -521,14 +767,20 @@
 	adm_params.token = copp_id;
 	adm_params.opcode = opcode;
 
+	/* fill for out-of-band */
+	rtac_adm_buffer[5] = rtac_cal[ADM_RTAC_CAL].cal_data.paddr;
+	rtac_adm_buffer[6] = 0;
+	rtac_adm_buffer[7] = rtac_cal[ADM_RTAC_CAL].map_data.map_handle;
+
 	memcpy(rtac_adm_buffer, &adm_params, sizeof(adm_params));
 	atomic_set(&rtac_adm_apr_data.cmd_state, 1);
 
-	pr_debug("%s: Sending RTAC command size = %d\n",
-		__func__, adm_params.pkt_size);
+	pr_debug("%s: Sending RTAC command ioctl 0x%x, paddr 0x%x\n",
+		__func__, opcode,
+		rtac_cal[ADM_RTAC_CAL].cal_data.paddr);
 
 	result = apr_send_pkt(rtac_adm_apr_data.apr_handle,
-		(uint32_t *)rtac_adm_buffer);
+					(uint32_t *)rtac_adm_buffer);
 	if (result < 0) {
 		pr_err("%s: Set params failed port = %d, copp = %d\n",
 			__func__, port_index, copp_id);
@@ -544,21 +796,34 @@
 			__func__, port_index, copp_id);
 		goto done;
 	}
-
-	if (rtac_adm_payload_size != 0) {
-		if (copy_to_user(buf, rtac_adm_buffer,
-			rtac_adm_payload_size + sizeof(u32))) {
-			pr_err("%s: Could not copy buffer to user,size = %d\n",
-				__func__, payload_size);
-			goto done;
-		}
+	if (atomic_read(&rtac_common.apr_err_code)) {
+		pr_err("%s: DSP returned error code = %d, opcode = 0x%x\n",
+			__func__, atomic_read(&rtac_common.apr_err_code),
+			opcode);
+		goto done;
 	}
 
-	/* Return data written for SET & data read for GET */
-	if (opcode == ADM_CMD_GET_PP_PARAMS_V5)
-		bytes_returned = rtac_adm_payload_size;
-	else
-		bytes_returned = payload_size;
+	if (opcode == ADM_CMD_GET_PP_PARAMS_V5) {
+		bytes_returned = ((u32 *)rtac_cal[ADM_RTAC_CAL].cal_data.
+			kvaddr)[2] + 3 * sizeof(u32);
+
+		if (bytes_returned > user_buf_size) {
+			pr_err("%s: User buf not big enough, size = 0x%x, returned size = 0x%x\n",
+				__func__, user_buf_size, bytes_returned);
+			goto done;
+		}
+
+		if (copy_to_user(buf, (void *)
+				rtac_cal[ADM_RTAC_CAL].cal_data.kvaddr,
+				bytes_returned)) {
+			pr_err("%s: Could not copy buffer to user,size = %d\n",
+				__func__, bytes_returned);
+			goto done;
+		}
+	} else {
+		bytes_returned = data_size;
+	}
+
 done:
 	return bytes_returned;
 err:
@@ -584,51 +849,54 @@
 		return false;
 
 	pr_debug("%s\n", __func__);
-	/* Offset data for in-band payload */
-	rtac_copy_asm_payload_to_user(payload, payload_size);
+	if (payload_size == sizeof(uint32_t))
+		atomic_set(&rtac_common.apr_err_code, payload[0]);
+	else if (payload_size == (2*sizeof(uint32_t)))
+		atomic_set(&rtac_common.apr_err_code, payload[1]);
+
 	atomic_set(&rtac_asm_apr_data[session_id].cmd_state, 0);
 	wake_up(&rtac_asm_apr_data[session_id].cmd_wait);
 	return true;
 }
 
-void rtac_copy_asm_payload_to_user(void *payload, u32 payload_size)
-{
-	pr_debug("%s\n", __func__);
-	rtac_asm_payload_size = payload_size;
-
-	memcpy(rtac_asm_buffer, &payload_size, sizeof(u32));
-	if (payload_size) {
-		if (payload_size > rtac_asm_user_buf_size) {
-			pr_err("%s: Buffer set not big enough for returned data, buf size = %d, ret data = %d\n",
-			 __func__, rtac_asm_user_buf_size, payload_size);
-			rtac_asm_payload_size = 0;
-			goto done;
-		}
-		memcpy(rtac_asm_buffer + sizeof(u32), payload, payload_size);
-	}
-done:
-	return;
-}
-
 u32 send_rtac_asm_apr(void *buf, u32 opcode)
 {
 	s32	result;
-	u32	count = 0;
+	u32	user_buf_size = 0;
 	u32	bytes_returned = 0;
 	u32	session_id = 0;
 	u32	payload_size;
+	u32	data_size = 0;
 	struct apr_hdr		asm_params;
 	pr_debug("%s\n", __func__);
 
-	if (copy_from_user(&count, (void *)buf, sizeof(count))) {
-		pr_err("%s: Copy to user failed! buf = 0x%x\n",
-		       __func__, (unsigned int)buf);
-		result = -EFAULT;
-		goto done;
+	if (rtac_cal[ASM_RTAC_CAL].map_data.ion_handle == NULL) {
+		result = rtac_allocate_cal_buffer(ASM_RTAC_CAL);
+		if (result < 0) {
+			pr_err("%s: allocate buffer failed!",
+				__func__);
+			goto done;
+		}
 	}
 
-	if (count <= 0) {
-		pr_err("%s: Invalid buffer size = %d\n", __func__, count);
+	if (rtac_cal[ASM_RTAC_CAL].map_data.map_handle == 0) {
+		result = rtac_map_cal_buffer(ASM_RTAC_CAL);
+		if (result < 0) {
+			pr_err("%s: map buffer failed!",
+				__func__);
+			goto done;
+		}
+	}
+
+	if (copy_from_user(&user_buf_size, (void *)buf,
+						sizeof(user_buf_size))) {
+		pr_err("%s: Copy from user failed! buf = 0x%x\n",
+		       __func__, (unsigned int)buf);
+		goto done;
+	}
+	if (user_buf_size <= 0) {
+		pr_err("%s: Invalid buffer size = %d\n",
+			__func__, user_buf_size);
 		goto done;
 	}
 
@@ -638,40 +906,59 @@
 		goto done;
 	}
 
-	if (payload_size > MAX_PAYLOAD_SIZE) {
-		pr_err("%s: Invalid payload size = %d\n",
-			__func__, payload_size);
-		goto done;
-	}
-
 	if (copy_from_user(&session_id, buf + 2 * sizeof(u32), sizeof(u32))) {
 		pr_err("%s: Could not copy session id from user buffer\n",
 			__func__);
 		goto done;
 	}
-
-	if (session_id > (SESSION_MAX + 1)) {
+	if (session_id >= (SESSION_MAX + 1)) {
 		pr_err("%s: Invalid Session = %d\n", __func__, session_id);
 		goto done;
 	}
 
 	mutex_lock(&rtac_asm_apr_mutex);
-	if (session_id < SESSION_MAX+1) {
-		if (rtac_asm_apr_data[session_id].apr_handle == NULL) {
-			pr_err("%s: APR not initialized\n", __func__);
-			goto err;
-		}
+	if (rtac_asm_apr_data[session_id].apr_handle == NULL) {
+		pr_err("%s: APR not initialized\n", __func__);
+		goto err;
 	}
 
-	/* Set globals for copy of returned payload */
-	rtac_asm_user_buf_size = count;
+	if (opcode == ASM_STREAM_CMD_SET_PP_PARAMS_V2) {
+		/* set payload size to in-band payload */
+		/* set data size to actual out of band payload size */
+		data_size = payload_size - 4 * sizeof(u32);
+		if (data_size > rtac_cal[ASM_RTAC_CAL].map_data.map_size) {
+			pr_err("%s: Invalid data size = %d\n",
+				__func__, data_size);
+			goto done;
+		}
+		payload_size = 4 * sizeof(u32);
 
-	/* Copy buffer to in-band payload */
-	if (copy_from_user(rtac_asm_buffer + sizeof(asm_params),
-			buf + 3 * sizeof(u32), payload_size)) {
-		pr_err("%s: Could not copy payload from user buffer\n",
-			__func__);
-		goto err;
+		/* Copy buffer to out-of-band payload */
+		if (copy_from_user((void *)
+				rtac_cal[ASM_RTAC_CAL].cal_data.kvaddr,
+				buf + 7 * sizeof(u32), data_size)) {
+			pr_err("%s: Could not copy payload from user buffer\n",
+				__func__);
+			goto err;
+		}
+		/* set payload size in packet */
+		rtac_asm_buffer[8] = data_size;
+
+	} else {
+		if (payload_size > MAX_PAYLOAD_SIZE) {
+			pr_err("%s: Invalid payload size = %d\n",
+				__func__, payload_size);
+			goto done;
+		}
+
+		/* Copy buffer to in-band payload */
+		if (copy_from_user(rtac_asm_buffer +
+				sizeof(asm_params)/sizeof(u32),
+				buf + 3 * sizeof(u32), payload_size)) {
+			pr_err("%s: Could not copy payload from user buffer\n",
+				__func__);
+			goto err;
+		}
 	}
 
 	/* Pack header */
@@ -688,12 +975,17 @@
 	asm_params.token = session_id;
 	asm_params.opcode = opcode;
 
-	memcpy(rtac_asm_buffer, &asm_params, sizeof(asm_params));
-	if (session_id < SESSION_MAX+1)
-		atomic_set(&rtac_asm_apr_data[session_id].cmd_state, 1);
+	/* fill for out-of-band */
+	rtac_asm_buffer[5] = rtac_cal[ASM_RTAC_CAL].cal_data.paddr;
+	rtac_asm_buffer[6] = 0;
+	rtac_asm_buffer[7] = rtac_cal[ASM_RTAC_CAL].map_data.map_handle;
 
-	pr_debug("%s: Sending RTAC command size = %d, session_id=%d\n",
-		__func__, asm_params.pkt_size, session_id);
+	memcpy(rtac_asm_buffer, &asm_params, sizeof(asm_params));
+	atomic_set(&rtac_asm_apr_data[session_id].cmd_state, 1);
+
+	pr_debug("%s: Sending RTAC command ioctl 0x%x, paddr 0x%x\n",
+		__func__, opcode,
+		rtac_cal[ASM_RTAC_CAL].cal_data.paddr);
 
 	result = apr_send_pkt(rtac_asm_apr_data[session_id].apr_handle,
 				(uint32_t *)rtac_asm_buffer);
@@ -713,21 +1005,33 @@
 			__func__, session_id);
 		goto done;
 	}
-
-	if (rtac_asm_payload_size != 0) {
-		if (copy_to_user(buf, rtac_asm_buffer,
-			rtac_asm_payload_size + sizeof(u32))) {
-			pr_err("%s: Could not copy buffer to user,size = %d\n",
-				 __func__, payload_size);
-			goto done;
-		}
+	if (atomic_read(&rtac_common.apr_err_code)) {
+		pr_err("%s: DSP returned error code = %d, opcode = 0x%x\n",
+			__func__, atomic_read(&rtac_common.apr_err_code),
+			opcode);
+		goto done;
 	}
 
-	/* Return data written for SET & data read for GET */
-	if (opcode == ASM_STREAM_CMD_GET_PP_PARAMS_V2)
-		bytes_returned = rtac_asm_payload_size;
-	else
-		bytes_returned = payload_size;
+	if (opcode == ASM_STREAM_CMD_GET_PP_PARAMS_V2) {
+		bytes_returned = ((u32 *)rtac_cal[ASM_RTAC_CAL].cal_data.
+			kvaddr)[2] + 3 * sizeof(u32);
+
+		if (bytes_returned > user_buf_size) {
+			pr_err("%s: User buf not big enough, size = 0x%x, returned size = 0x%x\n",
+				__func__, user_buf_size, bytes_returned);
+			goto done;
+		}
+
+		if (copy_to_user(buf, (void *)
+				rtac_cal[ASM_RTAC_CAL].cal_data.kvaddr,
+				bytes_returned)) {
+			pr_err("%s: Could not copy buffer to user,size = %d\n",
+				 __func__, bytes_returned);
+			goto done;
+		}
+	} else {
+		bytes_returned = data_size;
+	}
 done:
 	return bytes_returned;
 err:
@@ -753,51 +1057,54 @@
 		return false;
 
 	pr_debug("%s\n", __func__);
-	/* Offset data for in-band payload */
-	rtac_copy_voice_payload_to_user(payload, payload_size);
+	if (payload_size == sizeof(uint32_t))
+		atomic_set(&rtac_common.apr_err_code, payload[0]);
+	else if (payload_size == (2*sizeof(uint32_t)))
+		atomic_set(&rtac_common.apr_err_code, payload[1]);
+
 	atomic_set(&rtac_voice_apr_data[mode].cmd_state, 0);
 	wake_up(&rtac_voice_apr_data[mode].cmd_wait);
 	return true;
 }
 
-void rtac_copy_voice_payload_to_user(void *payload, u32 payload_size)
-{
-	pr_debug("%s\n", __func__);
-	rtac_voice_payload_size = payload_size;
-
-	memcpy(rtac_voice_buffer, &payload_size, sizeof(u32));
-	if (payload_size) {
-		if (payload_size > rtac_voice_user_buf_size) {
-			pr_err("%s: Buffer set not big enough for returned data, buf size = %d, ret data = %d\n",
-			 __func__, rtac_voice_user_buf_size, payload_size);
-			rtac_voice_payload_size = 0;
-			goto done;
-		}
-		memcpy(rtac_voice_buffer + sizeof(u32), payload, payload_size);
-	}
-done:
-	return;
-}
-
 u32 send_voice_apr(u32 mode, void *buf, u32 opcode)
 {
 	s32	result;
-	u32	count = 0;
+	u32	user_buf_size = 0;
 	u32	bytes_returned = 0;
 	u32	payload_size;
 	u32	dest_port;
+	u32	data_size = 0;
 	struct apr_hdr		voice_params;
 	pr_debug("%s\n", __func__);
 
-	if (copy_from_user(&count, (void *)buf, sizeof(count))) {
-		pr_err("%s: Copy to user failed! buf = 0x%x\n",
-		       __func__, (unsigned int)buf);
-		result = -EFAULT;
-		goto done;
+	if (rtac_cal[VOICE_RTAC_CAL].map_data.ion_handle == NULL) {
+		result = rtac_allocate_cal_buffer(VOICE_RTAC_CAL);
+		if (result < 0) {
+			pr_err("%s: allocate buffer failed!",
+				__func__);
+			goto done;
+		}
 	}
 
-	if (count <= 0) {
-		pr_err("%s: Invalid buffer size = %d\n", __func__, count);
+	if (rtac_cal[VOICE_RTAC_CAL].map_data.map_handle == 0) {
+		result = rtac_map_cal_buffer(VOICE_RTAC_CAL);
+		if (result < 0) {
+			pr_err("%s: map buffer failed!",
+				__func__);
+			goto done;
+		}
+	}
+
+	if (copy_from_user(&user_buf_size, (void *)buf,
+						sizeof(user_buf_size))) {
+		pr_err("%s: Copy from user failed! buf = 0x%x\n",
+		       __func__, (unsigned int)buf);
+		goto done;
+	}
+	if (user_buf_size <= 0) {
+		pr_err("%s: Invalid buffer size = %d\n",
+			__func__, user_buf_size);
 		goto done;
 	}
 
@@ -807,12 +1114,6 @@
 		goto done;
 	}
 
-	if (payload_size > MAX_PAYLOAD_SIZE) {
-		pr_err("%s: Invalid payload size = %d\n",
-				__func__, payload_size);
-		goto done;
-	}
-
 	if (copy_from_user(&dest_port, buf + 2 * sizeof(u32), sizeof(u32))) {
 		pr_err("%s: Could not copy port id from user buffer\n",
 			__func__);
@@ -831,15 +1132,42 @@
 		goto err;
 	}
 
-	/* Set globals for copy of returned payload */
-	rtac_voice_user_buf_size = count;
+	if (opcode == VOICE_CMD_SET_PARAM) {
+		/* set payload size to in-band payload */
+		/* set data size to actual out of band payload size */
+		data_size = payload_size - 4 * sizeof(u32);
+		if (data_size > rtac_cal[VOICE_RTAC_CAL].map_data.map_size) {
+			pr_err("%s: Invalid data size = %d\n",
+				__func__, data_size);
+			goto done;
+		}
+		payload_size = 4 * sizeof(u32);
 
-	/* Copy buffer to in-band payload */
-	if (copy_from_user(rtac_voice_buffer + sizeof(voice_params),
-			buf + 3 * sizeof(u32), payload_size)) {
-		pr_err("%s: Could not copy payload from user buffer\n",
-			__func__);
-		goto err;
+		/* Copy buffer to out-of-band payload */
+		if (copy_from_user((void *)
+				rtac_cal[VOICE_RTAC_CAL].cal_data.kvaddr,
+				buf + 7 * sizeof(u32), data_size)) {
+			pr_err("%s: Could not copy payload from user buffer\n",
+				__func__);
+			goto err;
+		}
+		/* set payload size in packet */
+		rtac_voice_buffer[8] = data_size;
+	} else {
+		if (payload_size > MAX_PAYLOAD_SIZE) {
+			pr_err("%s: Invalid payload size = %d\n",
+					__func__, payload_size);
+			goto done;
+		}
+
+		/* Copy buffer to in-band payload */
+		if (copy_from_user(rtac_voice_buffer +
+				sizeof(voice_params)/sizeof(u32),
+				buf + 3 * sizeof(u32), payload_size)) {
+			pr_err("%s: Could not copy payload from user buffer\n",
+				__func__);
+			goto err;
+		}
 	}
 
 	/* Pack header */
@@ -856,11 +1184,17 @@
 	voice_params.token = 0;
 	voice_params.opcode = opcode;
 
+	/* fill for out-of-band */
+	rtac_voice_buffer[5] = rtac_cal[VOICE_RTAC_CAL].map_data.map_handle;
+	rtac_voice_buffer[6] = rtac_cal[VOICE_RTAC_CAL].cal_data.paddr;
+	rtac_voice_buffer[7] = 0;
+
 	memcpy(rtac_voice_buffer, &voice_params, sizeof(voice_params));
 	atomic_set(&rtac_voice_apr_data[mode].cmd_state, 1);
 
-	pr_debug("%s: Sending RTAC command size = %d, opcode = %x\n",
-		__func__, voice_params.pkt_size, opcode);
+	pr_debug("%s: Sending RTAC command ioctl 0x%x, paddr 0x%x\n",
+		__func__, opcode,
+		rtac_cal[VOICE_RTAC_CAL].cal_data.paddr);
 
 	result = apr_send_pkt(rtac_voice_apr_data[mode].apr_handle,
 					(uint32_t *)rtac_voice_buffer);
@@ -879,21 +1213,33 @@
 			__func__, opcode);
 		goto done;
 	}
-
-	if (rtac_voice_payload_size != 0) {
-		if (copy_to_user(buf, rtac_voice_buffer,
-			rtac_voice_payload_size + sizeof(u32))) {
-			pr_err("%s: Could not copy buffer to user, size = %d\n",
-				 __func__, payload_size);
-			goto done;
-		}
+	if (atomic_read(&rtac_common.apr_err_code)) {
+		pr_err("%s: DSP returned error code = %d, opcode = 0x%x\n",
+			__func__, atomic_read(&rtac_common.apr_err_code),
+			opcode);
+		goto done;
 	}
 
-	/* Return data written for SET & data read for GET */
-	if (opcode == VOICE_CMD_GET_PARAM)
-		bytes_returned = rtac_voice_payload_size;
-	else
-		bytes_returned = payload_size;
+	if (opcode == VOICE_CMD_GET_PARAM) {
+		bytes_returned = ((u32 *)rtac_cal[VOICE_RTAC_CAL].cal_data.
+			kvaddr)[2] + 3 * sizeof(u32);
+
+		if (bytes_returned > user_buf_size) {
+			pr_err("%s: User buf not big enough, size = 0x%x, returned size = 0x%x\n",
+				__func__, user_buf_size, bytes_returned);
+			goto done;
+		}
+
+		if (copy_to_user(buf, (void *)
+				rtac_cal[VOICE_RTAC_CAL].cal_data.kvaddr,
+				bytes_returned)) {
+			pr_err("%s: Could not copy buffer to user, size = %d\n",
+				 __func__, bytes_returned);
+			goto done;
+		}
+	} else {
+		bytes_returned = data_size;
+	}
 done:
 	return bytes_returned;
 err:
@@ -987,6 +1333,10 @@
 	int i = 0;
 	pr_debug("%s\n", __func__);
 
+	/* Driver */
+	atomic_set(&rtac_common.usage_count, 0);
+	atomic_set(&rtac_common.apr_err_code, 0);
+
 	/* ADM */
 	memset(&rtac_adm_data, 0, sizeof(rtac_adm_data));
 	rtac_adm_apr_data.apr_handle = NULL;
@@ -995,10 +1345,11 @@
 	mutex_init(&rtac_adm_mutex);
 	mutex_init(&rtac_adm_apr_mutex);
 
-	rtac_adm_buffer = kzalloc(RTAC_BUF_SIZE, GFP_KERNEL);
+	rtac_adm_buffer = kzalloc(
+		rtac_cal[ADM_RTAC_CAL].map_data.map_size, GFP_KERNEL);
 	if (rtac_adm_buffer == NULL) {
 		pr_err("%s: Could not allocate payload of size = %d\n",
-			__func__, RTAC_BUF_SIZE);
+			__func__, rtac_cal[ADM_RTAC_CAL].map_data.map_size);
 		goto nomem;
 	}
 
@@ -1010,10 +1361,11 @@
 	}
 	mutex_init(&rtac_asm_apr_mutex);
 
-	rtac_asm_buffer = kzalloc(RTAC_BUF_SIZE, GFP_KERNEL);
+	rtac_asm_buffer = kzalloc(
+		rtac_cal[ASM_RTAC_CAL].map_data.map_size, GFP_KERNEL);
 	if (rtac_asm_buffer == NULL) {
 		pr_err("%s: Could not allocate payload of size = %d\n",
-			__func__, RTAC_BUF_SIZE);
+			__func__, rtac_cal[ASM_RTAC_CAL].map_data.map_size);
 		kzfree(rtac_adm_buffer);
 		goto nomem;
 	}
@@ -1028,10 +1380,11 @@
 	mutex_init(&rtac_voice_mutex);
 	mutex_init(&rtac_voice_apr_mutex);
 
-	rtac_voice_buffer = kzalloc(RTAC_BUF_SIZE, GFP_KERNEL);
+	rtac_voice_buffer = kzalloc(
+		rtac_cal[VOICE_RTAC_CAL].map_data.map_size, GFP_KERNEL);
 	if (rtac_voice_buffer == NULL) {
 		pr_err("%s: Could not allocate payload of size = %d\n",
-			__func__, RTAC_BUF_SIZE);
+			__func__, rtac_cal[VOICE_RTAC_CAL].map_data.map_size);
 		kzfree(rtac_adm_buffer);
 		kzfree(rtac_asm_buffer);
 		goto nomem;