Merge "ASoC: msm: qdsp6v2: Fix MI2S channel mapping"
diff --git a/Documentation/devicetree/bindings/arm/msm/cpr-regulator.txt b/Documentation/devicetree/bindings/arm/msm/cpr-regulator.txt
index 3a29004..203730f 100644
--- a/Documentation/devicetree/bindings/arm/msm/cpr-regulator.txt
+++ b/Documentation/devicetree/bindings/arm/msm/cpr-regulator.txt
@@ -47,6 +47,22 @@
 				  3 (SUPER_TURBO voltage):	1275000 uV
 - vdd-apc-supply:		Regulator to supply VDD APC power
 
+
+Optional properties:
+- vdd-mx-supply:		Regulator to supply memory power as dependency
+				of VDD APC.
+- qcom,vdd-mx-vmax:		The maximum voltage in uV for vdd-mx-supply. This
+				is required when vdd-mx-supply is present.
+- qcom,vdd-mx-vmin-method:	The method to determine the minimum voltage for
+				vdd-mx-supply, which can be one of following
+				choices compared with VDD APC:
+				  0 => equal to the voltage(vmin) of VDD APC
+				  1 => equal to PVS corner ceiling voltage
+				  2 => equal to slow speed corner ceiling
+				  3 => equal to qcom,vdd-mx-vmax
+				This is required when vdd-mx-supply is present.
+
+
 Example:
 	apc_vreg_corner: regulator@f9018000 {
 		status = "okay";
@@ -65,5 +81,8 @@
 		qcom,pvs-corner-ceiling-nom  =  <975000 1075000 1200000 1200000>;
 		qcom,pvs-corner-ceiling-fast =  <900000 1000000 1140000 1140000>;
 		vdd-apc-supply = <&pm8226_s2>;
+		vdd-mx-supply = <&pm8226_l3_ao>;
+		qcom,vdd-mx-vmax = <1350000>;
+		qcom,vdd-mx-vmin-method = <1>;
 	};
 
diff --git a/Documentation/devicetree/bindings/fb/mdss-dsi-panel.txt b/Documentation/devicetree/bindings/fb/mdss-dsi-panel.txt
index b55bd53..a9528c5 100644
--- a/Documentation/devicetree/bindings/fb/mdss-dsi-panel.txt
+++ b/Documentation/devicetree/bindings/fb/mdss-dsi-panel.txt
@@ -61,6 +61,30 @@
 - qcom,dsi-pwm-gpio :			PWM gpio.
 - qcom,mdss-pan-broadcast-mode:		Boolean used to enable broadcast mode.
 - qcom,cont-splash-enabled:		Boolean used to enable continuous splash mode.
+- qcom,fbc-enabled:			Boolean used to enable frame buffer compression mode.
+- qcom,fbc-mode-select:			An array of length 7 that specifies the fbc mode supported
+					by the panel. FBC enabled panels may or may not support
+					the modes specified here. Each entry will
+					have the format specified below:
+					--> compressed bpp supported by the panel
+					--> component packing
+					--> enable/disable quantization error calculation
+					--> Bias for CD
+					--> enable/disable PAT mode
+					--> enable/disable VLC mode
+					--> enable/disable BFLC mode
+- qcom,fbc-budget-ctl:			An array of length 3 that specifies the budget control settings
+					supported by the fbc enabled panel. Each entry will have the format
+					specified below:
+					--> per line extra budget
+					--> extra budget level
+					--> per block budget
+- qcom,fbc-lossy-mode:			An array of 3 that specifies the lossy mode settings
+					supported by the fbc enabled panel. Each entry will
+					have the format specified below:
+					--> lossless mode threshold
+					--> lossy mode threshold
+					--> lossy RGB threshold
 - qcom,mdss-pan-porch-values:		An array of size 6 that specifies the panel blanking values.
 - qcom,mdss-pan-underflow-clr:		Specifies the controller settings for the panel underflow clear
 					settings. Default value is 0xff.
@@ -184,5 +208,9 @@
 		qcom,on-cmds-dsi-state = "DSI_LP_MODE";
 		qcom,panel-off-cmds = [22 01 00 00 00 00 00];
 		qcom,off-cmds-dsi-state = "DSI LP MODE";
+		qcom,fbc-enabled;
+		qcom,fbc-mode = <12 0 1 2 1 1 1>;
+		qcom,fbc-budget-ctl = <675 5 91>;
+		qcom,fbc-lossy-mode = <0 0xc0 0 3>;
 	};
 };
diff --git a/Documentation/devicetree/bindings/input/touchscreen/synaptics_i2c_rmi4.txt b/Documentation/devicetree/bindings/input/touchscreen/synaptics_i2c_rmi4.txt
index b31ec30..d24139b 100644
--- a/Documentation/devicetree/bindings/input/touchscreen/synaptics_i2c_rmi4.txt
+++ b/Documentation/devicetree/bindings/input/touchscreen/synaptics_i2c_rmi4.txt
@@ -20,6 +20,7 @@
  - synaptics,y-flip		: modify orientation of the y axis
  - synaptics,panel-x		: panel x dimension
  - synaptics,panel-y		: panel y dimension
+ - synaptics,fw-image-name	: name of firmware .img file in /etc/firmware
 
 Example:
 	i2c@f9927000 { /* BLSP1 QUP5 */
diff --git a/Documentation/devicetree/bindings/pil/pil-q6v5-mss.txt b/Documentation/devicetree/bindings/pil/pil-q6v5-mss.txt
index acd0ae3..383da0c 100644
--- a/Documentation/devicetree/bindings/pil/pil-q6v5-mss.txt
+++ b/Documentation/devicetree/bindings/pil/pil-q6v5-mss.txt
@@ -46,8 +46,8 @@
 		qcom,pil-self-auth;
 
 		/* GPIO inputs from mss */
-		gpio_err_fatal = <&smp2pgpio_ssr_smp2p_1_in 0 0>;
+		qcom,gpio-err-fatal = <&smp2pgpio_ssr_smp2p_1_in 0 0>;
 
 		/* GPIO output to mss */
-		gpio_force_stop = <&smp2pgpio_ssr_smp2p_1_out 0 0>;
+		qcom,gpio-force-stop = <&smp2pgpio_ssr_smp2p_1_out 0 0>;
 	};
diff --git a/Documentation/devicetree/bindings/sound/qcom-audio-dev.txt b/Documentation/devicetree/bindings/sound/qcom-audio-dev.txt
index a4c05d4..fe3d62f 100644
--- a/Documentation/devicetree/bindings/sound/qcom-audio-dev.txt
+++ b/Documentation/devicetree/bindings/sound/qcom-audio-dev.txt
@@ -389,15 +389,25 @@
                 qcom,msm-cpudai-auxpcm-data = <0>, <0>;
                 qcom,msm-cpudai-auxpcm-pcm-clk-rate = <2048000>, <2048000>;
 
-                qcom,msm-auxpcm-rx {
+                qcom,msm-prim-auxpcm-rx {
                         qcom,msm-auxpcm-dev-id = <4106>;
                         compatible = "qcom,msm-auxpcm-dev";
                 };
 
-                qcom,msm-auxpcm-tx {
+                qcom,msm-prim-auxpcm-tx {
                         qcom,msm-auxpcm-dev-id = <4107>;
                         compatible = "qcom,msm-auxpcm-dev";
                 };
+
+		qcom,msm-sec-auxpcm-rx {
+			qcom,msm-auxpcm-dev-id = <4108>;
+			compatible = "qcom,msm-auxpcm-dev";
+		};
+
+		qcom,msm-sec-auxpcm-tx {
+			qcom,msm-auxpcm-dev-id = <4109>;
+			compatible = "qcom,msm-auxpcm-dev";
+		};
         };
 
         qcom,msm-pcm-hostless {
@@ -436,10 +446,14 @@
 - taiko-mclk-clk : phandle to PMIC8941 clkdiv1 node.
 - qcom,taiko-mclk-clk-freq : Taiko mclk Freq in Hz. currently only 9600000Hz
 				is supported.
-- prim-auxpcm-gpio-clk : GPIO on which AUXPCM clk signal is coming.
-- prim-auxpcm-gpio-sync : GPIO on which AUXPCM SYNC signal is coming.
-- prim-auxpcm-gpio-din : GPIO on which AUXPCM DIN signal is coming.
-- prim-auxpcm-gpio-dout : GPIO on which AUXPCM DOUT signal is coming.
+- qcom,prim-auxpcm-gpio-clk  : GPIO on which Primary AUXPCM clk signal is coming.
+- qcom,prim-auxpcm-gpio-sync : GPIO on which Primary AUXPCM SYNC signal is coming.
+- qcom,prim-auxpcm-gpio-din  : GPIO on which Primary AUXPCM DIN signal is coming.
+- qcom,prim-auxpcm-gpio-dout : GPIO on which Primary AUXPCM DOUT signal is coming.
+- qcom,sec-auxpcm-gpio-clk  : GPIO on which Secondary AUXPCM clk signal is coming.
+- qcom,sec-auxpcm-gpio-sync : GPIO on which Secondary AUXPCM SYNC signal is coming.
+- qcom,sec-auxpcm-gpio-din  : GPIO on which Secondary AUXPCM DIN signal is coming.
+- qcom,sec-auxpcm-gpio-dout : GPIO on which Secondary AUXPCM DOUT signal is coming.
 - qcom,us-euro-gpios : GPIO on which gnd/mic swap signal is coming.
 
 Optional properties:
@@ -487,10 +501,14 @@
 
 	qcom,hdmi-audio-rx;
 
-	prim-auxpcm-gpio-clk  = <&msmgpio 65 0>;
-	prim-auxpcm-gpio-sync = <&msmgpio 66 0>;
-	prim-auxpcm-gpio-din  = <&msmgpio 67 0>;
-	prim-auxpcm-gpio-dout = <&msmgpio 68 0>;
+	qcom,prim-auxpcm-gpio-clk  = <&msmgpio 65 0>;
+	qcom,prim-auxpcm-gpio-sync = <&msmgpio 66 0>;
+	qcom,prim-auxpcm-gpio-din  = <&msmgpio 67 0>;
+	qcom,prim-auxpcm-gpio-dout = <&msmgpio 68 0>;
+	qcom,sec-auxpcm-gpio-clk  = <&msmgpio 79 0>;
+	qcom,sec-auxpcm-gpio-sync = <&msmgpio 80 0>;
+	qcom,sec-auxpcm-gpio-din  = <&msmgpio 81 0>;
+	qcom,sec-auxpcm-gpio-dout = <&msmgpio 82 0>;
 };
 
 * msm-dai-mi2s
@@ -608,7 +626,7 @@
 * msm-adsp-loader
 
 Required properties:
- - compatible : "msm-adsp-loader"
+ - compatible : "qcom,adsp-loader"
  - qcom,adsp-state:
 	It is possible that some MSM use PIL to load the ADSP image. While
 	other MSM may use SBL to load the ADSP image at boot. Audio APR needs
@@ -623,3 +641,22 @@
 	compatible = "qcom,adsp-loader";
 	qcom,adsp-state = <2>;
 };
+
+* msm-audio-ion
+
+Required properties:
+ - compatible : "qcom,msm-audio-ion"
+
+Optional properties:
+ - qcom,smmu-enabled:
+        It is possible that some MSM have SMMU in ADSP.  While other MSM use
+	no SMMU. Audio lib introduce wrapper for ION APIs. The wrapper needs
+        presence of SMMU in ADSP to handle ION APIs differently.
+        Presence of this property means ADSP has SMMU in it.
+
+Example:
+
+qcom,msm-audio-ion {
+	compatible = "qcom,msm-audio-ion;
+	qcom,smmu-enabled;
+};
diff --git a/Documentation/devicetree/bindings/sound/taiko_codec.txt b/Documentation/devicetree/bindings/sound/taiko_codec.txt
index cbc77ad..ffea58f 100644
--- a/Documentation/devicetree/bindings/sound/taiko_codec.txt
+++ b/Documentation/devicetree/bindings/sound/taiko_codec.txt
@@ -61,6 +61,12 @@
  - qcom,cdc-slim-ifd-dev - namme of the codec slim interface device.
  - qcom,cdc-slim-ifd-elemental-addr - codec slimbus slave interface device
 				     enumeration address.
+
+Optional properties:
+ - cdc-dmic-sample-rate: Specifies the sample rate of digital mic in HZ. The
+			 values for 9.6MHZ mclk can be 2400000 Hz, 3200000 Hz
+			 and 4800000 Hz.  The values for 12.288MHz mclk can be
+			 3072200 Hz, 4096000 Hz and 6144000 Hz.
 Example:
 
 taiko_codec {
@@ -112,6 +118,7 @@
 	qcom,cdc-mclk-clk-rate = <9600000>;
 	qcom,cdc-slim-ifd = "taiko-slim-ifd";
 	qcom,cdc-slim-ifd-elemental-addr = [00 00 A0 00 17 02];
+	qcom,cdc-dmic-sample-rate = <4800000>;
 };
 
 Wcd9xxx audio CODEC in I2C mode
diff --git a/Documentation/devicetree/bindings/usb/dwc3.txt b/Documentation/devicetree/bindings/usb/dwc3.txt
index 9ce5421..fd5b93e 100644
--- a/Documentation/devicetree/bindings/usb/dwc3.txt
+++ b/Documentation/devicetree/bindings/usb/dwc3.txt
@@ -6,6 +6,9 @@
  - compatible: must be "synopsys,dwc3"
  - reg : Address and length of the register set for the device
  - interrupts: Interrupts used by the dwc3 controller.
+ - interrupt-names : Required interrupt resource entries are:
+	"irq" : Interrupt for DWC3 core
+	"otg_irq" : Interrupt for DWC3 core's OTG Events
 
 Optional properties:
  - tx-fifo-resize: determines if the FIFO *has* to be reallocated.
@@ -15,6 +18,7 @@
 dwc3@4a030000 {
 	compatible = "synopsys,dwc3";
 	reg = <0x4a030000 0xcfff>;
-	interrupts = <0 92 4>
+	interrupts = <0 92 4>, <0 179 0>;
+	interrupt-names = "irq", "otg_irq";
 	tx-fifo-resize;
 };
diff --git a/Documentation/devicetree/bindings/usb/msm-ehci-hsic.txt b/Documentation/devicetree/bindings/usb/msm-ehci-hsic.txt
index 1fb2ba9..6ea9e62 100644
--- a/Documentation/devicetree/bindings/usb/msm-ehci-hsic.txt
+++ b/Documentation/devicetree/bindings/usb/msm-ehci-hsic.txt
@@ -38,6 +38,9 @@
   STROBE GPIO PAD.
 - hsic,data-pad-offset : Offset of TLMM register for configuring HSIC
   DATA GPIO PAD.
+- qcom,phy-sof-workaround : If present then HSIC PHY has h/w BUGs related to
+  SOFs. Software workarounds are required for the same.
+
 - Refer to "Documentation/devicetree/bindings/arm/msm/msm_bus.txt" for
   below optional properties:
     - qcom,msm_bus,name
diff --git a/Documentation/devicetree/bindings/usb/msm-hsusb.txt b/Documentation/devicetree/bindings/usb/msm-hsusb.txt
index 02c2871..c1d4a05 100644
--- a/Documentation/devicetree/bindings/usb/msm-hsusb.txt
+++ b/Documentation/devicetree/bindings/usb/msm-hsusb.txt
@@ -22,6 +22,10 @@
             1 - PHY control
 	    2 - PMIC control
 	    3 - User control (via debugfs)
+- <supply-name>-supply: handle to the regulator device tree node
+         Required "supply-name" is "HSUSB_VDDCX" (when voting for VDDCX) or
+         "hsusb_vdd_dig" (when voting for VDDCX Corner voltage),
+         "HSUSB_1p8-supply" and "HSUSB_3p3-supply".
 
 Optional properties :
 - qcom,hsusb-otg-disable-reset: If present then core is RESET only during
@@ -54,10 +58,8 @@
 	    Used for allowing USB to respond for remote wakup.
 - qcom,hsusb-otg-delay-lpm: If present then USB core will wait one second
 	after disconnect before entering low power mode.
-- <supply-name>-supply: handle to the regulator device tree node
-         Required "supply-name" is "HSUSB_VDDCX" (when voting for VDDCX) or
-         "hsusb_vdd_dig" (when voting for VDDCX Corner voltage),
-         "HSUSB_1p8-supply" and "HSUSB_3p3-supply".
+- <supply-name>-supply: handle to the regulator device tree node.
+         Optional "supply-name" is "vbus_otg" to supply vbus in host mode.
 - qcom,vdd-voltage-level: This property must be a list of three integer
 	values (no, min, max) where each value represents either a voltage
 	in microvolts or a value corresponding to voltage corner.
@@ -173,7 +175,11 @@
             If HSUSB_BAM is used, "hsusb" should be present.
             If HSIC_BAM is used, "hsic" should be present.
 - qcom,usb-bam-num-pipes: max number of pipes that can be used
-- qcom,usb-base-address: physical base address of the BAM
+
+Optional properties:
+- qcom,usb-bam-fifo-baseaddr: base address for bam pipe's data and descriptor
+  fifos. This can be on chip memory (ocimem) or usb private memory. This
+  property is required if sub-node's mem-type is ocimem or usb private mem.
 
 A number of USB BAM pipe parameters are represented as sub-nodes:
 
@@ -186,8 +192,9 @@
 	pipe num options: 0..127
 - qcom,usb-bam-mem-type: Type of memory used by this PIPE. Can be one of
             0 - Uses SPS's dedicated pipe memory
-            1 - USB's private memory residing @ 'qcom,usb-base-address'
+            1 - USB's private memory residing @ 'qcom,usb-bam-fifo-baseaddr'
             2 - System RAM allocated by driver
+	    3 - OCI memory residing @ 'qcom,usb-bam-fifo-baseaddr'
 - qcom,bam-type: BAM type can be one of
 	0 - SSUSB_BAM
 	1 - HSUSB_BAM
diff --git a/Documentation/devicetree/bindings/usb/msm-ssusb.txt b/Documentation/devicetree/bindings/usb/msm-ssusb.txt
index 51c0750..5391734 100644
--- a/Documentation/devicetree/bindings/usb/msm-ssusb.txt
+++ b/Documentation/devicetree/bindings/usb/msm-ssusb.txt
@@ -6,9 +6,6 @@
 	offset and length of the TCSR register for routing USB
 	signals to either picoPHY0 or picoPHY1.
 - interrupts: IRQ lines used by this controller
-- interrupt-names : Required interrupt resource entries are:
-	"irq" : Interrupt for DWC3 core
-	"otg_irq" : Interrupt for DWC3 core's OTG Events
 - <supply-name>-supply: phandle to the regulator device tree node
   Required "supply-name" examples are:
 	"SSUSB_lp8" : 1.8v supply for SSPHY
@@ -49,13 +46,18 @@
 		bits 13-19 PARAMETER_OVERRIDE_C
 		bits 20-25 PARAMETER_OVERRIDE_D
 
+Sub nodes:
+- Sub node for "DWC3- USB3 controller".
+  This sub node is required property for device node. The properties of this subnode
+  are specified in dwc3.txt.
+
 Example MSM USB3.0 controller device node :
 	usb@f9200000 {
 		compatible = "qcom,dwc-usb3-msm";
-		reg = <0xF9200000 0xFA000>,
-		      <0xFD4AB000 0x4>;
-		interrupts = <0 131 0>, <0 179 0>, <0 133 0>;
-		interrupt-names = "irq", "otg_irq", "hs_phy_irq";
+		reg = <0xf9200000 0xfc000>,
+		      <0xfd4ab000 0x4>;
+		interrupts = <0 133 0>;
+		interrupt-names = "hs_phy_irq";
 		ssusb_vdd_dig-supply = <&pm8841_s2_corner>;
 		SSUSB_1p8-supply = <&pm8941_l6>;
 		hsusb_vdd_dig-supply = <&pm8841_s2_corner>;
@@ -73,4 +75,11 @@
 		qcom,msm_bus,vectors =
 				<61 512 0 0>,
 				<61 512 240000000 960000000>;
+		dwc3@f9200000 {
+			compatible = "synopsys,dwc3";
+			reg = <0xf9200000 0xfc000>;
+			interrupts = <0 131 0>, <0 179 0>;
+			interrupt-names = "irq", "otg_irq";
+			tx-fifo-resize;
+};
 	};
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 2825288..c52b7dd 100644
--- a/arch/arm/boot/dts/dsi-panel-nt35590-720p-video.dtsi
+++ b/arch/arm/boot/dts/dsi-panel-nt35590-720p-video.dtsi
@@ -23,7 +23,7 @@
 		qcom,mdss-pan-porch-values = <164 8 140 1 1 6>;
 		qcom,mdss-pan-underflow-clr = <0xff>;
 		qcom,mdss-pan-bl-ctrl = "bl_ctrl_wled";
-		qcom,mdss-pan-bl-levels = <1 255>;
+		qcom,mdss-pan-bl-levels = <1 4095>;
 		qcom,mdss-pan-dsi-mode = <0>;
 		qcom,mdss-pan-dsi-h-pulse-mode = <1>;
 		qcom,mdss-pan-dsi-h-power-stop = <0 0 0>;
diff --git a/arch/arm/boot/dts/msm-pm8226.dtsi b/arch/arm/boot/dts/msm-pm8226.dtsi
index e2b6a66..72de900 100644
--- a/arch/arm/boot/dts/msm-pm8226.dtsi
+++ b/arch/arm/boot/dts/msm-pm8226.dtsi
@@ -690,6 +690,13 @@
 			status = "disabled";
 		};
 
+		qcom,vibrator@c000 {
+			compatible = "qcom,qpnp-vibrator";
+			reg = <0xc000 0x100>;
+			label = "vibrator";
+			status = "disabled";
+		};
+
                 qcom,leds@d300 {
                         compatible = "qcom,leds-qpnp";
                         status = "disable";
diff --git a/arch/arm/boot/dts/msm-pm8941.dtsi b/arch/arm/boot/dts/msm-pm8941.dtsi
index 9c0959d..6042f23 100644
--- a/arch/arm/boot/dts/msm-pm8941.dtsi
+++ b/arch/arm/boot/dts/msm-pm8941.dtsi
@@ -105,7 +105,7 @@
 			qcom,r-sense-uohm = <10000>;
 			qcom,v-cutoff-uv = <3400000>;
 			qcom,max-voltage-uv = <4200000>;
-			qcom,r-conn-mohm = <18>;
+			qcom,r-conn-mohm = <0>;
 			qcom,shutdown-soc-valid-limit = <20>;
 			qcom,adjust-soc-low-threshold = <25>;
 			qcom,adjust-soc-high-threshold = <45>;
diff --git a/arch/arm/boot/dts/msm8226-camera-sensor-cdp-mtp-qrd.dtsi b/arch/arm/boot/dts/msm8226-camera-sensor-cdp-qrd.dtsi
similarity index 100%
rename from arch/arm/boot/dts/msm8226-camera-sensor-cdp-mtp-qrd.dtsi
rename to arch/arm/boot/dts/msm8226-camera-sensor-cdp-qrd.dtsi
diff --git a/arch/arm/boot/dts/msm8226-camera-sensor-mtp.dtsi b/arch/arm/boot/dts/msm8226-camera-sensor-mtp.dtsi
new file mode 100644
index 0000000..02089be
--- /dev/null
+++ b/arch/arm/boot/dts/msm8226-camera-sensor-mtp.dtsi
@@ -0,0 +1,108 @@
+/*
+ * 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.
+ */
+
+/ {
+
+	led_flash0: qcom,camera-led-flash {
+		cell-index = <0>;
+		compatible = "qcom,camera-led-flash";
+		qcom,flash-type = <1>;
+		qcom,flash-source = <&pm8226_flash0 &pm8226_flash1>;
+	};
+};
+
+&cci {
+
+	actuator0: qcom,actuator@6e {
+		cell-index = <3>;
+		reg = <0x6c 0x0>;
+		compatible = "qcom,actuator";
+		qcom,cci-master = <0>;
+	};
+
+	qcom,camera@6f {
+		compatible = "qcom,ov8825";
+		reg = <0x6f>;
+		qcom,slave-id = <0x6c 0x300a 0x8825>;
+		qcom,csiphy-sd-index = <0>;
+		qcom,csid-sd-index = <0>;
+		qcom,actuator-src = <&actuator0>;
+		qcom,led-flash-src = <&led_flash0>;
+		qcom,mount-angle = <90>;
+		qcom,sensor-name = "ov8825";
+		cam_vdig-supply = <&pm8226_l5>;
+		cam_vana-supply = <&pm8226_l19>;
+		cam_vio-supply = <&pm8226_lvs1>;
+		cam_vaf-supply = <&pm8226_l15>;
+		qcom,cam-vreg-name = "cam_vdig", "cam_vio", "cam_vana",
+							 "cam_vaf";
+		qcom,cam-vreg-type = <0 1 0 0>;
+		qcom,cam-vreg-min-voltage = <1200000 0 2850000 2800000>;
+		qcom,cam-vreg-max-voltage = <1200000 0 2850000 2800000>;
+		qcom,cam-vreg-op-mode = <200000 0 80000 100000>;
+		qcom,gpio-no-mux = <0>;
+		gpios = <&msmgpio 26 0>,
+			<&msmgpio 37 0>,
+			<&msmgpio 35 0>;
+		qcom,gpio-reset = <1>;
+		qcom,gpio-standby = <2>;
+		qcom,gpio-req-tbl-num = <0 1 2>;
+		qcom,gpio-req-tbl-flags = <1 0 0>;
+		qcom,gpio-req-tbl-label = "CAMIF_MCLK",
+			"CAM_RESET1",
+			"CAM_STANDBY";
+		qcom,csi-lane-assign = <0x4320>;
+		qcom,csi-lane-mask = <0x1f>;
+		qcom,sensor-position = <0>;
+		qcom,sensor-mode = <1>;
+		qcom,cci-master = <0>;
+	};
+
+	qcom,camera@6d {
+		compatible = "qcom,ov9724";
+		reg = <0x6d>;
+		qcom,slave-id = <0x20 0x0 0x9724>;
+		qcom,csiphy-sd-index = <1>;
+		qcom,csid-sd-index = <0>;
+		qcom,mount-angle = <90>;
+		qcom,sensor-name = "ov9724";
+		cam_vdig-supply = <&pm8226_l5>;
+		cam_vana-supply = <&pm8226_l19>;
+		cam_vio-supply = <&pm8226_lvs1>;
+		qcom,cam-vreg-name = "cam_vdig", "cam_vio", "cam_vana";
+		qcom,cam-vreg-type = <0 1 0>;
+		qcom,cam-vreg-min-voltage = <1200000 0 2850000>;
+		qcom,cam-vreg-max-voltage = <1200000 0 2850000>;
+		qcom,cam-vreg-op-mode = <200000 0 80000>;
+		qcom,gpio-no-mux = <0>;
+		gpios = <&msmgpio 26 0>,
+				<&msmgpio 28 0>,
+				<&msmgpio 36 0>;
+		qcom,gpio-reset = <1>;
+		qcom,gpio-standby = <2>;
+		qcom,gpio-req-tbl-num = <0 1 2>;
+		qcom,gpio-req-tbl-flags = <1 0 0>;
+		qcom,gpio-req-tbl-label = "CAMIF_MCLK",
+				"CAM_RESET",
+				"CAM_STANDBY";
+		qcom,gpio-set-tbl-num = <1 1>;
+		qcom,gpio-set-tbl-flags = <0 2>;
+		qcom,gpio-set-tbl-delay = <1000 4000>;
+		qcom,csi-lane-assign = <0x4320>;
+		qcom,csi-lane-mask = <0x3>;
+		qcom,sensor-position = <1>;
+		qcom,sensor-mode = <1>;
+		qcom,cci-master = <0>;
+		status = "ok";
+	};
+};
diff --git a/arch/arm/boot/dts/msm8226-cdp.dts b/arch/arm/boot/dts/msm8226-cdp.dts
index eab8b07..7b8dd59 100644
--- a/arch/arm/boot/dts/msm8226-cdp.dts
+++ b/arch/arm/boot/dts/msm8226-cdp.dts
@@ -13,11 +13,11 @@
 /dts-v1/;
 /include/ "msm8226.dtsi"
 /include/ "dsi-panel-nt35590-720p-video.dtsi"
-/include/ "msm8226-camera-sensor-cdp-mtp-qrd.dtsi"
+/include/ "msm8226-camera-sensor-cdp-qrd.dtsi"
 
 / {
 	model = "Qualcomm MSM 8226 CDP";
-	compatible = "qcom,msm8226-cdp", "qcom,msm8226";
+	compatible = "qcom,msm8226-cdp", "qcom,msm8226", "qcom,cdp";
 	qcom,msm-id = <145 1 0>;
 
 	serial@f991f000 {
diff --git a/arch/arm/boot/dts/msm8226-fluid.dts b/arch/arm/boot/dts/msm8226-fluid.dts
index af86922..02a0b0b 100644
--- a/arch/arm/boot/dts/msm8226-fluid.dts
+++ b/arch/arm/boot/dts/msm8226-fluid.dts
@@ -15,7 +15,7 @@
 
 / {
 	model = "Qualcomm MSM 8226 FLUID";
-	compatible = "qcom,msm8226-fluid", "qcom,msm8226";
+	compatible = "qcom,msm8226-fluid", "qcom,msm8226", "qcom,fluid";
 	qcom,msm-id = <145 3 0>;
 
 	serial@f991f000 {
diff --git a/arch/arm/boot/dts/msm8226-gpu.dtsi b/arch/arm/boot/dts/msm8226-gpu.dtsi
index ebd7749..6a8ba3a 100644
--- a/arch/arm/boot/dts/msm8226-gpu.dtsi
+++ b/arch/arm/boot/dts/msm8226-gpu.dtsi
@@ -9,61 +9,156 @@
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
  */
+/ {
+	msm_gpu: qcom,kgsl-3d0@fdb00000 {
+		label = "kgsl-3d0";
+		compatible = "qcom,kgsl-3d0", "qcom,kgsl-3d";
+		reg = <0xfdb00000 0x10000
+		       0xfdb20000 0x10000>;
+		reg-names = "kgsl_3d0_reg_memory" , "kgsl_3d0_shader_memory";
+		interrupts = <0 33 0>;
+		interrupt-names = "kgsl_3d0_irq";
+		qcom,id = <0>;
 
-/include/ "msm8974-gpu.dtsi"
+		qcom,chipid = <0x03000510>;
 
-&msm_gpu {
-	qcom,chipid = <0x03000510>;
+		qcom,initial-pwrlevel = <2>;
+		qcom,step-pwrlevel = <2>;
 
-	qcom,clk-map = <0x00000016>; /* KGSL_CLK_CORE | KGSL_CLK_IFACE | KGSL_CLK_MEM_IFACE */
+		qcom,idle-timeout = <8>; //<HZ/12>
+		qcom,nap-allowed = <1>;
+		qcom,strtstp-sleepwake;
+		qcom,clk-map = <0x00000016>; /* KGSL_CLK_CORE | KGSL_CLK_IFACE | KGSL_CLK_MEM_IFACE */
 
-	/* Bus Scale Settings */
-	qcom,msm-bus,name = "grp3d";
-	qcom,msm-bus,num-cases = <4>;
-	qcom,msm-bus,active-only = <0>;
-	qcom,msm-bus,num-paths = <2>;
-	qcom,msm-bus,vectors-KBps =
+		/* Bus Scale Settings */
+		qcom,msm-bus,name = "grp3d";
+		qcom,msm-bus,num-cases = <4>;
+		qcom,msm-bus,active-only = <0>;
+		qcom,msm-bus,num-paths = <2>;
+		qcom,msm-bus,vectors-KBps =
 			<26 512 0 0>, <89 604 0 0>,
 			<26 512 0 1600000>, <89 604 0 3200000>,
 			<26 512 0 3200000>, <89 604 0 5120000>,
 			<26 512 0 4256000>, <89 604 0 6400000>;
 
-	/* GDSC oxili regulators */
-	vddcx-supply = "\0";
-	vdd-supply = <&gdsc_oxili_cx>;
 
-	qcom,gpu-pwrlevels {
-		#address-cells = <1>;
-		#size-cells = <0>;
+		/* GDSC oxili regulators */
+		vddcx-supply = "\0";
+		vdd-supply = <&gdsc_oxili_cx>;
 
-		compatible = "qcom,gpu-pwrlevels";
 
-		qcom,gpu-pwrlevel@0 {
-			reg = <0>;
-			qcom,gpu-freq = <450000000>;
-			qcom,bus-freq = <3>;
-			qcom,io-fraction = <0>;
+		/* IOMMU Data */
+		iommu = <&kgsl_iommu>;
+
+		/* Power levels */
+		qcom,gpu-pwrlevels {
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			compatible = "qcom,gpu-pwrlevels";
+
+			qcom,gpu-pwrlevel@0 {
+				reg = <0>;
+				qcom,gpu-freq = <450000000>;
+				qcom,bus-freq = <3>;
+				qcom,io-fraction = <0>;
+			};
+
+			qcom,gpu-pwrlevel@1 {
+				reg = <1>;
+				qcom,gpu-freq = <320000000>;
+				qcom,bus-freq = <2>;
+				qcom,io-fraction = <33>;
+			};
+
+			qcom,gpu-pwrlevel@2 {
+				reg = <2>;
+				qcom,gpu-freq = <200000000>;
+				qcom,bus-freq = <1>;
+				qcom,io-fraction = <100>;
+			};
+
+			qcom,gpu-pwrlevel@3 {
+				reg = <3>;
+				qcom,gpu-freq = <19000000>;
+				qcom,bus-freq = <0>;
+				qcom,io-fraction = <0>;
+			};
 		};
 
-		qcom,gpu-pwrlevel@1 {
-			reg = <1>;
-			qcom,gpu-freq = <320000000>;
-			qcom,bus-freq = <2>;
-			qcom,io-fraction = <33>;
+		qcom,dcvs-core-info {
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			compatible = "qcom,dcvs-core-info";
+
+			qcom,num-cores = <1>;
+			qcom,sensors = <0>;
+
+			qcom,core-core-type = <1>;
+
+			qcom,algo-disable-pc-threshold = <0>;
+			qcom,algo-em-win-size-min-us = <100000>;
+			qcom,algo-em-win-size-max-us = <300000>;
+			qcom,algo-em-max-util-pct = <97>;
+			qcom,algo-group-id = <95>;
+			qcom,algo-max-freq-chg-time-us = <100000>;
+			qcom,algo-slack-mode-dynamic = <100000>;
+			qcom,algo-slack-weight-thresh-pct = <0>;
+			qcom,algo-slack-time-min-us = <39000>;
+			qcom,algo-slack-time-max-us = <39000>;
+			qcom,algo-ss-win-size-min-us = <1000000>;
+			qcom,algo-ss-win-size-max-us = <1000000>;
+			qcom,algo-ss-util-pct = <95>;
+			qcom,algo-ss-no-corr-below-freq = <0>;
+
+			qcom,energy-active-coeff-a = <2492>;
+			qcom,energy-active-coeff-b = <0>;
+			qcom,energy-active-coeff-c = <0>;
+			qcom,energy-leakage-coeff-a = <11>;
+			qcom,energy-leakage-coeff-b = <157150>;
+			qcom,energy-leakage-coeff-c = <0>;
+			qcom,energy-leakage-coeff-d = <0>;
+
+			qcom,power-current-temp = <25>;
+			qcom,power-num-freq = <4>;
+
+			qcom,dcvs-freq@0 {
+				reg = <0>;
+				qcom,freq = <0>;
+				qcom,voltage = <0>;
+				qcom,is_trans_level = <0>;
+				qcom,active-energy-offset = <100>;
+				qcom,leakage-energy-offset = <0>;
+			};
+
+			qcom,dcvs-freq@1 {
+				reg = <1>;
+				qcom,freq = <0>;
+				qcom,voltage = <0>;
+				qcom,is_trans_level = <0>;
+				qcom,active-energy-offset = <100>;
+				qcom,leakage-energy-offset = <0>;
+			};
+
+			qcom,dcvs-freq@2 {
+				reg = <2>;
+				qcom,freq = <0>;
+				qcom,voltage = <0>;
+				qcom,is_trans_level = <0>;
+				qcom,active-energy-offset = <100>;
+				qcom,leakage-energy-offset = <0>;
+			};
+
+			qcom,dcvs-freq@3 {
+				reg = <3>;
+				qcom,freq = <0>;
+				qcom,voltage = <0>;
+				qcom,is_trans_level = <0>;
+				qcom,active-energy-offset = <844545>;
+				qcom,leakage-energy-offset = <0>;
+			};
 		};
 
-		qcom,gpu-pwrlevel@2 {
-			reg = <2>;
-			qcom,gpu-freq = <200000000>;
-			qcom,bus-freq = <1>;
-			qcom,io-fraction = <100>;
-		};
-
-		qcom,gpu-pwrlevel@3 {
-			reg = <3>;
-			qcom,gpu-freq = <19000000>;
-			qcom,bus-freq = <0>;
-			qcom,io-fraction = <0>;
-		};
 	};
 };
diff --git a/arch/arm/boot/dts/msm8226-mtp.dts b/arch/arm/boot/dts/msm8226-mtp.dts
index 5c6fbd5..dab15ae 100644
--- a/arch/arm/boot/dts/msm8226-mtp.dts
+++ b/arch/arm/boot/dts/msm8226-mtp.dts
@@ -13,11 +13,11 @@
 /dts-v1/;
 /include/ "msm8226.dtsi"
 /include/ "dsi-panel-nt35590-720p-video.dtsi"
-/include/ "msm8226-camera-sensor-cdp-mtp-qrd.dtsi"
+/include/ "msm8226-camera-sensor-mtp.dtsi"
 
 / {
 	model = "Qualcomm MSM 8226 MTP";
-	compatible = "qcom,msm8226-mtp", "qcom,msm8226";
+	compatible = "qcom,msm8226-mtp", "qcom,msm8226", "qcom,mtp";
 	qcom,msm-id = <145 8 0>;
 
 	serial@f991f000 {
diff --git a/arch/arm/boot/dts/msm8226-pm.dtsi b/arch/arm/boot/dts/msm8226-pm.dtsi
index 34283e8..2613e11 100644
--- a/arch/arm/boot/dts/msm8226-pm.dtsi
+++ b/arch/arm/boot/dts/msm8226-pm.dtsi
@@ -25,9 +25,9 @@
 		qcom,saw2-spm-ctl = <0x0>;
 		qcom,saw2-spm-cmd-wfi = [60 03 60 0b 0f];
 		qcom,saw2-spm-cmd-spc = [00 20 10 80 30 90 5b 60 03 60 3b 76 76
-				0b 94 5b 80 10 2b 06 26 30 0f];
+				0b 94 5b 80 10 06 26 30 0f];
 		qcom,saw2-spm-cmd-pc = [00 20 10 80 30 90 5b 60 07 60 3b 76 76
-				0b 94 5b 80 10 2b 06 26 30 0f];
+				0b 94 5b 80 10 06 26 30 0f];
 	};
 
 	qcom,spm@f9099000 {
@@ -42,9 +42,9 @@
 		qcom,saw2-spm-ctl = <0x0>;
 		qcom,saw2-spm-cmd-wfi = [60 03 60 0b 0f];
 		qcom,saw2-spm-cmd-spc = [00 20 10 80 30 90 5b 60 03 60 3b 76 76
-				0b 94 5b 80 10 2b 06 26 30 0f];
+				0b 94 5b 80 10 06 26 30 0f];
 		qcom,saw2-spm-cmd-pc = [00 20 10 80 30 90 5b 60 07 60 3b 76 76
-				0b 94 5b 80 10 2b 06 26 30 0f];
+				0b 94 5b 80 10 06 26 30 0f];
 	};
 
 	qcom,spm@f90a9000 {
@@ -57,11 +57,11 @@
 		qcom,saw2-cfg = <0x01>;
 		qcom,saw2-spm-dly= <0x3c102800>;
 		qcom,saw2-spm-ctl = <0x0>;
-		qcom,saw2-spm-cmd-wfi = [60 03 60 76 76 0b 0f];
+		qcom,saw2-spm-cmd-wfi = [60 03 60 0b 0f];
 		qcom,saw2-spm-cmd-spc = [00 20 10 80 30 90 5b 60 03 60 3b 76 76
-				0b 94 5b 80 10 2b 06 26 30 0f];
+				0b 94 5b 80 10 06 26 30 0f];
 		qcom,saw2-spm-cmd-pc = [00 20 10 80 30 90 5b 60 07 60 3b 76 76
-				0b 94 5b 80 10 2b 06 26 30 0f];
+				0b 94 5b 80 10 06 26 30 0f];
 	};
 
 	qcom,spm@f90b9000 {
@@ -74,11 +74,11 @@
 		qcom,saw2-cfg = <0x01>;
 		qcom,saw2-spm-dly= <0x3c102800>;
 		qcom,saw2-spm-ctl = <0x0>;
-		qcom,saw2-spm-cmd-wfi = [60 03 60 76 76 0b 0f];
+		qcom,saw2-spm-cmd-wfi = [60 03 60 0b 0f];
 		qcom,saw2-spm-cmd-spc = [00 20 10 80 30 90 5b 60 03 60 3b 76 76
-				0b 94 5b 80 10 2b 06 26 30 0f];
+				0b 94 5b 80 10 06 26 30 0f];
 		qcom,saw2-spm-cmd-pc = [00 20 10 80 30 90 5b 60 07 60 3b 76 76
-				0b 94 5b 80 10 2b 06 26 30 0f];
+				0b 94 5b 80 10 06 26 30 0f];
 	};
 
 	qcom,spm@f9012000 {
@@ -91,19 +91,16 @@
 		qcom,saw2-cfg = <0x14>;
 		qcom,saw2-spm-dly= <0x3c102800>;
 		qcom,saw2-spm-ctl = <0x0>;
-		qcom,saw2-pmic-data0 = <0x0400009c>;
-		qcom,saw2-pmic-data1 = <0x0000001c>;
+		qcom,saw2-pmic-data0 = <0x02030080>;
+		qcom,saw2-pmic-data1 = <0x00030000>;
 		qcom,vctl-timeout-us = <50>;
 		qcom,vctl-port = <0x0>;
 		qcom,phase-port = <0x1>;
 		qcom,pfm-port = <0x2>;
 		qcom,saw2-spm-cmd-ret = [00 03 00 7b 0f];
-		qcom,saw2-spm-cmd-gdhs = [00 20 32 60 70 80 6b c0 e0 d0 42 07
-				78 1f 80 4e d0 e0 c0 22 6b 50 4b 60 02 32 50 7b
-				0f];
-		qcom,saw2-spm-cmd-pc = [00 32 60 70 80 b0 10 e0 d0 6b c0
-				42 f0 11 07 01 b0 78 1f 80 4e c0 d0 12 e0 6b 50 4b
-				60 02 32 50 f0 7b 0f]; /*APCS_PMIC_OFF_L2RAM_OFF*/
+		qcom,saw2-spm-cmd-pc = [00 32 b0 10 e0 d0 6b c0 42 f0
+				11 07 01 b0 4e c0 d0 12 e0 6b 50 02 32
+				50 f0 7b 0f]; /*APCS_PMIC_OFF_L2RAM_OFF*/
 	};
 
 	qcom,lpm-resources {
@@ -125,8 +122,8 @@
 			qcom,name = "vdd-mem";
 			qcom,type = <0x616F646C>;	/* "ldoa" */
 			qcom,id = <0x03>;
-			qcom,key = <0x7675>;		/* "uv" */
-			qcom,init-value = <1050000>;	/* Super Turbo */
+			qcom,key = <0x6e726f63>;	/* "corn" */
+			qcom,init-value = <3>;		/* Active */
 		};
 
 		qcom,lpm-resources@2 {
@@ -156,10 +153,12 @@
 			qcom,mode = "wfi";
 			qcom,xo = "xo_on";
 			qcom,l2 = "l2_cache_active";
-			qcom,vdd-mem-upper-bound = <1150000>; /* MAX */
-			qcom,vdd-mem-lower-bound = <1050000>; /* ACTIVE */
-			qcom,vdd-dig-upper-bound = <5>; /* MAX */
-			qcom,vdd-dig-lower-bound = <3>;  /* ACTIVE */
+			qcom,vdd-mem-upper-bound = <5>; /* SUPER TURBO */
+			qcom,vdd-mem-lower-bound = <3>; /* NORMAL */
+			qcom,vdd-dig-upper-bound = <5>; /* SUPER TURBO */
+			qcom,vdd-dig-lower-bound = <3>;  /* NORMAL */
+			qcom,irqs-detectable;
+			qcom,gpio-detectable;
 			qcom,latency-us = <1>;
 			qcom,ss-power = <784>;
 			qcom,energy-overhead = <190000>;
@@ -168,78 +167,83 @@
 
 		qcom,lpm-level@1 {
 			reg = <0x1>;
-			qcom,mode = "retention";
-			qcom,xo = "xo_on";
-			qcom,l2 = "l2_cache_active";
-			qcom,vdd-mem-upper-bound = <1150000>; /* MAX */
-			qcom,vdd-mem-lower-bound = <1050000>; /* ACTIVE */
-			qcom,vdd-dig-upper-bound = <5>; /* MAX */
-			qcom,vdd-dig-lower-bound = <3>;  /* ACTIVE */
-			qcom,latency-us = <75>;
-			qcom,ss-power = <735>;
-			qcom,energy-overhead = <77341>;
-			qcom,time-overhead = <105>;
-		};
-
-
-		qcom,lpm-level@2 {
-			reg = <0x2>;
 			qcom,mode = "standalone_pc";
 			qcom,xo = "xo_on";
 			qcom,l2 = "l2_cache_active";
-			qcom,vdd-mem-upper-bound = <1150000>; /* MAX */
-			qcom,vdd-mem-lower-bound = <1050000>; /* ACTIVE */
-			qcom,vdd-dig-upper-bound = <5>; /* MAX */
-			qcom,vdd-dig-lower-bound = <3>;  /* ACTIVE */
-			qcom,latency-us = <95>;
+			qcom,vdd-mem-upper-bound = <5>; /* SUPER TURBO */
+			qcom,vdd-mem-lower-bound = <3>; /* NORMAL */
+			qcom,vdd-dig-upper-bound = <5>; /* SUPER TURBO */
+			qcom,vdd-dig-lower-bound = <3>;  /* NORMAL */
+			qcom,irqs-detectable;
+			qcom,gpio-detectable;
+			qcom,latency-us = <3000>;
 			qcom,ss-power = <725>;
 			qcom,energy-overhead = <99500>;
-			qcom,time-overhead = <130>;
+			qcom,time-overhead = <3130>;
+		};
+
+		qcom,lpm-level@2 {
+			reg = <0x2>;
+			qcom,mode = "pc";
+			qcom,xo = "xo_on";
+			qcom,l2 = "l2_cache_retention";
+			qcom,vdd-mem-upper-bound = <5>; /* SUPER TURBO */
+			qcom,vdd-mem-lower-bound = <3>; /* NORMAL */
+			qcom,vdd-dig-upper-bound = <5>; /* SUPER TURBO */
+			qcom,vdd-dig-lower-bound = <3>;  /* NORMAL */
+			qcom,irqs-detectable;
+			qcom,gpio-detectable;
+			qcom,latency-us = <8000>;
+			qcom,ss-power = <138>;
+			qcom,energy-overhead = <1208400>;
+			qcom,time-overhead = <9200>;
 		};
 
 		qcom,lpm-level@3 {
 			reg = <0x3>;
 			qcom,mode = "pc";
 			qcom,xo = "xo_on";
-			qcom,l2 = "l2_cache_gdhs";
-			qcom,vdd-mem-upper-bound = <1150000>; /* MAX */
-			qcom,vdd-mem-lower-bound = <1050000>; /* ACTIVE */
-			qcom,vdd-dig-upper-bound = <5>; /* MAX */
-			qcom,vdd-dig-lower-bound = <3>;  /* ACTIVE */
-			qcom,latency-us = <2000>;
-			qcom,ss-power = <138>;
-			qcom,energy-overhead = <1208400>;
-			qcom,time-overhead = <3200>;
+			qcom,l2 = "l2_cache_pc";
+			qcom,vdd-mem-upper-bound = <3>; /* NORMAL */
+			qcom,vdd-mem-lower-bound = <2>;  /* SVS SOC */
+			qcom,vdd-dig-upper-bound = <3>;  /* NORMAL */
+			qcom,vdd-dig-lower-bound = <2>;  /* SVS SOC */
+			qcom,irqs-detectable;
+			qcom,gpio-detectable;
+			qcom,latency-us = <9000>;
+			qcom,ss-power = <110>;
+			qcom,energy-overhead = <1250300>;
+			qcom,time-overhead = <9500>;
 		};
 
 		qcom,lpm-level@4 {
 			reg = <0x4>;
 			qcom,mode = "pc";
-			qcom,xo = "xo_on";
+			qcom,xo = "xo_off";
 			qcom,l2 = "l2_cache_pc";
-			qcom,vdd-mem-upper-bound = <1050000>; /* ACTIVE */
-			qcom,vdd-mem-lower-bound = <750000>;  /* RETENTION HIGH */
-			qcom,vdd-dig-upper-bound = <3>;  /* ACTIVE */
-			qcom,vdd-dig-lower-bound = <2>;  /* RETENTION HIGH */
-			qcom,latency-us = <3000>;
-			qcom,ss-power = <110>;
-			qcom,energy-overhead = <1250300>;
-			qcom,time-overhead = <3500>;
+			qcom,vdd-mem-upper-bound = <5>; /* SUPER TURBO */
+			qcom,vdd-mem-lower-bound = <3>; /* NORMAL */
+			qcom,vdd-dig-upper-bound = <5>; /* SUPER TURBO */
+			qcom,vdd-dig-lower-bound = <3>;  /* NORMAL */
+			qcom,latency-us = <16300>;
+			qcom,ss-power = <63>;
+			qcom,energy-overhead = <2128000>;
+			qcom,time-overhead = <24200>;
 		};
 
 		qcom,lpm-level@5 {
 			reg = <0x5>;
 			qcom,mode = "pc";
 			qcom,xo = "xo_off";
-			qcom,l2 = "l2_cache_gdhs";
-			qcom,vdd-mem-upper-bound = <1150000>; /* MAX */
-			qcom,vdd-mem-lower-bound = <1050000>; /* ACTIVE */
-			qcom,vdd-dig-upper-bound = <5>; /* MAX */
-			qcom,vdd-dig-lower-bound = <3>;  /* ACTIVE */
-			qcom,latency-us = <3000>;
-			qcom,ss-power = <68>;
-			qcom,energy-overhead = <1350200>;
-			qcom,time-overhead = <4000>;
+			qcom,l2 = "l2_cache_pc";
+			qcom,vdd-mem-upper-bound = <3>; /* NORMAL */
+			qcom,vdd-mem-lower-bound = <2>;  /* SVS SOC */
+			qcom,vdd-dig-upper-bound = <3>;  /* NORMAL */
+			qcom,vdd-dig-lower-bound = <2>;  /* SVS SOC */
+			qcom,latency-us = <24000>;
+			qcom,ss-power = <10>;
+			qcom,energy-overhead = <3202600>;
+			qcom,time-overhead = <33000>;
 		};
 
 		qcom,lpm-level@6 {
@@ -247,44 +251,14 @@
 			qcom,mode = "pc";
 			qcom,xo = "xo_off";
 			qcom,l2 = "l2_cache_pc";
-			qcom,vdd-mem-upper-bound = <1150000>; /* MAX */
-			qcom,vdd-mem-lower-bound = <1050000>; /* ACTIVE */
-			qcom,vdd-dig-upper-bound = <5>; /* MAX */
-			qcom,vdd-dig-lower-bound = <3>;  /* ACTIVE */
-			qcom,latency-us = <10300>;
-			qcom,ss-power = <63>;
-			qcom,energy-overhead = <2128000>;
-			qcom,time-overhead = <18200>;
-		};
-
-		qcom,lpm-level@7 {
-			reg = <0x7>;
-			qcom,mode = "pc";
-			qcom,xo = "xo_off";
-			qcom,l2 = "l2_cache_pc";
-			qcom,vdd-mem-upper-bound = <1050000>; /* ACTIVE */
-			qcom,vdd-mem-lower-bound = <750000>;  /* RETENTION HIGH */
-			qcom,vdd-dig-upper-bound = <3>;  /* ACTIVE */
-			qcom,vdd-dig-lower-bound = <2>;  /* RETIONTION HIGH */
-			qcom,latency-us = <18000>;
-			qcom,ss-power = <10>;
-			qcom,energy-overhead = <3202600>;
-			qcom,time-overhead = <27000>;
-		};
-
-		qcom,lpm-level@8 {
-			reg = <0x8>;
-			qcom,mode = "pc";
-			qcom,xo = "xo_off";
-			qcom,l2 = "l2_cache_pc";
-			qcom,vdd-mem-upper-bound = <750000>; /* RETENTION HIGH */
-			qcom,vdd-mem-lower-bound = <750000>; /* RETENTION LOW */
-			qcom,vdd-dig-upper-bound = <2>; /* RETENTION HIGH */
-			qcom,vdd-dig-lower-bound = <0>; /* RETENTION LOW */
-			qcom,latency-us = <20000>;
+			qcom,vdd-mem-upper-bound = <2>; /* SVS SOC */
+			qcom,vdd-mem-lower-bound = <0>; /* RETENTION */
+			qcom,vdd-dig-upper-bound = <2>; /* SVS SOC */
+			qcom,vdd-dig-lower-bound = <0>; /* RETENTION */
+			qcom,latency-us = <26000>;
 			qcom,ss-power = <2>;
 			qcom,energy-overhead = <4252000>;
-			qcom,time-overhead = <32000>;
+			qcom,time-overhead = <38000>;
 		};
 	};
 
@@ -306,6 +280,7 @@
 		qcom,gic-map = <47 172>, /* usb2_hsic_async_wakeup_irq */
 			<53 104>, /* mdss_irq */
 			<62 222>, /* ee0_krait_hlos_spmi_periph_irq */
+			<2 216>, /* tsens_upper_lower_int */
 			<0xff 56>,  /* q6_wdog_expired_irq */
 			<0xff 57>,  /* mss_to_apps_irq(0) */
 			<0xff 58>,  /* mss_to_apps_irq(1) */
@@ -393,6 +368,17 @@
 		qcom,use-sync-timer;
 	};
 
+	qcom,rpm-log@fc19dc00 {
+		compatible = "qcom,rpm-log";
+		reg = <0xfc19dc00 0x4000>;
+		qcom,rpm-addr-phys = <0xfc000000>;
+		qcom,offset-version = <4>;
+		qcom,offset-page-buffer-addr = <36>;
+		qcom,offset-log-len = <40>;
+		qcom,offset-log-len-mask = <44>;
+		qcom,offset-page-indices = <56>;
+	};
+
 	qcom,rpm-stats@0xfc19dbd0{
 		compatible = "qcom,rpm-stats";
 		reg = <0xfc19dbd0 0x1000>;
diff --git a/arch/arm/boot/dts/msm8226-qrd.dts b/arch/arm/boot/dts/msm8226-qrd.dts
index df74bf9..4879691 100644
--- a/arch/arm/boot/dts/msm8226-qrd.dts
+++ b/arch/arm/boot/dts/msm8226-qrd.dts
@@ -13,11 +13,11 @@
 /dts-v1/;
 /include/ "msm8226.dtsi"
 /include/ "dsi-panel-nt35590-720p-video.dtsi"
-/include/ "msm8226-camera-sensor-cdp-mtp-qrd.dtsi"
+/include/ "msm8226-camera-sensor-cdp-qrd.dtsi"
 
 / {
 	model = "Qualcomm MSM 8226 QRD";
-	compatible = "qcom,msm8226-qrd", "qcom,msm8226";
+	compatible = "qcom,msm8226-qrd", "qcom,msm8226", "qcom,qrd";
 	qcom,msm-id = <145 11 0>;
 
 	serial@f991f000 {
@@ -197,6 +197,13 @@
 				qcom,id = <0>;
 			};
 		};
+
+		qcom,vibrator@c000 {
+			status = "okay";
+			qcom,vib-timeout-ms = <15000>;
+			qcom,vib-vtg-level-mV = <3100>;
+		};
+
 	};
 };
 
diff --git a/arch/arm/boot/dts/msm8226-regulator.dtsi b/arch/arm/boot/dts/msm8226-regulator.dtsi
index 9c21707..70731d2 100644
--- a/arch/arm/boot/dts/msm8226-regulator.dtsi
+++ b/arch/arm/boot/dts/msm8226-regulator.dtsi
@@ -44,6 +44,9 @@
 		qcom,pvs-corner-ceiling-nom  =  <975000 1075000 1200000 1200000>;
 		qcom,pvs-corner-ceiling-fast =  <900000 1000000 1140000 1140000>;
 		vdd-apc-supply = <&pm8226_s2>;
+		vdd-mx-supply = <&pm8226_l3_ao>;
+		qcom,vdd-mx-vmax = <1350000>;
+		qcom,vdd-mx-vmin-method = <1>;
 	};
 };
 
@@ -64,7 +67,7 @@
 			regulator-min-microvolt = <1>;
 			regulator-max-microvolt = <7>;
 			qcom,use-voltage-corner;
-			qcom,consumer-supplies = "vdd_dig", "";
+			qcom,consumer-supplies = "vdd_dig", "", "vdd_sr2_dig", "";
 		};
 		pm8226_s1_corner_ao: regulator-s1-corner-ao {
 			compatible = "qcom,rpm-regulator-smd";
diff --git a/arch/arm/boot/dts/msm8226-sim.dts b/arch/arm/boot/dts/msm8226-sim.dts
index b6590b3..a86dc48 100644
--- a/arch/arm/boot/dts/msm8226-sim.dts
+++ b/arch/arm/boot/dts/msm8226-sim.dts
@@ -16,7 +16,7 @@
 
 / {
 	model = "Qualcomm MSM 8226 Simulator";
-	compatible = "qcom,msm8226-sim", "qcom,msm8226";
+	compatible = "qcom,msm8226-sim", "qcom,msm8226", "qcom,sim";
 	qcom,msm-id = <145 16 0>;
 
 	serial@f991f000 {
diff --git a/arch/arm/boot/dts/msm8226-smp2p.dtsi b/arch/arm/boot/dts/msm8226-smp2p.dtsi
index bdfc768..91029e2 100644
--- a/arch/arm/boot/dts/msm8226-smp2p.dtsi
+++ b/arch/arm/boot/dts/msm8226-smp2p.dtsi
@@ -174,6 +174,27 @@
 		#interrupt-cells = <2>;
 	};
 
+	smp2pgpio_ssr_smp2p_4_in: qcom,smp2pgpio-ssr-smp2p-4-in {
+		compatible = "qcom,smp2pgpio";
+		qcom,entry-name = "slave-kernel";
+		qcom,remote-pid = <4>;
+		qcom,is-inbound;
+		gpio-controller;
+		#gpio-cells = <2>;
+		interrupt-controller;
+		#interrupt-cells = <2>;
+	};
+
+	smp2pgpio_ssr_smp2p_4_out: qcom,smp2pgpio-ssr-smp2p-4-out {
+		compatible = "qcom,smp2pgpio";
+		qcom,entry-name = "master-kernel";
+		qcom,remote-pid = <4>;
+		gpio-controller;
+		#gpio-cells = <2>;
+		interrupt-controller;
+		#interrupt-cells = <2>;
+	};
+
 	qcom,smp2pgpio_test_smp2p_4_out {
 		compatible = "qcom,smp2pgpio_test_smp2p_4_out";
 		gpios = <&smp2pgpio_smp2p_4_out 0 0>;
diff --git a/arch/arm/boot/dts/msm8226.dtsi b/arch/arm/boot/dts/msm8226.dtsi
index b34fa1f..75cf6e5 100644
--- a/arch/arm/boot/dts/msm8226.dtsi
+++ b/arch/arm/boot/dts/msm8226.dtsi
@@ -129,6 +129,35 @@
 		interrupts = <0 94 0>;
 	};
 
+	qcom,usbbam@f9a44000 {
+		compatible = "qcom,usb-bam-msm";
+		reg = <0xf9a44000 0x11000>;
+		reg-names = "hsusb";
+		interrupts = <0 135 0>;
+		interrupt-names = "hsusb";
+		qcom,usb-bam-num-pipes = <16>;
+		qcom,usb-bam-fifo-baseaddr = <0xfe803000>;
+		qcom,ignore-core-reset-ack;
+		qcom,disable-clk-gating;
+
+		qcom,pipe0 {
+			label = "hsusb-qdss-in-0";
+			qcom,usb-bam-mem-type = <3>;
+			qcom,bam-type = <1>;
+			qcom,dir = <1>;
+			qcom,pipe-num = <0>;
+			qcom,peer-bam = <1>;
+			qcom,src-bam-physical-address = <0xfc37c000>;
+			qcom,src-bam-pipe-index = <0>;
+			qcom,dst-bam-physical-address = <0xf9a44000>;
+			qcom,dst-bam-pipe-index = <2>;
+			qcom,data-fifo-offset = <0x0>;
+			qcom,data-fifo-size = <0x600>;
+			qcom,descriptor-fifo-offset = <0x600>;
+			qcom,descriptor-fifo-size = <0x200>;
+		};
+	};
+
         usb@f9a55000 {
 		compatible = "qcom,hsusb-otg";
 		reg = <0xf9a55000 0x400>;
@@ -381,17 +410,7 @@
 	qcom,msm-pcm-hostless {
 		compatible = "qcom,msm-pcm-hostless";
 	};
-	qcom,pronto@fb21b000 {
-		compatible = "qcom,pil-pronto";
-		reg = <0xfb21b000 0x3000>,
-		      <0xfc401700 0x4>,
-		      <0xfd485300 0xc>;
-		reg-names = "pmu_base", "clk_base", "halt_base";
-		interrupts = <0 149 1>;
-		vdd_pronto_pll-supply = <&pm8226_l12>;
 
-		qcom,firmware-name = "wcnss";
-	};
 	qcom,wcnss-wlan@fb000000 {
 		compatible = "qcom,wcnss_wlan";
 		reg = <0xfb000000 0x280000>;
@@ -622,6 +641,12 @@
 		vdd_pronto_pll-supply = <&pm8226_l8>;
 
 		qcom,firmware-name = "wcnss";
+
+		/* GPIO input from wcnss */
+		qcom,gpio-err-fatal = <&smp2pgpio_ssr_smp2p_4_in 0 0>;
+
+		/* GPIO output to wcnss */
+		qcom,gpio-force-stop = <&smp2pgpio_ssr_smp2p_4_out 0 0>;
 	};
 
 	qcom,iris-fm {
diff --git a/arch/arm/boot/dts/msm8610-bus.dtsi b/arch/arm/boot/dts/msm8610-bus.dtsi
new file mode 100644
index 0000000..50066f3
--- /dev/null
+++ b/arch/arm/boot/dts/msm8610-bus.dtsi
@@ -0,0 +1,978 @@
+/* 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.
+ */
+
+/ {
+	msm-mmss-noc@fc478000 {
+		compatible = "msm-bus-fabric";
+		reg = <0xfc478000 0x00004000>;
+		cell-id = <2048>;
+		label = "msm_mmss_noc";
+		qcom,fabclk-dual = "bus_clk";
+		qcom,fabclk-active = "bus_a_clk";
+		qcom,ntieredslaves = <0>;
+		qcom,qos-freq = <4800>;
+		qcom,hw-sel = "NoC";
+		qcom,rpm-en;
+
+		mas-mdp-port0 {
+			cell-id = <22>;
+			label = "mas-mdp-port0";
+			qcom,masterp = <2>;
+			qcom,tier = <2>;
+			qcom,hw-sel = "NoC";
+			qcom,perm-mode = "Bypass";
+			qcom,mode = "Bypass";
+			qcom,qport = <0>;
+			qcom,ws = <10000>;
+			qcom,mas-hw-id = <8>;
+		};
+
+		mas-vfe {
+			cell-id = <29>;
+			label = "mas-vfe";
+			qcom,masterp = <3>;
+			qcom,tier = <2>;
+			qcom,hw-sel = "NoC";
+			qcom,perm-mode = "Bypass";
+			qcom,mode = "Bypass";
+			qcom,ws = <10000>;
+			qcom,qport = <2>;
+			qcom,mas-hw-id = <11>;
+		};
+
+		mas-mdpe {
+			cell-id = <92>;
+			label = "mas-mdpe";
+			qcom,masterp = <4>;
+			qcom,tier = <2>;
+			qcom,hw-sel = "NoC";
+			qcom,perm-mode = "Bypass";
+			qcom,mode = "Bypass";
+			qcom,ws = <10000>;
+			qcom,qport = <7>;
+			qcom,mas-hw-id = <11>;
+		};
+
+		fab-bimc {
+			cell-id = <0>;
+			label = "fab-bimc";
+			qcom,gateway;
+			qcom,slavep = <16>;
+			qcom,buswidth = <16>;
+			qcom,hw-sel = "NoC";
+			qcom,slv-hw-id = <16>;
+		};
+
+		slv-camera-cfg {
+			cell-id = <589>;
+			label = "slv-camera-cfg";
+			qcom,slavep = <0>;
+			qcom,tier = <2>;
+			qcom,buswidth = <16>;
+			qcom,hw-sel = "NoC";
+			qcom,slv-hw-id = <3>;
+		};
+
+		slv-display-cfg {
+			cell-id = <590>;
+			label = "slv-display-cfg";
+			qcom,slavep = <1>;
+			qcom,tier = <2>;
+			qcom,buswidth = <16>;
+			qcom,hw-sel = "NoC";
+			qcom,slv-hw-id = <4>;
+		};
+
+		slv-cpr-cfg {
+			cell-id = <592>;
+			label = "slv-cpr-cfg";
+			qcom,slavep = <3>;
+			qcom,tier = <2>;
+			qcom,buswidth = <16>;
+			qcom,hw-sel = "NoC";
+			qcom,slv-hw-id = <6>;
+		};
+
+		slv-cpr-xpu-cfg {
+			cell-id = <593>;
+			label = "slv-cpr-xpu-cfg";
+			qcom,slavep = <4>;
+			qcom,tier = <2>;
+			qcom,buswidth = <16>;
+			qcom,hw-sel = "NoC";
+			qcom,slv-hw-id = <7>;
+		};
+
+		slv-misc-cfg {
+			cell-id = <594>;
+			label = "slv-misc-cfg";
+			qcom,slavep = <6>;
+			qcom,tier = <2>;
+			qcom,buswidth = <16>;
+			qcom,hw-sel = "NoC";
+			qcom,slv-hw-id = <8>;
+		};
+
+		slv-misc-xpu-cfg {
+			cell-id = <595>;
+			label = "slv-misc-xpu-cfg";
+			qcom,slavep = <7>;
+			qcom,tier = <2>;
+			qcom,buswidth = <16>;
+			qcom,hw-sel = "NoC";
+			qcom,slv-hw-id = <9>;
+		};
+
+		slv-gfx3d-cfg {
+			cell-id = <598>;
+			label = "slv-gfx3d-cfg";
+			qcom,slavep = <9>;
+			qcom,tier = <2>;
+			qcom,buswidth = <16>;
+			qcom,hw-sel = "NoC";
+			qcom,slv-hw-id = <11>;
+		};
+
+		slv-mmss-clk-cfg {
+			cell-id = <599>;
+			label = "slv-mmss-clk-cfg";
+			qcom,slavep = <11>;
+			qcom,tier = <2>;
+			qcom,buswidth = <16>;
+			qcom,hw-sel = "NoC";
+			qcom,slv-hw-id = <12>;
+		};
+
+		slv-mmss-clk-xpu-cfg {
+			cell-id = <600>;
+			label = "slv-mmss-clk-xpu-cfg";
+			qcom,slavep = <12>;
+			qcom,tier = <2>;
+			qcom,buswidth = <16>;
+			qcom,hw-sel = "NoC";
+			qcom,slv-hw-id = <13>;
+		};
+
+		slv-mnoc-mpu-cfg {
+			cell-id = <601>;
+			label = "slv-mnoc-mpu-cfg";
+			qcom,slavep = <13>;
+			qcom,tier = <2>;
+			qcom,buswidth = <16>;
+			qcom,hw-sel = "NoC";
+			qcom,slv-hw-id = <14>;
+		};
+
+		slv-onoc-mpu-cfg {
+			cell-id = <602>;
+			label = "slv-onoc-mpu-cfg";
+			qcom,slavep = <14>;
+			qcom,tier = <2>;
+			qcom,buswidth = <16>;
+			qcom,hw-sel = "NoC";
+			qcom,slv-hw-id = <15>;
+		};
+
+		slv-service-mnoc {
+			cell-id = <603>;
+			label = "slv-service-mnoc";
+			qcom,slavep = <18>;
+			qcom,tier = <2>;
+			qcom,buswidth = <16>;
+			qcom,hw-sel = "NoC";
+			qcom,slv-hw-id = <17>;
+		};
+
+		slv-dsi-cfg {
+			cell-id = <649>;
+			label = "slv-dsi-cfg";
+			qcom,slavep = <19>;
+			qcom,tier = <2>;
+			qcom,buswidth = <16>;
+			qcom,hw-sel = "NoC";
+			qcom,slv-hw-id = <19>;
+		};
+	};
+
+	msm-sys-noc@fc460000 {
+		compatible = "msm-bus-fabric";
+		reg = <0xfc460000 0x00004000>;
+		cell-id = <1024>;
+		label = "msm_sys_noc";
+		qcom,fabclk-dual = "bus_clk";
+		qcom,fabclk-active = "bus_a_clk";
+		qcom,ntieredslaves = <0>;
+		qcom,qos-freq = <4800>;
+		qcom,hw-sel = "NoC";
+		qcom,rpm-en;
+
+		mas-lpass-ahb {
+			cell-id = <52>;
+			label = "mas-lpass-ahb";
+			qcom,masterp = <0>;
+			qcom,tier = <2>;
+			qcom,mas-hw-id = <18>;
+		};
+
+		mas-qdss-bam {
+			cell-id = <53>;
+			label = "mas-qdss-bam";
+			qcom,masterp = <1>;
+			qcom,tier = <2>;
+			qcom,mas-hw-id = <19>;
+		};
+
+		mas-snoc-cfg {
+			cell-id = <54>;
+			label = "mas-snoc-cfg";
+			qcom,masterp = <2>;
+			qcom,tier = <2>;
+			qcom,mas-hw-id = <20>;
+		};
+
+		fab-bimc {
+			cell-id = <0>;
+			label= "fab-bimc";
+			qcom,gateway;
+			qcom,slavep = <7>;
+			qcom,masterp = <3>;
+			qcom,buswidth = <8>;
+			qcom,mas-hw-id = <21>;
+			qcom,slv-hw-id = <24>;
+		};
+
+		fab-cnoc {
+			cell-id = <5120>;
+			label = "fab-cnoc";
+			qcom,gateway;
+			qcom,slavep = <8>;
+			qcom,masterp = <4>;
+			qcom,buswidth = <8>;
+			qcom,mas-hw-id = <22>;
+			qcom,slv-hw-id = <25>;
+		};
+
+		fab-pnoc {
+			cell-id = <4096>;
+			label = "fab-pnoc";
+			qcom,gateway;
+			qcom,slavep = <10>;
+			qcom,masterp = <10>;
+			qcom,buswidth = <8>;
+			qcom,qport = <8>;
+			qcom,mas-hw-id = <29>;
+			qcom,slv-hw-id = <28>;
+			qcom,mode = "Fixed";
+			qcom,prio-rd = <2>;
+			qcom,prio-wr = <2>;
+		};
+
+		fab-ovnoc {
+			cell-id = <6144>;
+			label = "fab-ovnoc";
+			qcom,gateway;
+			qcom,buswidth = <8>;
+			qcom,mas-hw-id = <53>;
+			qcom,slv-hw-id = <77>;
+		};
+
+		mas-crypto-core0 {
+			cell-id = <55>;
+			label = "mas-crypto-core0";
+			qcom,masterp = <5>;
+			qcom,tier = <2>;
+			qcom,mas-hw-id = <23>;
+		};
+
+		mas-mss {
+			cell-id = <38>;
+			label = "mas-mss";
+			qcom,masterp = <7>;
+			qcom,tier = <2>;
+			qcom,mas-hw-id = <26>;
+		};
+
+		mas-mss-nav {
+			cell-id = <57>;
+			label = "mas-mss-nav";
+			qcom,masterp = <8>;
+			qcom,tier = <2>;
+			qcom,mas-hw-id = <27>;
+		};
+
+		mas-ocmem-dma {
+			cell-id = <58>;
+			label = "mas-ocmem-dma";
+			qcom,masterp = <9>;
+			qcom,tier = <2>;
+			qcom,mode = "Fixed";
+			qcom,qport = <7>;
+			qcom,mas-hw-id = <28>;
+		};
+
+		mas-wcss {
+			cell-id = <59>;
+			label = "mas-wcss";
+			qcom,masterp = <11>;
+			qcom,tier = <2>;
+			qcom,mas-hw-id = <30>;
+		};
+
+		mas-qdss-etr {
+			cell-id = <60>;
+			label = "mas-qdss-etr";
+			qcom,masterp = <12>;
+			qcom,tier = <2>;
+			qcom,qport = <10>;
+			qcom,mode = "Fixed";
+			qcom,mas-hw-id = <31>;
+		};
+
+		slv-ocmem {
+			cell-id = <604>;
+			label = "slv-gmem";
+			qcom,slavep = <15>;
+			qcom,tier = <2>;
+			qcom,buswidth = <8>;
+			qcom,slv-hw-id = <18>;
+		};
+
+		slv-ampss {
+			cell-id = <520>;
+			label = "slv-ampss";
+			qcom,slavep = <1>;
+			qcom,tier = <2>;
+			qcom,buswidth = <8>;
+			qcom,slv-hw-id = <20>;
+		};
+
+		slv-lpass {
+			cell-id = <522>;
+			label = "slv-lpass";
+			qcom,slavep = <2>;
+			qcom,tier = <2>;
+			qcom,buswidth = <8>;
+			qcom,slv-hw-id = <21>;
+		};
+
+		slv-wcss {
+			cell-id = <584>;
+			label = "slv-wcss";
+			qcom,slavep = <6>;
+			qcom,tier = <2>;
+			qcom,buswidth = <8>;
+			qcom,slv-hw-id = <23>;
+		};
+
+		slv-ocimem {
+			cell-id = <585>;
+			label = "slv-ocimem";
+			qcom,slavep = <10>;
+			qcom,tier = <2>;
+			qcom,buswidth = <8>;
+			qcom,slv-hw-id = <26>;
+		};
+
+		slv-service-snoc {
+			cell-id = <587>;
+			label = "slv-service-snoc";
+			qcom,slavep = <11>;
+			qcom,tier = <2>;
+			qcom,buswidth = <8>;
+			qcom,slv-hw-id = <29>;
+		};
+
+		slv-qdss-stm {
+			cell-id = <588>;
+			label = "slv-qdss-stm";
+			qcom,slavep = <12>;
+			qcom,tier = <2>;
+			qcom,buswidth = <8>;
+			qcom,slv-hw-id = <30>;
+		};
+
+	};
+
+	msm-periph-noc@fc468000 {
+		compatible = "msm-bus-fabric";
+		reg = <0xfc468000 0x00004000>;
+		cell-id = <4096>;
+		label = "msm_periph_noc";
+		qcom,fabclk-dual = "bus_clk";
+		qcom,fabclk-active = "bus_a_clk";
+		qcom,ntieredslaves = <0>;
+		qcom,hw-sel = "NoC";
+		qcom,rpm-en;
+
+		mas-pnoc-cfg {
+			cell-id = <88>;
+			label = "mas-pnoc-cfg";
+			qcom,masterp = <7>;
+			qcom,tier = <2>;
+			qcom,buswidth = <8>;
+			qcom,mas-hw-id = <43>;
+		};
+
+		mas-sdcc-1 {
+			cell-id = <78>;
+			label = "mas-sdcc-1";
+			qcom,masterp = <0>;
+			qcom,tier = <2>;
+			qcom,buswidth = <8>;
+			qcom,mas-hw-id = <33>;
+		};
+
+		mas-sdcc-2 {
+			cell-id = <81>;
+			label = "mas-sdcc-2";
+			qcom,masterp = <2>;
+			qcom,tier = <2>;
+			qcom,buswidth = <8>;
+			qcom,mas-hw-id = <35>;
+		};
+
+		mas-blsp-1 {
+			cell-id = <86>;
+			label = "mas-blsp-1";
+			qcom,masterp = <5>;
+			qcom,tier = <2>;
+			qcom,buswidth = <8>;
+			qcom,mas-hw-id = <41>;
+		};
+
+		mas-usb-hs {
+			cell-id = <87>;
+			label = "mas-usb-hs";
+			qcom,masterp = <6>;
+			qcom,tier = <2>;
+			qcom,buswidth = <8>;
+			qcom,mas-hw-id = <42>;
+		};
+
+		fab-snoc {
+			cell-id = <1024>;
+			label = "fab-snoc";
+			qcom,gateway;
+			qcom,slavep = <12>;
+			qcom,masterp = <8>;
+			qcom,tier = <2>;
+			qcom,buswidth = <8>;
+			qcom,slv-hw-id = <45>;
+			qcom,mas-hw-id = <44>;
+		};
+
+		slv-sdcc-1 {
+			cell-id = <606>;
+			label = "slv-sdcc-1";
+			qcom,slavep = <0>;
+			qcom,tier = <2>;
+			qcom,buswidth = <8>;
+			qcom,slv-hw-id = <31>;
+		};
+
+		slv-sdcc-2 {
+			cell-id = <608>;
+			label = "slv-sdcc-2";
+			qcom,slavep = <2>;
+			qcom,tier = <2>;
+			qcom,buswidth = <8>;
+			qcom,slv-hw-id = <33>;
+		};
+
+		slv-blsp-1 {
+			cell-id = <613>;
+			label = "slv-blsp-1";
+			qcom,slavep = <5>;
+			qcom,tier = <2>;
+			qcom,buswidth = <8>;
+			qcom,slv-hw-id = <39>;
+		};
+
+		slv-usb-hs {
+			cell-id = <614>;
+			label = "slv-usb-hs";
+			qcom,slavep = <6>;
+			qcom,tier = <2>;
+			qcom,buswidth = <8>;
+			qcom,slv-hw-id = <40>;
+		};
+
+		slv-pdm	{
+			cell-id = <615>;
+			label = "slv-pdm";
+			qcom,slavep = <7>;
+			qcom,tier = <2>;
+			qcom,buswidth = <8>;
+			qcom,slv-hw-id = <41>;
+		};
+
+		slv-periph-apu-cfg {
+			cell-id = <616>;
+			label = "slv-periph-apu-cfg";
+			qcom,slavep = <8>;
+			qcom,tier = <2>;
+			qcom,buswidth = <8>;
+			qcom,slv-hw-id = <42>;
+		};
+
+		slv-pnoc-mpu-cfg {
+			cell-id = <617>;
+			label = "slv-pnoc-mpu-cfg";
+			qcom,slavep = <9>;
+			qcom,tier = <2>;
+			qcom,buswidth = <8>;
+			qcom,slv-hw-id = <43>;
+		};
+
+		slv-prng {
+			cell-id = <618>;
+			label = "slv-prng";
+			qcom,slavep = <10>;
+			qcom,tier = <2>;
+			qcom,buswidth = <8>;
+			qcom,slv-hw-id = <44>;
+		};
+
+		slv-service-pnoc {
+			cell-id = <619>;
+			label = "slv-service-pnoc";
+			qcom,slavep = <12>;
+			qcom,tier = <2>;
+			qcom,buswidth = <8>;
+			qcom,slv-hw-id = <46>;
+		};
+
+	};
+
+	msm-config-noc@fc480000 {
+		compatible = "msm-bus-fabric";
+		reg = <0xfc480000 0x00004000>;
+		cell-id = <5120>;
+		label = "msm_config_noc";
+		qcom,fabclk-dual = "bus_clk";
+		qcom,fabclk-active = "bus_a_clk";
+		qcom,ntieredslaves = <0>;
+		qcom,hw-sel = "NoC";
+		qcom,rpm-en;
+
+		mas-rpm-inst {
+			cell-id = <72>;
+			label = "mas-rpm-inst";
+			qcom,masterp = <0>;
+			qcom,tier = <2>;
+			qcom,buswidth = <8>;
+			qcom,mas-hw-id = <45>;
+		};
+
+		mas-rpm-data {
+			cell-id = <73>;
+			label = "mas-rpm-data";
+			qcom,masterp = <1>;
+			qcom,tier = <2>;
+			qcom,buswidth = <8>;
+			qcom,mas-hw-id = <46>;
+		};
+
+		mas-rpm-sys {
+			cell-id = <74>;
+			label = "mas-rpm-sys";
+			qcom,masterp = <2>;
+			qcom,tier = <2>;
+			qcom,buswidth = <8>;
+			qcom,mas-hw-id = <47>;
+		};
+
+		mas-dehr {
+			cell-id = <75>;
+			label = "mas-dehr";
+			qcom,masterp = <3>;
+			qcom,tier = <2>;
+			qcom,buswidth = <8>;
+			qcom,mas-hw-id = <48>;
+		};
+
+		mas-qdss-dsp {
+			cell-id = <76>;
+			label = "mas-qdss-dap";
+			qcom,masterp = <4>;
+			qcom,tier = <2>;
+			qcom,buswidth = <8>;
+			qcom,mas-hw-id = <49>;
+		};
+
+		mas-spdm {
+			cell-id = <36>;
+			label = "mas-spdm";
+			qcom,masterp = <5>;
+			qcom,tier = <2>;
+			qcom,buswidth = <8>;
+			qcom,mas-hw-id = <50>;
+		};
+
+		mas-tic	{
+			cell-id = <77>;
+			label = "mas-tic";
+			qcom,masterp = <6>;
+			qcom,tier = <2>;
+			qcom,buswidth = <8>;
+			qcom,mas-hw-id = <51>;
+		};
+
+		slv-clk-ctl {
+			cell-id = <620>;
+			label = "slv-clk-ctl";
+			qcom,slavep = <1>;
+			qcom,tier = <2>;
+			qcom,buswidth = <8>;
+			qcom,slv-hw-id = <47>;
+		};
+
+		slv-cnoc-mss {
+			cell-id = <621>;
+			label = "slv-cnoc-mss";
+			qcom,slavep = <2>;
+			qcom,tier = <2>;
+			qcom,buswidth = <8>;
+			qcom,slv-hw-id = <48>;
+		};
+
+		slv-security {
+			cell-id = <622>;
+			label = "slv-security";
+			qcom,slavep = <3>;
+			qcom,tier = <2>;
+			qcom,buswidth = <8>;
+			qcom,slv-hw-id = <49>;
+		};
+
+		slv-tcsr {
+			cell-id = <623>;
+			label = "slv-tcsr";
+			qcom,slavep = <4>;
+			qcom,tier = <2>;
+			qcom,buswidth = <8>;
+			qcom,slv-hw-id = <50>;
+		};
+
+		slv-tlmm {
+			cell-id = <624>;
+			label = "slv-tlmm";
+			qcom,slavep = <5>;
+			qcom,tier = <2>;
+			qcom,buswidth = <8>;
+			qcom,slv-hw-id = <51>;
+		};
+
+		slv-crypto-0-cfg {
+			cell-id = <625>;
+			label = "slv-crypto-0-cfg";
+			qcom,slavep = <6>;
+			qcom,tier = <2>;
+			qcom,buswidth = <8>;
+			qcom,slv-hw-id = <52>;
+		};
+
+		slv-imem-cfg {
+			cell-id = <627>;
+			label = "slv-imem-cfg";
+			qcom,slavep = <7>;
+			qcom,tier = <2>;
+			qcom,buswidth = <8>;
+			qcom,slv-hw-id = <54>;
+		};
+
+		slv-message-ram	{
+			cell-id = <628>;
+			label = "slv-message-ram";
+			qcom,slavep = <8>;
+			qcom,tier = <2>;
+			qcom,buswidth = <8>;
+			qcom,slv-hw-id = <55>;
+		};
+
+		slv-bimc-cfg {
+			cell-id = <629>;
+			label = "slv-bimc-cfg";
+			qcom,slavep = <9>;
+			qcom,tier = <2>;
+			qcom,buswidth = <8>;
+			qcom,slv-hw-id = <56>;
+		};
+
+		slv-boot-rom {
+			cell-id = <630>;
+			label = "slv-boot-rom";
+			qcom,slavep = <10>;
+			qcom,tier = <2>;
+			qcom,buswidth = <8>;
+			qcom,slv-hw-id = <57>;
+		};
+
+		slv-pmic-arb {
+			cell-id = <632>;
+			label = "slv-pmic-arb";
+			qcom,slavep = <12>;
+			qcom,tier = <2>;
+			qcom,buswidth = <8>;
+			qcom,slv-hw-id = <59>;
+		};
+
+		slv-spdm-wrapper {
+			cell-id = <633>;
+			label = "slv-spdm-wrapper";
+			qcom,slavep = <13>;
+			qcom,tier = <2>;
+			qcom,buswidth = <8>;
+			qcom,slv-hw-id = <60>;
+		};
+
+		slv-dehr-cfg {
+			cell-id = <634>;
+			label = "slv-dehr-cfg";
+			qcom,slavep = <14>;
+			qcom,tier = <2>;
+			qcom,buswidth = <8>;
+			qcom,slv-hw-id = <61>;
+		};
+
+		slv-mpm	{
+			cell-id = <536>;
+			label = "slv-mpm";
+			qcom,slavep = <15>;
+			qcom,tier = <2>;
+			qcom,buswidth = <8>;
+			qcom,slv-hw-id = <62>;
+		};
+
+		slv-qdss-cfg {
+			cell-id = <635>;
+			label = "slv-qdss-cfg";
+			qcom,slavep = <16>;
+			qcom,tier = <2>;
+			qcom,buswidth = <8>;
+			qcom,slv-hw-id = <63>;
+		};
+
+		slv-rbcpr-cfg {
+			cell-id = <636>;
+			label = "slv-rbcpr-cfg";
+			qcom,slavep = <17>;
+			qcom,tier = <2>;
+			qcom,buswidth = <8>;
+			qcom,slv-hw-id = <64>;
+		};
+
+		slv-rbcpr-qdss-apu-cfg {
+			cell-id = <637>;
+			label = "slv-rbcpr-qdss-apu-cfg";
+			qcom,slavep = <18>;
+			qcom,tier = <2>;
+			qcom,buswidth = <8>;
+			qcom,slv-hw-id = <65>;
+		};
+
+		fab-snoc {
+			cell-id = <1024>;
+			label = "fab-snoc";
+			qcom,gateway;
+			qcom,slavep = <26>;
+			qcom,masterp = <7>;
+			qcom,tier = <2>;
+			qcom,buswidth = <8>;
+			qcom,mas-hw-id = <52>;
+			qcom,slv-hw-id = <75>;
+		};
+
+		slv-cnoc-mnoc-mmss-cfg {
+			cell-id = <631>;
+			label = "slv-cnoc-mnoc-mmss-cfg";
+			qcom,slavep = <11>;
+			qcom,tier = <2>;
+			qcom,buswidth = <8>;
+			qcom,slv-hw-id = <58>;
+		};
+
+		slv-cnoc-mnoc-cfg {
+			cell-id = <640>;
+			label = "slv-cnoc-mnoc-cfg";
+			qcom,slavep = <19>;
+			qcom,tier = <2>;
+			qcom,buswidth = <8>;
+			qcom,slv-hw-id = <66>;
+		};
+
+		slv-pnoc-cfg {
+			cell-id = <641>;
+			label = "slv-pnoc-cfg";
+			qcom,slavep = <21>;
+			qcom,tier = <2>;
+			qcom,buswidth = <8>;
+			qcom,slv-hw-id = <69>;
+		};
+
+		slv-snoc-mpu-cfg {
+			cell-id = <638>;
+			label = "slv-snoc-mpu-cfg";
+			qcom,slavep = <20>;
+			qcom,tier = <2>;
+			qcom,buswidth = <8>;
+			qcom,slv-hw-id = <67>;
+		};
+
+		slv-snoc-cfg {
+			cell-id = <642>;
+			label = "slv-snoc-cfg";
+			qcom,slavep = <22>;
+			qcom,tier = <2>;
+			qcom,buswidth = <8>;
+			qcom,slv-hw-id = <70>;
+		};
+
+		slv-phy-apu-cfg {
+			cell-id = <644>;
+			label = "slv-phy-apu-cfg";
+			qcom,slavep = <23>;
+			qcom,tier = <2>;
+			qcom,buswidth = <8>;
+			qcom,slv-hw-id = <72>;
+		};
+
+		slv-ebi1-phy-cfg {
+			cell-id = <645>;
+			label = "slv-ebi1-phy-cfg";
+			qcom,slavep = <24>;
+			qcom,tier = <2>;
+			qcom,buswidth = <8>;
+			qcom,slv-hw-id = <73>;
+		};
+
+		slv-rpm {
+			cell-id = <534>;
+			label = "slv-rpm";
+			qcom,slavep = <25>;
+			qcom,tier = <2>;
+			qcom,buswidth = <8>;
+			qcom,slv-hw-id = <74>;
+		};
+
+		slv-service-cnoc {
+			cell-id = <646>;
+			label = "slv-service-cnoc";
+			qcom,slavep = <27>;
+			qcom,tier = <2>;
+			qcom,buswidth = <8>;
+			qcom,slv-hw-id = <76>;
+		};
+
+	};
+
+	msm-bimc@0xfc380000 {
+		compatible = "msm-bus-fabric";
+		reg = <0xfc380000 0x0006A000>;
+		cell-id = <0>;
+		label = "msm_bimc";
+		qcom,fabclk-dual = "mem_clk";
+		qcom,fabclk-active = "mem_a_clk";
+		qcom,ntieredslaves = <0>;
+		qcom,qos-freq = <4800>;
+		qcom,hw-sel = "BIMC";
+		qcom,rpm-en;
+
+		mas-ampss-m0 {
+			cell-id = <1>;
+			label = "mas-ampss-m0";
+			qcom,masterp = <0>;
+			qcom,tier = <2>;
+			qcom,hw-sel = "BIMC";
+			qcom,mode = "Fixed";
+			qcom,qport = <0>;
+			qcom,ws = <10000>;
+			qcom,mas-hw-id = <0>;
+			qcom,prio-rd = <1>;
+			qcom,prio-wr = <1>;
+		};
+
+		mas-mss-proc {
+			cell-id = <65>;
+			label = "mas-mss-proc";
+			qcom,masterp = <3>;
+			qcom,tier = <2>;
+			qcom,hw-sel = "RPM";
+			qcom,mas-hw-id = <1>;
+		};
+
+		fab-mmss-noc {
+			cell-id = <2048>;
+			label = "fab_mmss_noc";
+			qcom,masterp = <1>;
+			qcom,qport = <1>;
+			qcom,buswidth = <8>;
+			qcom,ws = <10000>;
+			qcom,mas-hw-id = <2>;
+			qcom,hw-sel = "BIMC";
+			qcom,mode = "Bypass";
+		};
+
+		fab-snoc {
+			cell-id = <1024>;
+			label = "fab-snoc";
+			qcom,gateway;
+			qcom,slavep = <2>;
+			qcom,masterp = <2>;
+			qcom,qport = <2>;
+			qcom,buswidth = <8>;
+			qcom,ws = <10000>;
+			qcom,mas-hw-id = <3>;
+			qcom,slv-hw-id = <2>;
+		};
+
+		mas-lpass-proc {
+			cell-id = <11>;
+			label = "mas-lpass-proc";
+			qcom,masterp = <4>;
+			qcom,tier = <2>;
+			qcom,qport = <4>;
+			qcom,mas-hw-id = <25>;
+			qcom,mode = "Fixed";
+			qcom,prio-rd = <1>;
+			qcom,prio-wr = <1>;
+		};
+
+		mas-gfx3d {
+			cell-id = <26>;
+			label = "mas-gfx3d";
+			qcom,masterp = <5>;
+			qcom,tier = <2>;
+			qcom,hw-sel = "NoC";
+			qcom,perm-mode = "Bypass";
+			qcom,mode = "Bypass";
+			qcom,ws = <10000>;
+			qcom,qport = <5>;
+			qcom,prio-rd = <1>;
+			qcom,prio-wr = <1>;
+			qcom,mas-hw-id = <6>;
+		};
+
+
+		slv-ebi-ch0 {
+			cell-id = <512>;
+			label = "slv-ebi-ch0";
+			qcom,slavep = <0>;
+			qcom,tier = <2>;
+			qcom,buswidth = <8>;
+			qcom,slv-hw-id = <0>;
+		};
+	};
+
+};
+
+
diff --git a/arch/arm/boot/dts/msm8610-cdp.dts b/arch/arm/boot/dts/msm8610-cdp.dts
index 390c02a..d523c67 100644
--- a/arch/arm/boot/dts/msm8610-cdp.dts
+++ b/arch/arm/boot/dts/msm8610-cdp.dts
@@ -16,7 +16,7 @@
 
 / {
 	model = "Qualcomm MSM 8610 CDP";
-	compatible = "qcom,msm8610-cdp", "qcom,msm8610";
+	compatible = "qcom,msm8610-cdp", "qcom,msm8610", "qcom,cdp";
 	qcom,msm-id = <147 1 0>;
 
 	serial@f991f000 {
diff --git a/arch/arm/boot/dts/msm8610-coresight.dtsi b/arch/arm/boot/dts/msm8610-coresight.dtsi
index 3612078..89a00f1 100644
--- a/arch/arm/boot/dts/msm8610-coresight.dtsi
+++ b/arch/arm/boot/dts/msm8610-coresight.dtsi
@@ -203,7 +203,7 @@
 		coresight-name = "coresight-csr";
 		coresight-nr-inports = <0>;
 
-		qcom,blk-size = <3>;
+		qcom,blk-size = <1>;
 	};
 
 	cti0: cti@fc310000 {
diff --git a/arch/arm/boot/dts/msm8610-mtp.dts b/arch/arm/boot/dts/msm8610-mtp.dts
index 70ac0e8..f718d5e 100644
--- a/arch/arm/boot/dts/msm8610-mtp.dts
+++ b/arch/arm/boot/dts/msm8610-mtp.dts
@@ -16,7 +16,7 @@
 
 / {
 	model = "Qualcomm MSM 8610 MTP";
-	compatible = "qcom,msm8610-mtp", "qcom,msm8610";
+	compatible = "qcom,msm8610-mtp", "qcom,msm8610", "qcom,mtp";
 	qcom,msm-id = <147 8 0>;
 
 	serial@f991f000 {
diff --git a/arch/arm/boot/dts/msm8610-pm.dtsi b/arch/arm/boot/dts/msm8610-pm.dtsi
index ff16b8d..08a3758 100644
--- a/arch/arm/boot/dts/msm8610-pm.dtsi
+++ b/arch/arm/boot/dts/msm8610-pm.dtsi
@@ -21,13 +21,13 @@
 		qcom,core-id = <0>;
 		qcom,saw2-ver-reg = <0xfd0>;
 		qcom,saw2-cfg = <0x01>;
-		qcom,saw2-spm-dly= <0x20000400>;
-		qcom,saw2-spm-ctl = <0x1>;
-		qcom,saw2-spm-cmd-wfi = [60 03 60 76 76 0b 0f];
-		qcom,saw2-spm-cmd-spc = [00 20 10 80 90 5b 60 03 60 3b 76 76 94
-				5b 80 10 2b 30 06 26 30 0f];
-		qcom,saw2-spm-cmd-pc = [00 20 10 80 90 5b 60 07 3b 76 76 0b 94
-				5b 80 10 2b 30 06 26 30 0f];
+		qcom,saw2-spm-dly= <0x3c102800>;
+		qcom,saw2-spm-ctl = <0x0>;
+		qcom,saw2-spm-cmd-wfi = [60 03 60 0b 0f];
+		qcom,saw2-spm-cmd-spc = [00 20 10 80 30 90 5b 60 03 60 3b 76 76
+				0b 94 5b 80 10 06 26 30 0f];
+		qcom,saw2-spm-cmd-pc = [00 20 10 80 30 90 5b 60 07 60 3b 76 76
+				0b 94 5b 80 10 06 26 30 0f];
 	};
 
 	qcom,spm@f9099000 {
@@ -38,13 +38,13 @@
 		qcom,core-id = <1>;
 		qcom,saw2-ver-reg = <0xfd0>;
 		qcom,saw2-cfg = <0x01>;
-		qcom,saw2-spm-dly= <0x20000400>;
-		qcom,saw2-spm-ctl = <0x1>;
-		qcom,saw2-spm-cmd-wfi = [60 03 60 76 76 0b 0f];
-		qcom,saw2-spm-cmd-spc = [00 20 10 80 90 5b 60 03 60 3b 76 76 94
-				5b 80 10 2b 30 06 26 30 0f];
-		qcom,saw2-spm-cmd-pc = [00 20 10 80 90 5b 60 07 3b 76 76 0b 94
-				5b 80 10 2b 30 06 26 30 0f];
+		qcom,saw2-spm-dly= <0x3c102800>;
+		qcom,saw2-spm-ctl = <0x0>;
+		qcom,saw2-spm-cmd-wfi = [60 03 60 0b 0f];
+		qcom,saw2-spm-cmd-spc = [00 20 10 80 30 90 5b 60 03 60 3b 76 76
+				0b 94 5b 80 10 06 26 30 0f];
+		qcom,saw2-spm-cmd-pc = [00 20 10 80 30 90 5b 60 07 60 3b 76 76
+				0b 94 5b 80 10 06 26 30 0f];
 	};
 
 	qcom,spm@f90a9000 {
@@ -55,13 +55,13 @@
 		qcom,core-id = <2>;
 		qcom,saw2-ver-reg = <0xfd0>;
 		qcom,saw2-cfg = <0x01>;
-		qcom,saw2-spm-dly= <0x20000400>;
-		qcom,saw2-spm-ctl = <0x1>;
-		qcom,saw2-spm-cmd-wfi = [60 03 60 76 76 0b 0f];
-		qcom,saw2-spm-cmd-spc = [00 20 10 80 90 5b 60 03 60 3b 76 76 94
-				5b 80 10 2b 30 06 26 30 0f];
-		qcom,saw2-spm-cmd-pc = [00 20 10 80 90 5b 60 07 3b 76 76 0b 94
-				5b 80 10 2b 30 06 26 30 0f];
+		qcom,saw2-spm-dly= <0x3c102800>;
+		qcom,saw2-spm-ctl = <0x0>;
+		qcom,saw2-spm-cmd-wfi = [60 03 60 0b 0f];
+		qcom,saw2-spm-cmd-spc = [00 20 10 80 30 90 5b 60 03 60 3b 76 76
+				0b 94 5b 80 10 06 26 30 0f];
+		qcom,saw2-spm-cmd-pc = [00 20 10 80 30 90 5b 60 07 60 3b 76 76
+				0b 94 5b 80 10 06 26 30 0f];
 	};
 
 	qcom,spm@f90b9000 {
@@ -72,13 +72,13 @@
 		qcom,core-id = <3>;
 		qcom,saw2-ver-reg = <0xfd0>;
 		qcom,saw2-cfg = <0x01>;
-		qcom,saw2-spm-dly= <0x20000400>;
-		qcom,saw2-spm-ctl = <0x1>;
-		qcom,saw2-spm-cmd-wfi = [60 03 60 76 76 0b 0f];
-		qcom,saw2-spm-cmd-spc = [00 20 10 80 90 5b 60 03 60 3b 76 76 94
-				5b 80 10 2b 30 06 26 30 0f];
-		qcom,saw2-spm-cmd-pc = [00 20 10 80 90 5b 60 07 3b 76 76 0b 94
-				5b 80 10 2b 30 06 26 30 0f];
+		qcom,saw2-spm-dly= <0x3c102800>;
+		qcom,saw2-spm-ctl = <0x0>;
+		qcom,saw2-spm-cmd-wfi = [60 03 60 0b 0f];
+		qcom,saw2-spm-cmd-spc = [00 20 10 80 30 90 5b 60 03 60 3b 76 76
+				0b 94 5b 80 10 06 26 30 0f];
+		qcom,saw2-spm-cmd-pc = [00 20 10 80 30 90 5b 60 07 60 3b 76 76
+				0b 94 5b 80 10 06 26 30 0f];
 	};
 
 	qcom,spm@f9012000 {
@@ -89,21 +89,18 @@
 		qcom,core-id = <0xffff>; /* L2/APCS SAW */
 		qcom,saw2-ver-reg = <0xfd0>;
 		qcom,saw2-cfg = <0x14>;
-		qcom,saw2-spm-dly= <0x20000400>;
-		qcom,saw2-spm-ctl = <0x1>;
+		qcom,saw2-spm-dly= <0x3c102800>;
+		qcom,saw2-spm-ctl = <0x0>;
 		qcom,saw2-pmic-data0 = <0x02030080>;
 		qcom,saw2-pmic-data1 = <0x00030000>;
 		qcom,vctl-timeout-us = <50>;
 		qcom,vctl-port = <0x0>;
 		qcom,phase-port = <0x1>;
 		qcom,pfm-port = <0x2>;
-		qcom,saw2-spm-cmd-ret = [0b 00 03 00 7b 0f];
-		qcom,saw2-spm-cmd-gdhs = [00 20 32 60 70 80 0b 6b c0 e0 d0 42 07
-				78 1f 80 4e d0 e0 c0 22 6b 50 4b 60 02 32 50 7b
-				0f];
-		qcom,saw2-spm-cmd-pc = [00 32 60 70 80 b0 0b 10 e0 d0 6b c0
-				42 f0 11 07 01 b0 78 1f 80 4e c0 d0 12 e0 6b 50 4b
-				60 02 32 50 f0 7b 0f]; /*APCS_PMIC_OFF_L2RAM_OFF*/
+		qcom,saw2-spm-cmd-ret = [00 03 00 7b 0f];
+		qcom,saw2-spm-cmd-pc = [00 32 b0 10 e0 d0 6b c0 42 f0
+				11 07 01 b0 4e c0 d0 12 e0 6b 50 02 32
+				50 f0 7b 0f]; /*APCS_PMIC_OFF_L2RAM_OFF*/
 	};
 
 	qcom,lpm-resources {
@@ -114,8 +111,8 @@
 		qcom,lpm-resources@0 {
 			reg = <0x0>;
 			qcom,name = "vdd-dig";
-			qcom,type = <0x62706d73>;	/* "smpb" */
-			qcom,id = <0x02>;
+			qcom,type = <0x61706d73>;	/* "smpa" */
+			qcom,id = <0x01>;
 			qcom,key = <0x6e726f63>;	/* "corn" */
 			qcom,init-value = <5>;		/* Super Turbo */
 		};
@@ -123,10 +120,10 @@
 		qcom,lpm-resources@1 {
 			reg = <0x1>;
 			qcom,name = "vdd-mem";
-			qcom,type = <0x62706d73>;	/* "smpb" */
-			qcom,id = <0x01>;
-			qcom,key = <0x7675>;		/* "uv" */
-			qcom,init-value = <1050000>;	/* Super Turbo */
+			qcom,type = <0x616F646C>;	/* "ldoa" */
+			qcom,id = <0x03>;
+			qcom,key = <0x6e726f63>;	/* "corn" */
+			qcom,init-value = <3>;		/* Active */
 		};
 
 		qcom,lpm-resources@2 {
@@ -156,10 +153,12 @@
 			qcom,mode = "wfi";
 			qcom,xo = "xo_on";
 			qcom,l2 = "l2_cache_active";
-			qcom,vdd-mem-upper-bound = <1150000>; /* MAX */
-			qcom,vdd-mem-lower-bound = <1050000>; /* ACTIVE */
-			qcom,vdd-dig-upper-bound = <5>; /* MAX */
-			qcom,vdd-dig-lower-bound = <3>;  /* ACTIVE */
+			qcom,vdd-mem-upper-bound = <5>; /* SUPER TURBO */
+			qcom,vdd-mem-lower-bound = <3>; /* NORMAL */
+			qcom,vdd-dig-upper-bound = <5>; /* SUPER TURBO */
+			qcom,vdd-dig-lower-bound = <3>;  /* NORMAL */
+			qcom,irqs-detectable;
+			qcom,gpio-detectable;
 			qcom,latency-us = <1>;
 			qcom,ss-power = <784>;
 			qcom,energy-overhead = <190000>;
@@ -168,78 +167,83 @@
 
 		qcom,lpm-level@1 {
 			reg = <0x1>;
-			qcom,mode = "retention";
-			qcom,xo = "xo_on";
-			qcom,l2 = "l2_cache_active";
-			qcom,vdd-mem-upper-bound = <1150000>; /* MAX */
-			qcom,vdd-mem-lower-bound = <1050000>; /* ACTIVE */
-			qcom,vdd-dig-upper-bound = <5>; /* MAX */
-			qcom,vdd-dig-lower-bound = <3>;  /* ACTIVE */
-			qcom,latency-us = <75>;
-			qcom,ss-power = <735>;
-			qcom,energy-overhead = <77341>;
-			qcom,time-overhead = <105>;
-		};
-
-
-		qcom,lpm-level@2 {
-			reg = <0x2>;
 			qcom,mode = "standalone_pc";
 			qcom,xo = "xo_on";
 			qcom,l2 = "l2_cache_active";
-			qcom,vdd-mem-upper-bound = <1150000>; /* MAX */
-			qcom,vdd-mem-lower-bound = <1050000>; /* ACTIVE */
-			qcom,vdd-dig-upper-bound = <5>; /* MAX */
-			qcom,vdd-dig-lower-bound = <3>;  /* ACTIVE */
-			qcom,latency-us = <95>;
+			qcom,vdd-mem-upper-bound = <5>; /* SUPER TURBO */
+			qcom,vdd-mem-lower-bound = <3>; /* NORMAL */
+			qcom,vdd-dig-upper-bound = <5>; /* SUPER TURBO */
+			qcom,vdd-dig-lower-bound = <3>;  /* NORMAL */
+			qcom,irqs-detectable;
+			qcom,gpio-detectable;
+			qcom,latency-us = <3000>;
 			qcom,ss-power = <725>;
 			qcom,energy-overhead = <99500>;
-			qcom,time-overhead = <130>;
+			qcom,time-overhead = <3130>;
+		};
+
+		qcom,lpm-level@2 {
+			reg = <0x2>;
+			qcom,mode = "pc";
+			qcom,xo = "xo_on";
+			qcom,l2 = "l2_cache_retention";
+			qcom,vdd-mem-upper-bound = <5>; /* SUPER TURBO */
+			qcom,vdd-mem-lower-bound = <3>; /* NORMAL */
+			qcom,vdd-dig-upper-bound = <5>; /* SUPER TURBO */
+			qcom,vdd-dig-lower-bound = <3>;  /* NORMAL */
+			qcom,irqs-detectable;
+			qcom,gpio-detectable;
+			qcom,latency-us = <8000>;
+			qcom,ss-power = <138>;
+			qcom,energy-overhead = <1208400>;
+			qcom,time-overhead = <9200>;
 		};
 
 		qcom,lpm-level@3 {
 			reg = <0x3>;
 			qcom,mode = "pc";
 			qcom,xo = "xo_on";
-			qcom,l2 = "l2_cache_gdhs";
-			qcom,vdd-mem-upper-bound = <1150000>; /* MAX */
-			qcom,vdd-mem-lower-bound = <1050000>; /* ACTIVE */
-			qcom,vdd-dig-upper-bound = <5>; /* MAX */
-			qcom,vdd-dig-lower-bound = <3>;  /* ACTIVE */
-			qcom,latency-us = <2000>;
-			qcom,ss-power = <138>;
-			qcom,energy-overhead = <1208400>;
-			qcom,time-overhead = <3200>;
+			qcom,l2 = "l2_cache_pc";
+			qcom,vdd-mem-upper-bound = <3>; /* NORMAL */
+			qcom,vdd-mem-lower-bound = <2>;  /* SVS SOC */
+			qcom,vdd-dig-upper-bound = <3>;  /* NORMAL */
+			qcom,vdd-dig-lower-bound = <2>;  /* SVS SOC */
+			qcom,irqs-detectable;
+			qcom,gpio-detectable;
+			qcom,latency-us = <9000>;
+			qcom,ss-power = <110>;
+			qcom,energy-overhead = <1250300>;
+			qcom,time-overhead = <9500>;
 		};
 
 		qcom,lpm-level@4 {
 			reg = <0x4>;
 			qcom,mode = "pc";
-			qcom,xo = "xo_on";
+			qcom,xo = "xo_off";
 			qcom,l2 = "l2_cache_pc";
-			qcom,vdd-mem-upper-bound = <1050000>; /* ACTIVE */
-			qcom,vdd-mem-lower-bound = <750000>;  /* RETENTION HIGH */
-			qcom,vdd-dig-upper-bound = <3>;  /* ACTIVE */
-			qcom,vdd-dig-lower-bound = <2>;  /* RETENTION HIGH */
-			qcom,latency-us = <3000>;
-			qcom,ss-power = <110>;
-			qcom,energy-overhead = <1250300>;
-			qcom,time-overhead = <3500>;
+			qcom,vdd-mem-upper-bound = <5>; /* SUPER TURBO */
+			qcom,vdd-mem-lower-bound = <3>; /* NORMAL */
+			qcom,vdd-dig-upper-bound = <5>; /* SUPER TURBO */
+			qcom,vdd-dig-lower-bound = <3>;  /* NORMAL */
+			qcom,latency-us = <16300>;
+			qcom,ss-power = <63>;
+			qcom,energy-overhead = <2128000>;
+			qcom,time-overhead = <24200>;
 		};
 
 		qcom,lpm-level@5 {
 			reg = <0x5>;
 			qcom,mode = "pc";
 			qcom,xo = "xo_off";
-			qcom,l2 = "l2_cache_gdhs";
-			qcom,vdd-mem-upper-bound = <1150000>; /* MAX */
-			qcom,vdd-mem-lower-bound = <1050000>; /* ACTIVE */
-			qcom,vdd-dig-upper-bound = <5>; /* MAX */
-			qcom,vdd-dig-lower-bound = <3>;  /* ACTIVE */
-			qcom,latency-us = <3000>;
-			qcom,ss-power = <68>;
-			qcom,energy-overhead = <1350200>;
-			qcom,time-overhead = <4000>;
+			qcom,l2 = "l2_cache_pc";
+			qcom,vdd-mem-upper-bound = <3>; /* NORMAL */
+			qcom,vdd-mem-lower-bound = <2>;  /* SVS SOC */
+			qcom,vdd-dig-upper-bound = <3>;  /* NORMAL */
+			qcom,vdd-dig-lower-bound = <2>;  /* SVS SOC */
+			qcom,latency-us = <24000>;
+			qcom,ss-power = <10>;
+			qcom,energy-overhead = <3202600>;
+			qcom,time-overhead = <33000>;
 		};
 
 		qcom,lpm-level@6 {
@@ -247,44 +251,14 @@
 			qcom,mode = "pc";
 			qcom,xo = "xo_off";
 			qcom,l2 = "l2_cache_pc";
-			qcom,vdd-mem-upper-bound = <1150000>; /* MAX */
-			qcom,vdd-mem-lower-bound = <1050000>; /* ACTIVE */
-			qcom,vdd-dig-upper-bound = <5>; /* MAX */
-			qcom,vdd-dig-lower-bound = <3>;  /* ACTIVE */
-			qcom,latency-us = <10300>;
-			qcom,ss-power = <63>;
-			qcom,energy-overhead = <2128000>;
-			qcom,time-overhead = <18200>;
-		};
-
-		qcom,lpm-level@7 {
-			reg = <0x7>;
-			qcom,mode = "pc";
-			qcom,xo = "xo_off";
-			qcom,l2 = "l2_cache_pc";
-			qcom,vdd-mem-upper-bound = <1050000>; /* ACTIVE */
-			qcom,vdd-mem-lower-bound = <750000>;  /* RETENTION HIGH */
-			qcom,vdd-dig-upper-bound = <3>;  /* ACTIVE */
-			qcom,vdd-dig-lower-bound = <2>;  /* RETIONTION HIGH */
-			qcom,latency-us = <18000>;
-			qcom,ss-power = <10>;
-			qcom,energy-overhead = <3202600>;
-			qcom,time-overhead = <27000>;
-		};
-
-		qcom,lpm-level@8 {
-			reg = <0x8>;
-			qcom,mode = "pc";
-			qcom,xo = "xo_off";
-			qcom,l2 = "l2_cache_pc";
-			qcom,vdd-mem-upper-bound = <750000>; /* RETENTION HIGH */
-			qcom,vdd-mem-lower-bound = <750000>; /* RETENTION LOW */
-			qcom,vdd-dig-upper-bound = <2>; /* RETENTION HIGH */
-			qcom,vdd-dig-lower-bound = <0>; /* RETENTION LOW */
-			qcom,latency-us = <20000>;
+			qcom,vdd-mem-upper-bound = <2>; /* SVS SOC */
+			qcom,vdd-mem-lower-bound = <0>; /* RETENTION */
+			qcom,vdd-dig-upper-bound = <2>; /* SVS SOC */
+			qcom,vdd-dig-lower-bound = <0>; /* RETENTION */
+			qcom,latency-us = <26000>;
 			qcom,ss-power = <2>;
 			qcom,energy-overhead = <4252000>;
-			qcom,time-overhead = <32000>;
+			qcom,time-overhead = <38000>;
 		};
 	};
 
@@ -306,6 +280,7 @@
 		qcom,gic-map = <47 172>, /* usb2_hsic_async_wakeup_irq */
 			<53 104>, /* mdss_irq */
 			<62 222>, /* ee0_krait_hlos_spmi_periph_irq */
+			<2 216>, /* tsens_upper_lower_int */
 			<0xff 56>,  /* q6_wdog_expired_irq */
 			<0xff 57>,  /* mss_to_apps_irq(0) */
 			<0xff 58>,  /* mss_to_apps_irq(1) */
@@ -395,6 +370,17 @@
 		qcom,use-sync-timer;
 	};
 
+	qcom,rpm-log@fc19dc00 {
+		compatible = "qcom,rpm-log";
+		reg = <0xfc19dc00 0x4000>;
+		qcom,rpm-addr-phys = <0xfc000000>;
+		qcom,offset-version = <4>;
+		qcom,offset-page-buffer-addr = <36>;
+		qcom,offset-log-len = <40>;
+		qcom,offset-log-len-mask = <44>;
+		qcom,offset-page-indices = <56>;
+	};
+
 	qcom,rpm-stats@0xfc19dbd0{
 		compatible = "qcom,rpm-stats";
 		reg = <0xfc19dbd0 0x1000>;
diff --git a/arch/arm/boot/dts/msm8610-regulator.dtsi b/arch/arm/boot/dts/msm8610-regulator.dtsi
index 5512ccd..d50902c 100644
--- a/arch/arm/boot/dts/msm8610-regulator.dtsi
+++ b/arch/arm/boot/dts/msm8610-regulator.dtsi
@@ -19,7 +19,7 @@
 		qcom,hpm-min-load = <100000>;
 		regulator-min-microvolt = <1>;
 		regulator-max-microvolt = <7>;
-		qcom,consumer-supplies = "vdd_dig", "";
+		qcom,consumer-supplies = "vdd_dig", "", "vdd_sr2_dig", "";
 	};
 };
 
diff --git a/arch/arm/boot/dts/msm8610-rumi.dts b/arch/arm/boot/dts/msm8610-rumi.dts
index a4507e3..cab7560 100644
--- a/arch/arm/boot/dts/msm8610-rumi.dts
+++ b/arch/arm/boot/dts/msm8610-rumi.dts
@@ -16,7 +16,7 @@
 
 / {
 	model = "Qualcomm MSM 8610 Rumi";
-	compatible = "qcom,msm8610-rumi", "qcom,msm8610";
+	compatible = "qcom,msm8610-rumi", "qcom,msm8610", "qcom,rumi";
 	qcom,msm-id = <147 15 0>;
 
 	serial@f991f000 {
diff --git a/arch/arm/boot/dts/msm8610-sim.dts b/arch/arm/boot/dts/msm8610-sim.dts
index 2268daf..1838b94 100644
--- a/arch/arm/boot/dts/msm8610-sim.dts
+++ b/arch/arm/boot/dts/msm8610-sim.dts
@@ -16,7 +16,7 @@
 
 / {
 	model = "Qualcomm MSM 8610 Simulator";
-	compatible = "qcom,msm8610-sim", "qcom,msm8610";
+	compatible = "qcom,msm8610-sim", "qcom,msm8610", "qcom,sim";
 	qcom,msm-id = <147 16 0>;
 
 	serial@f991f000 {
diff --git a/arch/arm/boot/dts/msm8610.dtsi b/arch/arm/boot/dts/msm8610.dtsi
index 91dfdbe..5967dfb 100644
--- a/arch/arm/boot/dts/msm8610.dtsi
+++ b/arch/arm/boot/dts/msm8610.dtsi
@@ -18,6 +18,7 @@
 /include/ "msm8610-coresight.dtsi"
 /include/ "msm8610-pm.dtsi"
 /include/ "msm8610-smp2p.dtsi"
+/include/ "msm8610-bus.dtsi"
 
 / {
 	model = "Qualcomm MSM 8610";
@@ -456,6 +457,12 @@
 		qcom,is-loadable;
 		qcom,firmware-name = "mba";
 		qcom,pil-self-auth;
+
+		/* GPIO input from mss */
+		qcom,gpio-err-fatal = <&smp2pgpio_ssr_smp2p_1_in 0 0>;
+
+		/* GPIO output to mss */
+		qcom,gpio-force-stop = <&smp2pgpio_ssr_smp2p_1_out 0 0>;
 	};
 
 	qcom,lpass@fe200000 {
@@ -482,6 +489,14 @@
 		qcom,tsens-local-init;
 	};
 
+	qcom,msm-thermal {
+		compatible = "qcom,msm-thermal";
+		qcom,sensor-id = <0>;
+		qcom,poll-ms = <250>;
+		qcom,limit-temp = <60>;
+		qcom,temp-hysteresis = <10>;
+		qcom,freq-step = <2>;
+	};
 };
 
 &gdsc_vfe {
diff --git a/arch/arm/boot/dts/msm8660-surf.dts b/arch/arm/boot/dts/msm8660-surf.dts
index 45bc4bb..4518fc4 100644
--- a/arch/arm/boot/dts/msm8660-surf.dts
+++ b/arch/arm/boot/dts/msm8660-surf.dts
@@ -4,7 +4,7 @@
 
 / {
 	model = "Qualcomm MSM8660 SURF";
-	compatible = "qcom,msm8660-surf", "qcom,msm8660";
+	compatible = "qcom,msm8660-surf", "qcom,msm8660", "qcom,surf";
 	interrupt-parent = <&intc>;
 
 	intc: interrupt-controller@02080000 {
diff --git a/arch/arm/boot/dts/msm8974-bus.dtsi b/arch/arm/boot/dts/msm8974-bus.dtsi
index 828e7ae..cebb907 100644
--- a/arch/arm/boot/dts/msm8974-bus.dtsi
+++ b/arch/arm/boot/dts/msm8974-bus.dtsi
@@ -296,6 +296,9 @@
 			qcom,mode = "Fixed";
 			qcom,qport = <1>;
 			qcom,mas-hw-id = <19>;
+			qcom,prio-rd = <1>;
+			qcom,prio-wr = <1>;
+			qcom,hw-sel = "NoC";
 		};
 
 		mas-snoc-cfg {
@@ -432,6 +435,9 @@
 			qcom,qport = <10>;
 			qcom,mode = "Fixed";
 			qcom,mas-hw-id = <31>;
+			qcom,prio-rd = <1>;
+			qcom,prio-wr = <1>;
+			qcom,hw-sel = "NoC";
 		};
 
 		mas-usb3 {
@@ -442,8 +448,8 @@
 			qcom,mode = "Fixed";
 			qcom,qport = <11>;
 			qcom,mas-hw-id = <32>;
-			qcom,prio-rd = <2>;
-			qcom,prio-wr = <2>;
+			qcom,prio-rd = <1>;
+			qcom,prio-wr = <1>;
 			qcom,hw-sel = "NoC";
 			qcom,iface-clk-node = "msm_usb3";
 		};
diff --git a/arch/arm/boot/dts/msm8974-camera-sensor-cdp-mtp.dtsi b/arch/arm/boot/dts/msm8974-camera-sensor-cdp.dtsi
similarity index 93%
copy from arch/arm/boot/dts/msm8974-camera-sensor-cdp-mtp.dtsi
copy to arch/arm/boot/dts/msm8974-camera-sensor-cdp.dtsi
index 3fb5b20..df0db7e 100644
--- a/arch/arm/boot/dts/msm8974-camera-sensor-cdp-mtp.dtsi
+++ b/arch/arm/boot/dts/msm8974-camera-sensor-cdp.dtsi
@@ -15,19 +15,25 @@
 
 	actuator0: qcom,actuator@18 {
 		cell-index = <0>;
-		reg = <0x18>;
+		reg = <0x18 0x0>;
+		compatible = "qcom,actuator";
+		qcom,cci-master = <0>;
+	};
+
+	actuator1: qcom,actuator@36 {
+		cell-index = <1>;
+		reg = <0x36>;
 		compatible = "qcom,actuator";
 		qcom,cci-master = <0>;
 	};
 
 	qcom,camera@6e {
 		compatible = "qcom,s5k3l1yx";
-		reg = <0x6e>;
+		reg = <0x6e 0x0>;
 		qcom,slave-id = <0x6e 0x0 0x3121>;
 		qcom,csiphy-sd-index = <0>;
 		qcom,csid-sd-index = <0>;
 		qcom,actuator-src = <&actuator0>;
-		qcom,led-flash-src = <&led_flash0>;
 		qcom,mount-angle = <90>;
 		qcom,sensor-name = "s5k3l1yx";
 		cam_vdig-supply = <&pm8941_l3>;
@@ -65,11 +71,12 @@
     qcom,camera@20 {
 		compatible = "qcom,imx135";
 		reg = <0x20>;
-		qcom,slave-id = <0x20 0x0 0x1210>;
+		qcom,slave-id = <0x20 0x0016 0x0135>;
 		qcom,csiphy-sd-index = <0>;
 		qcom,csid-sd-index = <0>;
 		qcom,mount-angle = <90>;
 		qcom,sensor-name = "imx135";
+		qcom,actuator-src = <&actuator1>;
 		cam_vdig-supply = <&pm8941_l3>;
 		cam_vana-supply = <&pm8941_l17>;
 		cam_vio-supply = <&pm8941_lvs3>;
@@ -99,10 +106,9 @@
 		status = "ok";
 	};
 
-
 	qcom,camera@6c {
 		compatible = "qcom,ov2720";
-		reg = <0x6c>;
+		reg = <0x6c 0x0>;
 		qcom,slave-id = <0x6c 0x300A 0x2720>;
 		qcom,csiphy-sd-index = <2>;
 		qcom,csid-sd-index = <0>;
@@ -131,13 +137,13 @@
 		qcom,csi-lane-mask = <0x7>;
 		qcom,sensor-position = <1>;
 		qcom,sensor-mode = <1>;
-		qcom,cci-master = <1>;
+		qcom,cci-master = <0>;
 		status = "ok";
 	};
 
 	qcom,camera@90 {
 		compatible = "qcom,mt9m114";
-		reg = <0x90>;
+		reg = <0x90 0x0>;
 		qcom,slave-id = <0x90 0x0 0x2481>;
 		qcom,csiphy-sd-index = <1>;
 		qcom,csid-sd-index = <0>;
diff --git a/arch/arm/boot/dts/msm8974-camera-sensor-fluid.dtsi b/arch/arm/boot/dts/msm8974-camera-sensor-fluid.dtsi
index c9d1abc..f58c1e2 100644
--- a/arch/arm/boot/dts/msm8974-camera-sensor-fluid.dtsi
+++ b/arch/arm/boot/dts/msm8974-camera-sensor-fluid.dtsi
@@ -20,6 +20,13 @@
 		qcom,cci-master = <0>;
 	};
 
+	actuator1: qcom,actuator@36 {
+		cell-index = <1>;
+		reg = <0x36>;
+		compatible = "qcom,actuator";
+		qcom,cci-master = <0>;
+	};
+
 	qcom,camera@6e {
 		compatible = "qcom,s5k3l1yx";
 		reg = <0x6e>;
@@ -62,6 +69,44 @@
 		status = "ok";
 	};
 
+    qcom,camera@20 {
+		compatible = "qcom,imx135";
+		reg = <0x20>;
+		qcom,slave-id = <0x20 0x0016 0x0135>;
+		qcom,csiphy-sd-index = <0>;
+		qcom,csid-sd-index = <0>;
+		qcom,mount-angle = <270>;
+		qcom,sensor-name = "imx135";
+		qcom,actuator-src = <&actuator1>;
+		cam_vdig-supply = <&pm8941_l3>;
+		cam_vana-supply = <&pm8941_l17>;
+		cam_vio-supply = <&pm8941_lvs3>;
+		cam_vaf-supply = <&pm8941_l23>;
+		qcom,cam-vreg-name = "cam_vdig", "cam_vio", "cam_vana",
+				     "cam_vaf";
+		qcom,cam-vreg-type = <0 1 0 0>;
+		qcom,cam-vreg-min-voltage = <1225000 0 2850000 3000000>;
+		qcom,cam-vreg-max-voltage = <1225000 0 2850000 3000000>;
+		qcom,cam-vreg-op-mode = <105000 0 80000 100000>;
+		qcom,gpio-no-mux = <0>;
+		gpios = <&msmgpio 15 0>,
+			<&msmgpio 90 0>;
+		qcom,gpio-reset = <1>;
+		qcom,gpio-req-tbl-num = <0 1>;
+		qcom,gpio-req-tbl-flags = <1 0>;
+		qcom,gpio-req-tbl-label = "CAMIF_MCLK", "CAM_RESET1";
+		qcom,gpio-set-tbl-num = <1 1>;
+		qcom,gpio-set-tbl-flags = <0 2>;
+		qcom,gpio-set-tbl-delay = <1000 30000>;
+		qcom,csi-lane-assign = <0x4320>;
+		qcom,csi-lane-mask = <0x1F>;
+		qcom,sensor-position = <0>;
+		qcom,sensor-mode = <0>;
+	        qcom,sensor-type = <0>;
+		qcom,cci-master = <0>;
+		status = "ok";
+	};
+
 	qcom,camera@6c {
 		compatible = "qcom,ov2720";
 		reg = <0x6c>;
diff --git a/arch/arm/boot/dts/msm8974-camera-sensor-liquid.dtsi b/arch/arm/boot/dts/msm8974-camera-sensor-liquid.dtsi
index f9b89e1..5a97a11 100644
--- a/arch/arm/boot/dts/msm8974-camera-sensor-liquid.dtsi
+++ b/arch/arm/boot/dts/msm8974-camera-sensor-liquid.dtsi
@@ -21,6 +21,13 @@
 		qcom,cci-master = <0>;
 	};
 
+	actuator1: qcom,actuator@36 {
+		cell-index = <1>;
+		reg = <0x36>;
+		compatible = "qcom,actuator";
+		qcom,cci-master = <0>;
+	};
+
 	qcom,camera@6e {
 		compatible = "qcom,s5k3l1yx";
 		reg = <0x6e>;
@@ -31,7 +38,7 @@
 		qcom,sensor-name = "s5k3l1yx";
 		cam_vdig-supply = <&pm8941_l3>;
 		cam_vana-supply = <&pm8941_l17>;
-		cam_vio-supply = <&pm8941_lvs3>;
+		cam_vio-supply = <&pm8941_lvs2>;
 		cam_vaf-supply = <&pm8941_l23>;
 		qcom,cam-vreg-name = "cam_vdig", "cam_vio", "cam_vana",
 				     "cam_vaf";
@@ -58,6 +65,44 @@
 		status = "ok";
 	};
 
+    qcom,camera@20 {
+		compatible = "qcom,imx135";
+		reg = <0x20>;
+		qcom,slave-id = <0x20 0x0016 0x0135>;
+		qcom,csiphy-sd-index = <0>;
+		qcom,csid-sd-index = <0>;
+		qcom,mount-angle = <0>;
+		qcom,sensor-name = "imx135";
+		qcom,actuator-src = <&actuator1>;
+		cam_vdig-supply = <&pm8941_l3>;
+		cam_vana-supply = <&pm8941_l17>;
+		cam_vio-supply = <&pm8941_lvs2>;
+		cam_vaf-supply = <&pm8941_l23>;
+		qcom,cam-vreg-name = "cam_vdig", "cam_vio", "cam_vana",
+				     "cam_vaf";
+		qcom,cam-vreg-type = <0 1 0 0>;
+		qcom,cam-vreg-min-voltage = <1225000 0 2850000 3000000>;
+		qcom,cam-vreg-max-voltage = <1225000 0 2850000 3000000>;
+		qcom,cam-vreg-op-mode = <105000 0 80000 100000>;
+		qcom,gpio-no-mux = <0>;
+		gpios = <&msmgpio 15 0>,
+			<&msmgpio 90 0>;
+		qcom,gpio-reset = <1>;
+		qcom,gpio-req-tbl-num = <0 1>;
+		qcom,gpio-req-tbl-flags = <1 0>;
+		qcom,gpio-req-tbl-label = "CAMIF_MCLK", "CAM_RESET1";
+		qcom,gpio-set-tbl-num = <1 1>;
+		qcom,gpio-set-tbl-flags = <0 2>;
+		qcom,gpio-set-tbl-delay = <1000 30000>;
+		qcom,csi-lane-assign = <0x4320>;
+		qcom,csi-lane-mask = <0x1F>;
+		qcom,sensor-position = <0>;
+		qcom,sensor-mode = <0>;
+	        qcom,sensor-type = <0>;
+		qcom,cci-master = <0>;
+		status = "ok";
+	};
+
 	qcom,camera@6c {
 		compatible = "qcom,ov2720";
 		reg = <0x6c>;
@@ -68,7 +113,7 @@
 		qcom,sensor-name = "ov2720";
 		cam_vdig-supply = <&pm8941_l3>;
 		cam_vana-supply = <&pm8941_l17>;
-		cam_vio-supply = <&pm8941_lvs3>;
+		cam_vio-supply = <&pm8941_lvs2>;
 		qcom,cam-vreg-name = "cam_vdig", "cam_vana", "cam_vio";
 		qcom,cam-vreg-type = <0 0 1>;
 		qcom,cam-vreg-min-voltage = <1225000 2850000 0>;
@@ -103,7 +148,7 @@
 		qcom,sensor-name = "mt9m114";
 		cam_vdig-supply = <&pm8941_l3>;
 		cam_vana-supply = <&pm8941_l17>;
-		cam_vio-supply = <&pm8941_lvs3>;
+		cam_vio-supply = <&pm8941_lvs2>;
 		qcom,cam-vreg-name = "cam_vdig", "cam_vana", "cam_vio";
 		qcom,cam-vreg-type = <0 0 1>;
 		qcom,cam-vreg-min-voltage = <1225000 2850000 0>;
diff --git a/arch/arm/boot/dts/msm8974-camera-sensor-cdp-mtp.dtsi b/arch/arm/boot/dts/msm8974-camera-sensor-mtp.dtsi
similarity index 95%
rename from arch/arm/boot/dts/msm8974-camera-sensor-cdp-mtp.dtsi
rename to arch/arm/boot/dts/msm8974-camera-sensor-mtp.dtsi
index 3fb5b20..767a705 100644
--- a/arch/arm/boot/dts/msm8974-camera-sensor-cdp-mtp.dtsi
+++ b/arch/arm/boot/dts/msm8974-camera-sensor-mtp.dtsi
@@ -20,6 +20,13 @@
 		qcom,cci-master = <0>;
 	};
 
+	actuator1: qcom,actuator@36 {
+		cell-index = <1>;
+		reg = <0x36>;
+		compatible = "qcom,actuator";
+		qcom,cci-master = <0>;
+	};
+
 	qcom,camera@6e {
 		compatible = "qcom,s5k3l1yx";
 		reg = <0x6e>;
@@ -65,11 +72,12 @@
     qcom,camera@20 {
 		compatible = "qcom,imx135";
 		reg = <0x20>;
-		qcom,slave-id = <0x20 0x0 0x1210>;
+		qcom,slave-id = <0x20 0x0016 0x0135>;
 		qcom,csiphy-sd-index = <0>;
 		qcom,csid-sd-index = <0>;
 		qcom,mount-angle = <90>;
 		qcom,sensor-name = "imx135";
+		qcom,actuator-src = <&actuator1>;
 		cam_vdig-supply = <&pm8941_l3>;
 		cam_vana-supply = <&pm8941_l17>;
 		cam_vio-supply = <&pm8941_lvs3>;
diff --git a/arch/arm/boot/dts/msm8974-cdp.dtsi b/arch/arm/boot/dts/msm8974-cdp.dtsi
index 2919709..41e3783 100644
--- a/arch/arm/boot/dts/msm8974-cdp.dtsi
+++ b/arch/arm/boot/dts/msm8974-cdp.dtsi
@@ -13,7 +13,7 @@
 /include/ "dsi-panel-toshiba-720p-video.dtsi"
 /include/ "dsi-panel-orise-720p-video.dtsi"
 /include/ "msm8974-leds.dtsi"
-/include/ "msm8974-camera-sensor-cdp-mtp.dtsi"
+/include/ "msm8974-camera-sensor-cdp.dtsi"
 
 / {
 	serial@f991e000 {
diff --git a/arch/arm/boot/dts/msm8974-fluid.dtsi b/arch/arm/boot/dts/msm8974-fluid.dtsi
index 046939e..ec8a459 100644
--- a/arch/arm/boot/dts/msm8974-fluid.dtsi
+++ b/arch/arm/boot/dts/msm8974-fluid.dtsi
@@ -354,6 +354,7 @@
 
 &pm8941_chg {
 	status = "ok";
+	qcom,chg-charging-disabled;
 
 	qcom,chg-chgr@1000 {
 		status = "ok";
diff --git a/arch/arm/boot/dts/msm8974-gpu.dtsi b/arch/arm/boot/dts/msm8974-gpu.dtsi
index ceba72f..a7544ab 100644
--- a/arch/arm/boot/dts/msm8974-gpu.dtsi
+++ b/arch/arm/boot/dts/msm8974-gpu.dtsi
@@ -62,21 +62,21 @@
 				reg = <0>;
 				qcom,gpu-freq = <450000000>;
 				qcom,bus-freq = <5>;
-				qcom,io-fraction = <0>;
+				qcom,io-fraction = <33>;
 			};
 
 			qcom,gpu-pwrlevel@1 {
 				reg = <1>;
 				qcom,gpu-freq = <300000000>;
 				qcom,bus-freq = <4>;
-				qcom,io-fraction = <33>;
+				qcom,io-fraction = <66>;
 			};
 
 			qcom,gpu-pwrlevel@2 {
 				reg = <2>;
 				qcom,gpu-freq = <300000000>;
 				qcom,bus-freq = <3>;
-				qcom,io-fraction = <33>;
+				qcom,io-fraction = <66>;
 			};
 
 			qcom,gpu-pwrlevel@3 {
diff --git a/arch/arm/boot/dts/msm8974-mdss.dtsi b/arch/arm/boot/dts/msm8974-mdss.dtsi
index 0912a33..5c42b2c 100644
--- a/arch/arm/boot/dts/msm8974-mdss.dtsi
+++ b/arch/arm/boot/dts/msm8974-mdss.dtsi
@@ -50,7 +50,13 @@
 				     <0x0160 0x22222222>,
 				     <0x0164 0x00002222>;
 		qcom,mdp-settings = <0x02E0 0x000000AA>,
-				    <0x02E4 0x00000055>;
+				    <0x02E4 0x00000055>,
+				    <0x03AC 0xC0000CCC>,
+				    <0x03B4 0xC0000CCC>,
+				    <0x03BC 0x00CCCCCC>,
+				    <0x04A8 0x0CCCC0C0>,
+				    <0x04B0 0xCCCCC0C0>,
+				    <0x04B8 0xCCCCC000>;
 
 		mdss_fb0: qcom,mdss_fb_primary {
 			cell-index = <0>;
diff --git a/arch/arm/boot/dts/msm8974-mtp.dtsi b/arch/arm/boot/dts/msm8974-mtp.dtsi
index 8fa1d75..5970e6b 100644
--- a/arch/arm/boot/dts/msm8974-mtp.dtsi
+++ b/arch/arm/boot/dts/msm8974-mtp.dtsi
@@ -11,7 +11,7 @@
  */
 
 /include/ "dsi-panel-toshiba-720p-video.dtsi"
-/include/ "msm8974-camera-sensor-cdp-mtp.dtsi"
+/include/ "msm8974-camera-sensor-mtp.dtsi"
 /include/ "msm8974-leds.dtsi"
 
 / {
@@ -336,6 +336,7 @@
 
 &pm8941_chg {
 	status = "ok";
+	qcom,chg-charging-disabled;
 
 	qcom,chg-chgr@1000 {
 		status = "ok";
diff --git a/arch/arm/boot/dts/msm8974-rumi.dtsi b/arch/arm/boot/dts/msm8974-rumi.dtsi
index ce9d6c9..c569e58 100644
--- a/arch/arm/boot/dts/msm8974-rumi.dtsi
+++ b/arch/arm/boot/dts/msm8974-rumi.dtsi
@@ -11,7 +11,7 @@
  */
 
 /include/ "msm8974-leds.dtsi"
-/include/ "msm8974-camera-sensor-cdp-mtp.dtsi"
+/include/ "msm8974-camera-sensor-cdp.dtsi"
 
 / {
 	timer {
diff --git a/arch/arm/boot/dts/msm8974-sim.dtsi b/arch/arm/boot/dts/msm8974-sim.dtsi
index a5606b8..786c50c 100644
--- a/arch/arm/boot/dts/msm8974-sim.dtsi
+++ b/arch/arm/boot/dts/msm8974-sim.dtsi
@@ -12,7 +12,7 @@
 
 /include/ "dsi-panel-sim-video.dtsi"
 /include/ "msm8974-leds.dtsi"
-/include/ "msm8974-camera-sensor-cdp-mtp.dtsi"
+/include/ "msm8974-camera-sensor-cdp.dtsi"
 
 / {
 	qcom,mdss_dsi@fd922800 {
diff --git a/arch/arm/boot/dts/msm8974-v1-cdp.dts b/arch/arm/boot/dts/msm8974-v1-cdp.dts
index 33bd1fb..cb58026 100644
--- a/arch/arm/boot/dts/msm8974-v1-cdp.dts
+++ b/arch/arm/boot/dts/msm8974-v1-cdp.dts
@@ -17,7 +17,7 @@
 
 / {
 	model = "Qualcomm MSM 8974 CDP";
-	compatible = "qcom,msm8974-cdp", "qcom,msm8974";
+	compatible = "qcom,msm8974-cdp", "qcom,msm8974", "qcom,cdp";
 	qcom,msm-id = <126 1 0>;
 };
 
@@ -25,3 +25,7 @@
 	status = "ok";
 	vbus-supply = <&usb2_otg_sw>;
 };
+
+&hsic_host {
+       qcom,phy-sof-workaround;
+};
diff --git a/arch/arm/boot/dts/msm8974-v1-fluid.dts b/arch/arm/boot/dts/msm8974-v1-fluid.dts
index 9fb287c..0f762a8 100644
--- a/arch/arm/boot/dts/msm8974-v1-fluid.dts
+++ b/arch/arm/boot/dts/msm8974-v1-fluid.dts
@@ -17,7 +17,7 @@
 
 / {
 	model = "Qualcomm MSM 8974 FLUID";
-	compatible = "qcom,msm8974-fluid", "qcom,msm8974";
+	compatible = "qcom,msm8974-fluid", "qcom,msm8974", "qcom,fluid";
 	qcom,msm-id = <126 3 0>;
 
 };
diff --git a/arch/arm/boot/dts/msm8974-v1-liquid.dts b/arch/arm/boot/dts/msm8974-v1-liquid.dts
index 5c12569..ccbd82f 100644
--- a/arch/arm/boot/dts/msm8974-v1-liquid.dts
+++ b/arch/arm/boot/dts/msm8974-v1-liquid.dts
@@ -17,6 +17,6 @@
 
 / {
 	model = "Qualcomm MSM 8974 LIQUID";
-	compatible = "qcom,msm8974-liquid", "qcom,msm8974";
+	compatible = "qcom,msm8974-liquid", "qcom,msm8974", "qcom,liquid";
 	qcom,msm-id = <126 9 0>;
 };
diff --git a/arch/arm/boot/dts/msm8974-v1-mtp.dts b/arch/arm/boot/dts/msm8974-v1-mtp.dts
index 205ee24..6cb9f09 100644
--- a/arch/arm/boot/dts/msm8974-v1-mtp.dts
+++ b/arch/arm/boot/dts/msm8974-v1-mtp.dts
@@ -17,7 +17,7 @@
 
 / {
 	model = "Qualcomm MSM 8974 MTP";
-	compatible = "qcom,msm8974-mtp", "qcom,msm8974";
+	compatible = "qcom,msm8974-mtp", "qcom,msm8974", "qcom,mtp";
 	qcom,msm-id = <126 8 0>;
 };
 
diff --git a/arch/arm/boot/dts/msm8974-v1-rumi.dts b/arch/arm/boot/dts/msm8974-v1-rumi.dts
index ebb37b7..caf89ee 100644
--- a/arch/arm/boot/dts/msm8974-v1-rumi.dts
+++ b/arch/arm/boot/dts/msm8974-v1-rumi.dts
@@ -17,6 +17,6 @@
 
 / {
 	model = "Qualcomm MSM 8974 RUMI";
-	compatible = "qcom,msm8974-rumi", "qcom,msm8974";
+	compatible = "qcom,msm8974-rumi", "qcom,msm8974", "qcom,rumi";
 	qcom,msm-id = <126 15 0>;
 };
diff --git a/arch/arm/boot/dts/msm8974-v1-sim.dts b/arch/arm/boot/dts/msm8974-v1-sim.dts
index 29add5d..c4b29c2 100644
--- a/arch/arm/boot/dts/msm8974-v1-sim.dts
+++ b/arch/arm/boot/dts/msm8974-v1-sim.dts
@@ -17,6 +17,6 @@
 
 / {
 	model = "Qualcomm MSM 8974 Simulator";
-	compatible = "qcom,msm8974-sim", "qcom,msm8974";
+	compatible = "qcom,msm8974-sim", "qcom,msm8974", "qcom,sim";
 	qcom,msm-id = <126 16 0>;
 };
diff --git a/arch/arm/boot/dts/msm8974-v1.dtsi b/arch/arm/boot/dts/msm8974-v1.dtsi
index ae8cf83..62837a1 100644
--- a/arch/arm/boot/dts/msm8974-v1.dtsi
+++ b/arch/arm/boot/dts/msm8974-v1.dtsi
@@ -128,3 +128,7 @@
 &ldrex_spinlock {
 	status = "ok";
 };
+
+&usb_otg {
+	qcom,hsusb-otg-pnoc-errata-fix;
+};
diff --git a/arch/arm/boot/dts/msm8974-v2-cdp.dts b/arch/arm/boot/dts/msm8974-v2-cdp.dts
index e591dee..4fa1f2a 100644
--- a/arch/arm/boot/dts/msm8974-v2-cdp.dts
+++ b/arch/arm/boot/dts/msm8974-v2-cdp.dts
@@ -17,21 +17,18 @@
 
 / {
 	model = "Qualcomm MSM 8974v2 CDP";
-	compatible = "qcom,msm8974-cdp", "qcom,msm8974";
+	compatible = "qcom,msm8974-cdp", "qcom,msm8974", "qcom,cdp";
 	qcom,msm-id = <126 1 0x20000>;
 };
 
 &usb3 {
-	#address-cells = <0>;
 	interrupt-parent = <&usb3>;
-	interrupts = <0 1 2 3>;
+	interrupts = <0 1>;
 	#interrupt-cells = <1>;
-	interrupt-map-mask = <0xffffffff>;
-	interrupt-map = <0 &intc 0 131 0
-			1 &intc 0 179 0
-			2 &intc 0 133 0
-			3 &spmi_bus 0x0 0x0 0x9 0x0>;
-	interrupt-names = "irq", "otg_irq", "hs_phy_irq", "pmic_id_irq";
+	interrupt-map-mask = <0x0 0xffffffff>;
+	interrupt-map = <0x0 0 &intc 0 133 0
+			 0x0 1 &spmi_bus 0x0 0x0 0x9 0x0>;
+	interrupt-names = "hs_phy_irq", "pmic_id_irq";
 
 	qcom,misc-ref = <&pm8941_misc>;
 };
diff --git a/arch/arm/boot/dts/msm8974-v2-fluid.dts b/arch/arm/boot/dts/msm8974-v2-fluid.dts
index 4efad9e..c5779b1 100644
--- a/arch/arm/boot/dts/msm8974-v2-fluid.dts
+++ b/arch/arm/boot/dts/msm8974-v2-fluid.dts
@@ -17,21 +17,18 @@
 
 / {
 	model = "Qualcomm MSM 8974v2 FLUID";
-	compatible = "qcom,msm8974-fluid", "qcom,msm8974";
+	compatible = "qcom,msm8974-fluid", "qcom,msm8974", "qcom,fluid";
 	qcom,msm-id = <126 3 0x20000>;
 };
 
 &usb3 {
-	#address-cells = <0>;
 	interrupt-parent = <&usb3>;
-	interrupts = <0 1 2 3>;
+	interrupts = <0 1>;
 	#interrupt-cells = <1>;
-	interrupt-map-mask = <0xffffffff>;
-	interrupt-map = <0 &intc 0 131 0
-			1 &intc 0 179 0
-			2 &intc 0 133 0
-			3 &spmi_bus 0x0 0x0 0x9 0x0>;
-	interrupt-names = "irq", "otg_irq", "hs_phy_irq", "pmic_id_irq";
+	interrupt-map-mask = <0x0 0xffffffff>;
+	interrupt-map = <0x0 0 &intc 0 133 0
+			 0x0 1 &spmi_bus 0x0 0x0 0x9 0x0>;
+	interrupt-names = "hs_phy_irq", "pmic_id_irq";
 
 	qcom,misc-ref = <&pm8941_misc>;
 };
diff --git a/arch/arm/boot/dts/msm8974-v2-liquid.dts b/arch/arm/boot/dts/msm8974-v2-liquid.dts
index 86584f8..7132f43 100644
--- a/arch/arm/boot/dts/msm8974-v2-liquid.dts
+++ b/arch/arm/boot/dts/msm8974-v2-liquid.dts
@@ -17,21 +17,18 @@
 
 / {
 	model = "Qualcomm MSM 8974v2 LIQUID";
-	compatible = "qcom,msm8974-liquid", "qcom,msm8974";
+	compatible = "qcom,msm8974-liquid", "qcom,msm8974", "qcom,liquid";
 	qcom,msm-id = <126 9 0x20000>;
 };
 
 &usb3 {
-	#address-cells = <0>;
 	interrupt-parent = <&usb3>;
-	interrupts = <0 1 2 3>;
+	interrupts = <0 1>;
 	#interrupt-cells = <1>;
-	interrupt-map-mask = <0xffffffff>;
-	interrupt-map = <0 &intc 0 131 0
-			1 &intc 0 179 0
-			2 &intc 0 133 0
-			3 &spmi_bus 0x0 0x0 0x9 0x0>;
-	interrupt-names = "irq", "otg_irq", "hs_phy_irq", "pmic_id_irq";
+	interrupt-map-mask = <0x0 0xffffffff>;
+	interrupt-map = <0x0 0 &intc 0 133 0
+			 0x0 1 &spmi_bus 0x0 0x0 0x9 0x0>;
+	interrupt-names = "hs_phy_irq", "pmic_id_irq";
 
 	qcom,misc-ref = <&pm8941_misc>;
 };
diff --git a/arch/arm/boot/dts/msm8974-v2-mtp.dts b/arch/arm/boot/dts/msm8974-v2-mtp.dts
index a2e2ffa..d38e663 100644
--- a/arch/arm/boot/dts/msm8974-v2-mtp.dts
+++ b/arch/arm/boot/dts/msm8974-v2-mtp.dts
@@ -17,21 +17,18 @@
 
 / {
 	model = "Qualcomm MSM 8974v2 MTP";
-	compatible = "qcom,msm8974-mtp", "qcom,msm8974";
+	compatible = "qcom,msm8974-mtp", "qcom,msm8974", "qcom,mtp";
 	qcom,msm-id = <126 8 0x20000>;
 };
 
 &usb3 {
-	#address-cells = <0>;
 	interrupt-parent = <&usb3>;
-	interrupts = <0 1 2 3>;
+	interrupts = <0 1>;
 	#interrupt-cells = <1>;
-	interrupt-map-mask = <0xffffffff>;
-	interrupt-map = <0 &intc 0 131 0
-			1 &intc 0 179 0
-			2 &intc 0 133 0
-			3 &spmi_bus 0x0 0x0 0x9 0x0>;
-	interrupt-names = "irq", "otg_irq", "hs_phy_irq", "pmic_id_irq";
+	interrupt-map-mask = <0x0 0xffffffff>;
+	interrupt-map = <0x0 0 &intc 0 133 0
+			 0x0 1 &spmi_bus 0x0 0x0 0x9 0x0>;
+	interrupt-names = "hs_phy_irq", "pmic_id_irq";
 
 	qcom,misc-ref = <&pm8941_misc>;
 };
diff --git a/arch/arm/boot/dts/msm8974.dtsi b/arch/arm/boot/dts/msm8974.dtsi
index c16feee..9a5a5d2 100644
--- a/arch/arm/boot/dts/msm8974.dtsi
+++ b/arch/arm/boot/dts/msm8974.dtsi
@@ -144,16 +144,16 @@
 		reg = <0xf9a55000 0x400>;
 		interrupts = <0 134 0 0 140 0>;
 		interrupt-names = "core_irq", "async_irq";
-		HSUSB_VDDCX-supply = <&pm8841_s2>;
+		HSUSB_VDDCX-supply = <&pm8841_s2_corner>;
 		HSUSB_1p8-supply = <&pm8941_l6>;
 		HSUSB_3p3-supply = <&pm8941_l24>;
+		qcom,vdd-voltage-level = <1 5 7>;
 
 		qcom,hsusb-otg-phy-type = <2>;
 		qcom,hsusb-otg-phy-init-seq = <0x63 0x81 0xffffffff>;
 		qcom,hsusb-otg-mode = <1>;
 		qcom,hsusb-otg-otg-control = <1>;
 		qcom,hsusb-otg-disable-reset;
-		qcom,hsusb-otg-pnoc-errata-fix;
 
 		qcom,msm-bus,name = "usb2";
 		qcom,msm-bus,num-cases = <2>;
@@ -593,6 +593,7 @@
 			qcom,cdc-mclk-clk-rate = <9600000>;
 			qcom,cdc-slim-ifd = "taiko-slim-ifd";
 			qcom,cdc-slim-ifd-elemental-addr = [00 00 A0 00 17 02];
+			qcom,cdc-dmic-sample-rate = <4800000>;
 		};
 	};
 
@@ -628,10 +629,14 @@
 		qcom,cdc-mclk-gpios = <&pm8941_gpios 15 0>;
 		taiko-mclk-clk = <&pm8941_clkdiv1>;
 		qcom,taiko-mclk-clk-freq = <9600000>;
-		prim-auxpcm-gpio-clk  = <&msmgpio 65 0>;
-		prim-auxpcm-gpio-sync = <&msmgpio 66 0>;
-		prim-auxpcm-gpio-din  = <&msmgpio 67 0>;
-		prim-auxpcm-gpio-dout = <&msmgpio 68 0>;
+		qcom,prim-auxpcm-gpio-clk  = <&msmgpio 65 0>;
+		qcom,prim-auxpcm-gpio-sync = <&msmgpio 66 0>;
+		qcom,prim-auxpcm-gpio-din  = <&msmgpio 67 0>;
+		qcom,prim-auxpcm-gpio-dout = <&msmgpio 68 0>;
+		qcom,sec-auxpcm-gpio-clk  = <&msmgpio 79 0>;
+		qcom,sec-auxpcm-gpio-sync = <&msmgpio 80 0>;
+		qcom,sec-auxpcm-gpio-din  = <&msmgpio 81 0>;
+		qcom,sec-auxpcm-gpio-dout = <&msmgpio 82 0>;
 	};
 
 	spmi_bus: qcom,spmi@fc4c0000 {
@@ -712,8 +717,11 @@
 		compatible = "qcom,dwc-usb3-msm";
 		reg = <0xf9200000 0xfc000>,
 			  <0xfd4ab000 0x4>;
-		interrupts = <0 131 0>, <0 179 0>, <0 133 0>;
-		interrupt-names = "irq", "otg_irq", "hs_phy_irq";
+		#address-cells = <1>;
+		#size-cells = <1>;
+		ranges;
+		interrupts = <0 133 0>;
+		interrupt-names = "hs_phy_irq";
 		ssusb_vdd_dig-supply = <&pm8841_s2_corner>;
 		SSUSB_1p8-supply = <&pm8941_l6>;
 		hsusb_vdd_dig-supply = <&pm8841_s2_corner>;
@@ -731,6 +739,14 @@
 		qcom,msm-bus,vectors-KBps =
 				<61 512 0 0>,
 				<61 512 240000 960000>;
+		dwc3@f9200000 {
+			compatible = "synopsys,dwc3";
+			reg = <0xf9200000 0xfc000>;
+			interrupt-parent = <&intc>;
+			interrupts = <0 131 0>, <0 179 0>;
+			interrupt-names = "irq", "otg_irq";
+			tx-fifo-resize;
+		};
 	};
 
 	ehci: qcom,ehci-host@f9a55000 {
@@ -767,6 +783,10 @@
 		qcom,adsp-state = <0>;
 	};
 
+	qcom,msm-audio-ion {
+		compatible = "qcom,msm-audio-ion";
+	};
+
 	qcom,msm-pcm {
 		compatible = "qcom,msm-pcm-dsp";
 		qcom,msm-pcm-dsp-id = <0>;
@@ -943,15 +963,25 @@
 		qcom,msm-cpudai-auxpcm-data = <0>, <0>;
 		qcom,msm-cpudai-auxpcm-pcm-clk-rate = <2048000>, <2048000>;
 
-		qcom,msm-auxpcm-rx {
+		qcom,msm-prim-auxpcm-rx {
 			qcom,msm-auxpcm-dev-id = <4106>;
 			compatible = "qcom,msm-auxpcm-dev";
 		};
 
-		qcom,msm-auxpcm-tx {
+		qcom,msm-prim-auxpcm-tx {
 			qcom,msm-auxpcm-dev-id = <4107>;
 			compatible = "qcom,msm-auxpcm-dev";
 		};
+
+		qcom,msm-sec-auxpcm-rx {
+			qcom,msm-auxpcm-dev-id = <4108>;
+			compatible = "qcom,msm-auxpcm-dev";
+		};
+
+		qcom,msm-sec-auxpcm-tx {
+			qcom,msm-auxpcm-dev-id = <4109>;
+			compatible = "qcom,msm-auxpcm-dev";
+		};
 	};
 
 	qcom,msm-dai-mi2s {
@@ -1225,7 +1255,7 @@
 		interrupts = <0 132 0 0 135 0>;
 		interrupt-names = "ssusb", "hsusb";
 		qcom,usb-bam-num-pipes = <16>;
-		qcom,usb-base-address = <0xf9200000>;
+		qcom,usb-bam-fifo-baseaddr = <0xf9200000>;
 		qcom,ignore-core-reset-ack;
 		qcom,disable-clk-gating;
 
diff --git a/arch/arm/boot/dts/msm9625-smp2p.dtsi b/arch/arm/boot/dts/msm9625-smp2p.dtsi
index 02c95e4..46af1b2 100644
--- a/arch/arm/boot/dts/msm9625-smp2p.dtsi
+++ b/arch/arm/boot/dts/msm9625-smp2p.dtsi
@@ -26,7 +26,6 @@
 		interrupts = <0 158 1>;
 	};
 
-	/* SMP2P Test Driver for inbound entries */
 	smp2pgpio_smp2p_7_in: qcom,smp2pgpio-smp2p-7-in {
 		compatible = "qcom,smp2pgpio";
 		qcom,entry-name = "smp2p";
@@ -43,7 +42,6 @@
 		gpios = <&smp2pgpio_smp2p_7_in 0 0>;
 	};
 
-	/* SMP2P Test Driver for outbound entries */
 	smp2pgpio_smp2p_7_out: qcom,smp2pgpio-smp2p-7-out {
 		compatible = "qcom,smp2pgpio";
 		qcom,entry-name = "smp2p";
@@ -59,7 +57,6 @@
 		gpios = <&smp2pgpio_smp2p_7_out 0 0>;
 	};
 
-	/* SMP2P Test Driver for modem inbound */
 	smp2pgpio_smp2p_1_in: qcom,smp2pgpio-smp2p-1-in {
 		compatible = "qcom,smp2pgpio";
 		qcom,entry-name = "smp2p";
@@ -76,7 +73,6 @@
 		gpios = <&smp2pgpio_smp2p_1_in 0 0>;
 	};
 
-	/* SMP2P Test Driver for modem output */
 	smp2pgpio_smp2p_1_out: qcom,smp2pgpio-smp2p-1-out {
 		compatible = "qcom,smp2pgpio";
 		qcom,entry-name = "smp2p";
@@ -92,7 +88,6 @@
 		gpios = <&smp2pgpio_smp2p_1_out 0 0>;
 	};
 
-	/* SMP2P SSR Driver for inbound entry from modem. */
 	smp2pgpio_ssr_smp2p_1_in: qcom,smp2pgpio-ssr-smp2p-1-in {
 		compatible = "qcom,smp2pgpio";
 		qcom,entry-name = "slave-kernel";
@@ -104,7 +99,6 @@
 		#interrupt-cells = <2>;
 	};
 
-	/* SMP2P SSR Driver for outbound entry to modem */
 	smp2pgpio_ssr_smp2p_1_out: qcom,smp2pgpio-ssr-smp2p-1-out {
 		compatible = "qcom,smp2pgpio";
 		qcom,entry-name = "master-kernel";
@@ -115,7 +109,6 @@
 		#interrupt-cells = <2>;
 	};
 
-	/* SMP2P Test Driver for adsp inbound */
 	smp2pgpio_smp2p_2_in: qcom,smp2pgpio-smp2p-2-in {
 		compatible = "qcom,smp2pgpio";
 		qcom,entry-name = "smp2p";
@@ -132,7 +125,6 @@
 		gpios = <&smp2pgpio_smp2p_2_in 0 0>;
 	};
 
-	/* SMP2P Test Driver for adsp output */
 	smp2pgpio_smp2p_2_out: qcom,smp2pgpio-smp2p-2-out {
 		compatible = "qcom,smp2pgpio";
 		qcom,entry-name = "smp2p";
diff --git a/arch/arm/boot/dts/msm9625-v1-cdp.dts b/arch/arm/boot/dts/msm9625-v1-cdp.dts
index cc7a758..cf17c69 100644
--- a/arch/arm/boot/dts/msm9625-v1-cdp.dts
+++ b/arch/arm/boot/dts/msm9625-v1-cdp.dts
@@ -16,7 +16,7 @@
 
 / {
 	model = "Qualcomm MSM 9625V1 CDP";
-	compatible = "qcom,msm9625-cdp", "qcom,msm9625";
+	compatible = "qcom,msm9625-cdp", "qcom,msm9625", "qcom,cdp";
 	qcom,msm-id = <134 1 0>, <152 1 0>, <149 1 0>, <150 1 0>,
 		      <151 1 0>, <148 1 0>, <173 1 0>, <174 1 0>,
 		      <175 1 0>;
diff --git a/arch/arm/boot/dts/msm9625-v1-mtp.dts b/arch/arm/boot/dts/msm9625-v1-mtp.dts
index d78bb77..24aa3af 100644
--- a/arch/arm/boot/dts/msm9625-v1-mtp.dts
+++ b/arch/arm/boot/dts/msm9625-v1-mtp.dts
@@ -16,7 +16,7 @@
 
 / {
 	model = "Qualcomm MSM 9625V1 MTP";
-	compatible = "qcom,msm9625-mtp", "qcom,msm9625";
+	compatible = "qcom,msm9625-mtp", "qcom,msm9625", "qcom,mtp";
 	qcom,msm-id = <134 7 0>, <152 7 0>, <149 7 0>, <150 7 0>,
 		      <151 7 0>, <148 7 0>, <173 7 0>, <174 7 0>,
 		      <175 7 0>;
@@ -97,11 +97,23 @@
 	};
 
 	mpp@a300 { /* MPP 4 */
+		/* VADC channel 19 */
+		qcom,mode = <4>;
+		qcom,ain-route = <3>; /* AMUX 8 */
+		qcom,master-en = <1>;
+		qcom,src-sel = <0>; /* Function constant */
+		qcom,invert = <1>;
 	};
 
 	mpp@a400 { /* MPP 5 */
 	};
 
 	mpp@a500 { /* MPP 6 */
+		/* VADC channel 21 */
+		qcom,mode = <4>;
+		qcom,ain-route = <1>; /* AMUX 6 */
+		qcom,master-en = <1>;
+		qcom,src-sel = <0>; /* Function constant */
+		qcom,invert = <1>;
 	};
 };
diff --git a/arch/arm/boot/dts/msm9625-v1-rumi.dts b/arch/arm/boot/dts/msm9625-v1-rumi.dts
index a854947..ef00681 100644
--- a/arch/arm/boot/dts/msm9625-v1-rumi.dts
+++ b/arch/arm/boot/dts/msm9625-v1-rumi.dts
@@ -16,7 +16,7 @@
 
 / {
 	model = "Qualcomm MSM 9625V1 RUMI";
-	compatible = "qcom,msm9625-rumi", "qcom,msm9625";
+	compatible = "qcom,msm9625-rumi", "qcom,msm9625", "qcom,rumi";
 	qcom,msm-id = <134 15 0>;
 
 	chosen{
diff --git a/arch/arm/boot/dts/msm9625-v1.dtsi b/arch/arm/boot/dts/msm9625-v1.dtsi
index 54aa02a..ad95601 100644
--- a/arch/arm/boot/dts/msm9625-v1.dtsi
+++ b/arch/arm/boot/dts/msm9625-v1.dtsi
@@ -57,3 +57,7 @@
 &ldrex_spinlock {
 	status = "ok";
 };
+
+&hsic_host {
+	qcom,phy-sof-workaround;
+};
diff --git a/arch/arm/boot/dts/msm9625-v2-1-cdp.dts b/arch/arm/boot/dts/msm9625-v2-1-cdp.dts
index 8702184..da07100 100644
--- a/arch/arm/boot/dts/msm9625-v2-1-cdp.dts
+++ b/arch/arm/boot/dts/msm9625-v2-1-cdp.dts
@@ -16,7 +16,7 @@
 
 / {
 	model = "Qualcomm MSM 9625V2.1 CDP";
-	compatible = "qcom,msm9625-cdp", "qcom,msm9625";
+	compatible = "qcom,msm9625-cdp", "qcom,msm9625", "qcom,cdp";
 	qcom,msm-id = <134 1 0x20001>, <152 1 0x20001>, <149 1 0x20001>,
 		      <150 1 0x20001>, <151 1 0x20001>, <148 1 0x20001>,
 		      <173 1 0x20001>, <174 1 0x20001>, <175 1 0x20001>;
diff --git a/arch/arm/boot/dts/msm9625-v2-1-mtp.dts b/arch/arm/boot/dts/msm9625-v2-1-mtp.dts
index 2dc040c..1e0f3c0 100644
--- a/arch/arm/boot/dts/msm9625-v2-1-mtp.dts
+++ b/arch/arm/boot/dts/msm9625-v2-1-mtp.dts
@@ -16,7 +16,7 @@
 
 / {
 	model = "Qualcomm MSM 9625V2.1 MTP";
-	compatible = "qcom,msm9625-mtp", "qcom,msm9625";
+	compatible = "qcom,msm9625-mtp", "qcom,msm9625", "qcom,mtp";
 	qcom,msm-id = <134 7 0x20001>, <152 7 0x20001>, <149 7 0x20001>,
 		      <150 7 0x20001>, <151 7 0x20001>, <148 7 0x20001>,
 		      <173 7 0x20001>, <174 7 0x20001>, <175 7 0x20001>;
diff --git a/arch/arm/boot/dts/msm9625-v2-cdp.dts b/arch/arm/boot/dts/msm9625-v2-cdp.dts
index 94fe019..660bdbd 100644
--- a/arch/arm/boot/dts/msm9625-v2-cdp.dts
+++ b/arch/arm/boot/dts/msm9625-v2-cdp.dts
@@ -18,7 +18,7 @@
 
 / {
 	model = "Qualcomm MSM 9625V2 CDP";
-	compatible = "qcom,msm9625-cdp", "qcom,msm9625";
+	compatible = "qcom,msm9625-cdp", "qcom,msm9625", "qcom,cdp";
 	qcom,msm-id = <134 1 0x20000>, <152 1 0x20000>, <149 1 0x20000>,
 		      <150 1 0x20000>, <151 1 0x20000>, <148 1 0x20000>,
 		      <173 1 0x20000>, <174 1 0x20000>, <175 1 0x20000>;
diff --git a/arch/arm/boot/dts/msm9625-v2-mtp.dts b/arch/arm/boot/dts/msm9625-v2-mtp.dts
index 2840024..c9e54be 100644
--- a/arch/arm/boot/dts/msm9625-v2-mtp.dts
+++ b/arch/arm/boot/dts/msm9625-v2-mtp.dts
@@ -16,7 +16,7 @@
 
 / {
 	model = "Qualcomm MSM 9625V2 MTP";
-	compatible = "qcom,msm9625-mtp", "qcom,msm9625";
+	compatible = "qcom,msm9625-mtp", "qcom,msm9625", "qcom,mtp";
 	qcom,msm-id = <134 7 0x20000>, <152 7 0x20000>, <149 7 0x20000>,
 		      <150 7 0x20000>, <151 7 0x20000>, <148 7 0x20000>,
 		      <173 7 0x20000>, <174 7 0x20000>, <175 7 0x20000>;
@@ -97,11 +97,23 @@
 	};
 
 	mpp@a300 { /* MPP 4 */
+		/* VADC channel 19 */
+		qcom,mode = <4>;
+		qcom,ain-route = <3>; /* AMUX 8 */
+		qcom,master-en = <1>;
+		qcom,src-sel = <0>; /* Function constant */
+		qcom,invert = <1>;
 	};
 
 	mpp@a400 { /* MPP 5 */
 	};
 
 	mpp@a500 { /* MPP 6 */
+		/* channel 21 */
+		qcom,mode = <4>;
+		qcom,ain-route = <1>; /* AMUX 6 */
+		qcom,master-en = <1>;
+		qcom,src-sel = <0>; /* Function constant */
+		qcom,invert = <1>;
 	};
 };
diff --git a/arch/arm/boot/dts/msm9625.dtsi b/arch/arm/boot/dts/msm9625.dtsi
index 3dbc95d..fe81fa9 100644
--- a/arch/arm/boot/dts/msm9625.dtsi
+++ b/arch/arm/boot/dts/msm9625.dtsi
@@ -108,7 +108,7 @@
 				<87 512 40000 640000>;
 	};
 
-	hsic@f9a15000 {
+	hsic_host: hsic@f9a15000 {
 		compatible = "qcom,hsic-host";
 		reg = <0xf9a15000 0x400>;
 		interrupts = <0 136 0>, <0 148 0>;
@@ -825,7 +825,7 @@
 	};
 
 	chan@33 {
-		label = "pa_therm1";
+		label = "pa_therm0";
 		reg = <0x33>;
 		qcom,decimation = <0>;
 		qcom,pre-div-channel-scaling = <0>;
@@ -836,7 +836,7 @@
 	};
 
 	chan@34 {
-		label = "pa_therm2";
+		label = "pa_therm1";
 		reg = <0x34>;
 		qcom,decimation = <0>;
 		qcom,pre-div-channel-scaling = <0>;
@@ -867,4 +867,26 @@
 		qcom,hw-settle-time = <2>;
 		qcom,fast-avg-setup = <0>;
 	};
+
+	chan@13 {
+		label = "case_therm";
+		reg = <0x13>;
+		qcom,decimation = <0>;
+		qcom,pre-div-channel-scaling = <0>;
+		qcom,calibration-type = "ratiometric";
+		qcom,scale-function = <2>;
+		qcom,hw-settle-time = <2>;
+		qcom,fast-avg-setup = <0>;
+	};
+
+	chan@15 {
+		label = "ambient_therm";
+		reg = <0x15>;
+		qcom,decimation = <0>;
+		qcom,pre-div-channel-scaling = <0>;
+		qcom,calibration-type = "ratiometric";
+		qcom,scale-function = <2>;
+		qcom,hw-settle-time = <2>;
+		qcom,fast-avg-setup = <0>;
+	};
 };
diff --git a/arch/arm/boot/dts/msmzinc-ion.dtsi b/arch/arm/boot/dts/msmzinc-ion.dtsi
index 4bf078a..aac4230 100644
--- a/arch/arm/boot/dts/msmzinc-ion.dtsi
+++ b/arch/arm/boot/dts/msmzinc-ion.dtsi
@@ -20,6 +20,10 @@
 			reg = <30>;
 		};
 
+		qcom,ion-heap@21 { /* SYSTEM CONTIG HEAP */
+			reg = <21>;
+		};
+
 		qcom,ion-heap@25 { /* IOMMU HEAP */
 			reg = <25>;
 		};
diff --git a/arch/arm/boot/dts/msmzinc-sim.dts b/arch/arm/boot/dts/msmzinc-sim.dts
index 48d7ef1..e410344 100644
--- a/arch/arm/boot/dts/msmzinc-sim.dts
+++ b/arch/arm/boot/dts/msmzinc-sim.dts
@@ -16,7 +16,7 @@
 
 / {
 	model = "Qualcomm MSM ZINC Simulator";
-	compatible = "qcom,msmzinc-sim", "qcom,msmzinc";
+	compatible = "qcom,msmzinc-sim", "qcom,msmzinc", "qcom,sim";
 	qcom,msm-id = <178 0 0>;
 
 	aliases {
diff --git a/arch/arm/configs/msm8610_defconfig b/arch/arm/configs/msm8610_defconfig
index 590692c..5e520f3 100644
--- a/arch/arm/configs/msm8610_defconfig
+++ b/arch/arm/configs/msm8610_defconfig
@@ -216,6 +216,7 @@
 CONFIG_INPUT_TOUCHSCREEN=y
 CONFIG_TOUCHSCREEN_SYNAPTICS_I2C_RMI4=y
 CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_RMI4_DEV=y
+CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_FW_UPDATE=y
 CONFIG_INPUT_MISC=y
 CONFIG_INPUT_UINPUT=y
 CONFIG_INPUT_GPIO=m
@@ -231,6 +232,7 @@
 CONFIG_SPI_QUP=y
 CONFIG_SPI_SPIDEV=m
 CONFIG_SPMI=y
+CONFIG_MSM_BUS_SCALING=y
 CONFIG_SPMI_MSM_PMIC_ARB=y
 CONFIG_MSM_QPNP_INT=y
 CONFIG_SLIMBUS_MSM_NGD=y
@@ -316,6 +318,7 @@
 CONFIG_ANDROID_TIMED_GPIO=y
 CONFIG_ANDROID_LOW_MEMORY_KILLER=y
 CONFIG_SPS=y
+CONFIG_USB_BAM=y
 CONFIG_SPS_SUPPORT_NDP_BAM=y
 CONFIG_QPNP_PWM=y
 CONFIG_QPNP_POWER_ON=y
@@ -344,8 +347,20 @@
 CONFIG_MAGIC_SYSRQ=y
 CONFIG_SCHEDSTATS=y
 CONFIG_TIMER_STATS=y
+CONFIG_DEBUG_KMEMLEAK=y
+CONFIG_DEBUG_KMEMLEAK_DEFAULT_OFF=y
+CONFIG_DEBUG_SPINLOCK=y
+CONFIG_DEBUG_MUTEXES=y
+CONFIG_DEBUG_ATOMIC_SLEEP=y
+CONFIG_DEBUG_STACK_USAGE=y
 CONFIG_DEBUG_INFO=y
 CONFIG_DEBUG_MEMORY_INIT=y
+CONFIG_DEBUG_LIST=y
+CONFIG_FAULT_INJECTION=y
+CONFIG_FAIL_PAGE_ALLOC=y
+CONFIG_FAULT_INJECTION_DEBUG_FS=y
+CONFIG_FAULT_INJECTION_STACKTRACE_FILTER=y
+CONFIG_DEBUG_PAGEALLOC=y
 CONFIG_ENABLE_DEFAULT_TRACERS=y
 CONFIG_DYNAMIC_DEBUG=y
 CONFIG_DEBUG_USER=y
@@ -355,3 +370,4 @@
 CONFIG_CRYPTO_TWOFISH=y
 # CONFIG_CRYPTO_HW is not set
 CONFIG_CRC_CCITT=y
+CONFIG_QPNP_VIBRATOR=y
diff --git a/arch/arm/configs/msm8974-perf_defconfig b/arch/arm/configs/msm8974-perf_defconfig
index c33a236..f76f810 100644
--- a/arch/arm/configs/msm8974-perf_defconfig
+++ b/arch/arm/configs/msm8974-perf_defconfig
@@ -330,6 +330,7 @@
 CONFIG_MSM_CSI30_HEADER=y
 CONFIG_MSM_CSIPHY=y
 CONFIG_MSM_CSID=y
+CONFIG_MSM_EEPROM=y
 CONFIG_MSM_ISPIF=y
 CONFIG_S5K3L1YX=y
 CONFIG_MSMB_CAMERA=y
@@ -387,6 +388,7 @@
 CONFIG_USB_EHSET_TEST_FIXTURE=y
 CONFIG_USB_GADGET=y
 CONFIG_USB_GADGET_DEBUG_FILES=y
+CONFIG_USB_CI13XXX_MSM=y
 CONFIG_USB_DWC3_MSM=y
 CONFIG_USB_G_ANDROID=y
 CONFIG_MMC=y
diff --git a/arch/arm/configs/msm8974_defconfig b/arch/arm/configs/msm8974_defconfig
index 1cda524..6112134 100644
--- a/arch/arm/configs/msm8974_defconfig
+++ b/arch/arm/configs/msm8974_defconfig
@@ -242,6 +242,7 @@
 CONFIG_CMA=y
 CONFIG_BLK_DEV_LOOP=y
 CONFIG_BLK_DEV_RAM=y
+CONFIG_UID_STAT=y
 CONFIG_TSPP=m
 CONFIG_HAPTIC_ISA1200=y
 CONFIG_QSEECOM=y
@@ -336,6 +337,7 @@
 CONFIG_MSM_CSI30_HEADER=y
 CONFIG_MSM_CSIPHY=y
 CONFIG_MSM_CSID=y
+CONFIG_MSM_EEPROM=y
 CONFIG_MSM_ISPIF=y
 CONFIG_S5K3L1YX=y
 CONFIG_MSMB_CAMERA=y
@@ -395,6 +397,7 @@
 CONFIG_USB_EHSET_TEST_FIXTURE=y
 CONFIG_USB_GADGET=y
 CONFIG_USB_GADGET_DEBUG_FILES=y
+CONFIG_USB_CI13XXX_MSM=y
 CONFIG_USB_DWC3_MSM=y
 CONFIG_USB_G_ANDROID=y
 CONFIG_MMC=y
diff --git a/arch/arm/mach-msm/Kconfig b/arch/arm/mach-msm/Kconfig
index 54806ae..601fcfa 100644
--- a/arch/arm/mach-msm/Kconfig
+++ b/arch/arm/mach-msm/Kconfig
@@ -428,6 +428,8 @@
 	select MSM_SPM_REGULATOR
 	select MSM_JTAG_MM if CORESIGHT_ETM
 	select MSM_CPR_REGULATOR
+	select MSM_RPM_LOG
+	select MSM_RPM_STATS_LOG
 
 config ARCH_MSM8226
 	bool "MSM8226"
@@ -466,6 +468,8 @@
 	select MSM_SPM_REGULATOR
 	select MSM_JTAG_MM if CORESIGHT_ETM
 	select MSM_CPR_REGULATOR
+	select MSM_RPM_LOG
+	select MSM_RPM_STATS_LOG
 endmenu
 
 choice
@@ -1079,7 +1083,7 @@
 config KERNEL_MSM_CONTIG_MEM_REGION
 	bool "Enable in-kernel contiguous memory region"
 	default y if ARCH_MSM8X60
-	depends on ANDROID_PMEM && (ARCH_MSM8X60 || ARCH_MSM8960 || ARCH_MSM8974)
+	depends on ARCH_MSM8X60 || ARCH_MSM8960 || ARCH_MSM8974
 	help
 	   Enable the in-kernel contiguous memory allocator. Sets up a
 	   region of physically contiguous memory. This memory is
diff --git a/arch/arm/mach-msm/Makefile b/arch/arm/mach-msm/Makefile
index d07b094..1c14ac6 100644
--- a/arch/arm/mach-msm/Makefile
+++ b/arch/arm/mach-msm/Makefile
@@ -5,7 +5,7 @@
 obj-y += timer.o
 endif
 obj-y += clock.o clock-voter.o clock-dummy.o
-obj-y += modem_notifier.o subsystem_map.o
+obj-y += modem_notifier.o
 obj-$(CONFIG_USE_OF) += board-dt.o
 obj-$(CONFIG_CPU_FREQ_MSM) += cpufreq.o
 obj-$(CONFIG_DEBUG_FS) += nohlt.o clock-debug.o
@@ -24,6 +24,7 @@
 endif
 
 obj-y += acpuclock.o
+obj-$(CONFIG_HW_PERF_EVENTS) += perf_trace_counters.o
 obj-$(CONFIG_ARCH_MSM_KRAIT) += acpuclock-krait.o
 ifdef CONFIG_ARCH_MSM_KRAIT
 obj-$(CONFIG_DEBUG_FS) += acpuclock-krait-debug.o
diff --git a/arch/arm/mach-msm/acpuclock-8226.c b/arch/arm/mach-msm/acpuclock-8226.c
index 6e93c57..799d629 100644
--- a/arch/arm/mach-msm/acpuclock-8226.c
+++ b/arch/arm/mach-msm/acpuclock-8226.c
@@ -17,6 +17,7 @@
 #include <linux/module.h>
 #include <linux/errno.h>
 #include <linux/io.h>
+#include <linux/clk.h>
 #include <linux/platform_device.h>
 #include <linux/regulator/consumer.h>
 #include <linux/regulator/cpr-regulator.h>
@@ -82,17 +83,21 @@
 		.update_mask = RCG_CONFIG_UPDATE_BIT,
 		.poll_mask = RCG_CONFIG_UPDATE_BIT,
 	},
+	.power_collapse_khz = 300000,
+	.wait_for_irq_khz = 300000,
 };
 
 static int __init acpuclk_a7_probe(struct platform_device *pdev)
 {
 	struct resource *res;
+	u32 i;
 
 	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "rcg_base");
 	if (!res)
 		return -EINVAL;
 
-	drv_data.apcs_rcg_cmd = ioremap(res->start, resource_size(res));
+	drv_data.apcs_rcg_cmd = devm_ioremap(&pdev->dev, res->start,
+		resource_size(res));
 	if (!drv_data.apcs_rcg_cmd)
 		return -ENOMEM;
 
@@ -110,6 +115,21 @@
 		return PTR_ERR(drv_data.vdd_mem);
 	}
 
+	for (i = 0; i < NUM_SRC; i++) {
+		if (!drv_data.src_clocks[i].name)
+			continue;
+		drv_data.src_clocks[i].clk =
+			devm_clk_get(&pdev->dev, drv_data.src_clocks[i].name);
+		if (IS_ERR(drv_data.src_clocks[i].clk)) {
+			dev_err(&pdev->dev, "Unable to get clock %s\n",
+				drv_data.src_clocks[i].name);
+			return -EPROBE_DEFER;
+		}
+	}
+
+	/* Enable the always on source */
+	clk_prepare_enable(drv_data.src_clocks[PLL0].clk);
+
 	return acpuclk_cortex_init(pdev, &drv_data);
 }
 
diff --git a/arch/arm/mach-msm/acpuclock-8974.c b/arch/arm/mach-msm/acpuclock-8974.c
index 83c14a8..b673f93 100644
--- a/arch/arm/mach-msm/acpuclock-8974.c
+++ b/arch/arm/mach-msm/acpuclock-8974.c
@@ -259,242 +259,452 @@
 
 static struct l2_level l2_freq_tbl_v2[] __initdata = {
 	[0]  = { {  300000, PLL_0, 0,   0 }, LVL_LOW,   950000, 0 },
-	[1]  = { {  345600, HFPLL, 2,  36 }, LVL_NOM,   950000, 1 },
-	[2]  = { {  422400, HFPLL, 2,  44 }, LVL_NOM,   950000, 1 },
-	[3]  = { {  499200, HFPLL, 2,  52 }, LVL_NOM,   950000, 2 },
-	[4]  = { {  576000, HFPLL, 1,  30 }, LVL_NOM,   950000, 3 },
-	[5]  = { {  652800, HFPLL, 1,  34 }, LVL_NOM,   950000, 3 },
-	[6]  = { {  729600, HFPLL, 1,  38 }, LVL_NOM,   950000, 3 },
-	[7]  = { {  806400, HFPLL, 1,  42 }, LVL_HIGH, 1050000, 4 },
-	[8]  = { {  883200, HFPLL, 1,  46 }, LVL_HIGH, 1050000, 4 },
-	[9]  = { {  960000, HFPLL, 1,  50 }, LVL_HIGH, 1050000, 4 },
-	[10] = { { 1036800, HFPLL, 1,  54 }, LVL_HIGH, 1050000, 5 },
-	[11] = { { 1113600, HFPLL, 1,  58 }, LVL_HIGH, 1050000, 5 },
+	[1]  = { {  345600, HFPLL, 2,  36 }, LVL_LOW,   950000, 1 },
+	[2]  = { {  422400, HFPLL, 2,  44 }, LVL_LOW,   950000, 2 },
+	[3]  = { {  499200, HFPLL, 2,  52 }, LVL_LOW,   950000, 3 },
+	[4]  = { {  576000, HFPLL, 1,  30 }, LVL_LOW,   950000, 4 },
+	[5]  = { {  652800, HFPLL, 1,  34 }, LVL_NOM,   950000, 4 },
+	[6]  = { {  729600, HFPLL, 1,  38 }, LVL_NOM,   950000, 4 },
+	[7]  = { {  806400, HFPLL, 1,  42 }, LVL_NOM,   950000, 4 },
+	[8]  = { {  883200, HFPLL, 1,  46 }, LVL_NOM,   950000, 5 },
+	[9]  = { {  960000, HFPLL, 1,  50 }, LVL_NOM,   950000, 5 },
+	[10] = { { 1036800, HFPLL, 1,  54 }, LVL_NOM,   950000, 6 },
+	[11] = { { 1113600, HFPLL, 1,  58 }, LVL_HIGH, 1050000, 6 },
 	[12] = { { 1190400, HFPLL, 1,  62 }, LVL_HIGH, 1050000, 6 },
-	[13] = { { 1267200, HFPLL, 1,  66 }, LVL_HIGH, 1050000, 6 },
+	[13] = { { 1267200, HFPLL, 1,  66 }, LVL_HIGH, 1050000, 7 },
 	[14] = { { 1344000, HFPLL, 1,  70 }, LVL_HIGH, 1050000, 7 },
 	[15] = { { 1420800, HFPLL, 1,  74 }, LVL_HIGH, 1050000, 7 },
 	[16] = { { 1497600, HFPLL, 1,  78 }, LVL_HIGH, 1050000, 7 },
-	[17] = { { 1574400, HFPLL, 1,  82 }, LVL_HIGH, 1050000, 8 },
-	[18] = { { 1651200, HFPLL, 1,  86 }, LVL_HIGH, 1050000, 8 },
+	[17] = { { 1574400, HFPLL, 1,  82 }, LVL_HIGH, 1050000, 7 },
+	[18] = { { 1651200, HFPLL, 1,  86 }, LVL_HIGH, 1050000, 7 },
 	[19] = { { 1728000, HFPLL, 1,  90 }, LVL_HIGH, 1050000, 8 },
 	{ }
 };
 
 static struct acpu_level acpu_freq_tbl_2g_pvs0[] __initdata = {
-	{ 1, {  300000, PLL_0, 0,   0 }, L2(0),   815000,  400000 },
-	{ 0, {  345600, HFPLL, 2,  36 }, L2(3),   825000, 3200000 },
-	{ 1, {  422400, HFPLL, 2,  44 }, L2(3),   835000, 3200000 },
-	{ 0, {  499200, HFPLL, 2,  52 }, L2(6),   845000, 3200000 },
-	{ 1, {  576000, HFPLL, 1,  30 }, L2(6),   855000, 3200000 },
-	{ 1, {  652800, HFPLL, 1,  34 }, L2(7),   865000, 3200000 },
-	{ 1, {  729600, HFPLL, 1,  38 }, L2(7),   875000, 3200000 },
-	{ 0, {  806400, HFPLL, 1,  42 }, L2(10),  890000, 3200000 },
-	{ 1, {  883200, HFPLL, 1,  46 }, L2(10),  900000, 3200000 },
-	{ 0, {  960000, HFPLL, 1,  50 }, L2(10),  915000, 3200000 },
+	{ 1, {  300000, PLL_0, 0,   0 },  L2(0),  815000,  400000 },
+	{ 0, {  345600, HFPLL, 2,  36 },  L2(1),  825000, 3200000 },
+	{ 1, {  422400, HFPLL, 2,  44 },  L2(2),  835000, 3200000 },
+	{ 0, {  499200, HFPLL, 2,  52 },  L2(2),  845000, 3200000 },
+	{ 0, {  576000, HFPLL, 1,  30 },  L2(3),  855000, 3200000 },
+	{ 1, {  652800, HFPLL, 1,  34 },  L2(3),  865000, 3200000 },
+	{ 1, {  729600, HFPLL, 1,  38 },  L2(4),  875000, 3200000 },
+	{ 0, {  806400, HFPLL, 1,  42 },  L2(4),  890000, 3200000 },
+	{ 1, {  883200, HFPLL, 1,  46 },  L2(4),  900000, 3200000 },
+	{ 1, {  960000, HFPLL, 1,  50 },  L2(9),  915000, 3200000 },
 	{ 1, { 1036800, HFPLL, 1,  54 }, L2(10),  925000, 3200000 },
-	{ 0, { 1113600, HFPLL, 1,  58 }, L2(12),  940000, 3200000 },
-	{ 0, { 1190400, HFPLL, 1,  62 }, L2(12),  950000, 3200000 },
-	{ 0, { 1267200, HFPLL, 1,  66 }, L2(12),  965000, 3200000 },
-	{ 1, { 1344000, HFPLL, 1,  70 }, L2(12),  980000, 3200000 },
-	{ 0, { 1420800, HFPLL, 1,  74 }, L2(16),  995000, 3200000 },
-	{ 0, { 1497600, HFPLL, 1,  78 }, L2(16), 1010000, 3200000 },
-	{ 0, { 1574400, HFPLL, 1,  82 }, L2(16), 1025000, 3200000 },
-	{ 0, { 1651200, HFPLL, 1,  86 }, L2(16), 1040000, 3200000 },
-	{ 1, { 1728000, HFPLL, 1,  90 }, L2(16), 1055000, 3200000 },
-	{ 0, { 1804800, HFPLL, 1,  94 }, L2(19), 1070000, 3200000 },
-	{ 0, { 1881600, HFPLL, 1,  98 }, L2(19), 1085000, 3200000 },
+	{ 0, { 1113600, HFPLL, 1,  58 }, L2(10),  940000, 3200000 },
+	{ 1, { 1190400, HFPLL, 1,  62 }, L2(10),  950000, 3200000 },
+	{ 1, { 1267200, HFPLL, 1,  66 }, L2(13),  965000, 3200000 },
+	{ 0, { 1344000, HFPLL, 1,  70 }, L2(14),  980000, 3200000 },
+	{ 0, { 1420800, HFPLL, 1,  74 }, L2(15),  995000, 3200000 },
+	{ 1, { 1497600, HFPLL, 1,  78 }, L2(16), 1010000, 3200000 },
+	{ 1, { 1574400, HFPLL, 1,  82 }, L2(17), 1025000, 3200000 },
+	{ 0, { 1651200, HFPLL, 1,  86 }, L2(17), 1040000, 3200000 },
+	{ 1, { 1728000, HFPLL, 1,  90 }, L2(18), 1055000, 3200000 },
+	{ 0, { 1804800, HFPLL, 1,  94 }, L2(18), 1070000, 3200000 },
+	{ 0, { 1881600, HFPLL, 1,  98 }, L2(18), 1085000, 3200000 },
 	{ 1, { 1958400, HFPLL, 1, 102 }, L2(19), 1100000, 3200000 },
 	{ 0, { 0 } }
 };
 
 static struct acpu_level acpu_freq_tbl_2g_pvs1[] __initdata = {
-	{ 1, {  300000, PLL_0, 0,   0 }, L2(0),   800000,  400000 },
-	{ 0, {  345600, HFPLL, 2,  36 }, L2(3),   810000, 3200000 },
-	{ 1, {  422400, HFPLL, 2,  44 }, L2(3),   820000, 3200000 },
-	{ 0, {  499200, HFPLL, 2,  52 }, L2(6),   830000, 3200000 },
-	{ 1, {  576000, HFPLL, 1,  30 }, L2(6),   840000, 3200000 },
-	{ 1, {  652800, HFPLL, 1,  34 }, L2(7),   850000, 3200000 },
-	{ 1, {  729600, HFPLL, 1,  38 }, L2(7),   860000, 3200000 },
-	{ 0, {  806400, HFPLL, 1,  42 }, L2(10),  875000, 3200000 },
-	{ 1, {  883200, HFPLL, 1,  46 }, L2(10),  885000, 3200000 },
-	{ 0, {  960000, HFPLL, 1,  50 }, L2(10),  895000, 3200000 },
+	{ 1, {  300000, PLL_0, 0,   0 },  L2(0),  800000,  400000 },
+	{ 0, {  345600, HFPLL, 2,  36 },  L2(1),  810000, 3200000 },
+	{ 1, {  422400, HFPLL, 2,  44 },  L2(2),  820000, 3200000 },
+	{ 0, {  499200, HFPLL, 2,  52 },  L2(2),  830000, 3200000 },
+	{ 0, {  576000, HFPLL, 1,  30 },  L2(3),  840000, 3200000 },
+	{ 1, {  652800, HFPLL, 1,  34 },  L2(3),  850000, 3200000 },
+	{ 1, {  729600, HFPLL, 1,  38 },  L2(4),  860000, 3200000 },
+	{ 0, {  806400, HFPLL, 1,  42 },  L2(4),  875000, 3200000 },
+	{ 1, {  883200, HFPLL, 1,  46 },  L2(4),  885000, 3200000 },
+	{ 1, {  960000, HFPLL, 1,  50 },  L2(9),  895000, 3200000 },
 	{ 1, { 1036800, HFPLL, 1,  54 }, L2(10),  910000, 3200000 },
-	{ 0, { 1113600, HFPLL, 1,  58 }, L2(12),  920000, 3200000 },
-	{ 0, { 1190400, HFPLL, 1,  62 }, L2(12),  930000, 3200000 },
-	{ 0, { 1267200, HFPLL, 1,  66 }, L2(12),  945000, 3200000 },
-	{ 1, { 1344000, HFPLL, 1,  70 }, L2(12),  960000, 3200000 },
-	{ 0, { 1420800, HFPLL, 1,  74 }, L2(16),  975000, 3200000 },
-	{ 0, { 1497600, HFPLL, 1,  78 }, L2(16),  990000, 3200000 },
-	{ 0, { 1574400, HFPLL, 1,  82 }, L2(16), 1005000, 3200000 },
-	{ 0, { 1651200, HFPLL, 1,  86 }, L2(16), 1020000, 3200000 },
-	{ 1, { 1728000, HFPLL, 1,  90 }, L2(16), 1030000, 3200000 },
-	{ 0, { 1804800, HFPLL, 1,  94 }, L2(19), 1045000, 3200000 },
-	{ 0, { 1881600, HFPLL, 1,  98 }, L2(19), 1060000, 3200000 },
+	{ 0, { 1113600, HFPLL, 1,  58 }, L2(10),  920000, 3200000 },
+	{ 1, { 1190400, HFPLL, 1,  62 }, L2(10),  930000, 3200000 },
+	{ 1, { 1267200, HFPLL, 1,  66 }, L2(13),  945000, 3200000 },
+	{ 0, { 1344000, HFPLL, 1,  70 }, L2(14),  960000, 3200000 },
+	{ 0, { 1420800, HFPLL, 1,  74 }, L2(15),  975000, 3200000 },
+	{ 1, { 1497600, HFPLL, 1,  78 }, L2(16),  990000, 3200000 },
+	{ 1, { 1574400, HFPLL, 1,  82 }, L2(17), 1005000, 3200000 },
+	{ 0, { 1651200, HFPLL, 1,  86 }, L2(17), 1020000, 3200000 },
+	{ 1, { 1728000, HFPLL, 1,  90 }, L2(18), 1030000, 3200000 },
+	{ 0, { 1804800, HFPLL, 1,  94 }, L2(18), 1045000, 3200000 },
+	{ 0, { 1881600, HFPLL, 1,  98 }, L2(18), 1060000, 3200000 },
 	{ 1, { 1958400, HFPLL, 1, 102 }, L2(19), 1075000, 3200000 },
 	{ 0, { 0 } }
 };
 
 static struct acpu_level acpu_freq_tbl_2g_pvs2[] __initdata = {
-	{ 1, {  300000, PLL_0, 0,   0 }, L2(0),   785000,  400000 },
-	{ 0, {  345600, HFPLL, 2,  36 }, L2(3),   795000, 3200000 },
-	{ 1, {  422400, HFPLL, 2,  44 }, L2(3),   805000, 3200000 },
-	{ 0, {  499200, HFPLL, 2,  52 }, L2(6),   815000, 3200000 },
-	{ 1, {  576000, HFPLL, 1,  30 }, L2(6),   825000, 3200000 },
-	{ 1, {  652800, HFPLL, 1,  34 }, L2(7),   835000, 3200000 },
-	{ 1, {  729600, HFPLL, 1,  38 }, L2(7),   845000, 3200000 },
-	{ 0, {  806400, HFPLL, 1,  42 }, L2(10),  855000, 3200000 },
-	{ 1, {  883200, HFPLL, 1,  46 }, L2(10),  865000, 3200000 },
-	{ 0, {  960000, HFPLL, 1,  50 }, L2(10),  875000, 3200000 },
+	{ 1, {  300000, PLL_0, 0,   0 },  L2(0),  785000,  400000 },
+	{ 0, {  345600, HFPLL, 2,  36 },  L2(1),  795000, 3200000 },
+	{ 1, {  422400, HFPLL, 2,  44 },  L2(2),  805000, 3200000 },
+	{ 0, {  499200, HFPLL, 2,  52 },  L2(2),  815000, 3200000 },
+	{ 0, {  576000, HFPLL, 1,  30 },  L2(3),  825000, 3200000 },
+	{ 1, {  652800, HFPLL, 1,  34 },  L2(3),  835000, 3200000 },
+	{ 1, {  729600, HFPLL, 1,  38 },  L2(4),  845000, 3200000 },
+	{ 0, {  806400, HFPLL, 1,  42 },  L2(4),  855000, 3200000 },
+	{ 1, {  883200, HFPLL, 1,  46 },  L2(4),  865000, 3200000 },
+	{ 1, {  960000, HFPLL, 1,  50 },  L2(9),  875000, 3200000 },
 	{ 1, { 1036800, HFPLL, 1,  54 }, L2(10),  890000, 3200000 },
-	{ 0, { 1113600, HFPLL, 1,  58 }, L2(12),  900000, 3200000 },
-	{ 0, { 1190400, HFPLL, 1,  62 }, L2(12),  910000, 3200000 },
-	{ 0, { 1267200, HFPLL, 1,  66 }, L2(12),  925000, 3200000 },
-	{ 1, { 1344000, HFPLL, 1,  70 }, L2(12),  940000, 3200000 },
-	{ 0, { 1420800, HFPLL, 1,  74 }, L2(16),  955000, 3200000 },
-	{ 0, { 1497600, HFPLL, 1,  78 }, L2(16),  970000, 3200000 },
-	{ 0, { 1574400, HFPLL, 1,  82 }, L2(16),  980000, 3200000 },
-	{ 0, { 1651200, HFPLL, 1,  86 }, L2(16),  995000, 3200000 },
-	{ 1, { 1728000, HFPLL, 1,  90 }, L2(16), 1005000, 3200000 },
-	{ 0, { 1804800, HFPLL, 1,  94 }, L2(19), 1020000, 3200000 },
-	{ 0, { 1881600, HFPLL, 1,  98 }, L2(19), 1035000, 3200000 },
+	{ 0, { 1113600, HFPLL, 1,  58 }, L2(10),  900000, 3200000 },
+	{ 1, { 1190400, HFPLL, 1,  62 }, L2(10),  910000, 3200000 },
+	{ 1, { 1267200, HFPLL, 1,  66 }, L2(13),  925000, 3200000 },
+	{ 0, { 1344000, HFPLL, 1,  70 }, L2(14),  940000, 3200000 },
+	{ 0, { 1420800, HFPLL, 1,  74 }, L2(15),  955000, 3200000 },
+	{ 1, { 1497600, HFPLL, 1,  78 }, L2(16),  970000, 3200000 },
+	{ 1, { 1574400, HFPLL, 1,  82 }, L2(17),  980000, 3200000 },
+	{ 0, { 1651200, HFPLL, 1,  86 }, L2(17),  995000, 3200000 },
+	{ 1, { 1728000, HFPLL, 1,  90 }, L2(18), 1005000, 3200000 },
+	{ 0, { 1804800, HFPLL, 1,  94 }, L2(18), 1020000, 3200000 },
+	{ 0, { 1881600, HFPLL, 1,  98 }, L2(18), 1035000, 3200000 },
 	{ 1, { 1958400, HFPLL, 1, 102 }, L2(19), 1050000, 3200000 },
 	{ 0, { 0 } }
 };
 
 static struct acpu_level acpu_freq_tbl_2g_pvs3[] __initdata = {
-	{ 1, {  300000, PLL_0, 0,   0 }, L2(0),   775000,  400000 },
-	{ 0, {  345600, HFPLL, 2,  36 }, L2(3),   780000, 3200000 },
-	{ 1, {  422400, HFPLL, 2,  44 }, L2(3),   790000, 3200000 },
-	{ 0, {  499200, HFPLL, 2,  52 }, L2(6),   800000, 3200000 },
-	{ 1, {  576000, HFPLL, 1,  30 }, L2(6),   810000, 3200000 },
-	{ 1, {  652800, HFPLL, 1,  34 }, L2(7),   820000, 3200000 },
-	{ 1, {  729600, HFPLL, 1,  38 }, L2(7),   830000, 3200000 },
-	{ 0, {  806400, HFPLL, 1,  42 }, L2(10),  840000, 3200000 },
-	{ 1, {  883200, HFPLL, 1,  46 }, L2(10),  850000, 3200000 },
-	{ 0, {  960000, HFPLL, 1,  50 }, L2(10),  860000, 3200000 },
+	{ 1, {  300000, PLL_0, 0,   0 },  L2(0),  775000,  400000 },
+	{ 0, {  345600, HFPLL, 2,  36 },  L2(1),  780000, 3200000 },
+	{ 1, {  422400, HFPLL, 2,  44 },  L2(2),  790000, 3200000 },
+	{ 0, {  499200, HFPLL, 2,  52 },  L2(2),  800000, 3200000 },
+	{ 0, {  576000, HFPLL, 1,  30 },  L2(3),  810000, 3200000 },
+	{ 1, {  652800, HFPLL, 1,  34 },  L2(3),  820000, 3200000 },
+	{ 1, {  729600, HFPLL, 1,  38 },  L2(4),  830000, 3200000 },
+	{ 0, {  806400, HFPLL, 1,  42 },  L2(4),  840000, 3200000 },
+	{ 1, {  883200, HFPLL, 1,  46 },  L2(4),  850000, 3200000 },
+	{ 1, {  960000, HFPLL, 1,  50 },  L2(9),  860000, 3200000 },
 	{ 1, { 1036800, HFPLL, 1,  54 }, L2(10),  875000, 3200000 },
-	{ 0, { 1113600, HFPLL, 1,  58 }, L2(12),  885000, 3200000 },
-	{ 0, { 1190400, HFPLL, 1,  62 }, L2(12),  895000, 3200000 },
-	{ 0, { 1267200, HFPLL, 1,  66 }, L2(12),  910000, 3200000 },
-	{ 1, { 1344000, HFPLL, 1,  70 }, L2(12),  925000, 3200000 },
-	{ 0, { 1420800, HFPLL, 1,  74 }, L2(16),  935000, 3200000 },
-	{ 0, { 1497600, HFPLL, 1,  78 }, L2(16),  950000, 3200000 },
-	{ 0, { 1574400, HFPLL, 1,  82 }, L2(16),  960000, 3200000 },
-	{ 0, { 1651200, HFPLL, 1,  86 }, L2(16),  970000, 3200000 },
-	{ 1, { 1728000, HFPLL, 1,  90 }, L2(16),  985000, 3200000 },
-	{ 0, { 1804800, HFPLL, 1,  94 }, L2(19),  995000, 3200000 },
-	{ 0, { 1881600, HFPLL, 1,  98 }, L2(19), 1010000, 3200000 },
+	{ 0, { 1113600, HFPLL, 1,  58 }, L2(10),  885000, 3200000 },
+	{ 1, { 1190400, HFPLL, 1,  62 }, L2(10),  895000, 3200000 },
+	{ 1, { 1267200, HFPLL, 1,  66 }, L2(13),  910000, 3200000 },
+	{ 0, { 1344000, HFPLL, 1,  70 }, L2(14),  925000, 3200000 },
+	{ 0, { 1420800, HFPLL, 1,  74 }, L2(15),  935000, 3200000 },
+	{ 1, { 1497600, HFPLL, 1,  78 }, L2(16),  950000, 3200000 },
+	{ 1, { 1574400, HFPLL, 1,  82 }, L2(17),  960000, 3200000 },
+	{ 0, { 1651200, HFPLL, 1,  86 }, L2(17),  970000, 3200000 },
+	{ 1, { 1728000, HFPLL, 1,  90 }, L2(18),  985000, 3200000 },
+	{ 0, { 1804800, HFPLL, 1,  94 }, L2(18),  995000, 3200000 },
+	{ 0, { 1881600, HFPLL, 1,  98 }, L2(18), 1010000, 3200000 },
 	{ 1, { 1958400, HFPLL, 1, 102 }, L2(19), 1025000, 3200000 },
 	{ 0, { 0 } }
 };
 
 static struct acpu_level acpu_freq_tbl_2g_pvs4[] __initdata = {
-	{ 1, {  300000, PLL_0, 0,   0 }, L2(0),   775000,  400000 },
-	{ 0, {  345600, HFPLL, 2,  36 }, L2(3),   775000, 3200000 },
-	{ 1, {  422400, HFPLL, 2,  44 }, L2(3),   780000, 3200000 },
-	{ 0, {  499200, HFPLL, 2,  52 }, L2(6),   790000, 3200000 },
-	{ 1, {  576000, HFPLL, 1,  30 }, L2(6),   800000, 3200000 },
-	{ 1, {  652800, HFPLL, 1,  34 }, L2(7),   810000, 3200000 },
-	{ 1, {  729600, HFPLL, 1,  38 }, L2(7),   820000, 3200000 },
-	{ 0, {  806400, HFPLL, 1,  42 }, L2(10),  830000, 3200000 },
-	{ 1, {  883200, HFPLL, 1,  46 }, L2(10),  840000, 3200000 },
-	{ 0, {  960000, HFPLL, 1,  50 }, L2(10),  850000, 3200000 },
+	{ 1, {  300000, PLL_0, 0,   0 },  L2(0),  775000,  400000 },
+	{ 0, {  345600, HFPLL, 2,  36 },  L2(1),  775000, 3200000 },
+	{ 1, {  422400, HFPLL, 2,  44 },  L2(2),  780000, 3200000 },
+	{ 0, {  499200, HFPLL, 2,  52 },  L2(2),  790000, 3200000 },
+	{ 0, {  576000, HFPLL, 1,  30 },  L2(3),  800000, 3200000 },
+	{ 1, {  652800, HFPLL, 1,  34 },  L2(3),  810000, 3200000 },
+	{ 1, {  729600, HFPLL, 1,  38 },  L2(4),  820000, 3200000 },
+	{ 0, {  806400, HFPLL, 1,  42 },  L2(4),  830000, 3200000 },
+	{ 1, {  883200, HFPLL, 1,  46 },  L2(4),  840000, 3200000 },
+	{ 1, {  960000, HFPLL, 1,  50 },  L2(9),  850000, 3200000 },
 	{ 1, { 1036800, HFPLL, 1,  54 }, L2(10),  860000, 3200000 },
-	{ 0, { 1113600, HFPLL, 1,  58 }, L2(12),  870000, 3200000 },
-	{ 0, { 1190400, HFPLL, 1,  62 }, L2(12),  880000, 3200000 },
-	{ 0, { 1267200, HFPLL, 1,  66 }, L2(12),  895000, 3200000 },
-	{ 1, { 1344000, HFPLL, 1,  70 }, L2(12),  910000, 3200000 },
-	{ 0, { 1420800, HFPLL, 1,  74 }, L2(16),  920000, 3200000 },
-	{ 0, { 1497600, HFPLL, 1,  78 }, L2(16),  930000, 3200000 },
-	{ 0, { 1574400, HFPLL, 1,  82 }, L2(16),  940000, 3200000 },
-	{ 0, { 1651200, HFPLL, 1,  86 }, L2(16),  950000, 3200000 },
-	{ 1, { 1728000, HFPLL, 1,  90 }, L2(16),  960000, 3200000 },
-	{ 0, { 1804800, HFPLL, 1,  94 }, L2(19),  975000, 3200000 },
-	{ 0, { 1881600, HFPLL, 1,  98 }, L2(19),  985000, 3200000 },
+	{ 0, { 1113600, HFPLL, 1,  58 }, L2(10),  870000, 3200000 },
+	{ 1, { 1190400, HFPLL, 1,  62 }, L2(10),  880000, 3200000 },
+	{ 1, { 1267200, HFPLL, 1,  66 }, L2(13),  895000, 3200000 },
+	{ 0, { 1344000, HFPLL, 1,  70 }, L2(14),  910000, 3200000 },
+	{ 0, { 1420800, HFPLL, 1,  74 }, L2(15),  920000, 3200000 },
+	{ 1, { 1497600, HFPLL, 1,  78 }, L2(16),  930000, 3200000 },
+	{ 1, { 1574400, HFPLL, 1,  82 }, L2(17),  940000, 3200000 },
+	{ 0, { 1651200, HFPLL, 1,  86 }, L2(17),  950000, 3200000 },
+	{ 1, { 1728000, HFPLL, 1,  90 }, L2(18),  960000, 3200000 },
+	{ 0, { 1804800, HFPLL, 1,  94 }, L2(18),  975000, 3200000 },
+	{ 0, { 1881600, HFPLL, 1,  98 }, L2(18),  985000, 3200000 },
 	{ 1, { 1958400, HFPLL, 1, 102 }, L2(19), 1000000, 3200000 },
 	{ 0, { 0 } }
 };
 
 static struct acpu_level acpu_freq_tbl_2g_pvs5[] __initdata = {
-	{ 1, {  300000, PLL_0, 0,   0 }, L2(0),   750000,  400000 },
-	{ 0, {  345600, HFPLL, 2,  36 }, L2(3),   760000, 3200000 },
-	{ 1, {  422400, HFPLL, 2,  44 }, L2(3),   770000, 3200000 },
-	{ 0, {  499200, HFPLL, 2,  52 }, L2(6),   780000, 3200000 },
-	{ 1, {  576000, HFPLL, 1,  30 }, L2(6),   790000, 3200000 },
-	{ 1, {  652800, HFPLL, 1,  34 }, L2(7),   800000, 3200000 },
-	{ 1, {  729600, HFPLL, 1,  38 }, L2(7),   810000, 3200000 },
-	{ 0, {  806400, HFPLL, 1,  42 }, L2(10),  820000, 3200000 },
-	{ 1, {  883200, HFPLL, 1,  46 }, L2(10),  830000, 3200000 },
-	{ 0, {  960000, HFPLL, 1,  50 }, L2(10),  840000, 3200000 },
+	{ 1, {  300000, PLL_0, 0,   0 },  L2(0),  750000,  400000 },
+	{ 0, {  345600, HFPLL, 2,  36 },  L2(1),  760000, 3200000 },
+	{ 1, {  422400, HFPLL, 2,  44 },  L2(2),  770000, 3200000 },
+	{ 0, {  499200, HFPLL, 2,  52 },  L2(2),  780000, 3200000 },
+	{ 0, {  576000, HFPLL, 1,  30 },  L2(3),  790000, 3200000 },
+	{ 1, {  652800, HFPLL, 1,  34 },  L2(3),  800000, 3200000 },
+	{ 1, {  729600, HFPLL, 1,  38 },  L2(4),  810000, 3200000 },
+	{ 0, {  806400, HFPLL, 1,  42 },  L2(4),  820000, 3200000 },
+	{ 1, {  883200, HFPLL, 1,  46 },  L2(4),  830000, 3200000 },
+	{ 1, {  960000, HFPLL, 1,  50 },  L2(9),  840000, 3200000 },
 	{ 1, { 1036800, HFPLL, 1,  54 }, L2(10),  850000, 3200000 },
-	{ 0, { 1113600, HFPLL, 1,  58 }, L2(12),  860000, 3200000 },
-	{ 0, { 1190400, HFPLL, 1,  62 }, L2(12),  870000, 3200000 },
-	{ 0, { 1267200, HFPLL, 1,  66 }, L2(12),  880000, 3200000 },
-	{ 1, { 1344000, HFPLL, 1,  70 }, L2(12),  890000, 3200000 },
-	{ 0, { 1420800, HFPLL, 1,  74 }, L2(16),  900000, 3200000 },
-	{ 0, { 1497600, HFPLL, 1,  78 }, L2(16),  910000, 3200000 },
-	{ 0, { 1574400, HFPLL, 1,  82 }, L2(16),  920000, 3200000 },
-	{ 0, { 1651200, HFPLL, 1,  86 }, L2(16),  930000, 3200000 },
-	{ 1, { 1728000, HFPLL, 1,  90 }, L2(16),  940000, 3200000 },
-	{ 0, { 1804800, HFPLL, 1,  94 }, L2(19),  955000, 3200000 },
-	{ 0, { 1881600, HFPLL, 1,  98 }, L2(19),  965000, 3200000 },
+	{ 0, { 1113600, HFPLL, 1,  58 }, L2(10),  860000, 3200000 },
+	{ 1, { 1190400, HFPLL, 1,  62 }, L2(10),  870000, 3200000 },
+	{ 1, { 1267200, HFPLL, 1,  66 }, L2(13),  880000, 3200000 },
+	{ 0, { 1344000, HFPLL, 1,  70 }, L2(14),  890000, 3200000 },
+	{ 0, { 1420800, HFPLL, 1,  74 }, L2(15),  900000, 3200000 },
+	{ 1, { 1497600, HFPLL, 1,  78 }, L2(16),  910000, 3200000 },
+	{ 1, { 1574400, HFPLL, 1,  82 }, L2(17),  920000, 3200000 },
+	{ 0, { 1651200, HFPLL, 1,  86 }, L2(17),  930000, 3200000 },
+	{ 1, { 1728000, HFPLL, 1,  90 }, L2(18),  940000, 3200000 },
+	{ 0, { 1804800, HFPLL, 1,  94 }, L2(18),  955000, 3200000 },
+	{ 0, { 1881600, HFPLL, 1,  98 }, L2(18),  965000, 3200000 },
 	{ 1, { 1958400, HFPLL, 1, 102 }, L2(19),  975000, 3200000 },
 	{ 0, { 0 } }
 };
 
 static struct acpu_level acpu_freq_tbl_2g_pvs6[] __initdata = {
-	{ 1, {  300000, PLL_0, 0,   0 }, L2(0),   750000,  400000 },
-	{ 0, {  345600, HFPLL, 2,  36 }, L2(3),   750000, 3200000 },
-	{ 1, {  422400, HFPLL, 2,  44 }, L2(3),   760000, 3200000 },
-	{ 0, {  499200, HFPLL, 2,  52 }, L2(6),   770000, 3200000 },
-	{ 1, {  576000, HFPLL, 1,  30 }, L2(6),   780000, 3200000 },
-	{ 1, {  652800, HFPLL, 1,  34 }, L2(7),   790000, 3200000 },
-	{ 1, {  729600, HFPLL, 1,  38 }, L2(7),   800000, 3200000 },
-	{ 0, {  806400, HFPLL, 1,  42 }, L2(10),  810000, 3200000 },
-	{ 1, {  883200, HFPLL, 1,  46 }, L2(10),  820000, 3200000 },
-	{ 0, {  960000, HFPLL, 1,  50 }, L2(10),  830000, 3200000 },
+	{ 1, {  300000, PLL_0, 0,   0 },  L2(0),  750000,  400000 },
+	{ 0, {  345600, HFPLL, 2,  36 },  L2(1),  750000, 3200000 },
+	{ 1, {  422400, HFPLL, 2,  44 },  L2(2),  760000, 3200000 },
+	{ 0, {  499200, HFPLL, 2,  52 },  L2(2),  770000, 3200000 },
+	{ 0, {  576000, HFPLL, 1,  30 },  L2(3),  780000, 3200000 },
+	{ 1, {  652800, HFPLL, 1,  34 },  L2(3),  790000, 3200000 },
+	{ 1, {  729600, HFPLL, 1,  38 },  L2(4),  800000, 3200000 },
+	{ 0, {  806400, HFPLL, 1,  42 },  L2(4),  810000, 3200000 },
+	{ 1, {  883200, HFPLL, 1,  46 },  L2(4),  820000, 3200000 },
+	{ 1, {  960000, HFPLL, 1,  50 },  L2(9),  830000, 3200000 },
 	{ 1, { 1036800, HFPLL, 1,  54 }, L2(10),  840000, 3200000 },
-	{ 0, { 1113600, HFPLL, 1,  58 }, L2(12),  850000, 3200000 },
-	{ 0, { 1190400, HFPLL, 1,  62 }, L2(12),  860000, 3200000 },
-	{ 0, { 1267200, HFPLL, 1,  66 }, L2(12),  870000, 3200000 },
-	{ 1, { 1344000, HFPLL, 1,  70 }, L2(12),  875000, 3200000 },
-	{ 0, { 1420800, HFPLL, 1,  74 }, L2(16),  885000, 3200000 },
-	{ 0, { 1497600, HFPLL, 1,  78 }, L2(16),  895000, 3200000 },
-	{ 0, { 1574400, HFPLL, 1,  82 }, L2(16),  905000, 3200000 },
-	{ 0, { 1651200, HFPLL, 1,  86 }, L2(16),  915000, 3200000 },
-	{ 1, { 1728000, HFPLL, 1,  90 }, L2(16),  920000, 3200000 },
-	{ 0, { 1804800, HFPLL, 1,  94 }, L2(19),  930000, 3200000 },
-	{ 0, { 1881600, HFPLL, 1,  98 }, L2(19),  940000, 3200000 },
+	{ 0, { 1113600, HFPLL, 1,  58 }, L2(10),  850000, 3200000 },
+	{ 1, { 1190400, HFPLL, 1,  62 }, L2(10),  860000, 3200000 },
+	{ 1, { 1267200, HFPLL, 1,  66 }, L2(13),  870000, 3200000 },
+	{ 0, { 1344000, HFPLL, 1,  70 }, L2(14),  875000, 3200000 },
+	{ 0, { 1420800, HFPLL, 1,  74 }, L2(15),  885000, 3200000 },
+	{ 1, { 1497600, HFPLL, 1,  78 }, L2(16),  895000, 3200000 },
+	{ 1, { 1574400, HFPLL, 1,  82 }, L2(17),  905000, 3200000 },
+	{ 0, { 1651200, HFPLL, 1,  86 }, L2(17),  915000, 3200000 },
+	{ 1, { 1728000, HFPLL, 1,  90 }, L2(18),  920000, 3200000 },
+	{ 0, { 1804800, HFPLL, 1,  94 }, L2(18),  930000, 3200000 },
+	{ 0, { 1881600, HFPLL, 1,  98 }, L2(18),  940000, 3200000 },
 	{ 1, { 1958400, HFPLL, 1, 102 }, L2(19),  950000, 3200000 },
 	{ 0, { 0 } }
 };
 
-static struct acpu_level acpu_freq_tbl_2p3g_pvs0[] __initdata = {
-	{ 1, {  300000, PLL_0, 0,   0 }, L2(0),   800000,  400000 },
-	{ 0, {  345600, HFPLL, 2,  36 }, L2(3),   800000, 3200000 },
-	{ 1, {  422400, HFPLL, 2,  44 }, L2(3),   800000, 3200000 },
-	{ 0, {  499200, HFPLL, 2,  52 }, L2(6),   805000, 3200000 },
-	{ 1, {  576000, HFPLL, 1,  30 }, L2(6),   815000, 3200000 },
-	{ 1, {  652800, HFPLL, 1,  34 }, L2(7),   825000, 3200000 },
-	{ 1, {  729600, HFPLL, 1,  38 }, L2(7),   835000, 3200000 },
-	{ 0, {  806400, HFPLL, 1,  42 }, L2(10),  845000, 3200000 },
-	{ 1, {  883200, HFPLL, 1,  46 }, L2(10),  855000, 3200000 },
-	{ 0, {  960000, HFPLL, 1,  50 }, L2(10),  865000, 3200000 },
+static struct acpu_level acpu_freq_tbl_2p2g_pvs0[] __initdata = {
+	{ 1, {  300000, PLL_0, 0,   0 },  L2(0),  800000,  400000 },
+	{ 0, {  345600, HFPLL, 2,  36 },  L2(1),  800000, 3200000 },
+	{ 1, {  422400, HFPLL, 2,  44 },  L2(2),  805000, 3200000 },
+	{ 0, {  499200, HFPLL, 2,  52 },  L2(2),  815000, 3200000 },
+	{ 0, {  576000, HFPLL, 1,  30 },  L2(3),  825000, 3200000 },
+	{ 1, {  652800, HFPLL, 1,  34 },  L2(3),  835000, 3200000 },
+	{ 1, {  729600, HFPLL, 1,  38 },  L2(4),  845000, 3200000 },
+	{ 0, {  806400, HFPLL, 1,  42 },  L2(4),  855000, 3200000 },
+	{ 1, {  883200, HFPLL, 1,  46 },  L2(4),  865000, 3200000 },
+	{ 1, {  960000, HFPLL, 1,  50 },  L2(9),  875000, 3200000 },
+	{ 1, { 1036800, HFPLL, 1,  54 }, L2(10),  890000, 3200000 },
+	{ 0, { 1113600, HFPLL, 1,  58 }, L2(10),  900000, 3200000 },
+	{ 1, { 1190400, HFPLL, 1,  62 }, L2(10),  915000, 3200000 },
+	{ 1, { 1267200, HFPLL, 1,  66 }, L2(13),  925000, 3200000 },
+	{ 0, { 1344000, HFPLL, 1,  70 }, L2(14),  940000, 3200000 },
+	{ 0, { 1420800, HFPLL, 1,  74 }, L2(15),  950000, 3200000 },
+	{ 1, { 1497600, HFPLL, 1,  78 }, L2(16),  965000, 3200000 },
+	{ 1, { 1574400, HFPLL, 1,  82 }, L2(17),  980000, 3200000 },
+	{ 0, { 1651200, HFPLL, 1,  86 }, L2(17),  995000, 3200000 },
+	{ 1, { 1728000, HFPLL, 1,  90 }, L2(18), 1010000, 3200000 },
+	{ 0, { 1804800, HFPLL, 1,  94 }, L2(18), 1025000, 3200000 },
+	{ 0, { 1881600, HFPLL, 1,  98 }, L2(18), 1040000, 3200000 },
+	{ 1, { 1958400, HFPLL, 1, 102 }, L2(19), 1055000, 3200000 },
+	{ 0, { 2035200, HFPLL, 1, 106 }, L2(19), 1070000, 3200000 },
+	{ 0, { 2112000, HFPLL, 1, 110 }, L2(19), 1085000, 3200000 },
+	{ 1, { 2150400, HFPLL, 1, 112 }, L2(19), 1100000, 3200000 },
+	{ 0, { 0 } }
+};
+
+static struct acpu_level acpu_freq_tbl_2p2g_pvs1[] __initdata = {
+	{ 1, {  300000, PLL_0, 0,   0 },  L2(0),  800000,  400000 },
+	{ 0, {  345600, HFPLL, 2,  36 },  L2(1),  800000, 3200000 },
+	{ 1, {  422400, HFPLL, 2,  44 },  L2(2),  800000, 3200000 },
+	{ 0, {  499200, HFPLL, 2,  52 },  L2(2),  800000, 3200000 },
+	{ 0, {  576000, HFPLL, 1,  30 },  L2(3),  810000, 3200000 },
+	{ 1, {  652800, HFPLL, 1,  34 },  L2(3),  820000, 3200000 },
+	{ 1, {  729600, HFPLL, 1,  38 },  L2(4),  830000, 3200000 },
+	{ 0, {  806400, HFPLL, 1,  42 },  L2(4),  840000, 3200000 },
+	{ 1, {  883200, HFPLL, 1,  46 },  L2(4),  850000, 3200000 },
+	{ 1, {  960000, HFPLL, 1,  50 },  L2(9),  860000, 3200000 },
 	{ 1, { 1036800, HFPLL, 1,  54 }, L2(10),  875000, 3200000 },
-	{ 0, { 1113600, HFPLL, 1,  58 }, L2(12),  890000, 3200000 },
-	{ 0, { 1190400, HFPLL, 1,  62 }, L2(12),  900000, 3200000 },
-	{ 0, { 1267200, HFPLL, 1,  66 }, L2(12),  915000, 3200000 },
-	{ 1, { 1344000, HFPLL, 1,  70 }, L2(12),  925000, 3200000 },
-	{ 0, { 1420800, HFPLL, 1,  74 }, L2(16),  940000, 3200000 },
-	{ 0, { 1497600, HFPLL, 1,  78 }, L2(16),  950000, 3200000 },
-	{ 0, { 1574400, HFPLL, 1,  82 }, L2(16),  965000, 3200000 },
-	{ 0, { 1651200, HFPLL, 1,  86 }, L2(16),  980000, 3200000 },
-	{ 1, { 1728000, HFPLL, 1,  90 }, L2(16),  995000, 3200000 },
-	{ 0, { 1804800, HFPLL, 1,  94 }, L2(19), 1010000, 3200000 },
-	{ 0, { 1881600, HFPLL, 1,  98 }, L2(19), 1025000, 3200000 },
-	{ 0, { 1958400, HFPLL, 1, 102 }, L2(19), 1040000, 3200000 },
-	{ 1, { 2035200, HFPLL, 1, 106 }, L2(19), 1055000, 3200000 },
+	{ 0, { 1113600, HFPLL, 1,  58 }, L2(10),  885000, 3200000 },
+	{ 1, { 1190400, HFPLL, 1,  62 }, L2(10),  895000, 3200000 },
+	{ 1, { 1267200, HFPLL, 1,  66 }, L2(13),  910000, 3200000 },
+	{ 0, { 1344000, HFPLL, 1,  70 }, L2(14),  920000, 3200000 },
+	{ 0, { 1420800, HFPLL, 1,  74 }, L2(15),  930000, 3200000 },
+	{ 1, { 1497600, HFPLL, 1,  78 }, L2(16),  945000, 3200000 },
+	{ 1, { 1574400, HFPLL, 1,  82 }, L2(17),  960000, 3200000 },
+	{ 0, { 1651200, HFPLL, 1,  86 }, L2(17),  975000, 3200000 },
+	{ 1, { 1728000, HFPLL, 1,  90 }, L2(18),  990000, 3200000 },
+	{ 0, { 1804800, HFPLL, 1,  94 }, L2(18), 1005000, 3200000 },
+	{ 0, { 1881600, HFPLL, 1,  98 }, L2(18), 1020000, 3200000 },
+	{ 1, { 1958400, HFPLL, 1, 102 }, L2(19), 1030000, 3200000 },
+	{ 0, { 2035200, HFPLL, 1, 106 }, L2(19), 1045000, 3200000 },
+	{ 0, { 2112000, HFPLL, 1, 110 }, L2(19), 1060000, 3200000 },
+	{ 1, { 2150400, HFPLL, 1, 112 }, L2(19), 1075000, 3200000 },
+	{ 0, { 0 } }
+};
+
+static struct acpu_level acpu_freq_tbl_2p2g_pvs2[] __initdata = {
+	{ 1, {  300000, PLL_0, 0,   0 },  L2(0),  775000,  400000 },
+	{ 0, {  345600, HFPLL, 2,  36 },  L2(1),  775000, 3200000 },
+	{ 1, {  422400, HFPLL, 2,  44 },  L2(2),  775000, 3200000 },
+	{ 0, {  499200, HFPLL, 2,  52 },  L2(2),  785000, 3200000 },
+	{ 0, {  576000, HFPLL, 1,  30 },  L2(3),  795000, 3200000 },
+	{ 1, {  652800, HFPLL, 1,  34 },  L2(3),  805000, 3200000 },
+	{ 1, {  729600, HFPLL, 1,  38 },  L2(4),  815000, 3200000 },
+	{ 0, {  806400, HFPLL, 1,  42 },  L2(4),  825000, 3200000 },
+	{ 1, {  883200, HFPLL, 1,  46 },  L2(4),  835000, 3200000 },
+	{ 1, {  960000, HFPLL, 1,  50 },  L2(9),  845000, 3200000 },
+	{ 1, { 1036800, HFPLL, 1,  54 }, L2(10),  855000, 3200000 },
+	{ 0, { 1113600, HFPLL, 1,  58 }, L2(10),  865000, 3200000 },
+	{ 1, { 1190400, HFPLL, 1,  62 }, L2(10),  875000, 3200000 },
+	{ 1, { 1267200, HFPLL, 1,  66 }, L2(13),  890000, 3200000 },
+	{ 0, { 1344000, HFPLL, 1,  70 }, L2(14),  900000, 3200000 },
+	{ 0, { 1420800, HFPLL, 1,  74 }, L2(15),  910000, 3200000 },
+	{ 1, { 1497600, HFPLL, 1,  78 }, L2(16),  925000, 3200000 },
+	{ 1, { 1574400, HFPLL, 1,  82 }, L2(17),  940000, 3200000 },
+	{ 0, { 1651200, HFPLL, 1,  86 }, L2(17),  955000, 3200000 },
+	{ 1, { 1728000, HFPLL, 1,  90 }, L2(18),  970000, 3200000 },
+	{ 0, { 1804800, HFPLL, 1,  94 }, L2(18),  980000, 3200000 },
+	{ 0, { 1881600, HFPLL, 1,  98 }, L2(18),  995000, 3200000 },
+	{ 1, { 1958400, HFPLL, 1, 102 }, L2(19), 1005000, 3200000 },
+	{ 0, { 2035200, HFPLL, 1, 106 }, L2(19), 1020000, 3200000 },
+	{ 0, { 2112000, HFPLL, 1, 110 }, L2(19), 1035000, 3200000 },
+	{ 1, { 2150400, HFPLL, 1, 112 }, L2(19), 1050000, 3200000 },
+	{ 0, { 0 } }
+};
+
+static struct acpu_level acpu_freq_tbl_2p2g_pvs3[] __initdata = {
+	{ 1, {  300000, PLL_0, 0,   0 },  L2(0),  775000,  400000 },
+	{ 0, {  345600, HFPLL, 2,  36 },  L2(1),  775000, 3200000 },
+	{ 1, {  422400, HFPLL, 2,  44 },  L2(2),  775000, 3200000 },
+	{ 0, {  499200, HFPLL, 2,  52 },  L2(2),  775000, 3200000 },
+	{ 0, {  576000, HFPLL, 1,  30 },  L2(3),  780000, 3200000 },
+	{ 1, {  652800, HFPLL, 1,  34 },  L2(3),  790000, 3200000 },
+	{ 1, {  729600, HFPLL, 1,  38 },  L2(4),  800000, 3200000 },
+	{ 0, {  806400, HFPLL, 1,  42 },  L2(4),  810000, 3200000 },
+	{ 1, {  883200, HFPLL, 1,  46 },  L2(4),  820000, 3200000 },
+	{ 1, {  960000, HFPLL, 1,  50 },  L2(9),  830000, 3200000 },
+	{ 1, { 1036800, HFPLL, 1,  54 }, L2(10),  840000, 3200000 },
+	{ 0, { 1113600, HFPLL, 1,  58 }, L2(10),  850000, 3200000 },
+	{ 1, { 1190400, HFPLL, 1,  62 }, L2(10),  860000, 3200000 },
+	{ 1, { 1267200, HFPLL, 1,  66 }, L2(13),  875000, 3200000 },
+	{ 0, { 1344000, HFPLL, 1,  70 }, L2(14),  885000, 3200000 },
+	{ 0, { 1420800, HFPLL, 1,  74 }, L2(15),  895000, 3200000 },
+	{ 1, { 1497600, HFPLL, 1,  78 }, L2(16),  910000, 3200000 },
+	{ 1, { 1574400, HFPLL, 1,  82 }, L2(17),  925000, 3200000 },
+	{ 0, { 1651200, HFPLL, 1,  86 }, L2(17),  935000, 3200000 },
+	{ 1, { 1728000, HFPLL, 1,  90 }, L2(18),  950000, 3200000 },
+	{ 0, { 1804800, HFPLL, 1,  94 }, L2(18),  960000, 3200000 },
+	{ 0, { 1881600, HFPLL, 1,  98 }, L2(18),  970000, 3200000 },
+	{ 1, { 1958400, HFPLL, 1, 102 }, L2(19),  985000, 3200000 },
+	{ 0, { 2035200, HFPLL, 1, 106 }, L2(19),  995000, 3200000 },
+	{ 0, { 2112000, HFPLL, 1, 110 }, L2(19), 1010000, 3200000 },
+	{ 1, { 2150400, HFPLL, 1, 112 }, L2(19), 1025000, 3200000 },
+	{ 0, { 0 } }
+};
+
+static struct acpu_level acpu_freq_tbl_2p2g_pvs4[] __initdata = {
+	{ 1, {  300000, PLL_0, 0,   0 },  L2(0),  775000,  400000 },
+	{ 0, {  345600, HFPLL, 2,  36 },  L2(1),  775000, 3200000 },
+	{ 1, {  422400, HFPLL, 2,  44 },  L2(2),  775000, 3200000 },
+	{ 0, {  499200, HFPLL, 2,  52 },  L2(2),  775000, 3200000 },
+	{ 0, {  576000, HFPLL, 1,  30 },  L2(3),  775000, 3200000 },
+	{ 1, {  652800, HFPLL, 1,  34 },  L2(3),  780000, 3200000 },
+	{ 1, {  729600, HFPLL, 1,  38 },  L2(4),  790000, 3200000 },
+	{ 0, {  806400, HFPLL, 1,  42 },  L2(4),  800000, 3200000 },
+	{ 1, {  883200, HFPLL, 1,  46 },  L2(4),  810000, 3200000 },
+	{ 1, {  960000, HFPLL, 1,  50 },  L2(9),  820000, 3200000 },
+	{ 1, { 1036800, HFPLL, 1,  54 }, L2(10),  830000, 3200000 },
+	{ 0, { 1113600, HFPLL, 1,  58 }, L2(10),  840000, 3200000 },
+	{ 1, { 1190400, HFPLL, 1,  62 }, L2(10),  850000, 3200000 },
+	{ 1, { 1267200, HFPLL, 1,  66 }, L2(13),  860000, 3200000 },
+	{ 0, { 1344000, HFPLL, 1,  70 }, L2(14),  870000, 3200000 },
+	{ 0, { 1420800, HFPLL, 1,  74 }, L2(15),  880000, 3200000 },
+	{ 1, { 1497600, HFPLL, 1,  78 }, L2(16),  895000, 3200000 },
+	{ 1, { 1574400, HFPLL, 1,  82 }, L2(17),  910000, 3200000 },
+	{ 0, { 1651200, HFPLL, 1,  86 }, L2(17),  920000, 3200000 },
+	{ 1, { 1728000, HFPLL, 1,  90 }, L2(18),  930000, 3200000 },
+	{ 0, { 1804800, HFPLL, 1,  94 }, L2(18),  940000, 3200000 },
+	{ 0, { 1881600, HFPLL, 1,  98 }, L2(18),  950000, 3200000 },
+	{ 1, { 1958400, HFPLL, 1, 102 }, L2(19),  960000, 3200000 },
+	{ 0, { 2035200, HFPLL, 1, 106 }, L2(19),  975000, 3200000 },
+	{ 0, { 2112000, HFPLL, 1, 110 }, L2(19),  985000, 3200000 },
+	{ 1, { 2150400, HFPLL, 1, 112 }, L2(19), 1000000, 3200000 },
+	{ 0, { 0 } }
+};
+
+static struct acpu_level acpu_freq_tbl_2p2g_pvs5[] __initdata = {
+	{ 1, {  300000, PLL_0, 0,   0 },  L2(0),  750000,  400000 },
+	{ 0, {  345600, HFPLL, 2,  36 },  L2(1),  750000, 3200000 },
+	{ 1, {  422400, HFPLL, 2,  44 },  L2(2),  750000, 3200000 },
+	{ 0, {  499200, HFPLL, 2,  52 },  L2(2),  750000, 3200000 },
+	{ 0, {  576000, HFPLL, 1,  30 },  L2(3),  760000, 3200000 },
+	{ 1, {  652800, HFPLL, 1,  34 },  L2(3),  770000, 3200000 },
+	{ 1, {  729600, HFPLL, 1,  38 },  L2(4),  780000, 3200000 },
+	{ 0, {  806400, HFPLL, 1,  42 },  L2(4),  790000, 3200000 },
+	{ 1, {  883200, HFPLL, 1,  46 },  L2(4),  800000, 3200000 },
+	{ 1, {  960000, HFPLL, 1,  50 },  L2(9),  810000, 3200000 },
+	{ 1, { 1036800, HFPLL, 1,  54 }, L2(10),  820000, 3200000 },
+	{ 0, { 1113600, HFPLL, 1,  58 }, L2(10),  830000, 3200000 },
+	{ 1, { 1190400, HFPLL, 1,  62 }, L2(10),  840000, 3200000 },
+	{ 1, { 1267200, HFPLL, 1,  66 }, L2(13),  850000, 3200000 },
+	{ 0, { 1344000, HFPLL, 1,  70 }, L2(14),  860000, 3200000 },
+	{ 0, { 1420800, HFPLL, 1,  74 }, L2(15),  870000, 3200000 },
+	{ 1, { 1497600, HFPLL, 1,  78 }, L2(16),  880000, 3200000 },
+	{ 1, { 1574400, HFPLL, 1,  82 }, L2(17),  890000, 3200000 },
+	{ 0, { 1651200, HFPLL, 1,  86 }, L2(17),  900000, 3200000 },
+	{ 1, { 1728000, HFPLL, 1,  90 }, L2(18),  910000, 3200000 },
+	{ 0, { 1804800, HFPLL, 1,  94 }, L2(18),  920000, 3200000 },
+	{ 0, { 1881600, HFPLL, 1,  98 }, L2(18),  930000, 3200000 },
+	{ 1, { 1958400, HFPLL, 1, 102 }, L2(19),  940000, 3200000 },
+	{ 0, { 2035200, HFPLL, 1, 106 }, L2(19),  955000, 3200000 },
+	{ 0, { 2112000, HFPLL, 1, 110 }, L2(19),  965000, 3200000 },
+	{ 1, { 2150400, HFPLL, 1, 112 }, L2(19),  975000, 3200000 },
+	{ 0, { 0 } }
+};
+
+static struct acpu_level acpu_freq_tbl_2p2g_pvs6[] __initdata = {
+	{ 1, {  300000, PLL_0, 0,   0 },  L2(0),  75000,  400000 },
+	{ 0, {  345600, HFPLL, 2,  36 },  L2(1),  75000, 3200000 },
+	{ 1, {  422400, HFPLL, 2,  44 },  L2(2),  75000, 3200000 },
+	{ 0, {  499200, HFPLL, 2,  52 },  L2(2),  75000, 3200000 },
+	{ 0, {  576000, HFPLL, 1,  30 },  L2(3),  75000, 3200000 },
+	{ 1, {  652800, HFPLL, 1,  34 },  L2(3),  76000, 3200000 },
+	{ 1, {  729600, HFPLL, 1,  38 },  L2(4),  77000, 3200000 },
+	{ 0, {  806400, HFPLL, 1,  42 },  L2(4),  78000, 3200000 },
+	{ 1, {  883200, HFPLL, 1,  46 },  L2(4),  79000, 3200000 },
+	{ 1, {  960000, HFPLL, 1,  50 },  L2(9),  80000, 3200000 },
+	{ 1, { 1036800, HFPLL, 1,  54 }, L2(10),  81000, 3200000 },
+	{ 0, { 1113600, HFPLL, 1,  58 }, L2(10),  82000, 3200000 },
+	{ 1, { 1190400, HFPLL, 1,  62 }, L2(10),  83000, 3200000 },
+	{ 1, { 1267200, HFPLL, 1,  66 }, L2(13),  84000, 3200000 },
+	{ 0, { 1344000, HFPLL, 1,  70 }, L2(14),  85000, 3200000 },
+	{ 0, { 1420800, HFPLL, 1,  74 }, L2(15),  86000, 3200000 },
+	{ 1, { 1497600, HFPLL, 1,  78 }, L2(16),  87000, 3200000 },
+	{ 1, { 1574400, HFPLL, 1,  82 }, L2(17),  87500, 3200000 },
+	{ 0, { 1651200, HFPLL, 1,  86 }, L2(17),  88500, 3200000 },
+	{ 1, { 1728000, HFPLL, 1,  90 }, L2(18),  89500, 3200000 },
+	{ 0, { 1804800, HFPLL, 1,  94 }, L2(18),  90500, 3200000 },
+	{ 0, { 1881600, HFPLL, 1,  98 }, L2(18),  91500, 3200000 },
+	{ 1, { 1958400, HFPLL, 1, 102 }, L2(19),  92000, 3200000 },
+	{ 0, { 2035200, HFPLL, 1, 106 }, L2(19),  93000, 3200000 },
+	{ 0, { 2112000, HFPLL, 1, 110 }, L2(19),  94000, 3200000 },
+	{ 1, { 2150400, HFPLL, 1, 112 }, L2(19),  95000, 3200000 },
+	{ 0, { 0 } }
+};
+
+static struct acpu_level acpu_freq_tbl_2p3g_pvs0[] __initdata = {
+	{ 1, {  300000, PLL_0, 0,   0 },  L2(0),  800000,  400000 },
+	{ 0, {  345600, HFPLL, 2,  36 },  L2(1),  800000, 3200000 },
+	{ 1, {  422400, HFPLL, 2,  44 },  L2(2),  800000, 3200000 },
+	{ 0, {  499200, HFPLL, 2,  52 },  L2(2),  805000, 3200000 },
+	{ 0, {  576000, HFPLL, 1,  30 },  L2(3),  815000, 3200000 },
+	{ 1, {  652800, HFPLL, 1,  34 },  L2(3),  825000, 3200000 },
+	{ 1, {  729600, HFPLL, 1,  38 },  L2(4),  835000, 3200000 },
+	{ 0, {  806400, HFPLL, 1,  42 },  L2(4),  845000, 3200000 },
+	{ 1, {  883200, HFPLL, 1,  46 },  L2(4),  855000, 3200000 },
+	{ 1, {  960000, HFPLL, 1,  50 },  L2(9),  865000, 3200000 },
+	{ 1, { 1036800, HFPLL, 1,  54 }, L2(10),  875000, 3200000 },
+	{ 0, { 1113600, HFPLL, 1,  58 }, L2(10),  890000, 3200000 },
+	{ 1, { 1190400, HFPLL, 1,  62 }, L2(10),  900000, 3200000 },
+	{ 1, { 1267200, HFPLL, 1,  66 }, L2(13),  915000, 3200000 },
+	{ 0, { 1344000, HFPLL, 1,  70 }, L2(14),  925000, 3200000 },
+	{ 0, { 1420800, HFPLL, 1,  74 }, L2(15),  940000, 3200000 },
+	{ 1, { 1497600, HFPLL, 1,  78 }, L2(16),  950000, 3200000 },
+	{ 1, { 1574400, HFPLL, 1,  82 }, L2(17),  965000, 3200000 },
+	{ 0, { 1651200, HFPLL, 1,  86 }, L2(17),  980000, 3200000 },
+	{ 1, { 1728000, HFPLL, 1,  90 }, L2(18),  995000, 3200000 },
+	{ 0, { 1804800, HFPLL, 1,  94 }, L2(18), 1010000, 3200000 },
+	{ 0, { 1881600, HFPLL, 1,  98 }, L2(18), 1025000, 3200000 },
+	{ 1, { 1958400, HFPLL, 1, 102 }, L2(19), 1040000, 3200000 },
+	{ 0, { 2035200, HFPLL, 1, 106 }, L2(19), 1055000, 3200000 },
 	{ 0, { 2112000, HFPLL, 1, 110 }, L2(19), 1070000, 3200000 },
 	{ 0, { 2188800, HFPLL, 1, 114 }, L2(19), 1085000, 3200000 },
 	{ 1, { 2265600, HFPLL, 1, 118 }, L2(19), 1100000, 3200000 },
@@ -502,30 +712,30 @@
 };
 
 static struct acpu_level acpu_freq_tbl_2p3g_pvs1[] __initdata = {
-	{ 1, {  300000, PLL_0, 0,   0 }, L2(0),   800000,  400000 },
-	{ 0, {  345600, HFPLL, 2,  36 }, L2(3),   800000, 3200000 },
-	{ 1, {  422400, HFPLL, 2,  44 }, L2(3),   800000, 3200000 },
-	{ 0, {  499200, HFPLL, 2,  52 }, L2(6),   800000, 3200000 },
-	{ 1, {  576000, HFPLL, 1,  30 }, L2(6),   800000, 3200000 },
-	{ 1, {  652800, HFPLL, 1,  34 }, L2(7),   810000, 3200000 },
-	{ 1, {  729600, HFPLL, 1,  38 }, L2(7),   820000, 3200000 },
-	{ 0, {  806400, HFPLL, 1,  42 }, L2(10),  830000, 3200000 },
-	{ 1, {  883200, HFPLL, 1,  46 }, L2(10),  840000, 3200000 },
-	{ 0, {  960000, HFPLL, 1,  50 }, L2(10),  850000, 3200000 },
+	{ 1, {  300000, PLL_0, 0,   0 },  L2(0),  800000,  400000 },
+	{ 0, {  345600, HFPLL, 2,  36 },  L2(1),  800000, 3200000 },
+	{ 1, {  422400, HFPLL, 2,  44 },  L2(2),  800000, 3200000 },
+	{ 0, {  499200, HFPLL, 2,  52 },  L2(2),  800000, 3200000 },
+	{ 0, {  576000, HFPLL, 1,  30 },  L2(3),  800000, 3200000 },
+	{ 1, {  652800, HFPLL, 1,  34 },  L2(3),  810000, 3200000 },
+	{ 1, {  729600, HFPLL, 1,  38 },  L2(4),  820000, 3200000 },
+	{ 0, {  806400, HFPLL, 1,  42 },  L2(4),  830000, 3200000 },
+	{ 1, {  883200, HFPLL, 1,  46 },  L2(4),  840000, 3200000 },
+	{ 1, {  960000, HFPLL, 1,  50 },  L2(9),  850000, 3200000 },
 	{ 1, { 1036800, HFPLL, 1,  54 }, L2(10),  860000, 3200000 },
-	{ 0, { 1113600, HFPLL, 1,  58 }, L2(12),  875000, 3200000 },
-	{ 0, { 1190400, HFPLL, 1,  62 }, L2(12),  885000, 3200000 },
-	{ 0, { 1267200, HFPLL, 1,  66 }, L2(12),  895000, 3200000 },
-	{ 1, { 1344000, HFPLL, 1,  70 }, L2(12),  910000, 3200000 },
-	{ 0, { 1420800, HFPLL, 1,  74 }, L2(16),  920000, 3200000 },
-	{ 0, { 1497600, HFPLL, 1,  78 }, L2(16),  930000, 3200000 },
-	{ 0, { 1574400, HFPLL, 1,  82 }, L2(16),  945000, 3200000 },
-	{ 0, { 1651200, HFPLL, 1,  86 }, L2(16),  960000, 3200000 },
-	{ 1, { 1728000, HFPLL, 1,  90 }, L2(16),  975000, 3200000 },
-	{ 0, { 1804800, HFPLL, 1,  94 }, L2(19),  990000, 3200000 },
-	{ 0, { 1881600, HFPLL, 1,  98 }, L2(19), 1005000, 3200000 },
-	{ 0, { 1958400, HFPLL, 1, 102 }, L2(19), 1020000, 3200000 },
-	{ 1, { 2035200, HFPLL, 1, 106 }, L2(19), 1030000, 3200000 },
+	{ 0, { 1113600, HFPLL, 1,  58 }, L2(10),  875000, 3200000 },
+	{ 1, { 1190400, HFPLL, 1,  62 }, L2(10),  885000, 3200000 },
+	{ 1, { 1267200, HFPLL, 1,  66 }, L2(13),  895000, 3200000 },
+	{ 0, { 1344000, HFPLL, 1,  70 }, L2(14),  910000, 3200000 },
+	{ 0, { 1420800, HFPLL, 1,  74 }, L2(15),  920000, 3200000 },
+	{ 1, { 1497600, HFPLL, 1,  78 }, L2(16),  930000, 3200000 },
+	{ 1, { 1574400, HFPLL, 1,  82 }, L2(17),  945000, 3200000 },
+	{ 0, { 1651200, HFPLL, 1,  86 }, L2(17),  960000, 3200000 },
+	{ 1, { 1728000, HFPLL, 1,  90 }, L2(18),  975000, 3200000 },
+	{ 0, { 1804800, HFPLL, 1,  94 }, L2(18),  990000, 3200000 },
+	{ 0, { 1881600, HFPLL, 1,  98 }, L2(18), 1005000, 3200000 },
+	{ 1, { 1958400, HFPLL, 1, 102 }, L2(19), 1020000, 3200000 },
+	{ 0, { 2035200, HFPLL, 1, 106 }, L2(19), 1030000, 3200000 },
 	{ 0, { 2112000, HFPLL, 1, 110 }, L2(19), 1045000, 3200000 },
 	{ 0, { 2188800, HFPLL, 1, 114 }, L2(19), 1060000, 3200000 },
 	{ 1, { 2265600, HFPLL, 1, 118 }, L2(19), 1075000, 3200000 },
@@ -533,30 +743,30 @@
 };
 
 static struct acpu_level acpu_freq_tbl_2p3g_pvs2[] __initdata = {
-	{ 1, {  300000, PLL_0, 0,   0 }, L2(0),   775000,  400000 },
-	{ 0, {  345600, HFPLL, 2,  36 }, L2(3),   775000, 3200000 },
-	{ 1, {  422400, HFPLL, 2,  44 }, L2(3),   775000, 3200000 },
-	{ 0, {  499200, HFPLL, 2,  52 }, L2(6),   775000, 3200000 },
-	{ 1, {  576000, HFPLL, 1,  30 }, L2(6),   785000, 3200000 },
-	{ 1, {  652800, HFPLL, 1,  34 }, L2(7),   795000, 3200000 },
-	{ 1, {  729600, HFPLL, 1,  38 }, L2(7),   805000, 3200000 },
-	{ 0, {  806400, HFPLL, 1,  42 }, L2(10),  815000, 3200000 },
-	{ 1, {  883200, HFPLL, 1,  46 }, L2(10),  825000, 3200000 },
-	{ 0, {  960000, HFPLL, 1,  50 }, L2(10),  835000, 3200000 },
+	{ 1, {  300000, PLL_0, 0,   0 },  L2(0),  775000,  400000 },
+	{ 0, {  345600, HFPLL, 2,  36 },  L2(1),  775000, 3200000 },
+	{ 1, {  422400, HFPLL, 2,  44 },  L2(2),  775000, 3200000 },
+	{ 0, {  499200, HFPLL, 2,  52 },  L2(2),  775000, 3200000 },
+	{ 0, {  576000, HFPLL, 1,  30 },  L2(3),  785000, 3200000 },
+	{ 1, {  652800, HFPLL, 1,  34 },  L2(3),  795000, 3200000 },
+	{ 1, {  729600, HFPLL, 1,  38 },  L2(4),  805000, 3200000 },
+	{ 0, {  806400, HFPLL, 1,  42 },  L2(4),  815000, 3200000 },
+	{ 1, {  883200, HFPLL, 1,  46 },  L2(4),  825000, 3200000 },
+	{ 1, {  960000, HFPLL, 1,  50 },  L2(9),  835000, 3200000 },
 	{ 1, { 1036800, HFPLL, 1,  54 }, L2(10),  845000, 3200000 },
-	{ 0, { 1113600, HFPLL, 1,  58 }, L2(12),  855000, 3200000 },
-	{ 0, { 1190400, HFPLL, 1,  62 }, L2(12),  865000, 3200000 },
-	{ 0, { 1267200, HFPLL, 1,  66 }, L2(12),  875000, 3200000 },
-	{ 1, { 1344000, HFPLL, 1,  70 }, L2(12),  890000, 3200000 },
-	{ 0, { 1420800, HFPLL, 1,  74 }, L2(16),  900000, 3200000 },
-	{ 0, { 1497600, HFPLL, 1,  78 }, L2(16),  910000, 3200000 },
-	{ 0, { 1574400, HFPLL, 1,  82 }, L2(16),  925000, 3200000 },
-	{ 0, { 1651200, HFPLL, 1,  86 }, L2(16),  940000, 3200000 },
-	{ 1, { 1728000, HFPLL, 1,  90 }, L2(16),  955000, 3200000 },
-	{ 0, { 1804800, HFPLL, 1,  94 }, L2(19),  970000, 3200000 },
-	{ 0, { 1881600, HFPLL, 1,  98 }, L2(19),  980000, 3200000 },
-	{ 0, { 1958400, HFPLL, 1, 102 }, L2(19),  995000, 3200000 },
-	{ 1, { 2035200, HFPLL, 1, 106 }, L2(19), 1005000, 3200000 },
+	{ 0, { 1113600, HFPLL, 1,  58 }, L2(10),  855000, 3200000 },
+	{ 1, { 1190400, HFPLL, 1,  62 }, L2(10),  865000, 3200000 },
+	{ 1, { 1267200, HFPLL, 1,  66 }, L2(13),  875000, 3200000 },
+	{ 0, { 1344000, HFPLL, 1,  70 }, L2(14),  890000, 3200000 },
+	{ 0, { 1420800, HFPLL, 1,  74 }, L2(15),  900000, 3200000 },
+	{ 1, { 1497600, HFPLL, 1,  78 }, L2(16),  910000, 3200000 },
+	{ 1, { 1574400, HFPLL, 1,  82 }, L2(17),  925000, 3200000 },
+	{ 0, { 1651200, HFPLL, 1,  86 }, L2(17),  940000, 3200000 },
+	{ 1, { 1728000, HFPLL, 1,  90 }, L2(18),  955000, 3200000 },
+	{ 0, { 1804800, HFPLL, 1,  94 }, L2(18),  970000, 3200000 },
+	{ 0, { 1881600, HFPLL, 1,  98 }, L2(18),  980000, 3200000 },
+	{ 1, { 1958400, HFPLL, 1, 102 }, L2(19),  995000, 3200000 },
+	{ 0, { 2035200, HFPLL, 1, 106 }, L2(19), 1005000, 3200000 },
 	{ 0, { 2112000, HFPLL, 1, 110 }, L2(19), 1020000, 3200000 },
 	{ 0, { 2188800, HFPLL, 1, 114 }, L2(19), 1035000, 3200000 },
 	{ 1, { 2265600, HFPLL, 1, 118 }, L2(19), 1050000, 3200000 },
@@ -564,30 +774,30 @@
 };
 
 static struct acpu_level acpu_freq_tbl_2p3g_pvs3[] __initdata = {
-	{ 1, {  300000, PLL_0, 0,   0 }, L2(0),   775000,  400000 },
-	{ 0, {  345600, HFPLL, 2,  36 }, L2(3),   775000, 3200000 },
-	{ 1, {  422400, HFPLL, 2,  44 }, L2(3),   775000, 3200000 },
-	{ 0, {  499200, HFPLL, 2,  52 }, L2(6),   775000, 3200000 },
-	{ 1, {  576000, HFPLL, 1,  30 }, L2(6),   775000, 3200000 },
-	{ 1, {  652800, HFPLL, 1,  34 }, L2(7),   780000, 3200000 },
-	{ 1, {  729600, HFPLL, 1,  38 }, L2(7),   790000, 3200000 },
-	{ 0, {  806400, HFPLL, 1,  42 }, L2(10),  800000, 3200000 },
-	{ 1, {  883200, HFPLL, 1,  46 }, L2(10),  810000, 3200000 },
-	{ 0, {  960000, HFPLL, 1,  50 }, L2(10),  820000, 3200000 },
+	{ 1, {  300000, PLL_0, 0,   0 },  L2(0),  775000,  400000 },
+	{ 0, {  345600, HFPLL, 2,  36 },  L2(1),  775000, 3200000 },
+	{ 1, {  422400, HFPLL, 2,  44 },  L2(2),  775000, 3200000 },
+	{ 0, {  499200, HFPLL, 2,  52 },  L2(2),  775000, 3200000 },
+	{ 0, {  576000, HFPLL, 1,  30 },  L2(3),  775000, 3200000 },
+	{ 1, {  652800, HFPLL, 1,  34 },  L2(3),  780000, 3200000 },
+	{ 1, {  729600, HFPLL, 1,  38 },  L2(4),  790000, 3200000 },
+	{ 0, {  806400, HFPLL, 1,  42 },  L2(4),  800000, 3200000 },
+	{ 1, {  883200, HFPLL, 1,  46 },  L2(4),  810000, 3200000 },
+	{ 1, {  960000, HFPLL, 1,  50 },  L2(9),  820000, 3200000 },
 	{ 1, { 1036800, HFPLL, 1,  54 }, L2(10),  830000, 3200000 },
-	{ 0, { 1113600, HFPLL, 1,  58 }, L2(12),  840000, 3200000 },
-	{ 0, { 1190400, HFPLL, 1,  62 }, L2(12),  850000, 3200000 },
-	{ 0, { 1267200, HFPLL, 1,  66 }, L2(12),  860000, 3200000 },
-	{ 1, { 1344000, HFPLL, 1,  70 }, L2(12),  875000, 3200000 },
-	{ 0, { 1420800, HFPLL, 1,  74 }, L2(16),  885000, 3200000 },
-	{ 0, { 1497600, HFPLL, 1,  78 }, L2(16),  895000, 3200000 },
-	{ 0, { 1574400, HFPLL, 1,  82 }, L2(16),  910000, 3200000 },
-	{ 0, { 1651200, HFPLL, 1,  86 }, L2(16),  925000, 3200000 },
-	{ 1, { 1728000, HFPLL, 1,  90 }, L2(16),  935000, 3200000 },
-	{ 0, { 1804800, HFPLL, 1,  94 }, L2(19),  950000, 3200000 },
-	{ 0, { 1881600, HFPLL, 1,  98 }, L2(19),  960000, 3200000 },
-	{ 0, { 1958400, HFPLL, 1, 102 }, L2(19),  970000, 3200000 },
-	{ 1, { 2035200, HFPLL, 1, 106 }, L2(19),  985000, 3200000 },
+	{ 0, { 1113600, HFPLL, 1,  58 }, L2(10),  840000, 3200000 },
+	{ 1, { 1190400, HFPLL, 1,  62 }, L2(10),  850000, 3200000 },
+	{ 1, { 1267200, HFPLL, 1,  66 }, L2(13),  860000, 3200000 },
+	{ 0, { 1344000, HFPLL, 1,  70 }, L2(14),  875000, 3200000 },
+	{ 0, { 1420800, HFPLL, 1,  74 }, L2(15),  885000, 3200000 },
+	{ 1, { 1497600, HFPLL, 1,  78 }, L2(16),  895000, 3200000 },
+	{ 1, { 1574400, HFPLL, 1,  82 }, L2(17),  910000, 3200000 },
+	{ 0, { 1651200, HFPLL, 1,  86 }, L2(17),  925000, 3200000 },
+	{ 1, { 1728000, HFPLL, 1,  90 }, L2(18),  935000, 3200000 },
+	{ 0, { 1804800, HFPLL, 1,  94 }, L2(18),  950000, 3200000 },
+	{ 0, { 1881600, HFPLL, 1,  98 }, L2(18),  960000, 3200000 },
+	{ 1, { 1958400, HFPLL, 1, 102 }, L2(19),  970000, 3200000 },
+	{ 0, { 2035200, HFPLL, 1, 106 }, L2(19),  985000, 3200000 },
 	{ 0, { 2112000, HFPLL, 1, 110 }, L2(19),  995000, 3200000 },
 	{ 0, { 2188800, HFPLL, 1, 114 }, L2(19), 1010000, 3200000 },
 	{ 1, { 2265600, HFPLL, 1, 118 }, L2(19), 1025000, 3200000 },
@@ -595,30 +805,30 @@
 };
 
 static struct acpu_level acpu_freq_tbl_2p3g_pvs4[] __initdata = {
-	{ 1, {  300000, PLL_0, 0,   0 }, L2(0),   775000,  400000 },
-	{ 0, {  345600, HFPLL, 2,  36 }, L2(3),   775000, 3200000 },
-	{ 1, {  422400, HFPLL, 2,  44 }, L2(3),   775000, 3200000 },
-	{ 0, {  499200, HFPLL, 2,  52 }, L2(6),   775000, 3200000 },
-	{ 1, {  576000, HFPLL, 1,  30 }, L2(6),   775000, 3200000 },
-	{ 1, {  652800, HFPLL, 1,  34 }, L2(7),   775000, 3200000 },
-	{ 1, {  729600, HFPLL, 1,  38 }, L2(7),   780000, 3200000 },
-	{ 0, {  806400, HFPLL, 1,  42 }, L2(10),  790000, 3200000 },
-	{ 1, {  883200, HFPLL, 1,  46 }, L2(10),  800000, 3200000 },
-	{ 0, {  960000, HFPLL, 1,  50 }, L2(10),  810000, 3200000 },
+	{ 1, {  300000, PLL_0, 0,   0 },  L2(0),  775000,  400000 },
+	{ 0, {  345600, HFPLL, 2,  36 },  L2(1),  775000, 3200000 },
+	{ 1, {  422400, HFPLL, 2,  44 },  L2(2),  775000, 3200000 },
+	{ 0, {  499200, HFPLL, 2,  52 },  L2(2),  775000, 3200000 },
+	{ 0, {  576000, HFPLL, 1,  30 },  L2(3),  775000, 3200000 },
+	{ 1, {  652800, HFPLL, 1,  34 },  L2(3),  775000, 3200000 },
+	{ 1, {  729600, HFPLL, 1,  38 },  L2(4),  780000, 3200000 },
+	{ 0, {  806400, HFPLL, 1,  42 },  L2(4),  790000, 3200000 },
+	{ 1, {  883200, HFPLL, 1,  46 },  L2(4),  800000, 3200000 },
+	{ 1, {  960000, HFPLL, 1,  50 },  L2(9),  810000, 3200000 },
 	{ 1, { 1036800, HFPLL, 1,  54 }, L2(10),  820000, 3200000 },
-	{ 0, { 1113600, HFPLL, 1,  58 }, L2(12),  830000, 3200000 },
-	{ 0, { 1190400, HFPLL, 1,  62 }, L2(12),  840000, 3200000 },
-	{ 0, { 1267200, HFPLL, 1,  66 }, L2(12),  850000, 3200000 },
-	{ 1, { 1344000, HFPLL, 1,  70 }, L2(12),  860000, 3200000 },
-	{ 0, { 1420800, HFPLL, 1,  74 }, L2(16),  870000, 3200000 },
-	{ 0, { 1497600, HFPLL, 1,  78 }, L2(16),  880000, 3200000 },
-	{ 0, { 1574400, HFPLL, 1,  82 }, L2(16),  895000, 3200000 },
-	{ 0, { 1651200, HFPLL, 1,  86 }, L2(16),  910000, 3200000 },
-	{ 1, { 1728000, HFPLL, 1,  90 }, L2(16),  920000, 3200000 },
-	{ 0, { 1804800, HFPLL, 1,  94 }, L2(19),  930000, 3200000 },
-	{ 0, { 1881600, HFPLL, 1,  98 }, L2(19),  940000, 3200000 },
-	{ 0, { 1958400, HFPLL, 1, 102 }, L2(19),  950000, 3200000 },
-	{ 1, { 2035200, HFPLL, 1, 106 }, L2(19),  960000, 3200000 },
+	{ 0, { 1113600, HFPLL, 1,  58 }, L2(10),  830000, 3200000 },
+	{ 1, { 1190400, HFPLL, 1,  62 }, L2(10),  840000, 3200000 },
+	{ 1, { 1267200, HFPLL, 1,  66 }, L2(13),  850000, 3200000 },
+	{ 0, { 1344000, HFPLL, 1,  70 }, L2(14),  860000, 3200000 },
+	{ 0, { 1420800, HFPLL, 1,  74 }, L2(15),  870000, 3200000 },
+	{ 1, { 1497600, HFPLL, 1,  78 }, L2(16),  880000, 3200000 },
+	{ 1, { 1574400, HFPLL, 1,  82 }, L2(17),  895000, 3200000 },
+	{ 0, { 1651200, HFPLL, 1,  86 }, L2(17),  910000, 3200000 },
+	{ 1, { 1728000, HFPLL, 1,  90 }, L2(18),  920000, 3200000 },
+	{ 0, { 1804800, HFPLL, 1,  94 }, L2(18),  930000, 3200000 },
+	{ 0, { 1881600, HFPLL, 1,  98 }, L2(18),  940000, 3200000 },
+	{ 1, { 1958400, HFPLL, 1, 102 }, L2(19),  950000, 3200000 },
+	{ 0, { 2035200, HFPLL, 1, 106 }, L2(19),  960000, 3200000 },
 	{ 0, { 2112000, HFPLL, 1, 110 }, L2(19),  975000, 3200000 },
 	{ 0, { 2188800, HFPLL, 1, 114 }, L2(19),  985000, 3200000 },
 	{ 1, { 2265600, HFPLL, 1, 118 }, L2(19), 1000000, 3200000 },
@@ -626,30 +836,30 @@
 };
 
 static struct acpu_level acpu_freq_tbl_2p3g_pvs5[] __initdata = {
-	{ 1, {  300000, PLL_0, 0,   0 }, L2(0),   750000,  400000 },
-	{ 0, {  345600, HFPLL, 2,  36 }, L2(3),   750000, 3200000 },
-	{ 1, {  422400, HFPLL, 2,  44 }, L2(3),   750000, 3200000 },
-	{ 0, {  499200, HFPLL, 2,  52 }, L2(6),   750000, 3200000 },
-	{ 1, {  576000, HFPLL, 1,  30 }, L2(6),   750000, 3200000 },
-	{ 1, {  652800, HFPLL, 1,  34 }, L2(7),   760000, 3200000 },
-	{ 1, {  729600, HFPLL, 1,  38 }, L2(7),   770000, 3200000 },
-	{ 0, {  806400, HFPLL, 1,  42 }, L2(10),  780000, 3200000 },
-	{ 1, {  883200, HFPLL, 1,  46 }, L2(10),  790000, 3200000 },
-	{ 0, {  960000, HFPLL, 1,  50 }, L2(10),  800000, 3200000 },
+	{ 1, {  300000, PLL_0, 0,   0 },  L2(0),  750000,  400000 },
+	{ 0, {  345600, HFPLL, 2,  36 },  L2(1),  750000, 3200000 },
+	{ 1, {  422400, HFPLL, 2,  44 },  L2(2),  750000, 3200000 },
+	{ 0, {  499200, HFPLL, 2,  52 },  L2(2),  750000, 3200000 },
+	{ 0, {  576000, HFPLL, 1,  30 },  L2(3),  750000, 3200000 },
+	{ 1, {  652800, HFPLL, 1,  34 },  L2(3),  760000, 3200000 },
+	{ 1, {  729600, HFPLL, 1,  38 },  L2(4),  770000, 3200000 },
+	{ 0, {  806400, HFPLL, 1,  42 },  L2(4),  780000, 3200000 },
+	{ 1, {  883200, HFPLL, 1,  46 },  L2(4),  790000, 3200000 },
+	{ 1, {  960000, HFPLL, 1,  50 },  L2(9),  800000, 3200000 },
 	{ 1, { 1036800, HFPLL, 1,  54 }, L2(10),  810000, 3200000 },
-	{ 0, { 1113600, HFPLL, 1,  58 }, L2(12),  820000, 3200000 },
-	{ 0, { 1190400, HFPLL, 1,  62 }, L2(12),  830000, 3200000 },
-	{ 0, { 1267200, HFPLL, 1,  66 }, L2(12),  840000, 3200000 },
-	{ 1, { 1344000, HFPLL, 1,  70 }, L2(12),  850000, 3200000 },
-	{ 0, { 1420800, HFPLL, 1,  74 }, L2(16),  860000, 3200000 },
-	{ 0, { 1497600, HFPLL, 1,  78 }, L2(16),  870000, 3200000 },
-	{ 0, { 1574400, HFPLL, 1,  82 }, L2(16),  880000, 3200000 },
-	{ 0, { 1651200, HFPLL, 1,  86 }, L2(16),  890000, 3200000 },
-	{ 1, { 1728000, HFPLL, 1,  90 }, L2(16),  900000, 3200000 },
-	{ 0, { 1804800, HFPLL, 1,  94 }, L2(19),  910000, 3200000 },
-	{ 0, { 1881600, HFPLL, 1,  98 }, L2(19),  920000, 3200000 },
-	{ 0, { 1958400, HFPLL, 1, 102 }, L2(19),  930000, 3200000 },
-	{ 1, { 2035200, HFPLL, 1, 106 }, L2(19),  940000, 3200000 },
+	{ 0, { 1113600, HFPLL, 1,  58 }, L2(10),  820000, 3200000 },
+	{ 1, { 1190400, HFPLL, 1,  62 }, L2(10),  830000, 3200000 },
+	{ 1, { 1267200, HFPLL, 1,  66 }, L2(13),  840000, 3200000 },
+	{ 0, { 1344000, HFPLL, 1,  70 }, L2(14),  850000, 3200000 },
+	{ 0, { 1420800, HFPLL, 1,  74 }, L2(15),  860000, 3200000 },
+	{ 1, { 1497600, HFPLL, 1,  78 }, L2(16),  870000, 3200000 },
+	{ 1, { 1574400, HFPLL, 1,  82 }, L2(17),  880000, 3200000 },
+	{ 0, { 1651200, HFPLL, 1,  86 }, L2(17),  890000, 3200000 },
+	{ 1, { 1728000, HFPLL, 1,  90 }, L2(18),  900000, 3200000 },
+	{ 0, { 1804800, HFPLL, 1,  94 }, L2(18),  910000, 3200000 },
+	{ 0, { 1881600, HFPLL, 1,  98 }, L2(18),  920000, 3200000 },
+	{ 1, { 1958400, HFPLL, 1, 102 }, L2(19),  930000, 3200000 },
+	{ 0, { 2035200, HFPLL, 1, 106 }, L2(19),  940000, 3200000 },
 	{ 0, { 2112000, HFPLL, 1, 110 }, L2(19),  955000, 3200000 },
 	{ 0, { 2188800, HFPLL, 1, 114 }, L2(19),  965000, 3200000 },
 	{ 1, { 2265600, HFPLL, 1, 118 }, L2(19),  975000, 3200000 },
@@ -657,30 +867,30 @@
 };
 
 static struct acpu_level acpu_freq_tbl_2p3g_pvs6[] __initdata = {
-	{ 1, {  300000, PLL_0, 0,   0 }, L2(0),   750000,  400000 },
-	{ 0, {  345600, HFPLL, 2,  36 }, L2(3),   750000, 3200000 },
-	{ 1, {  422400, HFPLL, 2,  44 }, L2(3),   750000, 3200000 },
-	{ 0, {  499200, HFPLL, 2,  52 }, L2(6),   750000, 3200000 },
-	{ 1, {  576000, HFPLL, 1,  30 }, L2(6),   750000, 3200000 },
-	{ 1, {  652800, HFPLL, 1,  34 }, L2(7),   750000, 3200000 },
-	{ 1, {  729600, HFPLL, 1,  38 }, L2(7),   760000, 3200000 },
-	{ 0, {  806400, HFPLL, 1,  42 }, L2(10),  770000, 3200000 },
-	{ 1, {  883200, HFPLL, 1,  46 }, L2(10),  780000, 3200000 },
-	{ 0, {  960000, HFPLL, 1,  50 }, L2(10),  790000, 3200000 },
+	{ 1, {  300000, PLL_0, 0,   0 },  L2(0),  750000,  400000 },
+	{ 0, {  345600, HFPLL, 2,  36 },  L2(1),  750000, 3200000 },
+	{ 1, {  422400, HFPLL, 2,  44 },  L2(2),  750000, 3200000 },
+	{ 0, {  499200, HFPLL, 2,  52 },  L2(2),  750000, 3200000 },
+	{ 0, {  576000, HFPLL, 1,  30 },  L2(3),  750000, 3200000 },
+	{ 1, {  652800, HFPLL, 1,  34 },  L2(3),  750000, 3200000 },
+	{ 1, {  729600, HFPLL, 1,  38 },  L2(4),  760000, 3200000 },
+	{ 0, {  806400, HFPLL, 1,  42 },  L2(4),  770000, 3200000 },
+	{ 1, {  883200, HFPLL, 1,  46 },  L2(4),  780000, 3200000 },
+	{ 1, {  960000, HFPLL, 1,  50 },  L2(9),  790000, 3200000 },
 	{ 1, { 1036800, HFPLL, 1,  54 }, L2(10),  800000, 3200000 },
-	{ 0, { 1113600, HFPLL, 1,  58 }, L2(12),  810000, 3200000 },
-	{ 0, { 1190400, HFPLL, 1,  62 }, L2(12),  820000, 3200000 },
-	{ 0, { 1267200, HFPLL, 1,  66 }, L2(12),  830000, 3200000 },
-	{ 1, { 1344000, HFPLL, 1,  70 }, L2(12),  840000, 3200000 },
-	{ 0, { 1420800, HFPLL, 1,  74 }, L2(16),  850000, 3200000 },
-	{ 0, { 1497600, HFPLL, 1,  78 }, L2(16),  860000, 3200000 },
-	{ 0, { 1574400, HFPLL, 1,  82 }, L2(16),  870000, 3200000 },
-	{ 0, { 1651200, HFPLL, 1,  86 }, L2(16),  875000, 3200000 },
-	{ 1, { 1728000, HFPLL, 1,  90 }, L2(16),  885000, 3200000 },
-	{ 0, { 1804800, HFPLL, 1,  94 }, L2(19),  895000, 3200000 },
-	{ 0, { 1881600, HFPLL, 1,  98 }, L2(19),  905000, 3200000 },
-	{ 0, { 1958400, HFPLL, 1, 102 }, L2(19),  915000, 3200000 },
-	{ 1, { 2035200, HFPLL, 1, 106 }, L2(19),  920000, 3200000 },
+	{ 0, { 1113600, HFPLL, 1,  58 }, L2(10),  810000, 3200000 },
+	{ 1, { 1190400, HFPLL, 1,  62 }, L2(10),  820000, 3200000 },
+	{ 1, { 1267200, HFPLL, 1,  66 }, L2(13),  830000, 3200000 },
+	{ 0, { 1344000, HFPLL, 1,  70 }, L2(14),  840000, 3200000 },
+	{ 0, { 1420800, HFPLL, 1,  74 }, L2(15),  850000, 3200000 },
+	{ 1, { 1497600, HFPLL, 1,  78 }, L2(16),  860000, 3200000 },
+	{ 1, { 1574400, HFPLL, 1,  82 }, L2(17),  870000, 3200000 },
+	{ 0, { 1651200, HFPLL, 1,  86 }, L2(17),  875000, 3200000 },
+	{ 1, { 1728000, HFPLL, 1,  90 }, L2(18),  885000, 3200000 },
+	{ 0, { 1804800, HFPLL, 1,  94 }, L2(18),  895000, 3200000 },
+	{ 0, { 1881600, HFPLL, 1,  98 }, L2(18),  905000, 3200000 },
+	{ 1, { 1958400, HFPLL, 1, 102 }, L2(19),  915000, 3200000 },
+	{ 0, { 2035200, HFPLL, 1, 106 }, L2(19),  920000, 3200000 },
 	{ 0, { 2112000, HFPLL, 1, 110 }, L2(19),  930000, 3200000 },
 	{ 0, { 2188800, HFPLL, 1, 114 }, L2(19),  940000, 3200000 },
 	{ 1, { 2265600, HFPLL, 1, 118 }, L2(19),  950000, 3200000 },
@@ -716,6 +926,17 @@
 	[1][5] = { acpu_freq_tbl_2p3g_pvs5, sizeof(acpu_freq_tbl_2p3g_pvs5) },
 	[1][6] = { acpu_freq_tbl_2p3g_pvs6, sizeof(acpu_freq_tbl_2p3g_pvs6) },
 	[1][7] = { acpu_freq_tbl_2p3g_pvs6, sizeof(acpu_freq_tbl_2p3g_pvs6) },
+
+	/* 8974v2 2.0GHz Parts */
+	[2][0] = { acpu_freq_tbl_2p2g_pvs0, sizeof(acpu_freq_tbl_2p2g_pvs0) },
+	[2][1] = { acpu_freq_tbl_2p2g_pvs1, sizeof(acpu_freq_tbl_2p2g_pvs1) },
+	[2][2] = { acpu_freq_tbl_2p2g_pvs2, sizeof(acpu_freq_tbl_2p2g_pvs2) },
+	[2][3] = { acpu_freq_tbl_2p2g_pvs3, sizeof(acpu_freq_tbl_2p2g_pvs3) },
+	[2][4] = { acpu_freq_tbl_2p2g_pvs4, sizeof(acpu_freq_tbl_2p2g_pvs4) },
+	[2][5] = { acpu_freq_tbl_2p2g_pvs5, sizeof(acpu_freq_tbl_2p2g_pvs5) },
+	[2][6] = { acpu_freq_tbl_2p2g_pvs6, sizeof(acpu_freq_tbl_2p2g_pvs6) },
+	[2][7] = { acpu_freq_tbl_2p2g_pvs6, sizeof(acpu_freq_tbl_2p2g_pvs6) },
+
 };
 
 static struct msm_bus_scale_pdata bus_scale_data __initdata = {
diff --git a/arch/arm/mach-msm/acpuclock-9625.c b/arch/arm/mach-msm/acpuclock-9625.c
index 34952fb..42659f9 100644
--- a/arch/arm/mach-msm/acpuclock-9625.c
+++ b/arch/arm/mach-msm/acpuclock-9625.c
@@ -16,6 +16,7 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/io.h>
+#include <linux/clk.h>
 #include <linux/errno.h>
 #include <linux/platform_device.h>
 #include <linux/regulator/consumer.h>
@@ -80,18 +81,21 @@
 		.update_mask = RCG_CONFIG_PGM_DATA_BIT | RCG_CONFIG_PGM_ENA_BIT,
 		.poll_mask = RCG_CONFIG_PGM_DATA_BIT,
 	},
+	.power_collapse_khz = 19200,
+	.wait_for_irq_khz = 19200,
 };
 
 static int __init acpuclk_9625_probe(struct platform_device *pdev)
 {
 	struct resource *res;
-	u32 regval;
+	u32 regval, i;
 
 	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "rcg_base");
 	if (!res)
 		return -EINVAL;
 
-	drv_data.apcs_rcg_config = ioremap(res->start, resource_size(res));
+	drv_data.apcs_rcg_config = devm_ioremap(&pdev->dev, res->start,
+		resource_size(res));
 	if (!drv_data.apcs_rcg_config)
 		return -ENOMEM;
 
@@ -117,6 +121,18 @@
 		return PTR_ERR(drv_data.vdd_mem);
 	}
 
+	for (i = 0; i < NUM_SRC; i++) {
+		if (!drv_data.src_clocks[i].name)
+			continue;
+		drv_data.src_clocks[i].clk =
+			devm_clk_get(&pdev->dev, drv_data.src_clocks[i].name);
+		if (IS_ERR(drv_data.src_clocks[i].clk)) {
+			dev_err(&pdev->dev, "Unable to get clock %s\n",
+				drv_data.src_clocks[i].name);
+			return -EPROBE_DEFER;
+		}
+	}
+
 	/* Disable hardware gating of gpll0 to A5SS */
 	regval = readl_relaxed(drv_data.apcs_cpu_pwr_ctl);
 	regval |= GPLL0_TO_A5_ALWAYS_ENABLE;
diff --git a/arch/arm/mach-msm/acpuclock-cortex.c b/arch/arm/mach-msm/acpuclock-cortex.c
index 88bf919..ca7fc2b 100644
--- a/arch/arm/mach-msm/acpuclock-cortex.c
+++ b/arch/arm/mach-msm/acpuclock-cortex.c
@@ -317,8 +317,6 @@
 static struct acpuclk_data acpuclk_cortex_data = {
 	.set_rate = acpuclk_cortex_set_rate,
 	.get_rate = acpuclk_cortex_get_rate,
-	.power_collapse_khz = 19200,
-	.wait_for_irq_khz = 19200,
 };
 
 int __init acpuclk_cortex_init(struct platform_device *pdev,
@@ -330,20 +328,15 @@
 	priv = data;
 	mutex_init(&priv->lock);
 
+	acpuclk_cortex_data.power_collapse_khz = priv->wait_for_irq_khz;
+	acpuclk_cortex_data.wait_for_irq_khz = priv->wait_for_irq_khz;
+
 	bus_perf_client = msm_bus_scale_register_client(priv->bus_scale);
 	if (!bus_perf_client) {
 		pr_err("Unable to register bus client\n");
 		BUG();
 	}
 
-	for (i = 0; i < NUM_SRC; i++) {
-		if (!priv->src_clocks[i].name)
-			continue;
-		priv->src_clocks[i].clk =
-			devm_clk_get(&pdev->dev, priv->src_clocks[i].name);
-		BUG_ON(IS_ERR(priv->src_clocks[i].clk));
-	}
-
 	/* Improve boot time by ramping up CPU immediately */
 	for (i = 0; priv->freq_tbl[i].khz != 0; i++)
 		if (priv->freq_tbl[i].use_for_scaling)
diff --git a/arch/arm/mach-msm/acpuclock-cortex.h b/arch/arm/mach-msm/acpuclock-cortex.h
index 2db3987..89a0a84 100644
--- a/arch/arm/mach-msm/acpuclock-cortex.h
+++ b/arch/arm/mach-msm/acpuclock-cortex.h
@@ -63,6 +63,8 @@
 	unsigned long			vdd_max_mem;
 	struct src_clock		src_clocks[NUM_SRC];
 	struct acpuclk_reg_data		reg_data;
+	unsigned long                   power_collapse_khz;
+	unsigned long                   wait_for_irq_khz;
 };
 
 /* Instantaneous bandwidth requests in MB/s. */
diff --git a/arch/arm/mach-msm/bam_dmux.c b/arch/arm/mach-msm/bam_dmux.c
index cbb9e37..92be927 100644
--- a/arch/arm/mach-msm/bam_dmux.c
+++ b/arch/arm/mach-msm/bam_dmux.c
@@ -434,8 +434,7 @@
 		list_add_tail(&info->list_node, &bam_rx_pool);
 		rx_len_cached = ++bam_rx_pool_len;
 		ret = sps_transfer_one(bam_rx_pipe, info->dma_address,
-			BUFFER_SIZE, info,
-			SPS_IOVEC_FLAG_INT | SPS_IOVEC_FLAG_EOT);
+			BUFFER_SIZE, info, 0);
 		if (ret) {
 			list_del(&info->list_node);
 			rx_len_cached = --bam_rx_pool_len;
@@ -657,7 +656,7 @@
 	spin_lock_irqsave(&bam_tx_pool_spinlock, flags);
 	list_add_tail(&pkt->list_node, &bam_tx_pool);
 	rc = sps_transfer_one(bam_tx_pipe, dma_address, len,
-				pkt, SPS_IOVEC_FLAG_INT | SPS_IOVEC_FLAG_EOT);
+				pkt, SPS_IOVEC_FLAG_EOT);
 	if (rc) {
 		DMUX_LOG_KERR("%s sps_transfer_one failed rc=%d\n",
 			__func__, rc);
@@ -830,7 +829,7 @@
 	spin_lock_irqsave(&bam_tx_pool_spinlock, flags);
 	list_add_tail(&pkt->list_node, &bam_tx_pool);
 	rc = sps_transfer_one(bam_tx_pipe, dma_address, skb->len,
-				pkt, SPS_IOVEC_FLAG_INT | SPS_IOVEC_FLAG_EOT);
+				pkt, SPS_IOVEC_FLAG_EOT);
 	if (rc) {
 		DMUX_LOG_KERR("%s sps_transfer_one failed rc=%d\n",
 			__func__, rc);
diff --git a/arch/arm/mach-msm/board-8064.c b/arch/arm/mach-msm/board-8064.c
index 42bde8f..e36884e 100644
--- a/arch/arm/mach-msm/board-8064.c
+++ b/arch/arm/mach-msm/board-8064.c
@@ -675,6 +675,7 @@
 static struct msm_hsic_host_platform_data msm_hsic_pdata = {
 	.strobe			= 88,
 	.data			= 89,
+	.phy_sof_workaround	= true,
 	.bus_scale_table	= &hsic_bus_scale_pdata,
 };
 #else
@@ -3804,6 +3805,8 @@
 	if (meminfo_init(SYS_MEMORY, SZ_256M) < 0)
 		pr_err("meminfo_init() failed!\n");
 
+	msm_thermal_pdata.limit_temp_degC = 80;
+
 	apq8064_common_init();
 	ethernet_init();
 	fsm8064_ep_pcie_init();
diff --git a/arch/arm/mach-msm/board-8226.c b/arch/arm/mach-msm/board-8226.c
index 872fabe..6371b9d 100644
--- a/arch/arm/mach-msm/board-8226.c
+++ b/arch/arm/mach-msm/board-8226.c
@@ -108,7 +108,7 @@
 	msm_spm_device_init();
 	rpm_regulator_smd_driver_init();
 	qpnp_regulator_init();
-	if (machine_is_msm8226_rumi())
+	if (of_board_is_rumi())
 		msm_clock_init(&msm8226_rumi_clock_init_data);
 	else
 		msm_clock_init(&msm8226_clock_init_data);
diff --git a/arch/arm/mach-msm/board-8610.c b/arch/arm/mach-msm/board-8610.c
index 5f5366f..9495b72 100644
--- a/arch/arm/mach-msm/board-8610.c
+++ b/arch/arm/mach-msm/board-8610.c
@@ -103,7 +103,7 @@
 	qpnp_regulator_init();
 	msm_thermal_device_init();
 
-	if (machine_is_msm8610_rumi())
+	if (of_board_is_rumi())
 		msm_clock_init(&msm8610_rumi_clock_init_data);
 	else
 		msm_clock_init(&msm8610_clock_init_data);
diff --git a/arch/arm/mach-msm/board-8960.c b/arch/arm/mach-msm/board-8960.c
index 7ef6fed..f3d8a2f 100644
--- a/arch/arm/mach-msm/board-8960.c
+++ b/arch/arm/mach-msm/board-8960.c
@@ -1459,8 +1459,9 @@
 #ifdef CONFIG_USB_EHCI_MSM_HSIC
 #define HSIC_HUB_RESET_GPIO	91
 static struct msm_hsic_host_platform_data msm_hsic_pdata = {
-	.strobe		= 150,
-	.data		= 151,
+	.strobe			= 150,
+	.data			= 151,
+	.phy_sof_workaround	= true,
 };
 
 static struct smsc_hub_platform_data hsic_hub_pdata = {
diff --git a/arch/arm/mach-msm/board-8974-gpiomux.c b/arch/arm/mach-msm/board-8974-gpiomux.c
index 688c6f7..35f3f99 100644
--- a/arch/arm/mach-msm/board-8974-gpiomux.c
+++ b/arch/arm/mach-msm/board-8974-gpiomux.c
@@ -718,14 +718,14 @@
 	},
 };
 
-static struct gpiomux_setting pri_auxpcm_act_cfg = {
+static struct gpiomux_setting auxpcm_act_cfg = {
 	.func = GPIOMUX_FUNC_1,
 	.drv = GPIOMUX_DRV_8MA,
 	.pull = GPIOMUX_PULL_NONE,
 };
 
 
-static struct gpiomux_setting pri_auxpcm_sus_cfg = {
+static struct gpiomux_setting auxpcm_sus_cfg = {
 	.func = GPIOMUX_FUNC_1,
 	.drv = GPIOMUX_DRV_2MA,
 	.pull = GPIOMUX_PULL_DOWN,
@@ -735,29 +735,60 @@
 	{
 		.gpio = 65,
 		.settings = {
-			[GPIOMUX_SUSPENDED] = &pri_auxpcm_sus_cfg,
-			[GPIOMUX_ACTIVE] = &pri_auxpcm_act_cfg,
+			[GPIOMUX_SUSPENDED] = &auxpcm_sus_cfg,
+			[GPIOMUX_ACTIVE] = &auxpcm_act_cfg,
 		},
 	},
 	{
 		.gpio = 66,
 		.settings = {
-			[GPIOMUX_SUSPENDED] = &pri_auxpcm_sus_cfg,
-			[GPIOMUX_ACTIVE] = &pri_auxpcm_act_cfg,
+			[GPIOMUX_SUSPENDED] = &auxpcm_sus_cfg,
+			[GPIOMUX_ACTIVE] = &auxpcm_act_cfg,
 		},
 	},
 	{
 		.gpio = 67,
 		.settings = {
-			[GPIOMUX_SUSPENDED] = &pri_auxpcm_sus_cfg,
-			[GPIOMUX_ACTIVE] = &pri_auxpcm_act_cfg,
+			[GPIOMUX_SUSPENDED] = &auxpcm_sus_cfg,
+			[GPIOMUX_ACTIVE] = &auxpcm_act_cfg,
 		},
 	},
 	{
 		.gpio = 68,
 		.settings = {
-			[GPIOMUX_SUSPENDED] = &pri_auxpcm_sus_cfg,
-			[GPIOMUX_ACTIVE] = &pri_auxpcm_act_cfg,
+			[GPIOMUX_SUSPENDED] = &auxpcm_sus_cfg,
+			[GPIOMUX_ACTIVE] = &auxpcm_act_cfg,
+		},
+	},
+};
+
+static struct msm_gpiomux_config msm8974_sec_auxpcm_configs[] __initdata = {
+	{
+		.gpio = 79,
+		.settings = {
+			[GPIOMUX_SUSPENDED] = &auxpcm_sus_cfg,
+			[GPIOMUX_ACTIVE] = &auxpcm_act_cfg,
+		},
+	},
+	{
+		.gpio = 80,
+		.settings = {
+			[GPIOMUX_SUSPENDED] = &auxpcm_sus_cfg,
+			[GPIOMUX_ACTIVE] = &auxpcm_act_cfg,
+		},
+	},
+	{
+		.gpio = 81,
+		.settings = {
+			[GPIOMUX_SUSPENDED] = &auxpcm_sus_cfg,
+			[GPIOMUX_ACTIVE] = &auxpcm_act_cfg,
+		},
+	},
+	{
+		.gpio = 82,
+		.settings = {
+			[GPIOMUX_SUSPENDED] = &auxpcm_sus_cfg,
+			[GPIOMUX_ACTIVE] = &auxpcm_act_cfg,
 		},
 	},
 };
@@ -1024,17 +1055,19 @@
 				ARRAY_SIZE(msm_hsic_hub_configs));
 
 	msm_gpiomux_install(msm_hdmi_configs, ARRAY_SIZE(msm_hdmi_configs));
-	if (machine_is_msm8974_fluid())
+	if (of_board_is_fluid())
 		msm_gpiomux_install(msm_mhl_configs,
 				    ARRAY_SIZE(msm_mhl_configs));
 
 	msm_gpiomux_install(msm8974_pri_auxpcm_configs,
 				 ARRAY_SIZE(msm8974_pri_auxpcm_configs));
+	msm_gpiomux_install(msm8974_sec_auxpcm_configs,
+				 ARRAY_SIZE(msm8974_sec_auxpcm_configs));
 
 	msm_gpiomux_install_nowrite(msm_lcd_configs,
 			ARRAY_SIZE(msm_lcd_configs));
 
-	if (machine_is_msm8974_rumi())
+	if (of_board_is_rumi())
 		msm_gpiomux_install(msm_rumi_blsp_configs,
 				    ARRAY_SIZE(msm_rumi_blsp_configs));
 }
diff --git a/arch/arm/mach-msm/board-8974.c b/arch/arm/mach-msm/board-8974.c
index e624e3f..9b69c8f 100644
--- a/arch/arm/mach-msm/board-8974.c
+++ b/arch/arm/mach-msm/board-8974.c
@@ -97,7 +97,7 @@
 	rpm_regulator_smd_driver_init();
 	msm_spm_device_init();
 	krait_power_init();
-	if (machine_is_msm8974_rumi())
+	if (of_board_is_rumi())
 		msm_clock_init(&msm8974_rumi_clock_init_data);
 	else
 		msm_clock_init(&msm8974_clock_init_data);
diff --git a/arch/arm/mach-msm/board-9615.c b/arch/arm/mach-msm/board-9615.c
index 50f4fd7..b77a3b9 100644
--- a/arch/arm/mach-msm/board-9615.c
+++ b/arch/arm/mach-msm/board-9615.c
@@ -841,6 +841,10 @@
 	.prv_data = &msm_hsic_peripheral_pdata_private,
 };
 
+static struct msm_hsic_host_platform_data msm_hsic_pdata = {
+	.phy_sof_workaround	= true,
+};
+
 #define PID_MAGIC_ID		0x71432909
 #define SERIAL_NUM_MAGIC_ID	0x61945374
 #define SERIAL_NUMBER_LENGTH	127
@@ -1073,6 +1077,7 @@
 		&msm_peripheral_pdata;
 	msm_device_hsic_peripheral.dev.platform_data =
 		&msm_hsic_peripheral_pdata;
+	msm_device_hsic_host.dev.platform_data = &msm_hsic_pdata;
 	msm_device_usb_bam.dev.platform_data = &msm_usb_bam_pdata;
 	platform_add_devices(common_devices, ARRAY_SIZE(common_devices));
 	msm9615_pm8xxx_gpio_mpp_init();
diff --git a/arch/arm/mach-msm/clock-8226.c b/arch/arm/mach-msm/clock-8226.c
index 413927c..4079b5a 100644
--- a/arch/arm/mach-msm/clock-8226.c
+++ b/arch/arm/mach-msm/clock-8226.c
@@ -2736,16 +2736,20 @@
 
 enum vdd_sr2_pll_levels {
 	VDD_SR2_PLL_OFF,
-	VDD_SR2_PLL_ON,
+	VDD_SR2_PLL_SVS,
+	VDD_SR2_PLL_NOM,
+	VDD_SR2_PLL_TUR,
 	VDD_SR2_PLL_NUM
 };
 
 static const int *vdd_sr2_levels[] = {
-	[VDD_SR2_PLL_OFF] = VDD_UV(0),
-	[VDD_SR2_PLL_ON]  = VDD_UV(1800000),
+	[VDD_SR2_PLL_OFF] = VDD_UV(0,       RPM_REGULATOR_CORNER_NONE),
+	[VDD_SR2_PLL_SVS] = VDD_UV(1800000, RPM_REGULATOR_CORNER_SVS_SOC),
+	[VDD_SR2_PLL_NOM] = VDD_UV(1800000, RPM_REGULATOR_CORNER_NORMAL),
+	[VDD_SR2_PLL_TUR] = VDD_UV(1800000, RPM_REGULATOR_CORNER_SUPER_TURBO),
 };
 
-static DEFINE_VDD_REGULATORS(vdd_sr2_pll, VDD_SR2_PLL_NUM, 1, vdd_sr2_levels);
+static DEFINE_VDD_REGULATORS(vdd_sr2_pll, VDD_SR2_PLL_NUM, 2, vdd_sr2_levels);
 
 static struct pll_freq_tbl apcs_pll_freq[] = {
 	F_APCS_PLL( 384000000, 20, 0x0, 0x1, 0x0, 0x0, 0x0),
@@ -2776,7 +2780,8 @@
 		.ops = &clk_ops_sr2_pll,
 		.vdd_class = &vdd_sr2_pll,
 		.fmax = (unsigned long [VDD_SR2_PLL_NUM]) {
-			[VDD_SR2_PLL_ON] = ULONG_MAX,
+			[VDD_SR2_PLL_SVS] = 1000000000,
+			[VDD_SR2_PLL_NOM] = 1900000000,
 		},
 		.num_fmax = VDD_SR2_PLL_NUM,
 		CLK_INIT(a7sspll.c),
@@ -3514,12 +3519,17 @@
 	if (IS_ERR(vdd_sr2_pll.regulator[0]))
 		panic("clock-8226: Unable to get the sr2_pll regulator!");
 
+	vdd_sr2_pll.regulator[1] = regulator_get(NULL, "vdd_sr2_dig");
+	if (IS_ERR(vdd_sr2_pll.regulator[1]))
+		panic("clock-8226: Unable to get the vdd_sr2_dig regulator!");
+
 	/*
 	 * These regulators are used at boot. Ensure they stay on
 	 * while the clock framework comes online.
 	 */
-	regulator_set_voltage(vdd_sr2_pll.regulator[0], 1800000, 1800000);
+	vote_vdd_level(&vdd_sr2_pll, VDD_SR2_PLL_TUR);
 	regulator_enable(vdd_sr2_pll.regulator[0]);
+	regulator_enable(vdd_sr2_pll.regulator[1]);
 
 	vote_vdd_level(&vdd_dig, VDD_DIG_HIGH);
 	regulator_enable(vdd_dig.regulator[0]);
@@ -3548,7 +3558,9 @@
 
 static int __init msm8226_clock_late_init(void)
 {
-	return unvote_vdd_level(&vdd_dig, VDD_DIG_HIGH);
+	unvote_vdd_level(&vdd_sr2_pll, VDD_SR2_PLL_TUR);
+	unvote_vdd_level(&vdd_dig, VDD_DIG_HIGH);
+	return 0;
 }
 
 struct clock_init_data msm8226_clock_init_data __initdata = {
diff --git a/arch/arm/mach-msm/clock-8610.c b/arch/arm/mach-msm/clock-8610.c
index b7c46b4..768efe7 100644
--- a/arch/arm/mach-msm/clock-8610.c
+++ b/arch/arm/mach-msm/clock-8610.c
@@ -524,17 +524,20 @@
 
 enum vdd_sr2_pll_levels {
 	VDD_SR2_PLL_OFF,
-	VDD_SR2_PLL_ON,
+	VDD_SR2_PLL_SVS,
+	VDD_SR2_PLL_NOM,
+	VDD_SR2_PLL_TUR,
 	VDD_SR2_PLL_NUM
 };
 
-static const int *vdd_sr2_pll_levels[] = {
-	[VDD_SR2_PLL_OFF] = VDD_UV(0),
-	[VDD_SR2_PLL_ON]  = VDD_UV(1800000),
+static const int *vdd_sr2_levels[] = {
+	[VDD_SR2_PLL_OFF] = VDD_UV(0,       RPM_REGULATOR_CORNER_NONE),
+	[VDD_SR2_PLL_SVS] = VDD_UV(1800000, RPM_REGULATOR_CORNER_SVS_SOC),
+	[VDD_SR2_PLL_NOM] = VDD_UV(1800000, RPM_REGULATOR_CORNER_NORMAL),
+	[VDD_SR2_PLL_TUR] = VDD_UV(1800000, RPM_REGULATOR_CORNER_SUPER_TURBO),
 };
 
-static DEFINE_VDD_REGULATORS(vdd_sr2_pll, VDD_SR2_PLL_NUM, 1,
-		vdd_sr2_pll_levels);
+static DEFINE_VDD_REGULATORS(vdd_sr2_pll, VDD_SR2_PLL_NUM, 2, vdd_sr2_levels);
 
 static struct pll_freq_tbl apcs_pll_freq[] = {
 	F_APCS_PLL( 384000000, 20, 0x0, 0x1, 0x0, 0x0, 0x0),
@@ -565,7 +568,8 @@
 		.ops = &clk_ops_sr2_pll,
 		.vdd_class = &vdd_sr2_pll,
 		.fmax = (unsigned long [VDD_SR2_PLL_NUM]) {
-			[VDD_SR2_PLL_ON] = ULONG_MAX,
+			[VDD_SR2_PLL_SVS] = 1000000000,
+			[VDD_SR2_PLL_NOM] = 1900000000,
 		},
 		.num_fmax = VDD_SR2_PLL_NUM,
 		CLK_INIT(a7sspll.c),
@@ -2777,6 +2781,16 @@
 	CLK_LOOKUP("measure_clk", apc2_m_clk, ""),
 	CLK_LOOKUP("measure_clk", apc3_m_clk, ""),
 	CLK_LOOKUP("measure_clk",   l2_m_clk, ""),
+
+	CLK_LOOKUP("iface_clk", mdp_ahb_clk.c, "fd900000.qcom,mdss_mdp"),
+	CLK_LOOKUP("core_clk", mdp_axi_clk.c, "fd900000.qcom,mdss_mdp"),
+	CLK_LOOKUP("lcdc_clk", mdp_lcdc_clk.c, "fd900000.qcom,mdss_mdp"),
+	CLK_LOOKUP("vsync_clk", mdp_vsync_clk.c, "fd900000.qcom,mdss_mdp"),
+	CLK_LOOKUP("iface_clk", dsi_ahb_clk.c, "fdd00000.qcom,mdss_dsi"),
+	CLK_LOOKUP("core_clk", dsi_clk.c, "fdd00000.qcom,mdss_dsi"),
+	CLK_LOOKUP("byte_clk", dsi_byte_clk.c, "fdd00000.qcom,mdss_dsi"),
+	CLK_LOOKUP("esc_clk", dsi_esc_clk.c, "fdd00000.qcom,mdss_dsi"),
+	CLK_LOOKUP("pixel_clk", dsi_pclk_clk.c, "fdd00000.qcom,mdss_dsi"),
 };
 
 static struct clk_lookup msm_clocks_8610_rumi[] = {
@@ -2948,8 +2962,13 @@
 	if (IS_ERR(vdd_sr2_pll.regulator[0]))
 		panic("clock-8610: Unable to get the vdd_sr2_pll regulator!");
 
-	regulator_set_voltage(vdd_sr2_pll.regulator[0], 1800000, 1800000);
+	vdd_sr2_pll.regulator[1] = regulator_get(NULL, "vdd_sr2_dig");
+	if (IS_ERR(vdd_sr2_pll.regulator[1]))
+		panic("clock-8610: Unable to get the vdd_sr2_dig regulator!");
+
+	vote_vdd_level(&vdd_sr2_pll, VDD_SR2_PLL_TUR);
 	regulator_enable(vdd_sr2_pll.regulator[0]);
+	regulator_enable(vdd_sr2_pll.regulator[1]);
 
 	/*
 	 * TODO: Set a voltage and enable vdd_dig, leaving the voltage high
@@ -2978,7 +2997,9 @@
 
 static int __init msm8610_clock_late_init(void)
 {
-	return unvote_vdd_level(&vdd_dig, VDD_DIG_HIGH);
+	unvote_vdd_level(&vdd_dig, VDD_DIG_HIGH);
+	unvote_vdd_level(&vdd_sr2_pll, VDD_SR2_PLL_TUR);
+	return 0;
 }
 
 struct clock_init_data msm8610_clock_init_data __initdata = {
diff --git a/arch/arm/mach-msm/clock.c b/arch/arm/mach-msm/clock.c
index ecd25fc..9b34465 100644
--- a/arch/arm/mach-msm/clock.c
+++ b/arch/arm/mach-msm/clock.c
@@ -419,10 +419,21 @@
 
 int clk_set_parent(struct clk *clk, struct clk *parent)
 {
-	if (!clk->ops->set_parent)
-		return 0;
+	int rc = 0;
 
-	return clk->ops->set_parent(clk, parent);
+	if (!clk->ops->set_parent)
+		return -ENOSYS;
+
+	mutex_lock(&clk->prepare_lock);
+	if (clk->parent == parent)
+		goto out;
+	rc = clk->ops->set_parent(clk, parent);
+	if (!rc)
+		clk->parent = parent;
+out:
+	mutex_unlock(&clk->prepare_lock);
+
+	return rc;
 }
 EXPORT_SYMBOL(clk_set_parent);
 
diff --git a/arch/arm/mach-msm/cpr-regulator.c b/arch/arm/mach-msm/cpr-regulator.c
index 4e95e4e..08923e4 100644
--- a/arch/arm/mach-msm/cpr-regulator.c
+++ b/arch/arm/mach-msm/cpr-regulator.c
@@ -43,10 +43,16 @@
 	/* Process voltage variables */
 	u32		pvs_bin;
 	u32		pvs_process;
-	u32		*process_vmax;
+	u32		*corner_ceiling;
 
 	/* APC voltage regulator */
 	struct regulator	*vdd_apc;
+
+	/* Dependency parameters */
+	struct regulator	*vdd_mx;
+	int			vdd_mx_vmax;
+	int			vdd_mx_vmin_method;
+	int			vdd_mx_vmin;
 };
 
 static int cpr_regulator_is_enabled(struct regulator_dev *rdev)
@@ -59,11 +65,23 @@
 static int cpr_regulator_enable(struct regulator_dev *rdev)
 {
 	struct cpr_regulator *cpr_vreg = rdev_get_drvdata(rdev);
-	int rc;
+	int rc = 0;
+
+	/* Enable dependency power before vdd_apc */
+	if (cpr_vreg->vdd_mx) {
+		rc = regulator_enable(cpr_vreg->vdd_mx);
+		if (rc) {
+			pr_err("regulator_enable: vdd_mx: rc=%d\n", rc);
+			return rc;
+		}
+	}
 
 	rc = regulator_enable(cpr_vreg->vdd_apc);
 	if (!rc)
 		cpr_vreg->enabled = true;
+	else
+		pr_err("regulator_enable: vdd_apc: rc=%d\n", rc);
+
 	return rc;
 }
 
@@ -73,8 +91,18 @@
 	int rc;
 
 	rc = regulator_disable(cpr_vreg->vdd_apc);
-	if (!rc)
-		cpr_vreg->enabled = false;
+	if (!rc) {
+		if (cpr_vreg->vdd_mx)
+			rc = regulator_disable(cpr_vreg->vdd_mx);
+
+		if (rc)
+			pr_err("regulator_disable: vdd_mx: rc=%d\n", rc);
+		else
+			cpr_vreg->enabled = false;
+	} else {
+		pr_err("regulator_disable: vdd_apc: rc=%d\n", rc);
+	}
+
 	return rc;
 }
 
@@ -83,14 +111,84 @@
 {
 	struct cpr_regulator *cpr_vreg = rdev_get_drvdata(rdev);
 	int rc;
-	int vdd_apc_min, vdd_apc_max;
+	int vdd_apc_min, vdd_apc_max, vdd_mx_vmin = 0;
+	int change_dir = 0;
 
-	vdd_apc_min = cpr_vreg->process_vmax[min_uV];
-	vdd_apc_max = cpr_vreg->process_vmax[CPR_CORNER_SUPER_TURBO];
+	if (cpr_vreg->vdd_mx) {
+		if (min_uV > cpr_vreg->corner)
+			change_dir = 1;
+		else if (min_uV < cpr_vreg->corner)
+			change_dir = -1;
+	}
+
+	vdd_apc_min = cpr_vreg->corner_ceiling[min_uV];
+	vdd_apc_max = cpr_vreg->corner_ceiling[CPR_CORNER_SUPER_TURBO];
+
+	if (change_dir) {
+		/* Determine the vdd_mx voltage */
+		switch (cpr_vreg->vdd_mx_vmin_method) {
+		case VDD_MX_VMIN_APC:
+			vdd_mx_vmin = vdd_apc_min;
+			break;
+		case VDD_MX_VMIN_APC_CORNER_CEILING:
+			vdd_mx_vmin = vdd_apc_min;
+			break;
+		case VDD_MX_VMIN_APC_SLOW_CORNER_CEILING:
+			vdd_mx_vmin = cpr_vreg->pvs_corner_ceiling
+					[APC_PVS_SLOW][min_uV];
+			break;
+		case VDD_MX_VMIN_MX_VMAX:
+		default:
+			vdd_mx_vmin = cpr_vreg->vdd_mx_vmax;
+			break;
+		}
+	}
+
+	if (change_dir > 0) {
+		if (vdd_mx_vmin < cpr_vreg->vdd_mx_vmin) {
+			/* Check and report the value in case */
+			pr_err("Up: but new %d < old %d uV\n", vdd_mx_vmin,
+					cpr_vreg->vdd_mx_vmin);
+		}
+
+		rc = regulator_set_voltage(cpr_vreg->vdd_mx, vdd_mx_vmin,
+					   cpr_vreg->vdd_mx_vmax);
+		if (!rc) {
+			cpr_vreg->vdd_mx_vmin = vdd_mx_vmin;
+		} else {
+			pr_err("set: vdd_mx [%d] = %d uV: rc=%d\n",
+			       min_uV, vdd_mx_vmin, rc);
+			return rc;
+		}
+	}
+
 	rc = regulator_set_voltage(cpr_vreg->vdd_apc,
 				   vdd_apc_min, vdd_apc_max);
-	if (!rc)
+	if (!rc) {
 		cpr_vreg->corner = min_uV;
+	} else {
+		pr_err("set: vdd_apc [%d] = %d uV: rc=%d\n",
+		       min_uV, vdd_apc_min, rc);
+		return rc;
+	}
+
+	if (change_dir < 0) {
+		if (vdd_mx_vmin > cpr_vreg->vdd_mx_vmin) {
+			/* Check and report the value in case */
+			pr_err("Down: but new %d >= old %d uV\n", vdd_mx_vmin,
+			       cpr_vreg->vdd_mx_vmin);
+		}
+
+		rc = regulator_set_voltage(cpr_vreg->vdd_mx, vdd_mx_vmin,
+					   cpr_vreg->vdd_mx_vmax);
+		if (!rc) {
+			cpr_vreg->vdd_mx_vmin = vdd_mx_vmin;
+		} else {
+			pr_err("set: vdd_mx [%d] = %d uV: rc=%d\n",
+			       min_uV, vdd_mx_vmin, rc);
+			return rc;
+		}
+	}
 
 	pr_debug("set [corner:%d] = %d uV: rc=%d\n", min_uV, vdd_apc_min, rc);
 	return rc;
@@ -146,7 +244,7 @@
 		= cpr_vreg->pvs_corner_ceiling[APC_PVS_SLOW]
 					[CPR_CORNER_SUPER_TURBO];
 
-	cpr_vreg->process_vmax =
+	cpr_vreg->corner_ceiling =
 		cpr_vreg->pvs_corner_ceiling[cpr_vreg->pvs_process];
 
 	iounmap(efuse_base);
@@ -162,19 +260,62 @@
 static int __init cpr_regulator_apc_init(struct platform_device *pdev,
 					 struct cpr_regulator *cpr_vreg)
 {
+	struct device_node *of_node = pdev->dev.of_node;
+	int rc;
+
 	cpr_vreg->vdd_apc = devm_regulator_get(&pdev->dev, "vdd-apc");
 	if (IS_ERR_OR_NULL(cpr_vreg->vdd_apc)) {
-		pr_err("devm_regulator_get: rc=%d\n",
-		       (int)PTR_ERR(cpr_vreg->vdd_apc));
+		rc = PTR_RET(cpr_vreg->vdd_apc);
+		if (rc != -EPROBE_DEFER)
+			pr_err("devm_regulator_get: rc=%d\n", rc);
+		return rc;
 	}
 
-	return PTR_RET(cpr_vreg->vdd_apc);
+	/* Check dependencies */
+	if (of_property_read_bool(of_node, "vdd-mx-supply")) {
+		cpr_vreg->vdd_mx = devm_regulator_get(&pdev->dev, "vdd-mx");
+		if (IS_ERR_OR_NULL(cpr_vreg->vdd_mx)) {
+			rc = PTR_RET(cpr_vreg->vdd_mx);
+			if (rc != -EPROBE_DEFER)
+				pr_err("devm_regulator_get: vdd-mx: rc=%d\n",
+				       rc);
+			return rc;
+		}
+	}
+
+	/* Parse dependency parameters */
+	if (cpr_vreg->vdd_mx) {
+		rc = of_property_read_u32(of_node, "qcom,vdd-mx-vmax",
+				 &cpr_vreg->vdd_mx_vmax);
+		if (rc < 0) {
+			pr_err("vdd-mx-vmax missing: rc=%d\n", rc);
+			return rc;
+		}
+
+		rc = of_property_read_u32(of_node, "qcom,vdd-mx-vmin-method",
+				 &cpr_vreg->vdd_mx_vmin_method);
+		if (rc < 0) {
+			pr_err("vdd-mx-vmin-method missing: rc=%d\n", rc);
+			return rc;
+		}
+		if (cpr_vreg->vdd_mx_vmin_method > VDD_MX_VMIN_MX_VMAX) {
+			pr_err("Invalid vdd-mx-vmin-method(%d)\n",
+				cpr_vreg->vdd_mx_vmin_method);
+			return -EINVAL;
+		}
+	}
+
+	return 0;
 }
 
 static void cpr_regulator_apc_exit(struct cpr_regulator *cpr_vreg)
 {
-	if (cpr_vreg->enabled)
+	if (cpr_vreg->enabled) {
 		regulator_disable(cpr_vreg->vdd_apc);
+
+		if (cpr_vreg->vdd_mx)
+			regulator_disable(cpr_vreg->vdd_mx);
+	}
 }
 
 static int __init cpr_regulator_parse_dt(struct platform_device *pdev,
@@ -323,10 +464,10 @@
 	platform_set_drvdata(pdev, cpr_vreg);
 
 	pr_info("PVS [%d %d %d %d] uV\n",
-		cpr_vreg->process_vmax[CPR_CORNER_SVS],
-		cpr_vreg->process_vmax[CPR_CORNER_NORMAL],
-		cpr_vreg->process_vmax[CPR_CORNER_TURBO],
-		cpr_vreg->process_vmax[CPR_CORNER_SUPER_TURBO]);
+		cpr_vreg->corner_ceiling[CPR_CORNER_SVS],
+		cpr_vreg->corner_ceiling[CPR_CORNER_NORMAL],
+		cpr_vreg->corner_ceiling[CPR_CORNER_TURBO],
+		cpr_vreg->corner_ceiling[CPR_CORNER_SUPER_TURBO]);
 
 	return 0;
 }
diff --git a/arch/arm/mach-msm/devices-8064.c b/arch/arm/mach-msm/devices-8064.c
index 656c3f4..2f44566 100644
--- a/arch/arm/mach-msm/devices-8064.c
+++ b/arch/arm/mach-msm/devices-8064.c
@@ -2652,8 +2652,8 @@
 		[MSM_RPM_LOG_PAGE_BUFFER]  = 0x000000A0,
 	},
 	.phys_size = SZ_8K,
-	.log_len = 4096,		  /* log's buffer length in bytes */
-	.log_len_mask = (4096 >> 2) - 1,  /* length mask in units of u32 */
+	.log_len = 6144,		  /* log's buffer length in bytes */
+	.log_len_mask = (6144 >> 2) - 1,  /* length mask in units of u32 */
 };
 
 struct platform_device apq8064_rpm_log_device = {
diff --git a/arch/arm/mach-msm/devices-8930.c b/arch/arm/mach-msm/devices-8930.c
index 2f8f547..e2a57f9 100644
--- a/arch/arm/mach-msm/devices-8930.c
+++ b/arch/arm/mach-msm/devices-8930.c
@@ -550,14 +550,14 @@
 };
 
 static struct msm_rpm_log_platform_data msm_rpm_log_pdata = {
-	.phys_addr_base = 0x0010C000,
+	.phys_addr_base = 0x10B6A0,
 	.reg_offsets = {
 		[MSM_RPM_LOG_PAGE_INDICES] = 0x00000080,
 		[MSM_RPM_LOG_PAGE_BUFFER]  = 0x000000A0,
 	},
 	.phys_size = SZ_8K,
-	.log_len = 4096,		  /* log's buffer length in bytes */
-	.log_len_mask = (4096 >> 2) - 1,  /* length mask in units of u32 */
+	.log_len = 8192,		  /* log's buffer length in bytes */
+	.log_len_mask = (8192 >> 2) - 1,  /* length mask in units of u32 */
 };
 
 struct platform_device msm8930_rpm_log_device = {
diff --git a/arch/arm/mach-msm/devices-8960.c b/arch/arm/mach-msm/devices-8960.c
index e70a0a8..837aef3 100644
--- a/arch/arm/mach-msm/devices-8960.c
+++ b/arch/arm/mach-msm/devices-8960.c
@@ -3961,8 +3961,8 @@
 		[MSM_RPM_LOG_PAGE_BUFFER]  = 0x000000A0,
 	},
 	.phys_size = SZ_8K,
-	.log_len = 4096,		  /* log's buffer length in bytes */
-	.log_len_mask = (4096 >> 2) - 1,  /* length mask in units of u32 */
+	.log_len = 6144,		  /* log's buffer length in bytes */
+	.log_len_mask = (6144 >> 2) - 1,  /* length mask in units of u32 */
 };
 
 struct platform_device msm8960_rpm_log_device = {
diff --git a/arch/arm/mach-msm/include/mach/camera2.h b/arch/arm/mach-msm/include/mach/camera2.h
index b518e56..248c9b0 100644
--- a/arch/arm/mach-msm/include/mach/camera2.h
+++ b/arch/arm/mach-msm/include/mach/camera2.h
@@ -20,6 +20,7 @@
 enum msm_camera_device_type_t {
 	MSM_CAMERA_I2C_DEVICE,
 	MSM_CAMERA_PLATFORM_DEVICE,
+	MSM_CAMERA_SPI_DEVICE,
 };
 
 enum msm_bus_perf_setting {
@@ -100,4 +101,39 @@
 	enum msm_camera_i2c_data_type data_type;
 };
 
+struct eeprom_map_t {
+	uint32_t valid_size;
+	uint32_t addr;
+	uint32_t addr_t;
+	uint32_t data;
+	uint32_t data_t;
+	uint32_t delay;
+};
+
+struct eeprom_memory_map_t {
+	struct eeprom_map_t page;
+	struct eeprom_map_t poll;
+	struct eeprom_map_t mem;
+};
+
+struct msm_camera_power_ctrl_t {
+	struct device *dev;
+	struct msm_sensor_power_setting *power_setting;
+	uint16_t power_setting_size;
+	struct msm_camera_gpio_conf *gpio_conf;
+	struct camera_vreg_t *cam_vreg;
+	int num_vreg;
+	struct msm_camera_i2c_conf *i2c_conf;
+	struct msm_cam_clk_info *clk_info;
+	uint16_t clk_info_size;
+};
+
+struct msm_eeprom_board_info {
+	const char *eeprom_name;
+	uint16_t i2c_slaveaddr;
+	uint32_t num_blocks;
+	struct eeprom_memory_map_t *eeprom_map;
+	struct msm_camera_power_ctrl_t power_info;
+};
+
 #endif
diff --git a/arch/arm/mach-msm/include/mach/iommu.h b/arch/arm/mach-msm/include/mach/iommu.h
index c5c4988..f750dc8 100644
--- a/arch/arm/mach-msm/include/mach/iommu.h
+++ b/arch/arm/mach-msm/include/mach/iommu.h
@@ -123,6 +123,24 @@
 	unsigned int ctx_attach_count;
 };
 
+/**
+ * struct iommu_access_ops - Callbacks for accessing IOMMU
+ * @iommu_power_on:     Turn on power to unit
+ * @iommu_power_off:    Turn off power to unit
+ * @iommu_clk_on:       Turn on clks to unit
+ * @iommu_clk_off:      Turn off clks to unit
+ * @iommu_lock_acquire: Acquire any locks needed
+ * @iommu_lock_release: Release locks needed
+ */
+struct iommu_access_ops {
+	int (*iommu_power_on)(struct msm_iommu_drvdata *);
+	void (*iommu_power_off)(struct msm_iommu_drvdata *);
+	int (*iommu_clk_on)(struct msm_iommu_drvdata *);
+	void (*iommu_clk_off)(struct msm_iommu_drvdata *);
+	void (*iommu_lock_acquire)(void);
+	void (*iommu_lock_release)(void);
+};
+
 void msm_iommu_add_drv(struct msm_iommu_drvdata *drv);
 void msm_iommu_remove_drv(struct msm_iommu_drvdata *drv);
 void program_iommu_bfb_settings(void __iomem *base,
@@ -241,6 +259,7 @@
  * This should only be called on IOMMUs for which kernel programming
  * of global registers is not possible
  */
+void msm_iommu_sec_set_access_ops(struct iommu_access_ops *access_ops);
 int msm_iommu_sec_program_iommu(int sec_id);
 
 static inline int msm_soc_version_supports_iommu_v0(void)
diff --git a/arch/arm/mach-msm/include/mach/iommu_domains.h b/arch/arm/mach-msm/include/mach/iommu_domains.h
index fec734a..9a89508 100644
--- a/arch/arm/mach-msm/include/mach/iommu_domains.h
+++ b/arch/arm/mach-msm/include/mach/iommu_domains.h
@@ -13,6 +13,7 @@
 #ifndef _ARCH_IOMMU_DOMAINS_H
 #define _ARCH_IOMMU_DOMAINS_H
 
+#include <linux/errno.h>
 #include <linux/memory_alloc.h>
 
 #define MSM_IOMMU_DOMAIN_SECURE	0x1
diff --git a/arch/arm/mach-msm/include/mach/iommu_perfmon.h b/arch/arm/mach-msm/include/mach/iommu_perfmon.h
index c03c752..dcae83b 100644
--- a/arch/arm/mach-msm/include/mach/iommu_perfmon.h
+++ b/arch/arm/mach-msm/include/mach/iommu_perfmon.h
@@ -18,20 +18,6 @@
 #define MSM_IOMMU_PERFMON_H
 
 /**
- * struct iommu_access_ops - Callbacks for accessing IOMMU
- * @iommu_power_on:     Turn on clocks/power to unit
- * @iommu_power_off:    Turn off clocks/power to unit
- * @iommu_lock_acquire: Acquire any locks needed
- * @iommu_lock_release: Release locks needed
- */
-struct iommu_access_ops {
-	int (*iommu_power_on)(void *);
-	int (*iommu_power_off)(void *);
-	void (*iommu_lock_acquire)(void);
-	void (*iommu_lock_release)(void);
-};
-
-/**
  * struct iommu_pmon_counter - container for a performance counter.
  * @counter_no:          counter number within the group
  * @absolute_counter_no: counter number within IOMMU PMU
diff --git a/arch/arm/mach-msm/include/mach/msm_bus.h b/arch/arm/mach-msm/include/mach/msm_bus.h
index 049cf02..ebc43da 100644
--- a/arch/arm/mach-msm/include/mach/msm_bus.h
+++ b/arch/arm/mach-msm/include/mach/msm_bus.h
@@ -112,6 +112,8 @@
 #endif
 
 #if defined(CONFIG_OF) && defined(CONFIG_MSM_BUS_SCALING)
+struct msm_bus_scale_pdata *msm_bus_pdata_from_node(
+		struct platform_device *pdev, struct device_node *of_node);
 struct msm_bus_scale_pdata *msm_bus_cl_get_pdata(struct platform_device *pdev);
 void msm_bus_cl_clear_pdata(struct msm_bus_scale_pdata *pdata);
 #else
@@ -121,6 +123,12 @@
 	return NULL;
 }
 
+static inline struct msm_bus_scale_pdata *msm_bus_pdata_from_node(
+		struct platform_device *pdev, struct device_node *of_node)
+{
+	return NULL;
+}
+
 static inline void msm_bus_cl_clear_pdata(struct msm_bus_scale_pdata *pdata)
 {
 }
diff --git a/arch/arm/mach-msm/include/mach/msm_subsystem_map.h b/arch/arm/mach-msm/include/mach/msm_subsystem_map.h
deleted file mode 100644
index 3119023..0000000
--- a/arch/arm/mach-msm/include/mach/msm_subsystem_map.h
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
- * Copyright (c) 2011, The Linux Foundation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- */
-#ifndef __ARCH_MACH_MSM_SUBSYSTEM_MAP_H
-#define __ARCH_MACH_MSM_SUBSYSTEM_MAP_H
-
-#include <linux/iommu.h>
-#include <mach/iommu_domains.h>
-
-/* map the physical address in the kernel vaddr space */
-#define MSM_SUBSYSTEM_MAP_KADDR		0x1
-/* map the physical address in the iova address space */
-#define MSM_SUBSYSTEM_MAP_IOVA		0x2
-/* ioremaps in the kernel address space are cached */
-#define	MSM_SUBSYSTEM_MAP_CACHED	0x4
-/* ioremaps in the kernel address space are uncached */
-#define MSM_SUBSYSTEM_MAP_UNCACHED	0x8
-/*
- * Will map 2x the length requested.
- */
-#define MSM_SUBSYSTEM_MAP_IOMMU_2X 0x10
-
-/*
- * Shortcut flags for alignment.
- * The flag must be equal to the alignment requested.
- * e.g. for 8k alignment the flags must be (0x2000 | other flags)
- */
-#define	MSM_SUBSYSTEM_ALIGN_IOVA_8K	SZ_8K
-#define MSM_SUBSYSTEM_ALIGN_IOVA_1M	SZ_1M
-
-
-enum msm_subsystem_id {
-	INVALID_SUBSYS_ID = -1,
-	MSM_SUBSYSTEM_VIDEO,
-	MSM_SUBSYSTEM_VIDEO_FWARE,
-	MSM_SUBSYSTEM_CAMERA,
-	MSM_SUBSYSTEM_DISPLAY,
-	MSM_SUBSYSTEM_ROTATOR,
-	MAX_SUBSYSTEM_ID
-};
-
-static inline int msm_subsystem_check_id(int subsys_id)
-{
-	return subsys_id > INVALID_SUBSYS_ID && subsys_id < MAX_SUBSYSTEM_ID;
-}
-
-struct msm_mapped_buffer {
-	/*
-	 * VA mapped in the kernel address space. This field shall be NULL if
-	 * MSM_SUBSYSTEM_MAP_KADDR was not passed to the map buffer function.
-	 */
-	void *vaddr;
-	/*
-	 * iovas mapped in the iommu address space. The ith entry of this array
-	 * corresponds to the iova mapped in the ith subsystem in the array
-	 * pased in to msm_subsystem_map_buffer. This field shall be NULL if
-	 * MSM_SUBSYSTEM_MAP_IOVA was not passed to the map buffer function,
-	 */
-	unsigned long *iova;
-};
-
-extern struct msm_mapped_buffer *msm_subsystem_map_buffer(
-				unsigned long phys,
-				unsigned int length,
-				unsigned int flags,
-				int *subsys_ids,
-				unsigned int nsubsys);
-
-extern int msm_subsystem_unmap_buffer(struct msm_mapped_buffer *buf);
-
-extern phys_addr_t msm_subsystem_check_iova_mapping(int subsys_id,
-						unsigned long iova);
-
-#endif /* __ARCH_MACH_MSM_SUBSYSTEM_MAP_H */
diff --git a/arch/arm/mach-msm/include/mach/qdsp6v2/q6core.h b/arch/arm/mach-msm/include/mach/qdsp6v2/q6core.h
index ea345fb..91e4ef1 100644
--- a/arch/arm/mach-msm/include/mach/qdsp6v2/q6core.h
+++ b/arch/arm/mach-msm/include/mach/qdsp6v2/q6core.h
@@ -53,10 +53,19 @@
 	uint8_t   model_ID[128];
 };
 
+#define ADSP_CMD_SET_DOLBY_MANUFACTURER_ID 0x00012918
+
+struct adsp_dolby_manufacturer_id {
+	struct apr_hdr hdr;
+	int manufacturer_id;
+};
+
 int core_req_bus_bandwith(u16 bus_id, u32 ab_bps, u32 ib_bps);
 
 uint32_t core_get_adsp_version(void);
 
 uint32_t core_set_dts_model_id(uint32_t id_size, uint8_t *id);
 
+uint32_t core_set_dolby_manufacturer_id(int manufacturer_id);
+
 #endif /* __Q6CORE_H__ */
diff --git a/arch/arm/mach-msm/include/mach/qseecomi.h b/arch/arm/mach-msm/include/mach/qseecomi.h
index 3a13af8..20dc851 100644
--- a/arch/arm/mach-msm/include/mach/qseecomi.h
+++ b/arch/arm/mach-msm/include/mach/qseecomi.h
@@ -16,6 +16,8 @@
 
 #include <linux/qseecom.h>
 
+#define QSEECOM_KEY_ID_SIZE   32
+
 enum qseecom_command_scm_resp_type {
 	QSEOS_APP_ID = 0xEE01,
 	QSEOS_LISTENER_ID
@@ -36,6 +38,8 @@
 	QSEOS_UNLOAD_SERV_IMAGE_COMMAND,
 	QSEOS_APP_REGION_NOTIFICATION,
 	QSEOS_REGISTER_LOG_BUF_COMMAND,
+	QSEE_RPMB_PROVISION_KEY_COMMAND,
+	QSEE_RPMB_ERASE_COMMAND,
 	QSEOS_CMD_MAX     = 0xEFFFFFFF
 };
 
@@ -127,4 +131,57 @@
 	unsigned int data;
 };
 
+struct qseecom_rpmb_provision_key {
+	uint32_t key_type;
+};
+
+__packed struct qseecom_client_send_service_ireq {
+	uint32_t qsee_cmd_id;
+	uint32_t key_type; /* in */
+	unsigned int req_len; /* in */
+	void *rsp_ptr; /* in/out */
+	unsigned int rsp_len; /* in/out */
+};
+
+/* Key Management requests */
+enum qseecom_qceos_key_gen_cmd_id {
+	QSEOS_GENERATE_KEY      = 0x02,
+	QSEOS_SET_KEY,
+	QSEOS_DELETE_KEY,
+	QSEOS_MAX_KEY_COUNT,
+	QSEOS_KEY_CMD_MAX     = 0xEFFFFFFF
+};
+
+__packed struct qseecom_key_generate_ireq {
+	uint32_t flags;
+	uint8_t key_id[QSEECOM_KEY_ID_SIZE];
+};
+
+__packed struct qseecom_key_select_ireq {
+	uint32_t ce;
+	uint32_t pipe;
+	uint32_t flags;
+	uint8_t key_id[QSEECOM_KEY_ID_SIZE];
+	unsigned char hash[QSEECOM_HASH_SIZE];
+};
+
+__packed struct qseecom_key_delete_ireq {
+	uint32_t flags;
+	uint8_t key_id[QSEECOM_KEY_ID_SIZE];
+};
+
+__packed struct qseecom_key_max_count_query_ireq {
+	uint32_t flags;
+};
+
+__packed struct qseecom_key_max_count_query_irsp {
+	uint32_t max_key_count;
+};
+
+struct key_id_info {
+	uint32_t	ce_hw;
+	uint32_t	pipe;
+	bool		flags;
+};
+
 #endif /* __QSEECOMI_H_ */
diff --git a/arch/arm/mach-msm/include/mach/rpm-regulator-smd.h b/arch/arm/mach-msm/include/mach/rpm-regulator-smd.h
index 9e70510..cfe8ae7 100644
--- a/arch/arm/mach-msm/include/mach/rpm-regulator-smd.h
+++ b/arch/arm/mach-msm/include/mach/rpm-regulator-smd.h
@@ -38,6 +38,32 @@
 	RPM_REGULATOR_CORNER_SUPER_TURBO,
 };
 
+/**
+ * enum rpm_regulator_mode - control mode for LDO or SMPS type regulators
+ * %RPM_REGULATOR_MODE_AUTO:	For SMPS type regulators, use SMPS auto mode so
+ *				that the hardware can automatically switch
+ *				between PFM and PWM modes based on realtime
+ *				load.
+ *				LDO type regulators do not support this mode.
+ * %RPM_REGULATOR_MODE_IPEAK:	For SMPS type regulators, use aggregated
+ *				software current requests to determine
+ *				usage of PFM or PWM mode.
+ *				For LDO type regulators, use aggregated
+ *				software current requests to determine
+ *				usage of LPM or HPM mode.
+ * %RPM_REGULATOR_MODE_HPM:	For SMPS type regulators, force the
+ *				usage of PWM mode.
+ *				For LDO type regulators, force the
+ *				usage of HPM mode.
+ *
+ * These values should be used in calls to rpm_regulator_set_mode().
+ */
+enum rpm_regulator_mode {
+	RPM_REGULATOR_MODE_AUTO,
+	RPM_REGULATOR_MODE_IPEAK,
+	RPM_REGULATOR_MODE_HPM,
+};
+
 #if defined(CONFIG_MSM_RPM_REGULATOR_SMD) || defined(CONFIG_MSM_RPM_REGULATOR)
 
 struct rpm_regulator *rpm_regulator_get(struct device *dev, const char *supply);
@@ -71,6 +97,14 @@
 
 static inline int __init rpm_regulator_smd_driver_init(void) { return 0; }
 
-#endif /* CONFIG_MSM_RPM_REGULATOR_SMD */
+#endif /* CONFIG_MSM_RPM_REGULATOR_SMD || CONFIG_MSM_RPM_REGULATOR */
+
+#ifdef CONFIG_MSM_RPM_REGULATOR_SMD
+int rpm_regulator_set_mode(struct rpm_regulator *regulator,
+				enum rpm_regulator_mode mode);
+#else
+static inline int rpm_regulator_set_mode(struct rpm_regulator *regulator,
+				enum rpm_regulator_mode mode) { return 0; }
+#endif
 
 #endif
diff --git a/arch/arm/mach-msm/include/mach/scm.h b/arch/arm/mach-msm/include/mach/scm.h
index 0cc7bbf..4258dbd 100644
--- a/arch/arm/mach-msm/include/mach/scm.h
+++ b/arch/arm/mach-msm/include/mach/scm.h
@@ -22,6 +22,7 @@
 #define SCM_SVC_FUSE			0x8
 #define SCM_SVC_PWR			0x9
 #define SCM_SVC_MP			0xC
+#define SCM_SVC_CRYPTO			0xA
 #define SCM_SVC_DCVS			0xD
 #define SCM_SVC_TZSCHEDULER		0xFC
 
diff --git a/arch/arm/mach-msm/include/mach/socinfo.h b/arch/arm/mach-msm/include/mach/socinfo.h
index 45f2646..b898fe8 100644
--- a/arch/arm/mach-msm/include/mach/socinfo.h
+++ b/arch/arm/mach-msm/include/mach/socinfo.h
@@ -32,77 +32,36 @@
 #define SOCINFO_VERSION_MINOR(ver) (ver & 0x0000ffff)
 
 #ifdef CONFIG_OF
-#define early_machine_is_msm8974()	\
-	of_flat_dt_is_compatible(of_get_flat_dt_root(), "qcom,msm8974")
-#define machine_is_msm8974()		\
-	of_machine_is_compatible("qcom,msm8974")
-#define machine_is_msm8974_sim()		\
-	of_machine_is_compatible("qcom,msm8974-sim")
-#define machine_is_msm8974_rumi()	\
-	of_machine_is_compatible("qcom,msm8974-rumi")
-#define machine_is_msm8974_fluid()	\
-	of_machine_is_compatible("qcom,msm8974-fluid")
-#define early_machine_is_msm9625()	\
-	of_flat_dt_is_compatible(of_get_flat_dt_root(), "qcom,msm9625")
-#define machine_is_msm9625()		\
-	of_machine_is_compatible("qcom,msm9625")
-#define early_machine_is_mpq8092()	\
-	of_flat_dt_is_compatible(of_get_flat_dt_root(), "qcom,mpq8092")
-#define machine_is_mpq8092_sim()           \
-	of_machine_is_compatible("qcom,mpq8092-sim")
-#define early_machine_is_msm8226()	\
-	of_flat_dt_is_compatible(of_get_flat_dt_root(), "qcom,msm8226")
-#define machine_is_msm8226()		\
-	of_machine_is_compatible("qcom,msm8226")
-#define machine_is_msm8226_sim()		\
-	of_machine_is_compatible("qcom,msm8226-sim")
-#define machine_is_msm8226_rumi()		\
-	of_machine_is_compatible("qcom,msm8226-rumi")
-#define machine_is_msm8226_cdp()		\
-	of_machine_is_compatible("qcom,msm8226-cdp")
-#define machine_is_msm8226_fluid()		\
-	of_machine_is_compatible("qcom,msm8226-fluid")
-#define machine_is_msm8226_mtp()		\
-	of_machine_is_compatible("qcom,msm8226-mtp")
-#define machine_is_msm8226_qrd()		\
-	of_machine_is_compatible("qcom,msm8226-qrd")
+#define of_board_is_sim()	of_machine_is_compatible("qcom,sim")
+#define of_board_is_rumi()	of_machine_is_compatible("qcom,rumi")
+#define of_board_is_fluid()	of_machine_is_compatible("qcom,fluid")
+#define of_board_is_liquid()	of_machine_is_compatible("qcom,liquid")
+
+#define machine_is_msm8974()	of_machine_is_compatible("qcom,msm8974")
+#define machine_is_msm9625()	of_machine_is_compatible("qcom,msm9625")
+#define machine_is_msm8610()	of_machine_is_compatible("qcom,msm8610")
+#define machine_is_msm8226()	of_machine_is_compatible("qcom,msm8226")
+
 #define early_machine_is_msm8610()	\
 	of_flat_dt_is_compatible(of_get_flat_dt_root(), "qcom,msm8610")
-#define machine_is_msm8610()		\
-	of_machine_is_compatible("qcom,msm8610")
-#define machine_is_msm8610_sim()		\
-	of_machine_is_compatible("qcom,msm8610-sim")
-#define machine_is_msm8610_rumi()		\
-	of_machine_is_compatible("qcom,msm8610-rumi")
-#define machine_is_msm8610_mtp()		\
-	of_machine_is_compatible("qcom,msm8610-mtp")
-#define machine_is_msm8610_cdp()		\
-	of_machine_is_compatible("qcom,msm8610-cdp")
+#define early_machine_is_mpq8092()	\
+	of_flat_dt_is_compatible(of_get_flat_dt_root(), "qcom,mpq8092")
 #define early_machine_is_msmzinc()	\
 	of_flat_dt_is_compatible(of_get_flat_dt_root(), "qcom,msmzinc")
-#define machine_is_msmzinc_sim()		\
-	of_machine_is_compatible("qcom,msmzinc-sim")
 #else
-#define early_machine_is_msm8974()	0
-#define machine_is_msm8974()		0
-#define machine_is_msm8974_sim()	0
-#define machine_is_msm8974_rumi()	0
-#define machine_is_msm8974_fluid()	0
-#define early_machine_is_msm9625()	0
-#define machine_is_msm9625()		0
-#define early_machine_is_mpq8092()	0
-#define machine_is_mpq8092_sim()	0
-#define early_machine_is_msm8226()	0
-#define machine_is_msm8226()		0
-#define machine_is_msm8226_sim()	0
-#define machine_is_msm8226_rumi()	0
-#define early_machine_is_msm8610()	0
-#define machine_is_msm8610()		0
-#define machine_is_msm8610_sim()	0
-#define machine_is_msm8610_rumi()	0
-#define early_machine_is_msmzinc()	0
-#define machine_is_msmzinc_sim()	0
+#define of_board_is_sim()		0
+#define of_board_is_rumi()		0
+#define of_board_is_fluid()		0
+#define of_board_is_liquid()		0
 
+#define machine_is_msm8974()		0
+#define machine_is_msm9625()		0
+#define machine_is_msm8610()		0
+#define machine_is_msm8226()		0
+
+#define early_machine_is_msm8610()	0
+#define early_machine_is_mpq8092()	0
+#define early_machine_is_msmzinc()	0
 #endif
 
 #define PLATFORM_SUBTYPE_SGLTE	6
diff --git a/arch/arm/mach-msm/include/mach/sps.h b/arch/arm/mach-msm/include/mach/sps.h
index c20576a..662655b 100644
--- a/arch/arm/mach-msm/include/mach/sps.h
+++ b/arch/arm/mach-msm/include/mach/sps.h
@@ -146,6 +146,8 @@
 	SPS_O_WRITE_NWD   = 0x00040000,
 
 	/* Options to enable software features */
+	/* Do not disable a pipe during disconnection */
+	SPS_O_NO_DISABLE      = 0x00800000,
 	/* Transfer operation should be polled */
 	SPS_O_POLL      = 0x01000000,
 	/* Disable queuing of transfer events for the connection end point */
diff --git a/arch/arm/mach-msm/include/mach/usb_bam.h b/arch/arm/mach-msm/include/mach/usb_bam.h
index 5a77d99..68313c5 100644
--- a/arch/arm/mach-msm/include/mach/usb_bam.h
+++ b/arch/arm/mach-msm/include/mach/usb_bam.h
@@ -39,6 +39,7 @@
 	SPS_PIPE_MEM = 0,	/* Default, SPS dedicated pipe memory */
 	USB_PRIVATE_MEM,	/* USB's private memory */
 	SYSTEM_MEM,		/* System RAM, requires allocation */
+	OCI_MEM,		/* Shared memory among peripherals */
 };
 
 struct usb_bam_connect_ipa_params {
@@ -119,7 +120,9 @@
  * @connections: holds all pipe connections data.
  * @usb_bam_num_pipes: max number of pipes to use.
  * @active_conn_num: number of active pipe connections.
- * @usb_base_address: BAM physical address.
+ * @usb_bam_fifo_baseaddr: base address for bam pipe's data and descriptor
+ *                         fifos. This can be on chip memory (ocimem) or usb
+ *                         private memory.
  * @ignore_core_reset_ack: BAM can ignore ACK from USB core during PIPE RESET
  * @disable_clk_gating: Disable clock gating
  */
@@ -127,7 +130,7 @@
 	struct usb_bam_pipe_connect *connections;
 	u8 max_connections;
 	int usb_bam_num_pipes;
-	u32 usb_base_address;
+	phys_addr_t usb_bam_fifo_baseaddr;
 	bool ignore_core_reset_ack;
 	bool reset_on_connect[MAX_BAMS];
 	bool disable_clk_gating;
diff --git a/arch/arm/mach-msm/iommu_domains.c b/arch/arm/mach-msm/iommu_domains.c
index a837ca1..18562a3 100644
--- a/arch/arm/mach-msm/iommu_domains.c
+++ b/arch/arm/mach-msm/iommu_domains.c
@@ -27,7 +27,6 @@
 #include <mach/iommu_domains.h>
 #include <mach/msm_iommu_priv.h>
 #include <mach/socinfo.h>
-#include <mach/msm_subsystem_map.h>
 
 struct msm_iova_data {
 	struct rb_node node;
diff --git a/arch/arm/mach-msm/ipc_socket.c b/arch/arm/mach-msm/ipc_socket.c
index f40bd5d..c0422a1 100644
--- a/arch/arm/mach-msm/ipc_socket.c
+++ b/arch/arm/mach-msm/ipc_socket.c
@@ -194,7 +194,7 @@
 static int msm_ipc_router_extract_msg(struct msghdr *m,
 				      struct sk_buff_head *msg_head)
 {
-	struct sockaddr_msm_ipc *addr = (struct sockaddr_msm_ipc *)m->msg_name;
+	struct sockaddr_msm_ipc *addr;
 	struct rr_header *hdr;
 	struct sk_buff *temp;
 	int offset = 0, data_len = 0, copy_len;
@@ -203,10 +203,11 @@
 		pr_err("%s: Invalid pointers passed\n", __func__);
 		return -EINVAL;
 	}
+	addr = (struct sockaddr_msm_ipc *)m->msg_name;
 
 	temp = skb_peek(msg_head);
 	hdr = (struct rr_header *)(temp->data);
-	if (addr || (hdr->src_port_id != IPC_ROUTER_ADDRESS)) {
+	if (addr && (hdr->src_port_id != IPC_ROUTER_ADDRESS)) {
 		addr->family = AF_MSM_IPC;
 		addr->address.addrtype = MSM_IPC_ADDR_ID;
 		addr->address.addr.port_addr.node_id = hdr->src_node_id;
diff --git a/arch/arm/mach-msm/msm_bus/msm_bus_of.c b/arch/arm/mach-msm/msm_bus/msm_bus_of.c
index 489eb5c..b9a553a 100644
--- a/arch/arm/mach-msm/msm_bus/msm_bus_of.c
+++ b/arch/arm/mach-msm/msm_bus/msm_bus_of.c
@@ -42,20 +42,9 @@
 	return -EINVAL;
 }
 
-/**
- * msm_bus_cl_get_pdata() - Generate bus client data from device tree
- * provided by clients.
- *
- * of_node: Device tree node to extract information from
- *
- * The function returns a valid pointer to the allocated bus-scale-pdata
- * if the vectors were correctly read from the client's device node.
- * Any error in reading or parsing the device node will return NULL
- * to the caller.
- */
-struct msm_bus_scale_pdata *msm_bus_cl_get_pdata(struct platform_device *pdev)
+static struct msm_bus_scale_pdata *get_pdata(struct platform_device *pdev,
+	struct device_node *of_node)
 {
-	struct device_node *of_node;
 	struct msm_bus_scale_pdata *pdata = NULL;
 	struct msm_bus_paths *usecase = NULL;
 	int i = 0, j, ret, num_usecases = 0, num_paths, len;
@@ -67,7 +56,6 @@
 		return NULL;
 	}
 
-	of_node = pdev->dev.of_node;
 	pdata = devm_kzalloc(&pdev->dev, sizeof(struct msm_bus_scale_pdata),
 		GFP_KERNEL);
 	if (!pdata) {
@@ -154,9 +142,81 @@
 
 	return NULL;
 }
+
+/**
+ * msm_bus_cl_get_pdata() - Generate bus client data from device tree
+ * provided by clients.
+ *
+ * of_node: Device tree node to extract information from
+ *
+ * The function returns a valid pointer to the allocated bus-scale-pdata
+ * if the vectors were correctly read from the client's device node.
+ * Any error in reading or parsing the device node will return NULL
+ * to the caller.
+ */
+struct msm_bus_scale_pdata *msm_bus_cl_get_pdata(struct platform_device *pdev)
+{
+	struct device_node *of_node;
+	struct msm_bus_scale_pdata *pdata = NULL;
+
+	if (!pdev) {
+		pr_err("Error: Null Platform device\n");
+		return NULL;
+	}
+
+	of_node = pdev->dev.of_node;
+	pdata = get_pdata(pdev, of_node);
+	if (!pdata) {
+		pr_err("Error getting bus pdata!\n");
+		return NULL;
+	}
+
+	return pdata;
+}
 EXPORT_SYMBOL(msm_bus_cl_get_pdata);
 
 /**
+ * msm_bus_cl_pdata_from_node() - Generate bus client data from device tree
+ * node provided by clients. This function should be used when a client
+ * driver needs to register multiple bus-clients from a single device-tree
+ * node associated with the platform-device.
+ *
+ * of_node: The subnode containing information about the bus scaling
+ * data
+ *
+ * pdev: Platform device associated with the device-tree node
+ *
+ * The function returns a valid pointer to the allocated bus-scale-pdata
+ * if the vectors were correctly read from the client's device node.
+ * Any error in reading or parsing the device node will return NULL
+ * to the caller.
+ */
+struct msm_bus_scale_pdata *msm_bus_pdata_from_node(
+		struct platform_device *pdev, struct device_node *of_node)
+{
+	struct msm_bus_scale_pdata *pdata = NULL;
+
+	if (!pdev) {
+		pr_err("Error: Null Platform device\n");
+		return NULL;
+	}
+
+	if (!of_node) {
+		pr_err("Error: Null of_node passed to bus driver\n");
+		return NULL;
+	}
+
+	pdata = get_pdata(pdev, of_node);
+	if (!pdata) {
+		pr_err("Error getting bus pdata!\n");
+		return NULL;
+	}
+
+	return pdata;
+}
+EXPORT_SYMBOL(msm_bus_pdata_from_node);
+
+/**
  * msm_bus_cl_clear_pdata() - Clear pdata allocated from device-tree
  * of_node: Device tree node to extract information from
  */
diff --git a/arch/arm/mach-msm/perf_debug.c b/arch/arm/mach-msm/perf_debug.c
index 96122de..5bf88a2 100644
--- a/arch/arm/mach-msm/perf_debug.c
+++ b/arch/arm/mach-msm/perf_debug.c
@@ -29,6 +29,7 @@
 	"4  Perf: Check perf activity on correct CPU\n"
 	"5  Perf: Add DT support for L1 and L2 PMU\n"
 	"6  Perf: Add cortex A5 device tree support\n"
+	"7  Perf: Add L1 counters to tracepoints\n"
 ;
 
 static ssize_t desc_read(struct file *fp, char __user *buf,
diff --git a/arch/arm/mach-msm/perf_trace_counters.c b/arch/arm/mach-msm/perf_trace_counters.c
new file mode 100644
index 0000000..d961994
--- /dev/null
+++ b/arch/arm/mach-msm/perf_trace_counters.c
@@ -0,0 +1,42 @@
+/* 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 <asm/thread_notify.h>
+#define CREATE_TRACE_POINTS
+#include "perf_trace_counters.h"
+
+static int tracectr_notifier(struct notifier_block *self, unsigned long cmd,
+		void *v)
+{
+	static int old_pid = -1;
+	struct thread_info *thread = v;
+	int current_pid;
+
+	if (cmd != THREAD_NOTIFY_SWITCH)
+		return old_pid;
+
+	current_pid = thread->task->pid;
+	if (old_pid != -1)
+		trace_sched_switch_with_ctrs(old_pid, current_pid);
+	old_pid = current_pid;
+	return old_pid;
+}
+
+static struct notifier_block tracectr_notifier_block = {
+	.notifier_call  = tracectr_notifier,
+};
+
+int __init init_tracecounters(void)
+{
+	thread_register_notifier(&tracectr_notifier_block);
+	return 0;
+}
+late_initcall(init_tracecounters);
diff --git a/arch/arm/mach-msm/perf_trace_counters.h b/arch/arm/mach-msm/perf_trace_counters.h
new file mode 100644
index 0000000..ce7e336
--- /dev/null
+++ b/arch/arm/mach-msm/perf_trace_counters.h
@@ -0,0 +1,127 @@
+/* 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.
+ */
+
+#undef TRACE_SYSTEM
+#define TRACE_SYSTEM perf_trace_counters
+
+#if !defined(_PERF_TRACE_COUNTERS_H_) || defined(TRACE_HEADER_MULTI_READ)
+#define _PERF_TRACE_COUNTERS_H_
+
+/* Ctr index for PMCNTENSET/CLR */
+#define CC 0x80000000
+#define C0 0x1
+#define C1 0x10
+#define C2 0x100
+#define C3 0x1000
+
+
+#include <linux/sched.h>
+#include <linux/tracepoint.h>
+
+TRACE_EVENT(sched_switch_with_ctrs,
+
+		TP_PROTO(pid_t prev, pid_t next),
+
+		TP_ARGS(prev, next),
+
+		TP_STRUCT__entry(
+			__field(pid_t,	old_pid)
+			__field(pid_t,	new_pid)
+			__field(u32, cctr)
+			__field(u32, ctr0)
+			__field(u32, ctr1)
+			__field(u32, ctr2)
+			__field(u32, ctr3)
+		),
+
+		TP_fast_assign(
+			__entry->old_pid	= prev;
+			__entry->new_pid	= next;
+
+			/* cycle counter */
+			/* Disable */
+			asm volatile("mcr p15, 0, %0, c9, c12, 2" : : "r"(CC));
+			/* Read value */
+			asm volatile("mrc p15, 0, %0, c9, c13, 0"
+				: "=r"(__entry->cctr));
+			/* Reset */
+			asm volatile("mcr p15, 0, %0, c9, c13, 0" : : "r"(0));
+			/* Enable */
+			asm volatile("mcr p15, 0, %0, c9, c12, 1" : : "r"(CC));
+
+			/* ctr 0 */
+			/* Disable */
+			asm volatile("mcr p15, 0, %0, c9, c12, 2" : : "r"(C0));
+			/* Select */
+			asm volatile("mcr p15, 0, %0, c9, c12, 5" : : "r"(0));
+			/* Read value */
+			asm volatile("mrc p15, 0, %0, c9, c13, 2"
+					: "=r"(__entry->ctr0));
+			/* Reset */
+			asm volatile("mcr p15, 0, %0, c9, c13, 2" : : "r"(0));
+			/* Enable */
+			asm volatile("mcr p15, 0, %0, c9, c12, 1" : : "r"(C0));
+
+			/* ctr 1 */
+			/* Disable */
+			asm volatile("mcr p15, 0, %0, c9, c12, 2" : : "r"(C1));
+			/* Select */
+			asm volatile("mcr p15, 0, %0, c9, c12, 5" : : "r"(1));
+			/* Read value */
+			asm volatile("mrc p15, 0, %0, c9, c13, 2"
+					: "=r"(__entry->ctr1));
+			/* Reset */
+			asm volatile("mcr p15, 0, %0, c9, c13, 2" : : "r"(0));
+			/* Enable */
+			asm volatile("mcr p15, 0, %0, c9, c12, 1" : : "r"(C1));
+
+			/* ctr 2 */
+			/* Disable */
+			asm volatile("mcr p15, 0, %0, c9, c12, 2" : : "r"(C2));
+			/* Select */
+			asm volatile("mcr p15, 0, %0, c9, c12, 5" : : "r"(2));
+			/* Read value */
+			asm volatile("mrc p15, 0, %0, c9, c13, 2"
+					: "=r"(__entry->ctr2));
+			/* Reset */
+			asm volatile("mcr p15, 0, %0, c9, c13, 2" : : "r"(0));
+			/* Enable */
+			asm volatile("mcr p15, 0, %0, c9, c12, 1" : : "r"(C2));
+
+			/* ctr 3 */
+			/* Disable */
+			asm volatile("mcr p15, 0, %0, c9, c12, 2" : : "r"(C3));
+			/* Select */
+			asm volatile("mcr p15, 0, %0, c9, c12, 5" : : "r"(3));
+			/* Read value */
+			asm volatile("mrc p15, 0, %0, c9, c13, 2"
+					: "=r"(__entry->ctr3));
+			/* Reset */
+			asm volatile("mcr p15, 0, %0, c9, c13, 2" : : "r"(0));
+			/* Enable */
+			asm volatile("mcr p15, 0, %0, c9, c12, 1" : : "r"(C3));
+
+		),
+
+		TP_printk("prev_pid=%d, next_pid=%d, CCNTR: %u, CTR0: %u," \
+				" CTR1: %u, CTR2: %u, CTR3: %u",
+				__entry->old_pid, __entry->new_pid,
+				__entry->cctr, __entry->ctr0, __entry->ctr1,
+				__entry->ctr2, __entry->ctr3)
+);
+
+#endif
+#undef TRACE_INCLUDE_PATH
+#define TRACE_INCLUDE_PATH .
+#define TRACE_INCLUDE_FILE perf_trace_counters
+#include <trace/define_trace.h>
+
diff --git a/arch/arm/mach-msm/peripheral-loader.c b/arch/arm/mach-msm/peripheral-loader.c
index 958edaf..4e8674c 100644
--- a/arch/arm/mach-msm/peripheral-loader.c
+++ b/arch/arm/mach-msm/peripheral-loader.c
@@ -29,6 +29,7 @@
 #include <linux/list.h>
 #include <linux/list_sort.h>
 #include <linux/idr.h>
+#include <linux/interrupt.h>
 
 #include <asm/uaccess.h>
 #include <asm/setup.h>
@@ -226,10 +227,21 @@
 
 		if (immediate)
 			timeout = 0;
-		schedule_delayed_work(&priv->proxy, msecs_to_jiffies(timeout));
+
+		if (!desc->proxy_unvote_irq || immediate)
+			schedule_delayed_work(&priv->proxy,
+					      msecs_to_jiffies(timeout));
 	}
 }
 
+static irqreturn_t proxy_unvote_intr_handler(int irq, void *dev_id)
+{
+	struct pil_desc *desc = dev_id;
+
+	schedule_delayed_work(&desc->priv->proxy, 0);
+	return IRQ_HANDLED;
+}
+
 static bool segment_is_relocatable(const struct elf32_phdr *p)
 {
 	return !!(p->p_flags & BIT(27));
@@ -685,13 +697,16 @@
 int pil_desc_init(struct pil_desc *desc)
 {
 	struct pil_priv *priv;
-	int id;
+	int ret;
 	void __iomem *addr;
 	char buf[sizeof(priv->info->name)];
 
 	/* Ignore users who don't make any sense */
-	WARN(desc->ops->proxy_unvote && !desc->proxy_timeout,
-			"A proxy timeout of 0 was specified.\n");
+	WARN(desc->ops->proxy_unvote && desc->proxy_unvote_irq == 0
+		 && !desc->proxy_timeout,
+		 "Invalid proxy unvote callback or a proxy timeout of 0"
+		 " was specified or no proxy unvote IRQ was specified.\n");
+
 	if (WARN(desc->ops->proxy_unvote && !desc->ops->proxy_vote,
 				"Invalid proxy voting. Ignoring\n"))
 		((struct pil_reset_ops *)desc->ops)->proxy_unvote = NULL;
@@ -702,23 +717,38 @@
 	desc->priv = priv;
 	priv->desc = desc;
 
-	priv->id = id = ida_simple_get(&pil_ida, 0, 10, GFP_KERNEL);
-	if (id < 0) {
-		kfree(priv);
-		return id;
-	}
-	addr = PIL_IMAGE_INFO_BASE + sizeof(struct pil_image_info) * id;
+	priv->id = ret = ida_simple_get(&pil_ida, 0, 10, GFP_KERNEL);
+	if (priv->id < 0)
+		goto err;
+
+	addr = PIL_IMAGE_INFO_BASE + sizeof(struct pil_image_info) * priv->id;
 	priv->info = (struct pil_image_info __iomem *)addr;
 
 	strncpy(buf, desc->name, sizeof(buf));
 	__iowrite32_copy(priv->info->name, buf, sizeof(buf) / 4);
 
+	if (desc->proxy_unvote_irq > 0) {
+		ret = request_irq(desc->proxy_unvote_irq,
+				  proxy_unvote_intr_handler,
+				  IRQF_TRIGGER_RISING|IRQF_SHARED,
+				  desc->name, desc);
+		if (ret < 0) {
+			dev_err(desc->dev,
+				"Unable to request proxy unvote IRQ: %d\n",
+				ret);
+			goto err;
+		}
+	}
+
 	snprintf(priv->wname, sizeof(priv->wname), "pil-%s", desc->name);
 	wake_lock_init(&priv->wlock, WAKE_LOCK_SUSPEND, priv->wname);
 	INIT_DELAYED_WORK(&priv->proxy, pil_proxy_work);
 	INIT_LIST_HEAD(&priv->segs);
 
 	return 0;
+err:
+	kfree(priv);
+	return ret;
 }
 EXPORT_SYMBOL(pil_desc_init);
 
diff --git a/arch/arm/mach-msm/peripheral-loader.h b/arch/arm/mach-msm/peripheral-loader.h
index c1a4167..ff10fe5 100644
--- a/arch/arm/mach-msm/peripheral-loader.h
+++ b/arch/arm/mach-msm/peripheral-loader.h
@@ -25,6 +25,8 @@
  * @proxy_timeout: delay in ms until proxy vote is removed
  * @flags: bitfield for image flags
  * @priv: DON'T USE - internal only
+ * @proxy_unvote_irq: IRQ to trigger a proxy unvote. proxy_timeout
+ * is ignored if this is set.
  */
 struct pil_desc {
 	const char *name;
@@ -35,6 +37,7 @@
 	unsigned long flags;
 #define PIL_SKIP_ENTRY_CHECK	BIT(0)
 	struct pil_priv *priv;
+	unsigned int proxy_unvote_irq;
 };
 
 /**
diff --git a/arch/arm/mach-msm/platsmp.c b/arch/arm/mach-msm/platsmp.c
index bc40130..f4ca4e3 100644
--- a/arch/arm/mach-msm/platsmp.c
+++ b/arch/arm/mach-msm/platsmp.c
@@ -282,10 +282,9 @@
 	pr_debug("Starting secondary CPU %d\n", cpu);
 
 	if (per_cpu(cold_boot_done, cpu) == false) {
-		if (machine_is_msm8974_sim() || machine_is_mpq8092_sim())
+		if (of_board_is_sim())
 			release_secondary_sim(0xf9088000, cpu);
-		else if (!machine_is_msm8974_rumi() &&
-			 !machine_is_msmzinc_sim())
+		else if (!of_board_is_rumi())
 			msm8974_release_secondary(0xf9088000, cpu);
 
 		per_cpu(cold_boot_done, cpu) = true;
@@ -298,9 +297,9 @@
 	pr_debug("Starting secondary CPU %d\n", cpu);
 
 	if (per_cpu(cold_boot_done, cpu) == false) {
-		if (machine_is_msm8226_sim() || machine_is_msm8610_sim())
+		if (of_board_is_sim())
 			release_secondary_sim(0xf9088000, cpu);
-		else if (!machine_is_msm8610_rumi())
+		else if (!of_board_is_rumi())
 			arm_release_secondary(0xf9088000, cpu);
 
 		per_cpu(cold_boot_done, cpu) = true;
diff --git a/arch/arm/mach-msm/qdsp6v2/Makefile b/arch/arm/mach-msm/qdsp6v2/Makefile
index 88de98b..88e2894 100644
--- a/arch/arm/mach-msm/qdsp6v2/Makefile
+++ b/arch/arm/mach-msm/qdsp6v2/Makefile
@@ -23,7 +23,7 @@
 obj-$(CONFIG_MSM_QDSP6_CODECS) += audio_mp3.o audio_amrnb.o audio_amrwb.o audio_amrwbplus.o audio_evrc.o audio_qcelp.o amrwb_in.o
 obj-$(CONFIG_MSM_QDSP6V2_CODECS) += aac_in.o qcelp_in.o evrc_in.o amrnb_in.o audio_utils.o
 obj-$(CONFIG_MSM_QDSP6V2_CODECS) += audio_wma.o audio_wmapro.o audio_aac.o audio_multi_aac.o audio_utils_aio.o
-obj-$(CONFIG_MSM_QDSP6V2_CODECS) += q6audio_v2.o q6audio_v2_aio.o
+obj-$(CONFIG_MSM_QDSP6V2_CODECS) += q6audio_v2.o q6audio_v2_aio.o msm_audio_ion.o
 obj-$(CONFIG_MSM_QDSP6V2_CODECS)  += audio_mp3.o audio_amrnb.o audio_amrwb.o audio_amrwbplus.o audio_evrc.o audio_qcelp.o amrwb_in.o
 obj-$(CONFIG_MSM_ADSP_LOADER) += adsp-loader.o
 obj-$(CONFIG_MSM_ULTRASOUND_A) += ultrasound/version_a/
diff --git a/arch/arm/mach-msm/qdsp6v2/audio_utils_aio.c b/arch/arm/mach-msm/qdsp6v2/audio_utils_aio.c
index e6b9549..5d744a1 100644
--- a/arch/arm/mach-msm/qdsp6v2/audio_utils_aio.c
+++ b/arch/arm/mach-msm/qdsp6v2/audio_utils_aio.c
@@ -24,6 +24,7 @@
 #include <linux/atomic.h>
 #include <asm/ioctls.h>
 #include <linux/debugfs.h>
+#include <linux/msm_audio_ion.h>
 #include "audio_utils_aio.h"
 #ifdef CONFIG_USE_DEV_CTRL_VOLUME
 #include <mach/qdsp6v2/audio_dev_ctl.h>
@@ -374,8 +375,7 @@
 	list_for_each_safe(ptr, next, &audio->ion_region_queue) {
 		region = list_entry(ptr, struct audio_aio_ion_region, list);
 		list_del(&region->list);
-		ion_unmap_kernel(audio->client, region->handle);
-		ion_free(audio->client, region->handle);
+		msm_audio_ion_free_legacy(audio->client, region->handle);
 		kfree(region);
 	}
 
@@ -557,7 +557,7 @@
 	audio_aio_disable(audio);
 	audio_aio_unmap_ion_region(audio);
 	audio_aio_reset_ion_region(audio);
-	ion_client_destroy(audio->client);
+	msm_audio_ion_client_destroy(audio->client);
 	audio->event_abort = 1;
 	wake_up(&audio->event_wait);
 	audio_aio_reset_event_queue(audio);
@@ -771,12 +771,11 @@
 {
 	ion_phys_addr_t paddr;
 	size_t len;
-	unsigned long kvaddr;
 	struct audio_aio_ion_region *region;
 	int rc = -EINVAL;
 	struct ion_handle *handle;
 	unsigned long ionflag;
-	void *temp_ptr;
+	void *kvaddr;
 
 	pr_debug("%s[%p]:\n", __func__, audio);
 	region = kmalloc(sizeof(*region), GFP_KERNEL);
@@ -786,31 +785,14 @@
 		goto end;
 	}
 
-	handle = ion_import_dma_buf(audio->client, info->fd);
-	if (IS_ERR_OR_NULL(handle)) {
-		pr_err("%s: could not get handle of the given fd\n", __func__);
+	rc = msm_audio_ion_import_legacy("Audio_Dec_Client", audio->client,
+				&handle, info->fd, &ionflag,
+				0, &paddr, &len, &kvaddr);
+	if (rc) {
+		pr_err("%s: msm audio ion alloc failed\n", __func__);
 		goto import_error;
 	}
 
-	rc = ion_handle_get_flags(audio->client, handle, &ionflag);
-	if (rc) {
-		pr_err("%s: could not get flags for the handle\n", __func__);
-		goto flag_error;
-	}
-
-	temp_ptr = ion_map_kernel(audio->client, handle);
-	if (IS_ERR_OR_NULL(temp_ptr)) {
-		pr_err("%s: could not get virtual address\n", __func__);
-		goto map_error;
-	}
-	kvaddr = (unsigned long)temp_ptr;
-
-	rc = ion_phys(audio->client, handle, &paddr, &len);
-	if (rc) {
-		pr_err("%s: could not get physical address\n", __func__);
-		goto ion_error;
-	}
-
 	rc = audio_aio_ion_check(audio, info->vaddr, len);
 	if (rc < 0) {
 		pr_err("%s: audio_aio_ion_check failed\n", __func__);
@@ -821,7 +803,7 @@
 	region->vaddr = info->vaddr;
 	region->fd = info->fd;
 	region->paddr = paddr;
-	region->kvaddr = kvaddr;
+	region->kvaddr = (unsigned long)kvaddr;
 	region->len = len;
 	region->ref_cnt = 0;
 	pr_debug("%s[%p]:add region paddr %lx vaddr %p, len %lu kvaddr %lx\n",
@@ -839,10 +821,7 @@
 mmap_error:
 	list_del(&region->list);
 ion_error:
-	ion_unmap_kernel(audio->client, handle);
-map_error:
-flag_error:
-	ion_free(audio->client, handle);
+	msm_audio_ion_free_legacy(audio->client, handle);
 import_error:
 	kfree(region);
 end:
@@ -879,8 +858,8 @@
 					__func__, audio);
 
 			list_del(&region->list);
-			ion_unmap_kernel(audio->client, region->handle);
-			ion_free(audio->client, region->handle);
+			msm_audio_ion_free_legacy(audio->client,
+						 region->handle);
 			kfree(region);
 			rc = 0;
 			break;
@@ -1167,7 +1146,8 @@
 			break;
 		}
 	}
-	audio->client = msm_ion_client_create(UINT_MAX, "Audio_Dec_Client");
+	audio->client = msm_audio_ion_client_create(UINT_MAX,
+						    "Audio_Dec_Client");
 	if (IS_ERR_OR_NULL(audio->client)) {
 		pr_err("Unable to create ION client\n");
 		rc = -EACCES;
diff --git a/arch/arm/mach-msm/qdsp6v2/msm_audio_ion.c b/arch/arm/mach-msm/qdsp6v2/msm_audio_ion.c
new file mode 100644
index 0000000..c9bc3d7
--- /dev/null
+++ b/arch/arm/mach-msm/qdsp6v2/msm_audio_ion.c
@@ -0,0 +1,326 @@
+/*
+ * Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/err.h>
+#include <linux/delay.h>
+#include <linux/platform_device.h>
+#include <mach/subsystem_restart.h>
+#include <mach/qdsp6v2/apr.h>
+#include <linux/of_device.h>
+#include <linux/msm_audio_ion.h>
+
+struct msm_audio_ion_private {
+	bool smmu_enabled;
+	/*u32 group_id;*/
+	/*u32 domain_id;*/
+};
+
+static struct msm_audio_ion_private msm_audio_ion_data = {0,};
+
+
+static int msm_audio_ion_get_phys(struct ion_client *client,
+				  struct ion_handle *handle,
+				  ion_phys_addr_t *addr, size_t *len);
+
+
+
+int msm_audio_ion_alloc(const char *name, struct ion_client **client,
+			struct ion_handle **handle, size_t bufsz,
+			ion_phys_addr_t *paddr, size_t *pa_len, void **vaddr)
+{
+	int rc = 0;
+
+	*client = msm_audio_ion_client_create(UINT_MAX, name);
+	if (IS_ERR_OR_NULL((void *)(*client))) {
+		pr_err("%s: ION create client for AUDIO failed\n", __func__);
+		goto err;
+	}
+
+	*handle = ion_alloc(*client, bufsz, SZ_4K, (0x1<<ION_AUDIO_HEAP_ID), 0);
+	if (IS_ERR_OR_NULL((void *) (*handle))) {
+		pr_err("%s: ION memory allocation for AUDIO failed\n",
+			__func__);
+		goto err_ion_client;
+	}
+
+	rc = msm_audio_ion_get_phys(*client, *handle, paddr, pa_len);
+	if (rc) {
+		pr_err("%s: ION Get Physical for AUDIO failed, rc = %d\n",
+			__func__, rc);
+		goto err_ion_handle;
+	}
+
+	/*Need to add condition SMMU enable or not */
+	*vaddr = ion_map_kernel(*client, *handle);
+	if (IS_ERR_OR_NULL((void *)*vaddr)) {
+		pr_err("%s: ION memory mapping for AUDIO failed\n", __func__);
+		goto err_ion_handle;
+	}
+
+	if (bufsz != 0)
+		memset((void *)*vaddr, 0, bufsz);
+
+	return 0;
+
+err_ion_handle:
+	ion_free(*client, *handle);
+err_ion_client:
+	msm_audio_ion_client_destroy(*client);
+err:
+	return -EINVAL;
+
+}
+
+int msm_audio_ion_import(const char *name, struct ion_client **client,
+			struct ion_handle **handle, int fd,
+			unsigned long *ionflag, size_t bufsz,
+			ion_phys_addr_t *paddr, size_t *pa_len, void **vaddr)
+{
+	int rc = 0;
+
+	*client = msm_audio_ion_client_create(UINT_MAX, name);
+	if (IS_ERR_OR_NULL((void *)(*client))) {
+		pr_err("%s: ION create client for AUDIO failed\n", __func__);
+		goto err;
+	}
+
+	/* name should be audio_acdb_client or Audio_Dec_Client,
+	bufsz should be 0 and fd shouldn't be 0 as of now
+	*/
+	*handle = ion_import_dma_buf(*client, fd);
+	pr_err("%s: DMA Buf name=%s, fd=%d handle=%p\n", __func__,
+							name, fd, *handle);
+	if (IS_ERR_OR_NULL((void *) (*handle))) {
+		pr_err("%s: ion import dma buffer failed\n",
+				__func__);
+		goto err_ion_handle;
+		}
+
+	if (ionflag != NULL) {
+		rc = ion_handle_get_flags(*client, *handle, ionflag);
+		if (rc) {
+			pr_err("%s: could not get flags for the handle\n",
+				__func__);
+			goto err_ion_handle;
+		}
+	}
+
+	rc = msm_audio_ion_get_phys(*client, *handle, paddr, pa_len);
+	if (rc) {
+		pr_err("%s: ION Get Physical for AUDIO failed, rc = %d\n",
+				__func__, rc);
+		goto err_ion_handle;
+	}
+
+	/*Need to add condition SMMU enable or not */
+	*vaddr = ion_map_kernel(*client, *handle);
+	if (IS_ERR_OR_NULL((void *)*vaddr)) {
+		pr_err("%s: ION memory mapping for AUDIO failed\n", __func__);
+		goto err_ion_handle;
+	}
+
+	if (bufsz != 0)
+		memset((void *)*vaddr, 0, bufsz);
+
+	return 0;
+
+err_ion_handle:
+	ion_free(*client, *handle);
+	msm_audio_ion_client_destroy(*client);
+err:
+	return -EINVAL;
+
+}
+
+int msm_audio_ion_free(struct ion_client *client, struct ion_handle *handle)
+{
+	/* add condition for SMMU enabled */
+	ion_unmap_kernel(client, handle);
+
+	ion_free(client, handle);
+	msm_audio_ion_client_destroy(client);
+	return 0;
+}
+
+
+bool msm_audio_ion_is_smmu_available(void)
+{
+	return msm_audio_ion_data.smmu_enabled;
+}
+
+/* move to static section again */
+struct ion_client *msm_audio_ion_client_create(unsigned int heap_mask,
+					const char *name)
+{
+	pr_debug("%s: smmu_enabled = %d\n", __func__,
+					msm_audio_ion_data.smmu_enabled);
+
+
+	return msm_ion_client_create(heap_mask, name);
+}
+
+
+void msm_audio_ion_client_destroy(struct ion_client *client)
+{
+	pr_debug("%s: smmu_enabled = %d\n", __func__,
+		msm_audio_ion_data.smmu_enabled);
+
+	ion_client_destroy(client);
+}
+
+int msm_audio_ion_import_legacy(const char *name, struct ion_client *client,
+			struct ion_handle **handle, int fd,
+			unsigned long *ionflag, size_t bufsz,
+			ion_phys_addr_t *paddr, size_t *pa_len, void **vaddr)
+{
+	int rc = 0;
+	/* client is already created for legacy and given*/
+	/* name should be audio_acdb_client or Audio_Dec_Client,
+	bufsz should be 0 and fd shouldn't be 0 as of now
+	*/
+	*handle = ion_import_dma_buf(client, fd);
+	pr_err("%s: DMA Buf name=%s, fd=%d handle=%p\n", __func__,
+							name, fd, *handle);
+	if (IS_ERR_OR_NULL((void *) (*handle))) {
+		pr_err("%s: ion import dma buffer failed\n",
+			__func__);
+		goto err_ion_handle;
+		}
+
+	if (ionflag != NULL) {
+		rc = ion_handle_get_flags(client, *handle, ionflag);
+		if (rc) {
+			pr_err("%s: could not get flags for the handle\n",
+							__func__);
+			goto err_ion_handle;
+		}
+	}
+
+	rc = msm_audio_ion_get_phys(client, *handle, paddr, pa_len);
+	if (rc) {
+		pr_err("%s: ION Get Physical for AUDIO failed, rc = %d\n",
+			__func__, rc);
+		goto err_ion_handle;
+	}
+
+	/*Need to add condition SMMU enable or not */
+	*vaddr = ion_map_kernel(client, *handle);
+	if (IS_ERR_OR_NULL((void *)*vaddr)) {
+		pr_err("%s: ION memory mapping for AUDIO failed\n", __func__);
+		goto err_ion_handle;
+	}
+
+	if (bufsz != 0)
+		memset((void *)*vaddr, 0, bufsz);
+
+	return 0;
+
+err_ion_handle:
+	ion_free(client, *handle);
+	return -EINVAL;
+
+}
+
+int msm_audio_ion_free_legacy(struct ion_client *client,
+			      struct ion_handle *handle)
+{
+	/* To add condition for SMMU enabled */
+	ion_unmap_kernel(client, handle);
+
+	ion_free(client, handle);
+	/* no client_destrody in legacy*/
+	return 0;
+}
+
+
+static int msm_audio_ion_get_phys(struct ion_client *client,
+		struct ion_handle *handle,
+		ion_phys_addr_t *addr, size_t *len)
+{
+	int rc = 0;
+	pr_debug("%s: smmu_enabled = %d\n", __func__,
+		msm_audio_ion_data.smmu_enabled);
+
+	if (msm_audio_ion_data.smmu_enabled) {
+		/* SMMU enabled case ion_map_iommu()*/
+	} else {
+		/* SMMU is disabled*/
+		rc = ion_phys(client, handle, addr, len);
+	}
+	pr_debug("%s: addr= 0x%p, len= %d\n", __func__, addr, *len);
+	return rc;
+}
+
+
+
+
+static int msm_audio_ion_probe(struct platform_device *pdev)
+{
+	int rc = 0;
+	const char *msm_audio_ion_dt = "qcom,smmu-enabled";
+	bool smmu_enabled;
+
+	if (pdev->dev.of_node == NULL) {
+		pr_err("%s: device tree is not found\n", __func__);
+		msm_audio_ion_data.smmu_enabled = 0;
+		return 0;
+	}
+
+	smmu_enabled = of_property_read_bool(pdev->dev.of_node,
+					     msm_audio_ion_dt);
+	msm_audio_ion_data.smmu_enabled = smmu_enabled;
+
+	pr_debug("%s: SMMU-Enabled = %d\n", __func__, smmu_enabled);
+	return rc;
+}
+
+static int msm_audio_ion_remove(struct platform_device *pdev)
+{
+	pr_debug("%s: msm audio ion is unloaded\n", __func__);
+
+	return 0;
+}
+
+static const struct of_device_id msm_audio_ion_dt_match[] = {
+	{ .compatible = "qcom,msm-audio-ion" },
+	{ }
+};
+MODULE_DEVICE_TABLE(of, msm_audio_ion_dt_match);
+
+static struct platform_driver msm_audio_ion_driver = {
+	.driver = {
+		.name = "msm-audio-ion",
+		.owner = THIS_MODULE,
+		.of_match_table = msm_audio_ion_dt_match,
+	},
+	.probe = msm_audio_ion_probe,
+	.remove = __devexit_p(msm_audio_ion_remove),
+};
+
+static int __init msm_audio_ion_init(void)
+{
+	return platform_driver_register(&msm_audio_ion_driver);
+}
+module_init(msm_audio_ion_init);
+
+static void __exit msm_audio_ion_exit(void)
+{
+	platform_driver_unregister(&msm_audio_ion_driver);
+}
+module_exit(msm_audio_ion_exit);
+
+MODULE_DESCRIPTION("MSM Audio ION module");
+MODULE_LICENSE("GPL v2");
diff --git a/arch/arm/mach-msm/qdsp6v2/q6core.c b/arch/arm/mach-msm/qdsp6v2/q6core.c
index f23ba67..6594b08 100644
--- a/arch/arm/mach-msm/qdsp6v2/q6core.c
+++ b/arch/arm/mach-msm/qdsp6v2/q6core.c
@@ -413,6 +413,32 @@
 	return rc;
 }
 
+uint32_t core_set_dolby_manufacturer_id(int manufacturer_id)
+{
+	struct adsp_dolby_manufacturer_id payload;
+	int rc = 0;
+	pr_debug("%s manufacturer_id :%d\n", __func__, manufacturer_id);
+	core_open();
+	if (core_handle_q) {
+		payload.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_EVENT,
+			APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
+		payload.hdr.pkt_size =
+			sizeof(struct adsp_dolby_manufacturer_id);
+		payload.hdr.src_port = 0;
+		payload.hdr.dest_port = 0;
+		payload.hdr.token = 0;
+		payload.hdr.opcode = ADSP_CMD_SET_DOLBY_MANUFACTURER_ID;
+		payload.manufacturer_id = manufacturer_id;
+		pr_debug("Send Dolby security opcode=%x manufacturer ID = %d\n",
+			payload.hdr.opcode, payload.manufacturer_id);
+		rc = apr_send_pkt(core_handle_q, (uint32_t *)&payload);
+		if (rc < 0)
+			pr_err("%s: SET_DOLBY_MANUFACTURER_ID failed op[0x%x]rc[%d]\n",
+				__func__, payload.hdr.opcode, rc);
+	}
+	return rc;
+}
+
 static const struct file_operations apr_debug_fops = {
 	.write = apr_debug_write,
 	.open = apr_debug_open,
diff --git a/arch/arm/mach-msm/rpm-regulator-smd.c b/arch/arm/mach-msm/rpm-regulator-smd.c
index 55ce4b1..923e647 100644
--- a/arch/arm/mach-msm/rpm-regulator-smd.c
+++ b/arch/arm/mach-msm/rpm-regulator-smd.c
@@ -73,6 +73,17 @@
 	RPM_REGULATOR_PARAM_MAX,
 };
 
+enum rpm_regulator_smps_mode {
+	RPM_REGULATOR_SMPS_MODE_AUTO	= 0,
+	RPM_REGULATOR_SMPS_MODE_IPEAK	= 1,
+	RPM_REGULATOR_SMPS_MODE_PWM	= 2,
+};
+
+enum rpm_regulator_ldo_mode {
+	RPM_REGULATOR_LDO_MODE_IPEAK	= 0,
+	RPM_REGULATOR_LDO_MODE_HPM	= 1,
+};
+
 #define RPM_SET_CONFIG_ACTIVE			BIT(0)
 #define RPM_SET_CONFIG_SLEEP			BIT(1)
 #define RPM_SET_CONFIG_BOTH			(RPM_SET_CONFIG_ACTIVE \
@@ -118,6 +129,20 @@
 	PARAM(FLOOR_CORNER,    1,  1,  0,  0, "vfc",  0, 6,          "qcom,init-voltage-floor-corner"),
 };
 
+struct rpm_regulator_mode_map {
+	int			ldo_mode;
+	int			smps_mode;
+};
+
+static struct rpm_regulator_mode_map mode_mapping[] = {
+	[RPM_REGULATOR_MODE_AUTO]
+		= {-1,				 RPM_REGULATOR_SMPS_MODE_AUTO},
+	[RPM_REGULATOR_MODE_IPEAK]
+		= {RPM_REGULATOR_LDO_MODE_IPEAK, RPM_REGULATOR_SMPS_MODE_IPEAK},
+	[RPM_REGULATOR_MODE_HPM]
+		= {RPM_REGULATOR_LDO_MODE_HPM,   RPM_REGULATOR_SMPS_MODE_PWM},
+};
+
 struct rpm_vreg_request {
 	u32			param[RPM_REGULATOR_PARAM_MAX];
 	u32			valid;
@@ -1077,6 +1102,71 @@
 }
 EXPORT_SYMBOL_GPL(rpm_regulator_set_voltage);
 
+/**
+ * rpm_regulator_set_mode() - set regulator operating mode
+ * @regulator: RPM regulator handle
+ * @mode: operating mode requested for the regulator
+ *
+ * Requests that the mode of the regulator be set to the mode specified.  This
+ * parameter is aggregated using a max function such that AUTO < IPEAK < HPM.
+ *
+ * Returns 0 on success or errno on failure.
+ */
+int rpm_regulator_set_mode(struct rpm_regulator *regulator,
+				enum rpm_regulator_mode mode)
+{
+	int index = 0;
+	u32 new_mode, prev_mode;
+	int rc;
+
+	rc = rpm_regulator_check_input(regulator);
+	if (rc)
+		return rc;
+
+	if (mode < 0 || mode >= ARRAY_SIZE(mode_mapping)) {
+		vreg_err(regulator, "invalid mode requested: %d\n", mode);
+		return -EINVAL;
+	}
+
+	switch (regulator->rpm_vreg->regulator_type) {
+	case RPM_REGULATOR_SMD_TYPE_SMPS:
+		index = RPM_REGULATOR_PARAM_MODE_SMPS;
+		new_mode = mode_mapping[mode].smps_mode;
+		break;
+	case RPM_REGULATOR_SMD_TYPE_LDO:
+		index = RPM_REGULATOR_PARAM_MODE_LDO;
+		new_mode = mode_mapping[mode].ldo_mode;
+		break;
+	default:
+		vreg_err(regulator, "unsupported regulator type: %d\n",
+			regulator->rpm_vreg->regulator_type);
+		return -EINVAL;
+	};
+
+	if (new_mode < params[index].min || new_mode > params[index].max) {
+		vreg_err(regulator, "invalid mode requested: %d for type: %d\n",
+			mode, regulator->rpm_vreg->regulator_type);
+		return -EINVAL;
+	}
+
+	rpm_vreg_lock(regulator->rpm_vreg);
+
+	prev_mode = regulator->req.param[index];
+	regulator->req.param[index] = new_mode;
+	regulator->req.modified |= BIT(index);
+
+	rc = rpm_vreg_aggregate_requests(regulator);
+	if (rc) {
+		vreg_err(regulator, "set mode failed, rc=%d", rc);
+		regulator->req.param[index] = prev_mode;
+	}
+
+	rpm_vreg_unlock(regulator->rpm_vreg);
+
+	return rc;
+}
+EXPORT_SYMBOL_GPL(rpm_regulator_set_mode);
+
 static struct regulator_ops ldo_ops = {
 	.enable			= rpm_vreg_enable,
 	.disable		= rpm_vreg_disable,
diff --git a/arch/arm/mach-msm/smd_tty.c b/arch/arm/mach-msm/smd_tty.c
index 8a2c23f..0b270b7 100644
--- a/arch/arm/mach-msm/smd_tty.c
+++ b/arch/arm/mach-msm/smd_tty.c
@@ -63,7 +63,6 @@
 	struct tty_port port;
 	struct device *device_ptr;
 	struct wake_lock wake_lock;
-	int open_count;
 	struct tasklet_struct tty_tsklt;
 	struct timer_list buf_req_timer;
 	struct completion ch_allocated;
@@ -333,112 +332,106 @@
 	mutex_lock(&smd_tty_lock);
 	tty->driver_data = info;
 
-	if (info->open_count++ == 0) {
-		peripheral = smd_edge_to_subsystem(smd_tty[n].smd->edge);
-		if (peripheral) {
-			info->pil = subsystem_get(peripheral);
-			if (IS_ERR(info->pil)) {
-				SMD_TTY_INFO(
-					"%s failed on smd_tty device :%s subsystem_get failed for %s",
-					__func__, smd_tty[n].smd->port_name,
-					peripheral);
-				/*
-				 * Sleep, inorder to reduce the frequency of
-				 * retry by user-space modules and to avoid
-				 * possible watchdog bite.
-				 */
-				msleep((smd_tty[n].open_wait * 1000));
-				res = PTR_ERR(info->pil);
-				goto out;
-			}
-
-			/* Wait for the modem SMSM to be inited for the SMD
-			 * Loopback channel to be allocated at the modem. Since
-			 * the wait need to be done atmost once, using msleep
-			 * doesn't degrade the performance.
-			 */
-			if (n == LOOPBACK_IDX) {
-				if (!is_modem_smsm_inited())
-					msleep(5000);
-				smsm_change_state(SMSM_APPS_STATE,
-					0, SMSM_SMD_LOOPBACK);
-				msleep(100);
-			}
-
+	peripheral = smd_edge_to_subsystem(smd_tty[n].smd->edge);
+	if (peripheral) {
+		info->pil = subsystem_get(peripheral);
+		if (IS_ERR(info->pil)) {
+			SMD_TTY_INFO(
+				"%s failed on smd_tty device :%s subsystem_get failed for %s",
+				__func__, smd_tty[n].smd->port_name,
+				peripheral);
 
 			/*
-			 * Wait for a channel to be allocated so we know
-			 * the modem is ready enough.
+			 * Sleep, inorder to reduce the frequency of
+			 * retry by user-space modules and to avoid
+			 * possible watchdog bite.
 			 */
-			if (smd_tty[n].open_wait) {
-				res = wait_for_completion_interruptible_timeout(
+			msleep((smd_tty[n].open_wait * 1000));
+			res = PTR_ERR(info->pil);
+			goto out;
+		}
+
+		/* Wait for the modem SMSM to be inited for the SMD
+		 * Loopback channel to be allocated at the modem. Since
+		 * the wait need to be done atmost once, using msleep
+		 * doesn't degrade the performance.
+		 */
+		if (n == LOOPBACK_IDX) {
+			if (!is_modem_smsm_inited())
+				msleep(5000);
+			smsm_change_state(SMSM_APPS_STATE,
+					  0, SMSM_SMD_LOOPBACK);
+			msleep(100);
+		}
+
+		/*
+		 * Wait for a channel to be allocated so we know
+		 * the modem is ready enough.
+		 */
+		if (smd_tty[n].open_wait) {
+			res = wait_for_completion_interruptible_timeout(
 					&info->ch_allocated,
 					msecs_to_jiffies(smd_tty[n].open_wait *
 									1000));
 
-				if (res == 0) {
-					SMD_TTY_INFO(
-						"Timed out waiting for SMD channel %s",
-						smd_tty[n].smd->port_name);
-					res = -ETIMEDOUT;
-					goto release_pil;
-				} else if (res < 0) {
-					SMD_TTY_INFO(
-						"Error waiting for SMD channel %s : %d\n",
-						smd_tty[n].smd->port_name, res);
-					goto release_pil;
-				}
-
-				res = 0;
-			}
-		}
-
-		tasklet_init(&info->tty_tsklt, smd_tty_read,
-			     (unsigned long)info);
-		wake_lock_init(&info->wake_lock, WAKE_LOCK_SUSPEND,
-				smd_tty[n].smd->port_name);
-		scnprintf(info->ra_wake_lock_name,
-			  MAX_RA_WAKE_LOCK_NAME_LEN,
-			  "SMD_TTY_%s_RA", smd_tty[n].smd->port_name);
-		wake_lock_init(&info->ra_wake_lock, WAKE_LOCK_SUSPEND,
-				info->ra_wake_lock_name);
-		if (!info->ch) {
-			res = smd_named_open_on_edge(smd_tty[n].smd->port_name,
-							smd_tty[n].smd->edge,
-							&info->ch, info,
-							smd_tty_notify);
-			if (res < 0) {
+			if (res == 0) {
 				SMD_TTY_INFO(
-					"%s: %s open failed %d\n",
-					__func__, smd_tty[n].smd->port_name,
-					res);
-				goto release_pil;
-			}
-
-			res = wait_event_interruptible_timeout(
-				info->ch_opened_wait_queue,
-				info->is_open, (2 * HZ));
-			if (res == 0)
+					"Timed out waiting for SMD channel %s",
+					smd_tty[n].smd->port_name);
 				res = -ETIMEDOUT;
-			if (res < 0) {
+				goto release_pil;
+			} else if (res < 0) {
 				SMD_TTY_INFO(
-					"%s: wait for %s smd_open failed %d\n",
-					__func__, smd_tty[n].smd->port_name,
-					res);
+					"Error waiting for SMD channel %s : %d\n",
+					smd_tty[n].smd->port_name, res);
 				goto release_pil;
 			}
-			res = 0;
-			SMD_TTY_INFO("%s with PID %u opened port %s",
-				current->comm, current->pid,
-				smd_tty[n].smd->port_name);
 		}
 	}
 
+	tasklet_init(&info->tty_tsklt, smd_tty_read, (unsigned long)info);
+	wake_lock_init(&info->wake_lock, WAKE_LOCK_SUSPEND,
+			smd_tty[n].smd->port_name);
+	scnprintf(info->ra_wake_lock_name, MAX_RA_WAKE_LOCK_NAME_LEN,
+		  "SMD_TTY_%s_RA", smd_tty[n].smd->port_name);
+	wake_lock_init(&info->ra_wake_lock, WAKE_LOCK_SUSPEND,
+			info->ra_wake_lock_name);
+
+	res = smd_named_open_on_edge(smd_tty[n].smd->port_name,
+				     smd_tty[n].smd->edge, &info->ch, info,
+				     smd_tty_notify);
+	if (res < 0) {
+		SMD_TTY_INFO("%s: %s open failed %d\n",
+			      __func__, smd_tty[n].smd->port_name, res);
+		goto release_wl_tl;
+	}
+
+	res = wait_event_interruptible_timeout(info->ch_opened_wait_queue,
+					       info->is_open, (2 * HZ));
+	if (res == 0)
+		res = -ETIMEDOUT;
+	if (res < 0) {
+		SMD_TTY_INFO("%s: wait for %s smd_open failed %d\n",
+			      __func__, smd_tty[n].smd->port_name, res);
+		goto close_ch;
+	}
+	SMD_TTY_INFO("%s with PID %u opened port %s",
+		      current->comm, current->pid, smd_tty[n].smd->port_name);
+	smd_disable_read_intr(info->ch);
+	mutex_unlock(&smd_tty_lock);
+	return 0;
+
+close_ch:
+	smd_close(info->ch);
+	info->ch = NULL;
+
+release_wl_tl:
+	tasklet_kill(&info->tty_tsklt);
+	wake_lock_destroy(&info->wake_lock);
+	wake_lock_destroy(&info->ra_wake_lock);
+
 release_pil:
-	if (res < 0)
-		subsystem_put(info->pil);
-	else
-		smd_disable_read_intr(info->ch);
+	subsystem_put(info->pil);
 out:
 	mutex_unlock(&smd_tty_lock);
 
@@ -458,26 +451,25 @@
 	}
 
 	mutex_lock(&smd_tty_lock);
-	if (--info->open_count == 0) {
-		spin_lock_irqsave(&info->reset_lock, flags);
-		info->is_open = 0;
-		spin_unlock_irqrestore(&info->reset_lock, flags);
-		if (tty) {
-			tasklet_kill(&info->tty_tsklt);
-			wake_lock_destroy(&info->wake_lock);
-			wake_lock_destroy(&info->ra_wake_lock);
-		}
-		SMD_TTY_INFO("%s with PID %u closed port %s",
-				current->comm, current->pid,
-				info->smd->port_name);
-		tty->driver_data = 0;
-		del_timer(&info->buf_req_timer);
-		if (info->ch) {
-			smd_close(info->ch);
-			info->ch = 0;
-			subsystem_put(info->pil);
-		}
-	}
+
+	spin_lock_irqsave(&info->reset_lock, flags);
+	info->is_open = 0;
+	spin_unlock_irqrestore(&info->reset_lock, flags);
+
+	tasklet_kill(&info->tty_tsklt);
+	wake_lock_destroy(&info->wake_lock);
+	wake_lock_destroy(&info->ra_wake_lock);
+
+	SMD_TTY_INFO("%s with PID %u closed port %s",
+			current->comm, current->pid,
+			info->smd->port_name);
+	tty->driver_data = NULL;
+	del_timer(&info->buf_req_timer);
+
+	smd_close(info->ch);
+	info->ch = NULL;
+	subsystem_put(info->pil);
+
 	mutex_unlock(&smd_tty_lock);
 	tty_kref_put(tty);
 }
diff --git a/arch/arm/mach-msm/socinfo.c b/arch/arm/mach-msm/socinfo.c
index 1f0fa85..ee6dfbf 100644
--- a/arch/arm/mach-msm/socinfo.c
+++ b/arch/arm/mach-msm/socinfo.c
@@ -845,25 +845,7 @@
 
 static void * __init setup_dummy_socinfo(void)
 {
-	if (machine_is_msm8960_cdp())
-		dummy_socinfo.id = 87;
-	else if (machine_is_msm9615_mtp() || machine_is_msm9615_cdp())
-		dummy_socinfo.id = 104;
-	else if (early_machine_is_msm8974()) {
-		dummy_socinfo.id = 126;
-		strlcpy(dummy_socinfo.build_id, "msm8974 - ",
-			sizeof(dummy_socinfo.build_id));
-	} else if (early_machine_is_msm9625()) {
-		dummy_socinfo.id = 134;
-		strlcpy(dummy_socinfo.build_id, "msm9625 - ",
-			sizeof(dummy_socinfo.build_id));
-	} else if (early_machine_is_msm8226()) {
-		dummy_socinfo.id = 145;
-		strlcpy(dummy_socinfo.build_id, "msm8226 - ",
-			sizeof(dummy_socinfo.build_id));
-	} else if (machine_is_msm8625_rumi3())
-		dummy_socinfo.id = 127;
-	else if (early_machine_is_mpq8092()) {
+	if (early_machine_is_mpq8092()) {
 		dummy_socinfo.id = 146;
 		strlcpy(dummy_socinfo.build_id, "mpq8092 - ",
 		sizeof(dummy_socinfo.build_id));
diff --git a/arch/arm/mach-msm/subsystem_map.c b/arch/arm/mach-msm/subsystem_map.c
deleted file mode 100644
index 116fc2e..0000000
--- a/arch/arm/mach-msm/subsystem_map.c
+++ /dev/null
@@ -1,555 +0,0 @@
-/* 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
- * 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/io.h>
-#include <linux/types.h>
-#include <linux/err.h>
-#include <linux/slab.h>
-#include <linux/memory_alloc.h>
-#include <linux/module.h>
-#include <mach/iommu.h>
-#include <mach/iommu_domains.h>
-#include <mach/msm_subsystem_map.h>
-
-struct msm_buffer_node {
-	struct rb_node rb_node_all_buffer;
-	struct rb_node rb_node_paddr;
-	struct msm_mapped_buffer *buf;
-	unsigned long length;
-	unsigned int *subsystems;
-	unsigned int nsubsys;
-	unsigned int phys;
-};
-
-static struct rb_root buffer_root;
-static struct rb_root phys_root;
-DEFINE_MUTEX(msm_buffer_mutex);
-
-static unsigned long subsystem_to_domain_tbl[] = {
-	VIDEO_DOMAIN,
-	VIDEO_DOMAIN,
-	CAMERA_DOMAIN,
-	DISPLAY_READ_DOMAIN,
-	DISPLAY_WRITE_DOMAIN,
-	ROTATOR_SRC_DOMAIN,
-	ROTATOR_DST_DOMAIN,
-	0xFFFFFFFF
-};
-
-static struct msm_buffer_node *find_buffer(void *key)
-{
-	struct rb_root *root = &buffer_root;
-	struct rb_node *p = root->rb_node;
-
-	mutex_lock(&msm_buffer_mutex);
-
-	while (p) {
-		struct msm_buffer_node *node;
-
-		node = rb_entry(p, struct msm_buffer_node, rb_node_all_buffer);
-		if (node->buf->vaddr) {
-			if (key < node->buf->vaddr)
-				p = p->rb_left;
-			else if (key > node->buf->vaddr)
-				p = p->rb_right;
-			else {
-				mutex_unlock(&msm_buffer_mutex);
-				return node;
-			}
-		} else {
-			if (key < (void *)node->buf)
-				p = p->rb_left;
-			else if (key > (void *)node->buf)
-				p = p->rb_right;
-			else {
-				mutex_unlock(&msm_buffer_mutex);
-				return node;
-			}
-		}
-	}
-	mutex_unlock(&msm_buffer_mutex);
-	return NULL;
-}
-
-static struct msm_buffer_node *find_buffer_phys(unsigned int phys)
-{
-	struct rb_root *root = &phys_root;
-	struct rb_node *p = root->rb_node;
-
-	mutex_lock(&msm_buffer_mutex);
-
-	while (p) {
-		struct msm_buffer_node *node;
-
-		node = rb_entry(p, struct msm_buffer_node, rb_node_paddr);
-		if (phys < node->phys)
-			p = p->rb_left;
-		else if (phys > node->phys)
-			p = p->rb_right;
-		else {
-			mutex_unlock(&msm_buffer_mutex);
-			return node;
-		}
-	}
-	mutex_unlock(&msm_buffer_mutex);
-	return NULL;
-
-}
-
-static int add_buffer(struct msm_buffer_node *node)
-{
-	struct rb_root *root = &buffer_root;
-	struct rb_node **p = &root->rb_node;
-	struct rb_node *parent = NULL;
-	void *key;
-
-	if (node->buf->vaddr)
-		key = node->buf->vaddr;
-	else
-		key = node->buf;
-
-	mutex_lock(&msm_buffer_mutex);
-	while (*p) {
-		struct msm_buffer_node *tmp;
-		parent = *p;
-
-		tmp = rb_entry(parent, struct msm_buffer_node,
-						rb_node_all_buffer);
-
-		if (tmp->buf->vaddr) {
-			if (key < tmp->buf->vaddr)
-				p = &(*p)->rb_left;
-			else if (key > tmp->buf->vaddr)
-				p = &(*p)->rb_right;
-			else {
-				WARN(1, "tried to add buffer twice! buf = %p"
-					" vaddr = %p iova = %p", tmp->buf,
-					tmp->buf->vaddr,
-					tmp->buf->iova);
-				mutex_unlock(&msm_buffer_mutex);
-				return -EINVAL;
-
-			}
-		} else {
-			if (key < (void *)tmp->buf)
-				p = &(*p)->rb_left;
-			else if (key > (void *)tmp->buf)
-				p = &(*p)->rb_right;
-			else {
-				WARN(1, "tried to add buffer twice! buf = %p"
-					" vaddr = %p iova = %p", tmp->buf,
-					tmp->buf->vaddr,
-					tmp->buf->iova);
-				mutex_unlock(&msm_buffer_mutex);
-				return -EINVAL;
-			}
-		}
-	}
-	rb_link_node(&node->rb_node_all_buffer, parent, p);
-	rb_insert_color(&node->rb_node_all_buffer, root);
-	mutex_unlock(&msm_buffer_mutex);
-	return 0;
-}
-
-static int add_buffer_phys(struct msm_buffer_node *node)
-{
-	struct rb_root *root = &phys_root;
-	struct rb_node **p = &root->rb_node;
-	struct rb_node *parent = NULL;
-
-	mutex_lock(&msm_buffer_mutex);
-	while (*p) {
-		struct msm_buffer_node *tmp;
-		parent = *p;
-
-		tmp = rb_entry(parent, struct msm_buffer_node, rb_node_paddr);
-
-			if (node->phys < tmp->phys)
-				p = &(*p)->rb_left;
-			else if (node->phys > tmp->phys)
-				p = &(*p)->rb_right;
-			else {
-				WARN(1, "tried to add buffer twice! buf = %p"
-					" vaddr = %p iova = %p", tmp->buf,
-					tmp->buf->vaddr,
-					tmp->buf->iova);
-				mutex_unlock(&msm_buffer_mutex);
-				return -EINVAL;
-
-			}
-	}
-	rb_link_node(&node->rb_node_paddr, parent, p);
-	rb_insert_color(&node->rb_node_paddr, root);
-	mutex_unlock(&msm_buffer_mutex);
-	return 0;
-}
-
-static int remove_buffer(struct msm_buffer_node *victim_node)
-{
-	struct rb_root *root = &buffer_root;
-
-	if (!victim_node)
-		return -EINVAL;
-
-	mutex_lock(&msm_buffer_mutex);
-	rb_erase(&victim_node->rb_node_all_buffer, root);
-	mutex_unlock(&msm_buffer_mutex);
-	return 0;
-}
-
-static int remove_buffer_phys(struct msm_buffer_node *victim_node)
-{
-	struct rb_root *root = &phys_root;
-
-	if (!victim_node)
-		return -EINVAL;
-
-	mutex_lock(&msm_buffer_mutex);
-	rb_erase(&victim_node->rb_node_paddr, root);
-	mutex_unlock(&msm_buffer_mutex);
-	return 0;
-}
-
-static unsigned long msm_subsystem_get_domain_no(int subsys_id)
-{
-	if (subsys_id > INVALID_SUBSYS_ID && subsys_id <= MAX_SUBSYSTEM_ID &&
-	    subsys_id < ARRAY_SIZE(subsystem_to_domain_tbl))
-		return subsystem_to_domain_tbl[subsys_id];
-	else
-		return subsystem_to_domain_tbl[MAX_SUBSYSTEM_ID];
-}
-
-static unsigned long msm_subsystem_get_partition_no(int subsys_id)
-{
-	switch (subsys_id) {
-	case MSM_SUBSYSTEM_VIDEO_FWARE:
-		return VIDEO_FIRMWARE_POOL;
-	case MSM_SUBSYSTEM_VIDEO:
-		return VIDEO_MAIN_POOL;
-	case MSM_SUBSYSTEM_CAMERA:
-	case MSM_SUBSYSTEM_DISPLAY:
-	case MSM_SUBSYSTEM_ROTATOR:
-		return GEN_POOL;
-	default:
-		return 0xFFFFFFFF;
-	}
-}
-
-phys_addr_t msm_subsystem_check_iova_mapping(int subsys_id, unsigned long iova)
-{
-	struct iommu_domain *subsys_domain;
-
-	if (!msm_use_iommu())
-		/*
-		 * If there is no iommu, Just return the iova in this case.
-		 */
-		return iova;
-
-	subsys_domain = msm_get_iommu_domain(msm_subsystem_get_domain_no
-								(subsys_id));
-	if (!subsys_domain)
-		return -EINVAL;
-
-	return iommu_iova_to_phys(subsys_domain, iova);
-}
-EXPORT_SYMBOL(msm_subsystem_check_iova_mapping);
-
-struct msm_mapped_buffer *msm_subsystem_map_buffer(unsigned long phys,
-						unsigned int length,
-						unsigned int flags,
-						int *subsys_ids,
-						unsigned int nsubsys)
-{
-	struct msm_mapped_buffer *buf, *err;
-	struct msm_buffer_node *node;
-	int i = 0, j = 0, ret;
-	unsigned long iova_start = 0, temp_phys, temp_va = 0;
-	struct iommu_domain *d = NULL;
-	int map_size = length;
-
-	if (!((flags & MSM_SUBSYSTEM_MAP_KADDR) ||
-		(flags & MSM_SUBSYSTEM_MAP_IOVA))) {
-		pr_warn("%s: no mapping flag was specified. The caller"
-			" should explicitly specify what to map in the"
-			" flags.\n", __func__);
-		err = ERR_PTR(-EINVAL);
-		goto outret;
-	}
-
-	buf = kzalloc(sizeof(*buf), GFP_ATOMIC);
-	if (!buf) {
-		err = ERR_PTR(-ENOMEM);
-		goto outret;
-	}
-
-	node = kzalloc(sizeof(*node), GFP_ATOMIC);
-	if (!node) {
-		err = ERR_PTR(-ENOMEM);
-		goto outkfreebuf;
-	}
-
-	node->phys = phys;
-
-	if (flags & MSM_SUBSYSTEM_MAP_KADDR) {
-		struct msm_buffer_node *old_buffer;
-
-		old_buffer = find_buffer_phys(phys);
-
-		if (old_buffer) {
-			WARN(1, "%s: Attempting to map %lx twice in the kernel"
-				" virtual space. Don't do that!\n", __func__,
-				phys);
-			err = ERR_PTR(-EINVAL);
-			goto outkfreenode;
-		}
-
-		if (flags & MSM_SUBSYSTEM_MAP_CACHED)
-			buf->vaddr = ioremap(phys, length);
-		else if (flags & MSM_SUBSYSTEM_MAP_KADDR)
-			buf->vaddr = ioremap_nocache(phys, length);
-		else {
-			pr_warn("%s: no cachability flag was indicated. Caller"
-				" must specify a cachability flag.\n",
-				__func__);
-			err = ERR_PTR(-EINVAL);
-			goto outkfreenode;
-		}
-
-		if (!buf->vaddr) {
-			pr_err("%s: could not ioremap\n", __func__);
-			err = ERR_PTR(-EINVAL);
-			goto outkfreenode;
-		}
-
-		if (add_buffer_phys(node)) {
-			err = ERR_PTR(-EINVAL);
-			goto outiounmap;
-		}
-	}
-
-	if ((flags & MSM_SUBSYSTEM_MAP_IOVA) && subsys_ids) {
-		int min_align;
-
-		length = round_up(length, SZ_4K);
-
-		if (flags & MSM_SUBSYSTEM_MAP_IOMMU_2X)
-			map_size = 2 * length;
-		else
-			map_size = length;
-
-		buf->iova = kzalloc(sizeof(unsigned long)*nsubsys, GFP_ATOMIC);
-		if (!buf->iova) {
-			err = ERR_PTR(-ENOMEM);
-			goto outremovephys;
-		}
-
-		/*
-		 * The alignment must be specified as the exact value wanted
-		 * e.g. 8k alignment must pass (0x2000 | other flags)
-		 */
-		min_align = flags & ~(SZ_4K - 1);
-
-		for (i = 0; i < nsubsys; i++) {
-			unsigned int domain_no, partition_no;
-
-			if (!msm_use_iommu()) {
-				buf->iova[i] = phys;
-				continue;
-			}
-
-			d = msm_get_iommu_domain(
-				msm_subsystem_get_domain_no(subsys_ids[i]));
-
-			if (!d) {
-				pr_err("%s: could not get domain for subsystem"
-					" %d\n", __func__, subsys_ids[i]);
-				continue;
-			}
-
-			domain_no = msm_subsystem_get_domain_no(subsys_ids[i]);
-			partition_no = msm_subsystem_get_partition_no(
-								subsys_ids[i]);
-
-			ret = msm_allocate_iova_address(domain_no,
-						partition_no,
-						map_size,
-						max(min_align, SZ_4K),
-						&iova_start);
-
-			if (ret) {
-				pr_err("%s: could not allocate iova address\n",
-					__func__);
-				continue;
-			}
-
-			temp_phys = phys;
-			temp_va = iova_start;
-			for (j = length; j > 0; j -= SZ_4K,
-					temp_phys += SZ_4K,
-					temp_va += SZ_4K) {
-				ret = iommu_map(d, temp_va, temp_phys,
-						SZ_4K,
-						(IOMMU_READ | IOMMU_WRITE));
-				if (ret) {
-					pr_err("%s: could not map iommu for"
-						" domain %p, iova %lx,"
-						" phys %lx\n", __func__, d,
-						temp_va, temp_phys);
-					err = ERR_PTR(-EINVAL);
-					goto outdomain;
-				}
-			}
-			buf->iova[i] = iova_start;
-
-			if (flags & MSM_SUBSYSTEM_MAP_IOMMU_2X)
-				msm_iommu_map_extra
-					(d, temp_va, phys, length, SZ_4K,
-					IOMMU_READ);
-		}
-
-	}
-
-	node->buf = buf;
-	node->subsystems = subsys_ids;
-	node->length = map_size;
-	node->nsubsys = nsubsys;
-
-	if (add_buffer(node)) {
-		err = ERR_PTR(-EINVAL);
-		goto outiova;
-	}
-
-	return buf;
-
-outiova:
-	if (flags & MSM_SUBSYSTEM_MAP_IOVA) {
-		if (d)
-			iommu_unmap(d, temp_va, SZ_4K);
-	}
-outdomain:
-	if (flags & MSM_SUBSYSTEM_MAP_IOVA) {
-		/* Unmap the rest of the current domain, i */
-		if (d) {
-			for (j -= SZ_4K, temp_va -= SZ_4K;
-				j > 0; temp_va -= SZ_4K, j -= SZ_4K)
-				iommu_unmap(d, temp_va, SZ_4K);
-		}
-		/* Unmap all the other domains */
-		for (i--; i >= 0; i--) {
-			unsigned int domain_no, partition_no;
-			if (!msm_use_iommu())
-				continue;
-			domain_no = msm_subsystem_get_domain_no(subsys_ids[i]);
-			partition_no = msm_subsystem_get_partition_no(
-								subsys_ids[i]);
-
-			d = msm_get_iommu_domain(domain_no);
-
-			if (d) {
-				temp_va = buf->iova[i];
-				for (j = length; j > 0; j -= SZ_4K,
-							temp_va += SZ_4K)
-					iommu_unmap(d, temp_va, SZ_4K);
-			}
-			msm_free_iova_address(buf->iova[i], domain_no,
-					partition_no, length);
-		}
-
-		kfree(buf->iova);
-	}
-
-outremovephys:
-	if (flags & MSM_SUBSYSTEM_MAP_KADDR)
-		remove_buffer_phys(node);
-outiounmap:
-	if (flags & MSM_SUBSYSTEM_MAP_KADDR)
-		iounmap(buf->vaddr);
-outkfreenode:
-	kfree(node);
-outkfreebuf:
-	kfree(buf);
-outret:
-	return err;
-}
-EXPORT_SYMBOL(msm_subsystem_map_buffer);
-
-int msm_subsystem_unmap_buffer(struct msm_mapped_buffer *buf)
-{
-	struct msm_buffer_node *node;
-	int i, j, ret;
-	unsigned long temp_va;
-
-	if (IS_ERR_OR_NULL(buf))
-		goto out;
-
-	if (buf->vaddr)
-		node = find_buffer(buf->vaddr);
-	else
-		node = find_buffer(buf);
-
-	if (!node)
-		goto out;
-
-	if (node->buf != buf) {
-		pr_err("%s: caller must pass in the same buffer structure"
-			" returned from map_buffer when freeding\n", __func__);
-		goto out;
-	}
-
-	if (buf->iova) {
-		if (msm_use_iommu())
-			for (i = 0; i < node->nsubsys; i++) {
-				struct iommu_domain *subsys_domain;
-				unsigned int domain_no, partition_no;
-
-				subsys_domain = msm_get_iommu_domain(
-						msm_subsystem_get_domain_no(
-						node->subsystems[i]));
-
-				if (!subsys_domain)
-					continue;
-
-				domain_no = msm_subsystem_get_domain_no(
-							node->subsystems[i]);
-				partition_no = msm_subsystem_get_partition_no(
-							node->subsystems[i]);
-
-				temp_va = buf->iova[i];
-				for (j = node->length; j > 0; j -= SZ_4K,
-					temp_va += SZ_4K) {
-					ret = iommu_unmap(subsys_domain,
-							temp_va,
-							SZ_4K);
-					WARN(ret, "iommu_unmap returned a "
-						" non-zero value.\n");
-				}
-				msm_free_iova_address(buf->iova[i], domain_no,
-						partition_no, node->length);
-			}
-		kfree(buf->iova);
-
-	}
-
-	if (buf->vaddr) {
-		remove_buffer_phys(node);
-		iounmap(buf->vaddr);
-	}
-
-	remove_buffer(node);
-	kfree(node);
-	kfree(buf);
-
-	return 0;
-out:
-	return -EINVAL;
-}
-EXPORT_SYMBOL(msm_subsystem_unmap_buffer);
diff --git a/arch/arm/mach-msm/timer.c b/arch/arm/mach-msm/timer.c
index 3144113..06a4c29 100644
--- a/arch/arm/mach-msm/timer.c
+++ b/arch/arm/mach-msm/timer.c
@@ -292,8 +292,6 @@
 
 	clock = clockevent_to_clock(evt);
 	clock_state = &__get_cpu_var(msm_clocks_percpu)[clock->index];
-	if (clock_state->stopped)
-		return 0;
 	now = msm_read_timer_count(clock, LOCAL_TIMER);
 	alarm = now + (cycles << clock->shift);
 	if (clock->flags & MSM_CLOCK_FLAGS_ODD_MATCH_WRITE)
diff --git a/arch/arm/mm/init.c b/arch/arm/mm/init.c
index 66567bb..26b92d4 100644
--- a/arch/arm/mm/init.c
+++ b/arch/arm/mm/init.c
@@ -361,7 +361,7 @@
 
 	BUG_ON(!arm_memblock_steal_permitted);
 
-	phys = memblock_alloc(size, align);
+	phys = memblock_alloc_base(size, align, MEMBLOCK_ALLOC_ANYWHERE);
 	memblock_free(phys, size);
 	memblock_remove(phys, size);
 
diff --git a/drivers/char/msm_rotator.c b/drivers/char/msm_rotator.c
index b0fb9d8..e946b42 100644
--- a/drivers/char/msm_rotator.c
+++ b/drivers/char/msm_rotator.c
@@ -32,7 +32,6 @@
 #include <mach/msm_bus.h>
 #include <mach/msm_bus_board.h>
 #endif
-#include <mach/msm_subsystem_map.h>
 #include <mach/iommu_domains.h>
 
 #define DRIVER_NAME "msm_rotator"
diff --git a/drivers/crypto/msm/qce50.c b/drivers/crypto/msm/qce50.c
index 8545a5c..ba0fd7c 100644
--- a/drivers/crypto/msm/qce50.c
+++ b/drivers/crypto/msm/qce50.c
@@ -40,7 +40,6 @@
 
 #define CRYPTO_CONFIG_RESET 0xE001F
 #define QCE_MAX_NUM_DSCR    0x400
-#define QCE_SIZE_BAM_DSCR   0x08
 #define QCE_SECTOR_SIZE	    0x200
 
 static DEFINE_MUTEX(bam_register_cnt);
@@ -1095,7 +1094,8 @@
 	 * descriptor memory (256 bytes + 8 bytes). But in order to be
 	 * in power of 2, we are allocating 512 bytes of memory.
 	 */
-	sps_connect_info->desc.size = QCE_MAX_NUM_DSCR * QCE_SIZE_BAM_DSCR;
+	sps_connect_info->desc.size = QCE_MAX_NUM_DSCR *
+					sizeof(struct sps_iovec);
 	sps_connect_info->desc.base = dma_alloc_coherent(pce_dev->pdev,
 					sps_connect_info->desc.size,
 					&sps_connect_info->desc.phys_base,
@@ -2216,12 +2216,12 @@
 	pce_dev->ce_sps.in_transfer.iovec = (struct sps_iovec *)vaddr;
 	pce_dev->ce_sps.in_transfer.iovec_phys =
 					(uint32_t)GET_PHYS_ADDR(vaddr);
-	vaddr += MAX_BAM_DESCRIPTORS * 8;
+	vaddr += QCE_MAX_NUM_DSCR * sizeof(struct sps_iovec);
 
 	pce_dev->ce_sps.out_transfer.iovec = (struct sps_iovec *)vaddr;
 	pce_dev->ce_sps.out_transfer.iovec_phys =
 					(uint32_t)GET_PHYS_ADDR(vaddr);
-	vaddr += MAX_BAM_DESCRIPTORS * 8;
+	vaddr += QCE_MAX_NUM_DSCR * sizeof(struct sps_iovec);
 
 	qce_setup_cmdlistptrs(pce_dev, &vaddr);
 	vaddr = (unsigned char *) ALIGN(((unsigned int)vaddr),
diff --git a/drivers/crypto/msm/qce50.h b/drivers/crypto/msm/qce50.h
index dc4ccf7..f5123df 100644
--- a/drivers/crypto/msm/qce50.h
+++ b/drivers/crypto/msm/qce50.h
@@ -17,7 +17,6 @@
 /* MAX Data xfer block size between BAM and CE */
 #define MAX_CE_BAM_BURST_SIZE   0x40
 #define QCEBAM_BURST_SIZE	MAX_CE_BAM_BURST_SIZE
-#define MAX_BAM_DESCRIPTORS	(0x40 - 1)
 
 #define GET_VIRT_ADDR(x)  \
 		((uint32_t)pce_dev->coh_vmem +			\
diff --git a/drivers/gpu/ion/ion_cp_heap.c b/drivers/gpu/ion/ion_cp_heap.c
index 2ef285b..7bcae01 100644
--- a/drivers/gpu/ion/ion_cp_heap.c
+++ b/drivers/gpu/ion/ion_cp_heap.c
@@ -26,7 +26,6 @@
 #include <linux/vmalloc.h>
 #include <linux/memory_alloc.h>
 #include <linux/seq_file.h>
-#include <linux/fmem.h>
 #include <linux/iommu.h>
 #include <linux/dma-mapping.h>
 #include <trace/events/kmem.h>
@@ -70,8 +69,6 @@
  *		user space.
  * @iommu_iova: saved iova when mapping full heap at once.
  * @iommu_partition: partition used to map full heap.
- * @reusable: indicates if the memory should be reused via fmem.
- * @reserved_vrange: reserved virtual address range for use with fmem
  * @iommu_map_all:	Indicates whether we should map whole heap into IOMMU.
  * @iommu_2x_map_domain: Indicates the domain to use for overmapping.
  * @has_outer_cache:    set to 1 if outer cache is used, 0 otherwise.
@@ -95,7 +92,6 @@
 	unsigned long umap_count;
 	unsigned long iommu_iova[MAX_DOMAINS];
 	unsigned long iommu_partition[MAX_DOMAINS];
-	int reusable;
 	void *reserved_vrange;
 	int iommu_map_all;
 	int iommu_2x_map_domain;
@@ -198,12 +194,6 @@
 		container_of(heap, struct ion_cp_heap, heap);
 	int ret_value;
 
-	if (cp_heap->reusable) {
-		ret_value = fmem_set_state(FMEM_C_STATE);
-		if (ret_value)
-			return 1;
-	}
-
 	if (cp_heap->cma) {
 		ret_value = allocate_heap_memory(heap);
 		if (ret_value)
@@ -217,11 +207,6 @@
 	struct ion_cp_heap *cp_heap =
 		container_of(heap, struct ion_cp_heap, heap);
 
-	if (cp_heap->reusable)
-		if (fmem_set_state(FMEM_T_STATE) != 0)
-			pr_err("%s: unable to transition heap to T-state\n",
-				__func__);
-
 	if (cp_heap->cma)
 		free_heap_memory(heap);
 }
@@ -549,29 +534,6 @@
 	return ret_value;
 }
 
-void *ion_map_fmem_buffer(struct ion_buffer *buffer, unsigned long phys_base,
-				void *virt_base, unsigned long flags)
-{
-	int ret;
-	struct ion_cp_buffer *buf = buffer->priv_virt;
-	unsigned int offset = buf->buffer - phys_base;
-	unsigned long start = ((unsigned long)virt_base) + offset;
-	const struct mem_type *type = ION_IS_CACHED(flags) ?
-				get_mem_type(MT_DEVICE_CACHED) :
-				get_mem_type(MT_DEVICE);
-
-	if (phys_base > buf->buffer)
-		return NULL;
-
-
-	ret = ioremap_pages(start, buf->buffer, buffer->size, type);
-
-	if (!ret)
-		return (void *)start;
-	else
-		return NULL;
-}
-
 void *ion_cp_heap_map_kernel(struct ion_heap *heap, struct ion_buffer *buffer)
 {
 	struct ion_cp_heap *cp_heap =
@@ -589,10 +551,7 @@
 			return NULL;
 		}
 
-		if (cp_heap->reusable) {
-			ret_value = ion_map_fmem_buffer(buffer, cp_heap->base,
-				cp_heap->reserved_vrange, buffer->flags);
-		} else if (cp_heap->cma) {
+		if (cp_heap->cma) {
 			int npages = PAGE_ALIGN(buffer->size) / PAGE_SIZE;
 			struct page **pages = vmalloc(
 						sizeof(struct page *) * npages);
@@ -645,9 +604,7 @@
 		container_of(heap, struct ion_cp_heap, heap);
 	struct ion_cp_buffer *buf = buffer->priv_virt;
 
-	if (cp_heap->reusable)
-		unmap_kernel_range((unsigned long)buffer->vaddr, buffer->size);
-	else if (cp_heap->cma)
+	if (cp_heap->cma)
 		vunmap(buffer->vaddr);
 	else
 		__arm_iounmap(buffer->vaddr);
@@ -826,7 +783,6 @@
 	seq_printf(s, "umapping count: %lx\n", umap_count);
 	seq_printf(s, "kmapping count: %lx\n", kmap_count);
 	seq_printf(s, "heap protected: %s\n", heap_protected ? "Yes" : "No");
-	seq_printf(s, "reusable: %s\n", cp_heap->reusable  ? "Yes" : "No");
 
 	if (mem_map) {
 		unsigned long base = cp_heap->base;
@@ -1151,8 +1107,6 @@
 	if (heap_data->extra_data) {
 		struct ion_cp_heap_pdata *extra_data =
 				heap_data->extra_data;
-		cp_heap->reusable = extra_data->reusable;
-		cp_heap->reserved_vrange = extra_data->virt_addr;
 		cp_heap->permission_type = extra_data->permission_type;
 		if (extra_data->secure_size) {
 			cp_heap->secure_base = extra_data->secure_base;
diff --git a/drivers/gpu/ion/ion_heap.c b/drivers/gpu/ion/ion_heap.c
index 46fefb5..510b9ce 100644
--- a/drivers/gpu/ion/ion_heap.c
+++ b/drivers/gpu/ion/ion_heap.c
@@ -18,13 +18,12 @@
 #include <linux/err.h>
 #include <linux/ion.h>
 #include "ion_priv.h"
-#include <linux/msm_ion.h>
 
 struct ion_heap *ion_heap_create(struct ion_platform_heap *heap_data)
 {
 	struct ion_heap *heap = NULL;
 
-	switch ((int) heap_data->type) {
+	switch (heap_data->type) {
 	case ION_HEAP_TYPE_SYSTEM_CONTIG:
 		heap = ion_system_contig_heap_create(heap_data);
 		break;
@@ -34,21 +33,6 @@
 	case ION_HEAP_TYPE_CARVEOUT:
 		heap = ion_carveout_heap_create(heap_data);
 		break;
-	case ION_HEAP_TYPE_IOMMU:
-		heap = ion_iommu_heap_create(heap_data);
-		break;
-	case ION_HEAP_TYPE_CP:
-		heap = ion_cp_heap_create(heap_data);
-		break;
-#ifdef CONFIG_CMA
-	case ION_HEAP_TYPE_DMA:
-		heap = ion_cma_heap_create(heap_data);
-		break;
-
-	case ION_HEAP_TYPE_SECURE_DMA:
-		heap = ion_secure_cma_heap_create(heap_data);
-		break;
-#endif
 	default:
 		pr_err("%s: Invalid heap type %d\n", __func__,
 		       heap_data->type);
@@ -73,7 +57,7 @@
 	if (!heap)
 		return;
 
-	switch ((int) heap->type) {
+	switch (heap->type) {
 	case ION_HEAP_TYPE_SYSTEM_CONTIG:
 		ion_system_contig_heap_destroy(heap);
 		break;
@@ -83,20 +67,6 @@
 	case ION_HEAP_TYPE_CARVEOUT:
 		ion_carveout_heap_destroy(heap);
 		break;
-	case ION_HEAP_TYPE_IOMMU:
-		ion_iommu_heap_destroy(heap);
-		break;
-	case ION_HEAP_TYPE_CP:
-		ion_cp_heap_destroy(heap);
-		break;
-#ifdef CONFIG_CMA
-	case ION_HEAP_TYPE_DMA:
-		ion_cma_heap_destroy(heap);
-		break;
-	case ION_HEAP_TYPE_SECURE_DMA:
-		ion_secure_cma_heap_destroy(heap);
-		break;
-#endif
 	default:
 		pr_err("%s: Invalid heap type %d\n", __func__,
 		       heap->type);
diff --git a/drivers/gpu/ion/ion_iommu_heap.c b/drivers/gpu/ion/ion_iommu_heap.c
index 9ab6b85..512ebf3 100644
--- a/drivers/gpu/ion/ion_iommu_heap.c
+++ b/drivers/gpu/ion/ion_iommu_heap.c
@@ -76,10 +76,14 @@
 		if (max_order < orders[i])
 			continue;
 
-		gfp = GFP_KERNEL | __GFP_HIGHMEM | __GFP_COMP;
-		if (orders[i])
-			gfp |= __GFP_NOWARN;
+		gfp = __GFP_HIGHMEM;
 
+		if (orders[i]) {
+			gfp |= __GFP_COMP | __GFP_NORETRY |
+			       __GFP_NO_KSWAPD | __GFP_NOWARN;
+		} else {
+			gfp |= GFP_KERNEL;
+		}
 		page = alloc_pages(gfp, orders[i]);
 		if (!page)
 			continue;
diff --git a/drivers/gpu/ion/msm/ion_cp_common.c b/drivers/gpu/ion/msm/ion_cp_common.c
index 48c2efb..7d54cfa 100644
--- a/drivers/gpu/ion/msm/ion_cp_common.c
+++ b/drivers/gpu/ion/msm/ion_cp_common.c
@@ -1,6 +1,6 @@
 /*
  * Copyright (C) 2011 Google, Inc
- * Copyright (c) 2011-2012, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2011-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -20,6 +20,7 @@
 #include "ion_cp_common.h"
 
 #define MEM_PROTECT_LOCK_ID	0x05
+#define MEM_PROTECT_LOCK_ID2 0x0A
 
 struct cp2_mem_chunks {
 	unsigned int *chunk_list;
@@ -27,10 +28,11 @@
 	unsigned int chunk_size;
 } __attribute__ ((__packed__));
 
-struct cp2_lock_req {
+struct cp2_lock2_req {
 	struct cp2_mem_chunks chunks;
 	unsigned int mem_usage;
 	unsigned int lock;
+	unsigned int flags;
 } __attribute__ ((__packed__));
 
 /*  SCM related code for locking down memory for content protection */
@@ -144,17 +146,18 @@
 				enum cp_mem_usage usage,
 				int lock)
 {
-	struct cp2_lock_req request;
+	struct cp2_lock2_req request;
 	u32 resp;
 
 	request.mem_usage = usage;
 	request.lock = lock;
+	request.flags = 0;
 
 	request.chunks.chunk_list = (unsigned int *)chunks;
 	request.chunks.chunk_list_size = nchunks;
 	request.chunks.chunk_size = chunk_size;
 
-	return scm_call(SCM_SVC_MP, MEM_PROTECT_LOCK_ID,
+	return scm_call(SCM_SVC_MP, MEM_PROTECT_LOCK_ID2,
 			&request, sizeof(request), &resp, sizeof(resp));
 
 }
diff --git a/drivers/gpu/ion/msm/msm_ion.c b/drivers/gpu/ion/msm/msm_ion.c
index 33e6fed..4b55875 100644
--- a/drivers/gpu/ion/msm/msm_ion.c
+++ b/drivers/gpu/ion/msm/msm_ion.c
@@ -750,6 +750,68 @@
 	return 0;
 }
 
+static struct ion_heap *msm_ion_heap_create(struct ion_platform_heap *heap_data)
+{
+	struct ion_heap *heap = NULL;
+
+	switch ((int)heap_data->type) {
+	case ION_HEAP_TYPE_IOMMU:
+		heap = ion_iommu_heap_create(heap_data);
+		break;
+	case ION_HEAP_TYPE_CP:
+		heap = ion_cp_heap_create(heap_data);
+		break;
+#ifdef CONFIG_CMA
+	case ION_HEAP_TYPE_DMA:
+		heap = ion_cma_heap_create(heap_data);
+		break;
+
+	case ION_HEAP_TYPE_SECURE_DMA:
+		heap = ion_secure_cma_heap_create(heap_data);
+		break;
+#endif
+	default:
+		heap = ion_heap_create(heap_data);
+	}
+
+	if (IS_ERR_OR_NULL(heap)) {
+		pr_err("%s: error creating heap %s type %d base %pa size %u\n",
+		       __func__, heap_data->name, heap_data->type,
+		       &heap_data->base, heap_data->size);
+		return ERR_PTR(-EINVAL);
+	}
+
+	heap->name = heap_data->name;
+	heap->id = heap_data->id;
+	heap->priv = heap_data->priv;
+	return heap;
+}
+
+static void msm_ion_heap_destroy(struct ion_heap *heap)
+{
+	if (!heap)
+		return;
+
+	switch ((int)heap->type) {
+	case ION_HEAP_TYPE_IOMMU:
+		ion_iommu_heap_destroy(heap);
+		break;
+	case ION_HEAP_TYPE_CP:
+		ion_cp_heap_destroy(heap);
+		break;
+#ifdef CONFIG_CMA
+	case ION_HEAP_TYPE_DMA:
+		ion_cma_heap_destroy(heap);
+		break;
+	case ION_HEAP_TYPE_SECURE_DMA:
+		ion_secure_cma_heap_destroy(heap);
+		break;
+#endif
+	default:
+		ion_heap_destroy(heap);
+	}
+}
+
 static int msm_ion_probe(struct platform_device *pdev)
 {
 	struct ion_platform_data *pdata;
@@ -791,7 +853,7 @@
 		msm_ion_allocate(heap_data);
 
 		heap_data->has_outer_cache = pdata->has_outer_cache;
-		heaps[i] = ion_heap_create(heap_data);
+		heaps[i] = msm_ion_heap_create(heap_data);
 		if (IS_ERR_OR_NULL(heaps[i])) {
 			heaps[i] = 0;
 			continue;
@@ -829,7 +891,7 @@
 	int i;
 
 	for (i = 0; i < num_heaps; i++)
-		ion_heap_destroy(heaps[i]);
+		msm_ion_heap_destroy(heaps[i]);
 
 	ion_device_destroy(idev);
 	kfree(heaps);
diff --git a/drivers/gpu/msm/adreno.c b/drivers/gpu/msm/adreno.c
index 6f7e61d..62b6a71 100644
--- a/drivers/gpu/msm/adreno.c
+++ b/drivers/gpu/msm/adreno.c
@@ -1603,6 +1603,8 @@
 	int status = -EINVAL;
 	struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
 
+	kgsl_cffdump_open(device);
+
 	if (KGSL_STATE_DUMP_AND_FT != device->state)
 		kgsl_pwrctrl_set_state(device, KGSL_STATE_INIT);
 
@@ -1686,6 +1688,8 @@
 	/* Power down the device */
 	kgsl_pwrctrl_disable(device);
 
+	kgsl_cffdump_close(device->id);
+
 	return 0;
 }
 
@@ -1768,6 +1772,8 @@
 			start_ptr = adreno_ringbuffer_dec_wrapped(start_ptr,
 									size);
 		kgsl_sharedmem_readl(&rb->buffer_desc, &val1, start_ptr);
+		/* Ensure above read is finished before next read */
+		rmb();
 		if (KGSL_CMD_IDENTIFIER == val1) {
 			if ((start_ptr / sizeof(unsigned int)) != rb->wptr)
 				start_ptr = adreno_ringbuffer_dec_wrapped(
@@ -1805,6 +1811,8 @@
 					temp_rb_rptr, size);
 		kgsl_sharedmem_readl(&rb->buffer_desc, &val[i],
 					temp_rb_rptr);
+		/* Ensure above read is finished before next read */
+		rmb();
 
 		if (check && ((inc && val[i] == global_eop) ||
 			(!inc && (val[i] ==
@@ -1869,6 +1877,8 @@
 
 	while (temp_rb_rptr / sizeof(unsigned int) != rb->wptr) {
 		kgsl_sharedmem_readl(&rb->buffer_desc, &val[i], temp_rb_rptr);
+		/* Ensure above read is finished before next read */
+		rmb();
 
 		if (check && val[i] == ib1) {
 			/* decrement i, i.e i = (i - 1 + 2) % 2 */
@@ -1935,6 +1945,9 @@
 			KGSL_MEMSTORE_OFFSET(KGSL_MEMSTORE_GLOBAL,
 			eoptimestamp));
 
+	/* Ensure context id and global eop ts read complete */
+	rmb();
+
 	ft_data->rb_buffer = vmalloc(rb->buffer_desc.size);
 	if (!ft_data->rb_buffer) {
 		KGSL_MEM_ERR(device, "vmalloc(%d) failed\n",
@@ -2012,6 +2025,8 @@
 			&curr_global_ts,
 			KGSL_MEMSTORE_OFFSET(KGSL_MEMSTORE_GLOBAL,
 			eoptimestamp));
+	/* Ensure above read is finished before long ib check */
+	rmb();
 
 	/* Mark long ib as handled */
 	adreno_dev->long_ib = 0;
diff --git a/drivers/gpu/msm/adreno_a2xx.c b/drivers/gpu/msm/adreno_a2xx.c
index 335d407..dd9bdc3 100644
--- a/drivers/gpu/msm/adreno_a2xx.c
+++ b/drivers/gpu/msm/adreno_a2xx.c
@@ -1515,18 +1515,26 @@
 			"Current active context has caused gpu hang\n");
 
 	if (!(context->flags & CTXT_FLAGS_PREAMBLE)) {
-
+		kgsl_cffdump_syncmem(NULL, &context->gpustate,
+			context->reg_save[1],
+			context->reg_save[2] << 2, true);
 		/* save registers and constants. */
 		adreno_ringbuffer_issuecmds(device, context,
 			KGSL_CMD_FLAGS_NONE,
 			context->reg_save, 3);
 
 		if (context->flags & CTXT_FLAGS_SHADER_SAVE) {
+			kgsl_cffdump_syncmem(NULL, &context->gpustate,
+				context->shader_save[1],
+				context->shader_save[2] << 2, true);
 			/* save shader partitioning and instructions. */
 			adreno_ringbuffer_issuecmds(device, context,
 				KGSL_CMD_FLAGS_PMODE,
 				context->shader_save, 3);
 
+			kgsl_cffdump_syncmem(NULL, &context->gpustate,
+				context->shader_fixup[1],
+				context->shader_fixup[2] << 2, true);
 			/*
 			 * fixup shader partitioning parameter for
 			 *  SET_SHADER_BASES.
@@ -1541,6 +1549,9 @@
 
 	if ((context->flags & CTXT_FLAGS_GMEM_SAVE) &&
 	    (context->flags & CTXT_FLAGS_GMEM_SHADOW)) {
+		kgsl_cffdump_syncmem(NULL, &context->gpustate,
+			context->context_gmem_shadow.gmem_save[1],
+			context->context_gmem_shadow.gmem_save[2] << 2, true);
 		/* save gmem.
 		 * (note: changes shader. shader must already be saved.)
 		 */
@@ -1548,6 +1559,10 @@
 			KGSL_CMD_FLAGS_PMODE,
 			context->context_gmem_shadow.gmem_save, 3);
 
+		kgsl_cffdump_syncmem(NULL, &context->gpustate,
+			context->chicken_restore[1],
+			context->chicken_restore[2] << 2, true);
+
 		/* Restore TP0_CHICKEN */
 		if (!(context->flags & CTXT_FLAGS_PREAMBLE)) {
 			adreno_ringbuffer_issuecmds(device, context,
@@ -1584,21 +1599,24 @@
 					cmds, 5);
 	kgsl_mmu_setstate(&device->mmu, context->pagetable, context->id);
 
-#ifndef CONFIG_MSM_KGSL_CFF_DUMP_NO_CONTEXT_MEM_DUMP
-	kgsl_cffdump_syncmem(NULL, &context->gpustate,
-		context->gpustate.gpuaddr, LCC_SHADOW_SIZE +
-		REG_SHADOW_SIZE + CMD_BUFFER_SIZE + TEX_SHADOW_SIZE, false);
-#endif
-
 	/* restore gmem.
 	 *  (note: changes shader. shader must not already be restored.)
 	 */
 	if (context->flags & CTXT_FLAGS_GMEM_RESTORE) {
+		kgsl_cffdump_syncmem(NULL, &context->gpustate,
+			context->context_gmem_shadow.gmem_restore[1],
+			context->context_gmem_shadow.gmem_restore[2] << 2,
+			true);
+
 		adreno_ringbuffer_issuecmds(device, context,
 			KGSL_CMD_FLAGS_PMODE,
 			context->context_gmem_shadow.gmem_restore, 3);
 
 		if (!(context->flags & CTXT_FLAGS_PREAMBLE)) {
+			kgsl_cffdump_syncmem(NULL, &context->gpustate,
+				context->chicken_restore[1],
+				context->chicken_restore[2] << 2, true);
+
 			/* Restore TP0_CHICKEN */
 			adreno_ringbuffer_issuecmds(device, context,
 				KGSL_CMD_FLAGS_NONE,
@@ -1609,6 +1627,9 @@
 	}
 
 	if (!(context->flags & CTXT_FLAGS_PREAMBLE)) {
+		kgsl_cffdump_syncmem(NULL, &context->gpustate,
+			context->reg_restore[1],
+			context->reg_restore[2] << 2, true);
 
 		/* restore registers and constants. */
 		adreno_ringbuffer_issuecmds(device, context,
@@ -1616,6 +1637,10 @@
 
 		/* restore shader instructions & partitioning. */
 		if (context->flags & CTXT_FLAGS_SHADER_RESTORE) {
+			kgsl_cffdump_syncmem(NULL, &context->gpustate,
+				context->shader_restore[1],
+				context->shader_restore[2] << 2, true);
+
 			adreno_ringbuffer_issuecmds(device, context,
 				KGSL_CMD_FLAGS_NONE,
 				context->shader_restore, 3);
@@ -1815,14 +1840,14 @@
 static unsigned int a2xx_irq_pending(struct adreno_device *adreno_dev)
 {
 	struct kgsl_device *device = &adreno_dev->dev;
-	unsigned int rbbm, cp, mh;
+	unsigned int status;
 
-	adreno_regread(device, REG_RBBM_INT_CNTL, &rbbm);
-	adreno_regread(device, REG_CP_INT_CNTL, &cp);
-	adreno_regread(device, MH_INTERRUPT_MASK, &mh);
+	adreno_regread(device, REG_MASTER_INT_SIGNAL, &status);
 
-	return ((rbbm & RBBM_INT_MASK) || (cp & CP_INT_MASK) ||
-		(mh & kgsl_mmu_get_int_mask())) ? 1 : 0;
+	return (status &
+		(MASTER_INT_SIGNAL__MH_INT_STAT |
+		 MASTER_INT_SIGNAL__CP_INT_STAT |
+		 MASTER_INT_SIGNAL__RBBM_INT_STAT)) ? 1 : 0;
 }
 
 static int a2xx_rb_init(struct adreno_device *adreno_dev,
diff --git a/drivers/gpu/msm/adreno_a3xx.c b/drivers/gpu/msm/adreno_a3xx.c
index 19d9ca2..13c723a 100644
--- a/drivers/gpu/msm/adreno_a3xx.c
+++ b/drivers/gpu/msm/adreno_a3xx.c
@@ -2419,6 +2419,11 @@
 		 * already be saved.)
 		 */
 
+		kgsl_cffdump_syncmem(NULL,
+			&context->gpustate,
+			context->context_gmem_shadow.gmem_save[1],
+			context->context_gmem_shadow.gmem_save[2] << 2, true);
+
 		adreno_ringbuffer_issuecmds(device, context,
 					KGSL_CMD_FLAGS_PMODE,
 					    context->context_gmem_shadow.
@@ -2456,6 +2461,12 @@
 	 */
 
 	if (context->flags & CTXT_FLAGS_GMEM_RESTORE) {
+		kgsl_cffdump_syncmem(NULL,
+			&context->gpustate,
+			context->context_gmem_shadow.gmem_restore[1],
+			context->context_gmem_shadow.gmem_restore[2] << 2,
+			true);
+
 		adreno_ringbuffer_issuecmds(device, context,
 					KGSL_CMD_FLAGS_PMODE,
 					    context->context_gmem_shadow.
diff --git a/drivers/gpu/msm/adreno_drawctxt.c b/drivers/gpu/msm/adreno_drawctxt.c
index 023b057..176717d 100644
--- a/drivers/gpu/msm/adreno_drawctxt.c
+++ b/drivers/gpu/msm/adreno_drawctxt.c
@@ -12,6 +12,7 @@
  */
 
 #include <linux/slab.h>
+#include <linux/msm_kgsl.h>
 
 #include "kgsl.h"
 #include "kgsl_sharedmem.h"
@@ -143,7 +144,7 @@
  */
 int adreno_drawctxt_create(struct kgsl_device *device,
 			struct kgsl_pagetable *pagetable,
-			struct kgsl_context *context, uint32_t flags)
+			struct kgsl_context *context, uint32_t *flags)
 {
 	struct adreno_context *drawctxt;
 	struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
@@ -162,26 +163,36 @@
 	drawctxt->id = context->id;
 	rb->timestamp[context->id] = 0;
 
-	if (flags & KGSL_CONTEXT_PREAMBLE)
+	*flags &= (KGSL_CONTEXT_PREAMBLE |
+		KGSL_CONTEXT_NO_GMEM_ALLOC |
+		KGSL_CONTEXT_PER_CONTEXT_TS |
+		KGSL_CONTEXT_USER_GENERATED_TS |
+		KGSL_CONTEXT_NO_FAULT_TOLERANCE |
+		KGSL_CONTEXT_TYPE_MASK);
+
+	if (*flags & KGSL_CONTEXT_PREAMBLE)
 		drawctxt->flags |= CTXT_FLAGS_PREAMBLE;
 
-	if (flags & KGSL_CONTEXT_NO_GMEM_ALLOC)
+	if (*flags & KGSL_CONTEXT_NO_GMEM_ALLOC)
 		drawctxt->flags |= CTXT_FLAGS_NOGMEMALLOC;
 
-	if (flags & KGSL_CONTEXT_PER_CONTEXT_TS)
+	if (*flags & KGSL_CONTEXT_PER_CONTEXT_TS)
 		drawctxt->flags |= CTXT_FLAGS_PER_CONTEXT_TS;
 
-	if (flags & KGSL_CONTEXT_USER_GENERATED_TS) {
-		if (!(flags & KGSL_CONTEXT_PER_CONTEXT_TS)) {
+	if (*flags & KGSL_CONTEXT_USER_GENERATED_TS) {
+		if (!(*flags & KGSL_CONTEXT_PER_CONTEXT_TS)) {
 			ret = -EINVAL;
 			goto err;
 		}
 		drawctxt->flags |= CTXT_FLAGS_USER_GENERATED_TS;
 	}
 
-	if (flags & KGSL_CONTEXT_NO_FAULT_TOLERANCE)
+	if (*flags & KGSL_CONTEXT_NO_FAULT_TOLERANCE)
 		drawctxt->flags |= CTXT_FLAGS_NO_FAULT_TOLERANCE;
 
+	drawctxt->type =
+		(*flags & KGSL_CONTEXT_TYPE_MASK) >> KGSL_CONTEXT_TYPE_SHIFT;
+
 	ret = adreno_dev->gpudev->ctxt_create(adreno_dev, drawctxt);
 	if (ret)
 		goto err;
diff --git a/drivers/gpu/msm/adreno_drawctxt.h b/drivers/gpu/msm/adreno_drawctxt.h
index aba29ae..f0f3b6b 100644
--- a/drivers/gpu/msm/adreno_drawctxt.h
+++ b/drivers/gpu/msm/adreno_drawctxt.h
@@ -57,6 +57,14 @@
 /* Context no fault tolerance */
 #define CTXT_FLAGS_NO_FAULT_TOLERANCE  BIT(16)
 
+/* Symbolic table for the adreno draw context type */
+#define ADRENO_DRAWCTXT_TYPES \
+	{ KGSL_CONTEXT_TYPE_ANY, "any" }, \
+	{ KGSL_CONTEXT_TYPE_GL, "GL" }, \
+	{ KGSL_CONTEXT_TYPE_CL, "CL" }, \
+	{ KGSL_CONTEXT_TYPE_C2D, "C2D" }, \
+	{ KGSL_CONTEXT_TYPE_RS, "RS" }
+
 struct kgsl_device;
 struct adreno_device;
 struct kgsl_device_private;
@@ -95,6 +103,7 @@
 	uint32_t flags;
 	uint32_t pagefault;
 	unsigned long pagefault_ts;
+	unsigned int type;
 	struct kgsl_pagetable *pagetable;
 	struct kgsl_memdesc gpustate;
 	unsigned int reg_restore[3];
@@ -127,7 +136,7 @@
 int adreno_drawctxt_create(struct kgsl_device *device,
 			struct kgsl_pagetable *pagetable,
 			struct kgsl_context *context,
-			uint32_t flags);
+			uint32_t *flags);
 
 void adreno_drawctxt_destroy(struct kgsl_device *device,
 			  struct kgsl_context *context);
diff --git a/drivers/gpu/msm/adreno_ringbuffer.c b/drivers/gpu/msm/adreno_ringbuffer.c
index 8c23a13..a4bb4fa 100644
--- a/drivers/gpu/msm/adreno_ringbuffer.c
+++ b/drivers/gpu/msm/adreno_ringbuffer.c
@@ -18,6 +18,7 @@
 #include "kgsl.h"
 #include "kgsl_sharedmem.h"
 #include "kgsl_cffdump.h"
+#include "kgsl_trace.h"
 
 #include "adreno.h"
 #include "adreno_pm4types.h"
@@ -592,6 +593,9 @@
 	if (adreno_is_a20x(adreno_dev))
 		total_sizedwords += 2; /* CACHE_FLUSH */
 
+	if (flags & KGSL_CMD_FLAGS_EOF)
+		total_sizedwords += 2;
+
 	ringcmds = adreno_ringbuffer_allocspace(rb, context, total_sizedwords);
 	if (!ringcmds) {
 		/*
@@ -986,26 +990,31 @@
 {
 	struct kgsl_device *device = dev_priv->device;
 	struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
-	unsigned int *link;
+	unsigned int *link = 0;
 	unsigned int *cmds;
 	unsigned int i;
-	struct adreno_context *drawctxt;
+	struct adreno_context *drawctxt = NULL;
 	unsigned int start_index = 0;
 	int ret;
 
-	if (device->state & KGSL_STATE_HUNG)
-		return -EBUSY;
-	if (!(adreno_dev->ringbuffer.flags & KGSL_FLAGS_STARTED) ||
-	      context == NULL || ibdesc == 0 || numibs == 0)
-		return -EINVAL;
+	if (device->state & KGSL_STATE_HUNG) {
+		ret = -EBUSY;
+		goto done;
+	}
 
+	if (!(adreno_dev->ringbuffer.flags & KGSL_FLAGS_STARTED) ||
+	      context == NULL || ibdesc == 0 || numibs == 0) {
+		ret = -EINVAL;
+		goto done;
+	}
 	drawctxt = context->devctxt;
 
 	if (drawctxt->flags & CTXT_FLAGS_GPU_HANG) {
 		KGSL_CTXT_ERR(device, "proc %s failed fault tolerance"
 			" will not accept commands for context %d\n",
 			drawctxt->pid_name, drawctxt->id);
-		return -EDEADLK;
+		ret = -EDEADLK;
+		goto done;
 	}
 
 	/*When preamble is enabled, the preamble buffer with state restoration
@@ -1032,9 +1041,8 @@
 	cmds = link = kzalloc(sizeof(unsigned int) * (numibs * 3 + 4),
 				GFP_KERNEL);
 	if (!link) {
-		KGSL_CORE_ERR("kzalloc(%d) failed\n",
-			sizeof(unsigned int) * (numibs * 3 + 4));
-		return -ENOMEM;
+		ret = -ENOMEM;
+		goto done;
 	}
 
 	if (!start_index) {
@@ -1099,6 +1107,9 @@
 		ret = 0;
 
 done:
+	trace_kgsl_issueibcmds(device, context->id, ibdesc, numibs,
+		*timestamp, flags, ret, drawctxt->type);
+
 	kfree(link);
 	return ret;
 }
diff --git a/drivers/gpu/msm/kgsl.c b/drivers/gpu/msm/kgsl.c
index af25a3f..53ef392 100644
--- a/drivers/gpu/msm/kgsl.c
+++ b/drivers/gpu/msm/kgsl.c
@@ -1214,8 +1214,6 @@
 					     &param->timestamp,
 					     param->flags);
 
-	trace_kgsl_issueibcmds(dev_priv->device, param, ibdesc, result);
-
 free_ibdesc:
 	kfree(ibdesc);
 done:
@@ -1341,7 +1339,7 @@
 	if (dev_priv->device->ftbl->drawctxt_create) {
 		result = dev_priv->device->ftbl->drawctxt_create(
 			dev_priv->device, dev_priv->process_priv->pagetable,
-			context, param->flags);
+			context, &param->flags);
 		if (result)
 			goto done;
 	}
@@ -2976,7 +2974,6 @@
 	if (result)
 		goto error_pwrctrl_close;
 
-	kgsl_cffdump_open(device->id);
 
 	setup_timer(&device->idle_timer, kgsl_timer, (unsigned long) device);
 	status = kgsl_create_device_workqueue(device);
@@ -3105,7 +3102,6 @@
 {
 	kgsl_device_snapshot_close(device);
 
-	kgsl_cffdump_close(device->id);
 	kgsl_pwrctrl_uninit_sysfs(device);
 
 	pm_qos_remove_request(&device->pwrctrl.pm_qos_req_dma);
diff --git a/drivers/gpu/msm/kgsl_cffdump.c b/drivers/gpu/msm/kgsl_cffdump.c
index e06c94d..6dc2ccc 100644
--- a/drivers/gpu/msm/kgsl_cffdump.c
+++ b/drivers/gpu/msm/kgsl_cffdump.c
@@ -28,6 +28,7 @@
 #include "kgsl_log.h"
 #include "kgsl_sharedmem.h"
 #include "adreno_pm4types.h"
+#include "adreno.h"
 
 static struct rchan	*chan;
 static struct dentry	*dir;
@@ -334,7 +335,7 @@
 		return;
 	}
 
-	kgsl_cff_dump_enable = 1;
+	kgsl_cff_dump_enable = 0;
 
 	spin_lock_init(&cffdump_lock);
 
@@ -356,10 +357,21 @@
 		debugfs_remove(dir);
 }
 
-void kgsl_cffdump_open(enum kgsl_deviceid device_id)
+void kgsl_cffdump_open(struct kgsl_device *device)
 {
-	kgsl_cffdump_memory_base(device_id, KGSL_PAGETABLE_BASE,
-			kgsl_mmu_get_ptsize(), SZ_256K);
+	struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
+
+	if (KGSL_MMU_TYPE_IOMMU == kgsl_mmu_get_mmutype()) {
+		kgsl_cffdump_memory_base(device->id,
+			kgsl_mmu_get_base_addr(&device->mmu),
+			kgsl_mmu_get_ptsize(&device->mmu) +
+			KGSL_IOMMU_GLOBAL_MEM_SIZE, adreno_dev->gmem_size);
+	} else {
+		kgsl_cffdump_memory_base(device->id,
+			kgsl_mmu_get_base_addr(&device->mmu),
+			kgsl_mmu_get_ptsize(&device->mmu),
+			adreno_dev->gmem_size);
+	}
 }
 
 void kgsl_cffdump_memory_base(enum kgsl_deviceid device_id, unsigned int base,
@@ -387,7 +399,7 @@
 }
 
 void kgsl_cffdump_syncmem(struct kgsl_device_private *dev_priv,
-	const struct kgsl_memdesc *memdesc, uint gpuaddr, uint sizebytes,
+	struct kgsl_memdesc *memdesc, uint gpuaddr, uint sizebytes,
 	bool clean_cache)
 {
 	const void *src;
@@ -522,7 +534,7 @@
 }
 
 static struct dentry *create_buf_file_handler(const char *filename,
-	struct dentry *parent, int mode, struct rchan_buf *buf,
+	struct dentry *parent, unsigned short mode, struct rchan_buf *buf,
 	int *is_global)
 {
 	return debugfs_create_file(filename, mode, parent, buf,
diff --git a/drivers/gpu/msm/kgsl_cffdump.h b/drivers/gpu/msm/kgsl_cffdump.h
index 2733cc3..d5656f8 100644
--- a/drivers/gpu/msm/kgsl_cffdump.h
+++ b/drivers/gpu/msm/kgsl_cffdump.h
@@ -22,10 +22,10 @@
 
 void kgsl_cffdump_init(void);
 void kgsl_cffdump_destroy(void);
-void kgsl_cffdump_open(enum kgsl_deviceid device_id);
+void kgsl_cffdump_open(struct kgsl_device *device);
 void kgsl_cffdump_close(enum kgsl_deviceid device_id);
 void kgsl_cffdump_syncmem(struct kgsl_device_private *dev_priv,
-	const struct kgsl_memdesc *memdesc, uint physaddr, uint sizebytes,
+	struct kgsl_memdesc *memdesc, uint physaddr, uint sizebytes,
 	bool clean_cache);
 void kgsl_cffdump_setmem(uint addr, uint value, uint sizebytes);
 void kgsl_cffdump_regwrite(enum kgsl_deviceid device_id, uint addr,
@@ -49,7 +49,7 @@
 
 #define kgsl_cffdump_init()					(void)0
 #define kgsl_cffdump_destroy()					(void)0
-#define kgsl_cffdump_open(device_id)				(void)0
+#define kgsl_cffdump_open(device)				(void)0
 #define kgsl_cffdump_close(device_id)				(void)0
 #define kgsl_cffdump_syncmem(dev_priv, memdesc, addr, sizebytes, clean_cache) \
 	(void) 0
diff --git a/drivers/gpu/msm/kgsl_device.h b/drivers/gpu/msm/kgsl_device.h
index 37b5730..0d11660 100644
--- a/drivers/gpu/msm/kgsl_device.h
+++ b/drivers/gpu/msm/kgsl_device.h
@@ -106,7 +106,7 @@
 			uint32_t flags);
 	int (*drawctxt_create) (struct kgsl_device *device,
 		struct kgsl_pagetable *pagetable, struct kgsl_context *context,
-		uint32_t flags);
+		uint32_t *flags);
 	void (*drawctxt_destroy) (struct kgsl_device *device,
 		struct kgsl_context *context);
 	long (*ioctl) (struct kgsl_device_private *dev_priv,
diff --git a/drivers/gpu/msm/kgsl_iommu.c b/drivers/gpu/msm/kgsl_iommu.c
index f327c04..739fcff 100644
--- a/drivers/gpu/msm/kgsl_iommu.c
+++ b/drivers/gpu/msm/kgsl_iommu.c
@@ -33,6 +33,7 @@
 #include "adreno.h"
 #include "kgsl_trace.h"
 #include "z180.h"
+#include "kgsl_cffdump.h"
 
 
 static struct kgsl_iommu_register_list kgsl_iommuv0_reg[KGSL_IOMMU_REG_MAX] = {
@@ -1548,6 +1549,10 @@
 	kgsl_iommu_lock_rb_in_tlb(mmu);
 	msm_iommu_unlock();
 
+	/* For complete CFF */
+	kgsl_cffdump_setmem(mmu->setstate_memory.gpuaddr +
+				KGSL_IOMMU_SETSTATE_NOP_OFFSET,
+				cp_nop_packet(1), sizeof(unsigned int));
 
 	kgsl_iommu_disable_clk_on_ts(mmu, 0, false);
 	mmu->flags |= KGSL_FLAGS_STARTED;
diff --git a/drivers/gpu/msm/kgsl_sharedmem.c b/drivers/gpu/msm/kgsl_sharedmem.c
index c32fa68..595f78f 100644
--- a/drivers/gpu/msm/kgsl_sharedmem.c
+++ b/drivers/gpu/msm/kgsl_sharedmem.c
@@ -576,11 +576,10 @@
 	memdesc->pagetable = pagetable;
 	memdesc->ops = &kgsl_page_alloc_ops;
 
-	memdesc->sg = kgsl_sg_alloc(sglen_alloc);
+	memdesc->sglen_alloc = sglen_alloc;
+	memdesc->sg = kgsl_sg_alloc(memdesc->sglen_alloc);
 
 	if (memdesc->sg == NULL) {
-		KGSL_CORE_ERR("vmalloc(%d) failed\n",
-			sglen_alloc * sizeof(struct scatterlist));
 		ret = -ENOMEM;
 		goto done;
 	}
@@ -592,19 +591,17 @@
 	 * two pages; well within the acceptable limits for using kmalloc.
 	 */
 
-	pages = kmalloc(sglen_alloc * sizeof(struct page *), GFP_KERNEL);
+	pages = kmalloc(memdesc->sglen_alloc * sizeof(struct page *),
+		GFP_KERNEL);
 
 	if (pages == NULL) {
-		KGSL_CORE_ERR("kmalloc (%d) failed\n",
-			sglen_alloc * sizeof(struct page *));
 		ret = -ENOMEM;
 		goto done;
 	}
 
 	kmemleak_not_leak(memdesc->sg);
 
-	memdesc->sglen_alloc = sglen_alloc;
-	sg_init_table(memdesc->sg, sglen_alloc);
+	sg_init_table(memdesc->sg, memdesc->sglen_alloc);
 
 	len = size;
 
diff --git a/drivers/gpu/msm/kgsl_snapshot.c b/drivers/gpu/msm/kgsl_snapshot.c
index 296de11..4c9c744 100644
--- a/drivers/gpu/msm/kgsl_snapshot.c
+++ b/drivers/gpu/msm/kgsl_snapshot.c
@@ -106,7 +106,12 @@
 {
 	struct kgsl_snapshot_linux_context *header = _ctxtptr;
 	struct kgsl_context *context = ptr;
-	struct kgsl_device *device = context->dev_priv->device;
+	struct kgsl_device *device;
+
+	if (context)
+		device = context->dev_priv->device;
+	else
+		device = (struct kgsl_device *)data;
 
 	header->id = id;
 
@@ -141,6 +146,9 @@
 
 	idr_for_each(&device->context_idr, snapshot_context_count, &ctxtcount);
 
+	/* Increment ctxcount for the global memstore */
+	ctxtcount++;
+
 	size += ctxtcount * sizeof(struct kgsl_snapshot_linux_context);
 
 	/* Make sure there is enough room for the data */
@@ -186,8 +194,10 @@
 
 	header->ctxtcount = ctxtcount;
 
-	/* append information for each context */
 	_ctxtptr = snapshot + sizeof(*header);
+	/* append information for the global context */
+	snapshot_context_info(KGSL_MEMSTORE_GLOBAL, NULL, device);
+	/* append information for each context */
 	idr_for_each(&device->context_idr, snapshot_context_info, NULL);
 
 	/* Return the size of the data segment */
diff --git a/drivers/gpu/msm/kgsl_sync.c b/drivers/gpu/msm/kgsl_sync.c
index 98edb83..0e3e046 100644
--- a/drivers/gpu/msm/kgsl_sync.c
+++ b/drivers/gpu/msm/kgsl_sync.c
@@ -206,7 +206,7 @@
 	struct kgsl_sync_timeline *ktimeline =
 		(struct kgsl_sync_timeline *) timeline;
 
-	if (timestamp_cmp(timestamp, ktimeline->last_timestamp > 0))
+	if (timestamp_cmp(timestamp, ktimeline->last_timestamp) > 0)
 		ktimeline->last_timestamp = timestamp;
 	sync_timeline_signal(timeline);
 }
diff --git a/drivers/gpu/msm/kgsl_trace.h b/drivers/gpu/msm/kgsl_trace.h
index 8c4811e..5f7ee3c 100644
--- a/drivers/gpu/msm/kgsl_trace.h
+++ b/drivers/gpu/msm/kgsl_trace.h
@@ -24,6 +24,8 @@
 #include <linux/tracepoint.h>
 #include "kgsl_device.h"
 
+#include "adreno_drawctxt.h"
+
 struct kgsl_device;
 struct kgsl_ringbuffer_issueibcmds;
 struct kgsl_device_waittimestamp;
@@ -34,11 +36,16 @@
 TRACE_EVENT(kgsl_issueibcmds,
 
 	TP_PROTO(struct kgsl_device *device,
-			struct kgsl_ringbuffer_issueibcmds *cmd,
+			int drawctxt_id,
 			struct kgsl_ibdesc *ibdesc,
-			int result),
+			int numibs,
+			int timestamp,
+			int flags,
+			int result,
+			unsigned int type),
 
-	TP_ARGS(device, cmd, ibdesc, result),
+	TP_ARGS(device, drawctxt_id, ibdesc, numibs, timestamp, flags,
+		result, type),
 
 	TP_STRUCT__entry(
 		__string(device_name, device->name)
@@ -48,21 +55,23 @@
 		__field(unsigned int, timestamp)
 		__field(unsigned int, flags)
 		__field(int, result)
+		__field(unsigned int, drawctxt_type)
 	),
 
 	TP_fast_assign(
 		__assign_str(device_name, device->name);
-		__entry->drawctxt_id = cmd->drawctxt_id;
+		__entry->drawctxt_id = drawctxt_id;
 		__entry->ibdesc_addr = ibdesc[0].gpuaddr;
-		__entry->numibs = cmd->numibs;
-		__entry->timestamp = cmd->timestamp;
-		__entry->flags = cmd->flags;
+		__entry->numibs = numibs;
+		__entry->timestamp = timestamp;
+		__entry->flags = flags;
 		__entry->result = result;
+		__entry->drawctxt_type = type;
 	),
 
 	TP_printk(
 		"d_name=%s ctx=%u ib=0x%u numibs=%u timestamp=0x%x "
-		"flags=0x%x(%s) result=%d",
+		"flags=0x%x(%s) result=%d type=%s",
 		__get_str(device_name),
 		__entry->drawctxt_id,
 		__entry->ibdesc_addr,
@@ -74,7 +83,9 @@
 			{ KGSL_CONTEXT_SUBMIT_IB_LIST, "IB_LIST" },
 			{ KGSL_CONTEXT_CTX_SWITCH, "CTX_SWITCH" })
 			: "None",
-		__entry->result
+		__entry->result,
+		__print_symbolic(__entry->drawctxt_type,
+			ADRENO_DRAWCTXT_TYPES)
 	)
 );
 
diff --git a/drivers/gpu/msm/z180.c b/drivers/gpu/msm/z180.c
index b78c6fe..a07959b 100644
--- a/drivers/gpu/msm/z180.c
+++ b/drivers/gpu/msm/z180.c
@@ -17,6 +17,7 @@
 #include "kgsl.h"
 #include "kgsl_cffdump.h"
 #include "kgsl_sharedmem.h"
+#include "kgsl_trace.h"
 
 #include "z180.h"
 #include "z180_reg.h"
@@ -483,6 +484,10 @@
 	z180_cmdwindow_write(device, ADDR_VGV3_CONTROL, cmd);
 	z180_cmdwindow_write(device, ADDR_VGV3_CONTROL, 0);
 error:
+
+	trace_kgsl_issueibcmds(device, context->id, ibdesc, numibs,
+		*timestamp, ctrl, result, 0);
+
 	return (int)result;
 }
 
diff --git a/drivers/gpu/msm/z180.h b/drivers/gpu/msm/z180.h
index 268aac3..1be0870 100644
--- a/drivers/gpu/msm/z180.h
+++ b/drivers/gpu/msm/z180.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2008-2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2008-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -29,7 +29,7 @@
 #define Z180_DEFAULT_PWRSCALE_POLICY  NULL
 
 /* Wait a maximum of 10 seconds when trying to idle the core */
-#define Z180_IDLE_TIMEOUT (10 * 1000)
+#define Z180_IDLE_TIMEOUT (20 * 1000)
 
 struct z180_ringbuffer {
 	unsigned int prevctx;
diff --git a/drivers/hwmon/qpnp-adc-common.c b/drivers/hwmon/qpnp-adc-common.c
index b52df44..1458bc5 100644
--- a/drivers/hwmon/qpnp-adc-common.c
+++ b/drivers/hwmon/qpnp-adc-common.c
@@ -637,19 +637,26 @@
 		uint32_t *low_threshold, uint32_t *high_threshold)
 {
 	struct qpnp_vadc_linear_graph vbatt_param;
+	int rc = 0;
 
-	qpnp_get_vadc_gain_and_offset(&vbatt_param, CALIB_ABSOLUTE);
+	rc = qpnp_get_vadc_gain_and_offset(&vbatt_param, CALIB_ABSOLUTE);
+	if (rc < 0)
+		return rc;
 
-	*low_threshold = param->low_thr * vbatt_param.dy;
-	do_div(*low_threshold, vbatt_param.adc_vref);
+	*low_threshold = (((param->low_thr/3) - QPNP_ADC_625_UV) *
+				vbatt_param.dy);
+	do_div(*low_threshold, QPNP_ADC_625_UV);
 	*low_threshold += vbatt_param.adc_gnd;
 
-	*high_threshold = param->high_thr * vbatt_param.dy;
-	do_div(*high_threshold, vbatt_param.adc_vref);
+	*high_threshold = (((param->high_thr/3) - QPNP_ADC_625_UV) *
+				vbatt_param.dy);
+	do_div(*high_threshold, QPNP_ADC_625_UV);
 	*high_threshold += vbatt_param.adc_gnd;
 
 	pr_debug("high_volt:%d, low_volt:%d\n", param->high_thr,
 				param->low_thr);
+	pr_debug("adc_code_high:%x, adc_code_low:%x\n", *high_threshold,
+				*low_threshold);
 	return 0;
 }
 EXPORT_SYMBOL(qpnp_adc_vbatt_rscaler);
diff --git a/drivers/hwmon/qpnp-adc-current.c b/drivers/hwmon/qpnp-adc-current.c
index 1fd4fee..0b02a34 100644
--- a/drivers/hwmon/qpnp-adc-current.c
+++ b/drivers/hwmon/qpnp-adc-current.c
@@ -115,7 +115,7 @@
 #define QPNP_ADC_GAIN_NV				17857
 #define QPNP_OFFSET_CALIBRATION_SHORT_CADC_LEADS_IDEAL	0
 #define QPNP_IADC_INTERNAL_RSENSE_N_OHMS_FACTOR		10000000
-#define QPNP_IADC_NANO_VOLTS_FACTOR			1000000000
+#define QPNP_IADC_NANO_VOLTS_FACTOR			1000000
 #define QPNP_IADC_CALIB_SECONDS				300000
 #define QPNP_IADC_RSENSE_LSB_N_OHMS_PER_BIT		15625
 #define QPNP_IADC_DIE_TEMP_CALIB_OFFSET			5000
@@ -125,7 +125,6 @@
 #define QPNP_BIT_SHIFT_8				8
 #define QPNP_RSENSE_MSB_SIGN_CHECK			0x80
 #define QPNP_ADC_COMPLETION_TIMEOUT			HZ
-#define QPNP_IADC_ERR_CHK_RATELIMIT			3
 
 struct qpnp_iadc_drv {
 	struct qpnp_adc_drv			*adc;
@@ -136,7 +135,6 @@
 	struct delayed_work			iadc_work;
 	struct mutex				iadc_vadc_lock;
 	bool					iadc_mode_sel;
-	uint32_t				iadc_err_cnt;
 	struct sensor_device_attribute		sens_attr[0];
 };
 
@@ -254,7 +252,7 @@
 		return rc;
 	}
 
-	pr_err("EOC not set with status:%x, dig:%x, ch:%x, mode:%x, en:%x\n",
+	pr_debug("EOC not set with status:%x, dig:%x, ch:%x, mode:%x, en:%x\n",
 			status1, dig, chan, mode, en);
 
 	rc = qpnp_iadc_enable(false);
@@ -347,6 +345,8 @@
 		return rc;
 	}
 
+	INIT_COMPLETION(iadc->adc->adc_rslt_completion);
+
 	rc = qpnp_iadc_enable(true);
 	if (rc)
 		return rc;
@@ -495,16 +495,12 @@
 	int rc = 0;
 
 	rc = qpnp_iadc_calibrate_for_trim();
-	if (rc) {
-		pr_err("periodic IADC calibration failed\n");
-		iadc->iadc_err_cnt++;
-	}
-
-	if (iadc->iadc_err_cnt < QPNP_IADC_ERR_CHK_RATELIMIT)
+	if (rc)
+		pr_debug("periodic IADC calibration failed\n");
+	else
 		schedule_delayed_work(&iadc->iadc_work,
 			round_jiffies_relative(msecs_to_jiffies
 					(QPNP_IADC_CALIB_SECONDS)));
-
 	return;
 }
 
@@ -597,6 +593,7 @@
 {
 	struct qpnp_iadc_drv *iadc = qpnp_iadc;
 	int32_t rc, rsense_n_ohms, sign = 0, num, mode_sel = 0;
+	int32_t rsense_u_ohms = 0;
 	int64_t result_current;
 	uint16_t raw_data;
 
@@ -622,7 +619,7 @@
 	rc = qpnp_iadc_get_rsense(&rsense_n_ohms);
 	pr_debug("current raw:0%x and rsense:%d\n",
 			raw_data, rsense_n_ohms);
-
+	rsense_u_ohms = rsense_n_ohms/1000;
 	num = raw_data - iadc->adc->calib.offset_raw;
 	if (num < 0) {
 		sign = 1;
@@ -633,7 +630,7 @@
 		(iadc->adc->calib.gain_raw - iadc->adc->calib.offset_raw);
 	result_current = result->result_uv;
 	result_current *= QPNP_IADC_NANO_VOLTS_FACTOR;
-	do_div(result_current, rsense_n_ohms);
+	do_div(result_current, rsense_u_ohms);
 
 	if (sign) {
 		result->result_uv = -result->result_uv;
@@ -857,7 +854,6 @@
 
 	mutex_init(&iadc->iadc_vadc_lock);
 	INIT_DELAYED_WORK(&iadc->iadc_work, qpnp_iadc_work);
-	iadc->iadc_err_cnt = 0;
 	iadc->iadc_initialized = true;
 
 	rc = qpnp_iadc_calibrate_for_trim();
diff --git a/drivers/hwmon/qpnp-adc-voltage.c b/drivers/hwmon/qpnp-adc-voltage.c
index e268541..d296a47 100644
--- a/drivers/hwmon/qpnp-adc-voltage.c
+++ b/drivers/hwmon/qpnp-adc-voltage.c
@@ -90,6 +90,7 @@
 #define QPNP_VADC_CONV_TIME_MIN					2000
 #define QPNP_VADC_CONV_TIME_MAX					2100
 #define QPNP_ADC_COMPLETION_TIMEOUT				HZ
+#define QPNP_VADC_ERR_COUNT					5
 
 struct qpnp_vadc_drv {
 	struct qpnp_adc_drv		*adc;
@@ -434,7 +435,7 @@
 {
 	struct qpnp_vadc_drv *vadc = qpnp_vadc;
 	struct qpnp_adc_amux_properties conv;
-	int rc, calib_read_1, calib_read_2;
+	int rc, calib_read_1, calib_read_2, count = 0;
 	u8 status1 = 0;
 
 	conv.amux_channel = REF_125V;
@@ -456,6 +457,11 @@
 		status1 &= QPNP_VADC_STATUS1_REQ_STS_EOC_MASK;
 		usleep_range(QPNP_VADC_CONV_TIME_MIN,
 					QPNP_VADC_CONV_TIME_MAX);
+		count++;
+		if (count > QPNP_VADC_ERR_COUNT) {
+			rc = -ENODEV;
+			goto calib_fail;
+		}
 	}
 
 	rc = qpnp_vadc_read_conversion_result(&calib_read_1);
@@ -476,6 +482,7 @@
 	}
 
 	status1 = 0;
+	count = 0;
 	while (status1 != QPNP_VADC_STATUS1_EOC) {
 		rc = qpnp_vadc_read_reg(QPNP_VADC_STATUS1, &status1);
 		if (rc < 0)
@@ -483,6 +490,11 @@
 		status1 &= QPNP_VADC_STATUS1_REQ_STS_EOC_MASK;
 		usleep_range(QPNP_VADC_CONV_TIME_MIN,
 					QPNP_VADC_CONV_TIME_MAX);
+		count++;
+		if (count > QPNP_VADC_ERR_COUNT) {
+			rc = -ENODEV;
+			goto calib_fail;
+		}
 	}
 
 	rc = qpnp_vadc_read_conversion_result(&calib_read_2);
@@ -516,6 +528,7 @@
 	}
 
 	status1 = 0;
+	count = 0;
 	while (status1 != QPNP_VADC_STATUS1_EOC) {
 		rc = qpnp_vadc_read_reg(QPNP_VADC_STATUS1, &status1);
 		if (rc < 0)
@@ -523,6 +536,11 @@
 		status1 &= QPNP_VADC_STATUS1_REQ_STS_EOC_MASK;
 		usleep_range(QPNP_VADC_CONV_TIME_MIN,
 					QPNP_VADC_CONV_TIME_MAX);
+		count++;
+		if (count > QPNP_VADC_ERR_COUNT) {
+			rc = -ENODEV;
+			goto calib_fail;
+		}
 	}
 
 	rc = qpnp_vadc_read_conversion_result(&calib_read_1);
@@ -543,6 +561,7 @@
 	}
 
 	status1 = 0;
+	count = 0;
 	while (status1 != QPNP_VADC_STATUS1_EOC) {
 		rc = qpnp_vadc_read_reg(QPNP_VADC_STATUS1, &status1);
 		if (rc < 0)
@@ -550,6 +569,11 @@
 		status1 &= QPNP_VADC_STATUS1_REQ_STS_EOC_MASK;
 		usleep_range(QPNP_VADC_CONV_TIME_MIN,
 					QPNP_VADC_CONV_TIME_MAX);
+		count++;
+		if (count > QPNP_VADC_ERR_COUNT) {
+			rc = -ENODEV;
+			goto calib_fail;
+		}
 	}
 
 	rc = qpnp_vadc_read_conversion_result(&calib_read_2);
diff --git a/drivers/input/touchscreen/synaptics_fw_update.c b/drivers/input/touchscreen/synaptics_fw_update.c
index 7452587..986c062 100644
--- a/drivers/input/touchscreen/synaptics_fw_update.c
+++ b/drivers/input/touchscreen/synaptics_fw_update.c
@@ -30,7 +30,6 @@
 
 #define DEBUG_FW_UPDATE
 #define SHOW_PROGRESS
-#define FW_IMAGE_NAME "PR1063486-s7301_00000000.img"
 #define MAX_FIRMWARE_ID_LEN 10
 #define FORCE_UPDATE false
 #define INSIDE_FIRMWARE_UPDATE
@@ -561,8 +560,6 @@
 		goto exit;
 	}
 
-	imagePR = kzalloc(sizeof(MAX_FIRMWARE_ID_LEN), GFP_KERNEL);
-
 	/* Force update firmware when device is in bootloader mode */
 	if (f01_device_status.flash_prog) {
 		dev_info(&i2c_client->dev,
@@ -587,7 +584,8 @@
 	deviceFirmwareID = extract_uint(firmware_id);
 
 	/* .img firmware id */
-	strptr = strstr(FW_IMAGE_NAME, "PR");
+	strptr = strnstr(fwu->rmi4_data->fw_image_name, "PR",
+			sizeof(fwu->rmi4_data->fw_image_name));
 	if (!strptr) {
 		dev_err(&i2c_client->dev,
 			"No valid PR number (PRxxxxxxx)" \
@@ -616,6 +614,11 @@
 	if (imageFirmwareID > deviceFirmwareID) {
 		flash_area = UI_FIRMWARE;
 		goto exit;
+	} else if (imageFirmwareID < deviceFirmwareID) {
+		flash_area = NONE;
+		dev_info(&i2c_client->dev,
+			"Img fw is older than device fw.  Skip fw update.\n");
+		goto exit;
 	}
 
 	/* device config id */
@@ -1216,19 +1219,28 @@
 
 	pr_notice("%s: Start of reflash process\n", __func__);
 
+	if (!fwu->rmi4_data->fw_image_name) {
+		retval = 0;
+		dev_err(&fwu->rmi4_data->i2c_client->dev,
+			"Firmware image name not given, skipping update\n");
+		goto exit;
+	}
+
 	if (fwu->ext_data_source)
 		fw_image = fwu->ext_data_source;
 	else {
 		dev_dbg(&fwu->rmi4_data->i2c_client->dev,
 				"%s: Requesting firmware image %s\n",
-				__func__, FW_IMAGE_NAME);
+				__func__, fwu->rmi4_data->fw_image_name);
 
-		retval = request_firmware(&fw_entry, FW_IMAGE_NAME,
+		retval = request_firmware(&fw_entry,
+				fwu->rmi4_data->fw_image_name,
 				&fwu->rmi4_data->i2c_client->dev);
 		if (retval != 0) {
 			dev_err(&fwu->rmi4_data->i2c_client->dev,
 					"%s: Firmware image %s not available\n",
-					__func__, FW_IMAGE_NAME);
+					__func__,
+					fwu->rmi4_data->fw_image_name);
 			retval = -EINVAL;
 			goto exit;
 		}
@@ -1650,6 +1662,9 @@
 			&fwu->fwu_work,
 			msecs_to_jiffies(1000));
 #endif
+
+	init_completion(&remove_complete);
+
 	return 0;
 
 exit_remove_attrs:
@@ -1700,7 +1715,6 @@
 
 static void __exit rmi4_fw_update_module_exit(void)
 {
-	init_completion(&remove_complete);
 	synaptics_rmi4_new_function(RMI_FW_UPDATER, false,
 			synaptics_rmi4_fwu_init,
 			synaptics_rmi4_fwu_remove,
diff --git a/drivers/input/touchscreen/synaptics_i2c_rmi4.c b/drivers/input/touchscreen/synaptics_i2c_rmi4.c
index 775d62a..417ef83 100644
--- a/drivers/input/touchscreen/synaptics_i2c_rmi4.c
+++ b/drivers/input/touchscreen/synaptics_i2c_rmi4.c
@@ -65,8 +65,8 @@
 
 #define NORMAL_OPERATION (0 << 0)
 #define SENSOR_SLEEP (1 << 0)
-#define NO_SLEEP_OFF (0 << 3)
-#define NO_SLEEP_ON (1 << 3)
+#define NO_SLEEP_OFF (0 << 2)
+#define NO_SLEEP_ON (1 << 2)
 
 #define RMI4_VTG_MIN_UV		2700000
 #define RMI4_VTG_MAX_UV		3300000
@@ -125,6 +125,19 @@
 static ssize_t synaptics_rmi4_0dbutton_store(struct device *dev,
 		struct device_attribute *attr, const char *buf, size_t count);
 
+static ssize_t synaptics_rmi4_flipx_show(struct device *dev,
+		struct device_attribute *attr, char *buf);
+
+static ssize_t synaptics_rmi4_flipx_store(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t count);
+
+static ssize_t synaptics_rmi4_flipy_show(struct device *dev,
+		struct device_attribute *attr, char *buf);
+
+static ssize_t synaptics_rmi4_flipy_store(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t count);
+
+
 struct synaptics_rmi4_f01_device_status {
 	union {
 		struct {
@@ -223,6 +236,12 @@
 	__ATTR(0dbutton, (S_IRUGO | S_IWUGO),
 			synaptics_rmi4_0dbutton_show,
 			synaptics_rmi4_0dbutton_store),
+	__ATTR(flipx, (S_IRUGO | S_IWUGO),
+			synaptics_rmi4_flipx_show,
+			synaptics_rmi4_flipx_store),
+	__ATTR(flipy, (S_IRUGO | S_IWUGO),
+			synaptics_rmi4_flipy_show,
+			synaptics_rmi4_flipy_store),
 };
 
 static bool exp_fn_inited;
@@ -391,6 +410,52 @@
 	return count;
 }
 
+static ssize_t synaptics_rmi4_flipx_show(struct device *dev,
+	struct device_attribute *attr, char *buf)
+{
+	struct synaptics_rmi4_data *rmi4_data = dev_get_drvdata(dev);
+
+	return snprintf(buf, PAGE_SIZE, "%u\n",
+		rmi4_data->flip_x);
+}
+
+static ssize_t synaptics_rmi4_flipx_store(struct device *dev,
+	struct device_attribute *attr, const char *buf, size_t count)
+{
+	unsigned int input;
+	struct synaptics_rmi4_data *rmi4_data = dev_get_drvdata(dev);
+
+	if (sscanf(buf, "%u", &input) != 1)
+		return -EINVAL;
+
+	rmi4_data->flip_x = input > 0 ? 1 : 0;
+
+	return count;
+}
+
+static ssize_t synaptics_rmi4_flipy_show(struct device *dev,
+	struct device_attribute *attr, char *buf)
+{
+	struct synaptics_rmi4_data *rmi4_data = dev_get_drvdata(dev);
+
+	return snprintf(buf, PAGE_SIZE, "%u\n",
+		rmi4_data->flip_y);
+}
+
+static ssize_t synaptics_rmi4_flipy_store(struct device *dev,
+	struct device_attribute *attr, const char *buf, size_t count)
+{
+	unsigned int input;
+	struct synaptics_rmi4_data *rmi4_data = dev_get_drvdata(dev);
+
+	if (sscanf(buf, "%u", &input) != 1)
+		return -EINVAL;
+
+	rmi4_data->flip_y = input > 0 ? 1 : 0;
+
+	return count;
+}
+
  /**
  * synaptics_rmi4_set_page()
  *
@@ -581,6 +646,7 @@
 	int y;
 	int wx;
 	int wy;
+	int z;
 
 	/*
 	 * The number of finger status registers is determined by the
@@ -634,10 +700,11 @@
 			y = (data[1] << 4) | ((data[2] >> 4) & MASK_4BIT);
 			wx = (data[3] & MASK_4BIT);
 			wy = (data[3] >> 4) & MASK_4BIT;
+			z = data[4];
 
-			if (rmi4_data->board->x_flip)
+			if (rmi4_data->flip_x)
 				x = rmi4_data->sensor_max_x - x;
-			if (rmi4_data->board->y_flip)
+			if (rmi4_data->flip_y)
 				y = rmi4_data->sensor_max_y - y;
 
 			dev_dbg(&rmi4_data->i2c_client->dev,
@@ -655,6 +722,8 @@
 					ABS_MT_POSITION_X, x);
 			input_report_abs(rmi4_data->input_dev,
 					ABS_MT_POSITION_Y, y);
+			input_report_abs(rmi4_data->input_dev,
+					ABS_MT_PRESSURE, z);
 
 #ifdef REPORT_2D_W
 			input_report_abs(rmi4_data->input_dev,
@@ -937,6 +1006,13 @@
 		rmi4_pdata->panel_y = temp_val;
 	}
 
+	rc = of_property_read_string(np, "synaptics,fw-image-name",
+		&rmi4_pdata->fw_image_name);
+	if (rc && (rc != -EINVAL)) {
+		dev_err(dev, "Unable to read fw image name\n");
+		return rc;
+	}
+
 	/* reset, irq gpio info */
 	rmi4_pdata->reset_gpio = of_get_named_gpio_flags(np,
 			"synaptics,reset-gpio", 0, &rmi4_pdata->reset_flags);
@@ -1007,22 +1083,12 @@
 		if (retval < 0)
 			return retval;
 
-		retval = request_threaded_irq(rmi4_data->irq, NULL,
-				synaptics_rmi4_irq,
-				rmi4_data->board->irq_flags,
-				DRIVER_NAME, rmi4_data);
-		if (retval < 0) {
-			dev_err(&rmi4_data->i2c_client->dev,
-					"%s: Failed to create irq thread\n",
-					__func__);
-			return retval;
-		}
+		enable_irq(rmi4_data->irq);
 
 		rmi4_data->irq_enabled = true;
 	} else {
 		if (rmi4_data->irq_enabled) {
 			disable_irq(rmi4_data->irq);
-			free_irq(rmi4_data->irq, rmi4_data);
 			rmi4_data->irq_enabled = false;
 		}
 	}
@@ -1257,7 +1323,7 @@
 static int synaptics_rmi4_alloc_fh(struct synaptics_rmi4_fn **fhandler,
 		struct synaptics_rmi4_fn_desc *rmi_fd, int page_number)
 {
-	*fhandler = kmalloc(sizeof(**fhandler), GFP_KERNEL);
+	*fhandler = kzalloc(sizeof(**fhandler), GFP_KERNEL);
 	if (!(*fhandler))
 		return -ENOMEM;
 
@@ -1273,6 +1339,7 @@
 	(*fhandler)->full_addr.query_base =
 			(rmi_fd->query_base_addr |
 			(page_number << 8));
+	(*fhandler)->fn_number = rmi_fd->fn_number;
 
 	return 0;
 }
@@ -1331,7 +1398,7 @@
 				__func__, retval);
 		return retval;
 	}
-	return retval;
+	return 0;
 }
 
  /**
@@ -1423,15 +1490,6 @@
 				}
 				break;
 
-			case SYNAPTICS_RMI4_F34:
-				retval = synaptics_rmi4_i2c_read(rmi4_data,
-						rmi_fd.ctrl_base_addr,
-						rmi->config_id,
-						sizeof(rmi->config_id));
-				if (retval < 0)
-					return retval;
-				break;
-
 			case SYNAPTICS_RMI4_F11:
 				if (rmi_fd.intr_src_count == 0)
 					break;
@@ -1530,14 +1588,51 @@
 	return 0;
 }
 
-static int synaptics_rmi4_reset_device(struct synaptics_rmi4_data *rmi4_data)
+static int synaptics_rmi4_reset_command(struct synaptics_rmi4_data *rmi4_data)
 {
 	int retval;
+	int page_number;
 	unsigned char command = 0x01;
-	struct synaptics_rmi4_fn *fhandler;
-	struct synaptics_rmi4_device_info *rmi;
+	unsigned short pdt_entry_addr;
+	struct synaptics_rmi4_fn_desc rmi_fd;
+	bool done = false;
 
-	rmi = &(rmi4_data->rmi4_mod_info);
+	/* Scan the page description tables of the pages to service */
+	for (page_number = 0; page_number < PAGES_TO_SERVICE; page_number++) {
+		for (pdt_entry_addr = PDT_START; pdt_entry_addr > PDT_END;
+				pdt_entry_addr -= PDT_ENTRY_SIZE) {
+			retval = synaptics_rmi4_i2c_read(rmi4_data,
+				pdt_entry_addr,
+				(unsigned char *)&rmi_fd,
+				sizeof(rmi_fd));
+			if (retval < 0)
+				return retval;
+
+			if (rmi_fd.fn_number == 0)
+				break;
+
+			switch (rmi_fd.fn_number) {
+			case SYNAPTICS_RMI4_F01:
+				rmi4_data->f01_cmd_base_addr =
+					rmi_fd.cmd_base_addr;
+				done = true;
+				break;
+			}
+		}
+		if (done) {
+			dev_info(&rmi4_data->i2c_client->dev,
+				"%s: Find F01 in page description table 0x%x\n",
+				__func__, rmi4_data->f01_cmd_base_addr);
+			break;
+		}
+	}
+
+	if (!done) {
+		dev_err(&rmi4_data->i2c_client->dev,
+			"%s: Cannot find F01 in page description table\n",
+			__func__);
+		return -EINVAL;
+	}
 
 	retval = synaptics_rmi4_i2c_write(rmi4_data,
 			rmi4_data->f01_cmd_base_addr,
@@ -1551,6 +1646,24 @@
 	}
 
 	msleep(100);
+	return retval;
+};
+
+static int synaptics_rmi4_reset_device(struct synaptics_rmi4_data *rmi4_data)
+{
+	int retval;
+	struct synaptics_rmi4_fn *fhandler;
+	struct synaptics_rmi4_device_info *rmi;
+
+	rmi = &(rmi4_data->rmi4_mod_info);
+
+	retval = synaptics_rmi4_reset_command(rmi4_data);
+	if (retval < 0) {
+		dev_err(&rmi4_data->i2c_client->dev,
+			"%s: Failed to send command reset\n",
+			__func__);
+		return retval;
+	}
 
 	if (!list_empty(&rmi->support_fn_list)) {
 		list_for_each_entry(fhandler, &rmi->support_fn_list, link) {
@@ -1921,6 +2034,11 @@
 	rmi4_data->irq_enable = synaptics_rmi4_irq_enable;
 	rmi4_data->reset_device = synaptics_rmi4_reset_device;
 
+	rmi4_data->flip_x = rmi4_data->board->x_flip;
+	rmi4_data->flip_y = rmi4_data->board->y_flip;
+
+	rmi4_data->fw_image_name = rmi4_data->board->fw_image_name;
+
 	rmi4_data->input_dev->name = DRIVER_NAME;
 	rmi4_data->input_dev->phys = INPUT_PHYS_NAME;
 	rmi4_data->input_dev->id.bustype = BUS_I2C;
@@ -1993,7 +2111,8 @@
 		usleep(RMI4_GPIO_SLEEP_LOW_US);
 		gpio_set_value(platform_data->reset_gpio, 1);
 		msleep(RMI4_GPIO_WAIT_HIGH_MS);
-	}
+	} else
+		synaptics_rmi4_reset_command(rmi4_data);
 
 
 	init_waitqueue_head(&rmi4_data->wait);
@@ -2013,6 +2132,8 @@
 	input_set_abs_params(rmi4_data->input_dev,
 			ABS_MT_POSITION_Y, 0,
 			rmi4_data->sensor_max_y, 0, 0);
+	input_set_abs_params(rmi4_data->input_dev,
+			ABS_PRESSURE, 0, 255, 0, 0);
 #ifdef REPORT_2D_W
 	input_set_abs_params(rmi4_data->input_dev,
 			ABS_MT_TOUCH_MAJOR, 0,
@@ -2074,10 +2195,14 @@
 
 	rmi4_data->irq = gpio_to_irq(platform_data->irq_gpio);
 
-	retval = synaptics_rmi4_irq_enable(rmi4_data, true);
+	retval = request_threaded_irq(rmi4_data->irq, NULL,
+		synaptics_rmi4_irq, platform_data->irq_flags,
+		DRIVER_NAME, rmi4_data);
+	rmi4_data->irq_enabled = true;
+
 	if (retval < 0) {
 		dev_err(&client->dev,
-				"%s: Failed to enable attention interrupt\n",
+				"%s: Failed to create irq thread\n",
 				__func__);
 		goto err_enable_irq;
 	}
@@ -2092,6 +2217,13 @@
 			goto err_sysfs;
 		}
 	}
+	retval = synaptics_rmi4_irq_enable(rmi4_data, true);
+	if (retval < 0) {
+		dev_err(&client->dev,
+			"%s: Failed to enable attention interrupt\n",
+			__func__);
+		goto err_sysfs;
+	}
 
 	return retval;
 
@@ -2162,7 +2294,7 @@
 	rmi4_data->touch_stopped = true;
 	wake_up(&rmi4_data->wait);
 
-	synaptics_rmi4_irq_enable(rmi4_data, false);
+	free_irq(rmi4_data->irq, rmi4_data);
 
 	for (attr_count = 0; attr_count < ARRAY_SIZE(attrs); attr_count++) {
 		sysfs_remove_file(&rmi4_data->input_dev->dev.kobj,
diff --git a/drivers/input/touchscreen/synaptics_i2c_rmi4.h b/drivers/input/touchscreen/synaptics_i2c_rmi4.h
index b1d2645..16b1f8f 100644
--- a/drivers/input/touchscreen/synaptics_i2c_rmi4.h
+++ b/drivers/input/touchscreen/synaptics_i2c_rmi4.h
@@ -24,7 +24,7 @@
 #define SYNAPTICS_DS4 (1 << 0)
 #define SYNAPTICS_DS5 (1 << 1)
 #define SYNAPTICS_DSX_DRIVER_PRODUCT SYNAPTICS_DS4
-#define SYNAPTICS_DSX_DRIVER_VERSION 0x1002
+#define SYNAPTICS_DSX_DRIVER_VERSION 0x1004
 
 #include <linux/version.h>
 #ifdef CONFIG_HAS_EARLYSUSPEND
@@ -177,6 +177,8 @@
  * @irq_enabled: flag for indicating interrupt enable status
  * @touch_stopped: flag to stop interrupt thread processing
  * @fingers_on_2d: flag to indicate presence of fingers in 2d area
+ * @flip_x: set to TRUE if desired to flip direction on x-axis
+ * @flip_y: set to TRUE if desired to flip direction on y-axis
  * @sensor_sleep: flag to indicate sleep state of sensor
  * @wait: wait queue for touch data polling in interrupt thread
  * @i2c_read: pointer to i2c read function
@@ -196,6 +198,7 @@
 #ifdef CONFIG_HAS_EARLYSUSPEND
 	struct early_suspend early_suspend;
 #endif
+	const char *fw_image_name;
 	unsigned char current_page;
 	unsigned char button_0d_enabled;
 	unsigned char full_pm_cycle;
@@ -215,6 +218,8 @@
 	bool touch_stopped;
 	bool fingers_on_2d;
 	bool sensor_sleep;
+	bool flip_x;
+	bool flip_y;
 	wait_queue_head_t wait;
 	int (*i2c_read)(struct synaptics_rmi4_data *pdata, unsigned short addr,
 			unsigned char *data, unsigned short length);
diff --git a/drivers/input/touchscreen/synaptics_rmi_dev.c b/drivers/input/touchscreen/synaptics_rmi_dev.c
index 7f1aac5..c6b8a1c 100644
--- a/drivers/input/touchscreen/synaptics_rmi_dev.c
+++ b/drivers/input/touchscreen/synaptics_rmi_dev.c
@@ -619,6 +619,8 @@
 		}
 	}
 
+	init_completion(&remove_complete);
+
 	return 0;
 
 err_sysfs_attrs:
diff --git a/drivers/iommu/msm_iommu-v0.c b/drivers/iommu/msm_iommu-v0.c
index de35f9a..c0a4720 100644
--- a/drivers/iommu/msm_iommu-v0.c
+++ b/drivers/iommu/msm_iommu-v0.c
@@ -156,21 +156,15 @@
 	clk_disable_unprepare(drvdata->pclk);
 }
 
-static int _iommu_power_on(void *data)
+static int __enable_regulators(struct msm_iommu_drvdata *drvdata)
 {
-	struct msm_iommu_drvdata *drvdata;
-
-	drvdata = (struct msm_iommu_drvdata *)data;
-	return __enable_clocks(drvdata);
+	/* No need to do anything. IOMMUv0 is always on. */
+	return 0;
 }
 
-static int _iommu_power_off(void *data)
+static void __disable_regulators(struct msm_iommu_drvdata *drvdata)
 {
-	struct msm_iommu_drvdata *drvdata;
-
-	drvdata = (struct msm_iommu_drvdata *)data;
-	__disable_clocks(drvdata);
-	return 0;
+	/* No need to do anything. IOMMUv0 is always on. */
 }
 
 static void _iommu_lock_acquire(void)
@@ -184,8 +178,10 @@
 }
 
 struct iommu_access_ops iommu_access_ops_v0 = {
-	.iommu_power_on = _iommu_power_on,
-	.iommu_power_off = _iommu_power_off,
+	.iommu_power_on = __enable_regulators,
+	.iommu_power_off = __disable_regulators,
+	.iommu_clk_on = __enable_clocks,
+	.iommu_clk_off = __disable_clocks,
 	.iommu_lock_acquire = _iommu_lock_acquire,
 	.iommu_lock_release = _iommu_lock_release,
 };
diff --git a/drivers/iommu/msm_iommu-v1.c b/drivers/iommu/msm_iommu-v1.c
index f552474..8a26003 100644
--- a/drivers/iommu/msm_iommu-v1.c
+++ b/drivers/iommu/msm_iommu-v1.c
@@ -103,36 +103,6 @@
 	clk_disable_unprepare(drvdata->pclk);
 }
 
-static int _iommu_power_off(void *data)
-{
-	struct msm_iommu_drvdata *drvdata;
-
-	drvdata = (struct msm_iommu_drvdata *)data;
-	__disable_clocks(drvdata);
-	__disable_regulators(drvdata);
-	return 0;
-}
-
-static int _iommu_power_on(void *data)
-{
-	int ret;
-	struct msm_iommu_drvdata *drvdata;
-
-	drvdata = (struct msm_iommu_drvdata *)data;
-	ret = __enable_regulators(drvdata);
-	if (ret)
-		goto fail;
-
-	ret = __enable_clocks(drvdata);
-	if (ret) {
-		__disable_regulators(drvdata);
-		goto fail;
-	}
-	return 0;
-fail:
-	return -EIO;
-}
-
 static void _iommu_lock_acquire(void)
 {
 	mutex_lock(&msm_iommu_lock);
@@ -144,8 +114,10 @@
 }
 
 struct iommu_access_ops iommu_access_ops_v1 = {
-	.iommu_power_on = _iommu_power_on,
-	.iommu_power_off = _iommu_power_off,
+	.iommu_power_on = __enable_regulators,
+	.iommu_power_off = __disable_regulators,
+	.iommu_clk_on = __enable_clocks,
+	.iommu_clk_off = __disable_clocks,
 	.iommu_lock_acquire = _iommu_lock_acquire,
 	.iommu_lock_release = _iommu_lock_release,
 };
@@ -260,8 +232,6 @@
 	SET_GFAR(base, 0);
 	SET_GFSRRESTORE(base, 0);
 	SET_TLBIALLNSNH(base, 0);
-	SET_SCR1(base, 0);
-	SET_SSDR_N(base, 0, 0);
 	smt_size = GET_IDR0_NUMSMRG(base);
 
 	for (i = 0; i < smt_size; i++)
diff --git a/drivers/iommu/msm_iommu_dev-v1.c b/drivers/iommu/msm_iommu_dev-v1.c
index f994413..418a086 100644
--- a/drivers/iommu/msm_iommu_dev-v1.c
+++ b/drivers/iommu/msm_iommu_dev-v1.c
@@ -265,6 +265,8 @@
 
 	platform_set_drvdata(pdev, drvdata);
 
+	msm_iommu_sec_set_access_ops(&iommu_access_ops_v1);
+
 	pmon_info = msm_iommu_pm_alloc(&pdev->dev);
 	if (pmon_info != NULL) {
 		ret = msm_iommu_pmon_parse_dt(pdev, pmon_info);
diff --git a/drivers/iommu/msm_iommu_perfmon-v0.c b/drivers/iommu/msm_iommu_perfmon-v0.c
index c80d1e5..1073623 100644
--- a/drivers/iommu/msm_iommu_perfmon-v0.c
+++ b/drivers/iommu/msm_iommu_perfmon-v0.c
@@ -21,6 +21,7 @@
 #include <linux/device.h>
 #include <mach/iommu_hw-v0.h>
 #include <mach/iommu_perfmon.h>
+#include <mach/iommu.h>
 
 #define PM_RESET_MASK		(0xF)
 #define PM_RESET_SHIFT		(0x8)
@@ -280,7 +281,9 @@
 	 * for locking here.
 	 */
 	iommu->ops->iommu_power_on(iommu_drvdata);
+	iommu->ops->iommu_clk_on(iommu_drvdata);
 	iommu_pm_set_int_active_high(iommu);
+	iommu->ops->iommu_clk_off(iommu_drvdata);
 	iommu->ops->iommu_power_off(iommu_drvdata);
 }
 
diff --git a/drivers/iommu/msm_iommu_perfmon-v1.c b/drivers/iommu/msm_iommu_perfmon-v1.c
index d76ee7f..7d6dd34 100644
--- a/drivers/iommu/msm_iommu_perfmon-v1.c
+++ b/drivers/iommu/msm_iommu_perfmon-v1.c
@@ -20,6 +20,7 @@
 #include <linux/module.h>
 #include <mach/iommu_hw-v1.h>
 #include <mach/iommu_perfmon.h>
+#include <mach/iommu.h>
 
 #define PMCR_P_MASK		(0x1)
 #define PMCR_P_SHIFT		(1)
diff --git a/drivers/iommu/msm_iommu_perfmon.c b/drivers/iommu/msm_iommu_perfmon.c
index 41df1ed..fee8a4a 100644
--- a/drivers/iommu/msm_iommu_perfmon.c
+++ b/drivers/iommu/msm_iommu_perfmon.c
@@ -242,6 +242,7 @@
 					dev_get_drvdata(iommu->iommu_dev);
 
 	iommu->ops->iommu_power_on(iommu_drvdata);
+	iommu->ops->iommu_clk_on(iommu_drvdata);
 
 	/* Reset counters in HW */
 	iommu->ops->iommu_lock_acquire();
@@ -294,6 +295,7 @@
 	iommu_pm_read_all_counters(pmon);
 
 	iommu->ops->iommu_lock_release();
+	iommu->ops->iommu_clk_off(iommu_drvdata);
 	iommu->ops->iommu_power_off(iommu_drvdata);
 
 	pr_info("%s: TLB performance monitoring turned OFF\n",
diff --git a/drivers/iommu/msm_iommu_sec.c b/drivers/iommu/msm_iommu_sec.c
index 5ca6fd9..74d8b48 100644
--- a/drivers/iommu/msm_iommu_sec.c
+++ b/drivers/iommu/msm_iommu_sec.c
@@ -43,8 +43,11 @@
 #define IOMMU_SECURE_PTBL_INIT  4
 #define IOMMU_SECURE_MAP	6
 #define IOMMU_SECURE_UNMAP      7
+#define IOMMU_SECURE_MAP2 0x0B
+#define IOMMU_SECURE_UNMAP2 0x0C
+#define IOMMU_TLBINVAL_FLAG 0x00000001
 
-static DEFINE_MUTEX(msm_iommu_lock);
+static struct iommu_access_ops *iommu_access_ops;
 
 struct msm_scm_paddr_list {
 	unsigned int list;
@@ -59,11 +62,22 @@
 	unsigned int size;
 };
 
-struct msm_scm_map_req {
+struct msm_scm_map2_req {
 	struct msm_scm_paddr_list plist;
 	struct msm_scm_mapping_info info;
+	unsigned int flags;
 };
 
+struct msm_scm_unmap2_req {
+	struct msm_scm_mapping_info info;
+	unsigned int flags;
+};
+
+void msm_iommu_sec_set_access_ops(struct iommu_access_ops *access_ops)
+{
+	iommu_access_ops = access_ops;
+}
+
 static int msm_iommu_sec_ptbl_init(void)
 {
 	struct device_node *np;
@@ -153,7 +167,7 @@
 			struct msm_iommu_ctx_drvdata *ctx_drvdata,
 			unsigned long va, phys_addr_t pa, size_t len)
 {
-	struct msm_scm_map_req map;
+	struct msm_scm_map2_req map;
 	int ret = 0;
 
 	map.plist.list = virt_to_phys(&pa);
@@ -163,8 +177,9 @@
 	map.info.ctx_id = ctx_drvdata->num;
 	map.info.va = va;
 	map.info.size = len;
+	map.flags = IOMMU_TLBINVAL_FLAG;
 
-	if (scm_call(SCM_SVC_MP, IOMMU_SECURE_MAP, &map, sizeof(map), &ret,
+	if (scm_call(SCM_SVC_MP, IOMMU_SECURE_MAP2, &map, sizeof(map), &ret,
 								sizeof(ret)))
 		return -EINVAL;
 	if (ret)
@@ -191,7 +206,7 @@
 			unsigned long va, struct scatterlist *sg, size_t len)
 {
 	struct scatterlist *sgiter;
-	struct msm_scm_map_req map;
+	struct msm_scm_map2_req map;
 	unsigned int *pa_list = 0;
 	unsigned int pa, cnt;
 	unsigned int offset = 0, chunk_offset = 0;
@@ -201,6 +216,7 @@
 	map.info.ctx_id = ctx_drvdata->num;
 	map.info.va = va;
 	map.info.size = len;
+	map.flags = IOMMU_TLBINVAL_FLAG;
 
 	if (sg->length == len) {
 		pa = get_phys_addr(sg);
@@ -239,7 +255,7 @@
 		map.plist.size = SZ_1M;
 	}
 
-	ret = scm_call(SCM_SVC_MP, IOMMU_SECURE_MAP, &map, sizeof(map),
+	ret = scm_call(SCM_SVC_MP, IOMMU_SECURE_MAP2, &map, sizeof(map),
 			&scm_ret, sizeof(scm_ret));
 	kfree(pa_list);
 	return ret;
@@ -249,50 +265,20 @@
 			struct msm_iommu_ctx_drvdata *ctx_drvdata,
 			unsigned long va, size_t len)
 {
-	struct msm_scm_mapping_info mi;
+	struct msm_scm_unmap2_req unmap;
 	int ret, scm_ret;
 
-	mi.id = iommu_drvdata->sec_id;
-	mi.ctx_id = ctx_drvdata->num;
-	mi.va = va;
-	mi.size = len;
+	unmap.info.id = iommu_drvdata->sec_id;
+	unmap.info.ctx_id = ctx_drvdata->num;
+	unmap.info.va = va;
+	unmap.info.size = len;
+	unmap.flags = IOMMU_TLBINVAL_FLAG;
 
-	ret = scm_call(SCM_SVC_MP, IOMMU_SECURE_UNMAP, &mi, sizeof(mi),
+	ret = scm_call(SCM_SVC_MP, IOMMU_SECURE_UNMAP2, &unmap, sizeof(unmap),
 			&scm_ret, sizeof(scm_ret));
 	return ret;
 }
 
-static int __enable_clocks(struct msm_iommu_drvdata *drvdata)
-{
-	int ret;
-
-	ret = clk_prepare_enable(drvdata->pclk);
-	if (ret)
-		goto fail;
-
-	ret = clk_prepare_enable(drvdata->clk);
-	if (ret)
-		clk_disable_unprepare(drvdata->pclk);
-
-	if (drvdata->aclk) {
-		ret = clk_prepare_enable(drvdata->aclk);
-		if (ret) {
-			clk_disable_unprepare(drvdata->clk);
-			clk_disable_unprepare(drvdata->pclk);
-		}
-	}
-fail:
-	return ret;
-}
-
-static void __disable_clocks(struct msm_iommu_drvdata *drvdata)
-{
-	if (drvdata->aclk)
-		clk_disable_unprepare(drvdata->aclk);
-	clk_disable_unprepare(drvdata->clk);
-	clk_disable_unprepare(drvdata->pclk);
-}
-
 static int msm_iommu_domain_init(struct iommu_domain *domain, int flags)
 {
 	struct msm_iommu_priv *priv;
@@ -310,12 +296,12 @@
 {
 	struct msm_iommu_priv *priv;
 
-	mutex_lock(&msm_iommu_lock);
+	iommu_access_ops->iommu_lock_acquire();
 	priv = domain->priv;
 	domain->priv = NULL;
 
 	kfree(priv);
-	mutex_unlock(&msm_iommu_lock);
+	iommu_access_ops->iommu_lock_release();
 }
 
 static int msm_iommu_attach_dev(struct iommu_domain *domain, struct device *dev)
@@ -326,7 +312,7 @@
 	struct msm_iommu_ctx_drvdata *tmp_drvdata;
 	int ret = 0;
 
-	mutex_lock(&msm_iommu_lock);
+	iommu_access_ops->iommu_lock_acquire();
 
 	priv = domain->priv;
 	if (!priv || !dev) {
@@ -352,15 +338,15 @@
 			goto fail;
 		}
 
-	ret = regulator_enable(iommu_drvdata->gdsc);
+	ret = iommu_access_ops->iommu_power_on(iommu_drvdata);
 	if (ret)
 		goto fail;
 
 	/* We can only do this once */
 	if (!iommu_drvdata->ctx_attach_count) {
-		ret = __enable_clocks(iommu_drvdata);
+		ret = iommu_access_ops->iommu_clk_on(iommu_drvdata);
 		if (ret) {
-			regulator_disable(iommu_drvdata->gdsc);
+			iommu_access_ops->iommu_power_off(iommu_drvdata);
 			goto fail;
 		}
 
@@ -370,9 +356,9 @@
 		program_iommu_bfb_settings(iommu_drvdata->base,
 					   iommu_drvdata->bfb_settings);
 
-		__disable_clocks(iommu_drvdata);
+		iommu_access_ops->iommu_clk_off(iommu_drvdata);
 		if (ret) {
-			regulator_disable(iommu_drvdata->gdsc);
+			iommu_access_ops->iommu_power_off(iommu_drvdata);
 			goto fail;
 		}
 	}
@@ -381,12 +367,12 @@
 	ctx_drvdata->attached_domain = domain;
 	++iommu_drvdata->ctx_attach_count;
 
-	mutex_unlock(&msm_iommu_lock);
+	iommu_access_ops->iommu_lock_release();
 
 	msm_iommu_attached(dev->parent);
 	return ret;
 fail:
-	mutex_unlock(&msm_iommu_lock);
+	iommu_access_ops->iommu_lock_release();
 	return ret;
 }
 
@@ -398,7 +384,7 @@
 
 	msm_iommu_detached(dev->parent);
 
-	mutex_lock(&msm_iommu_lock);
+	iommu_access_ops->iommu_lock_acquire();
 	if (!dev)
 		goto fail;
 
@@ -410,11 +396,11 @@
 	list_del_init(&ctx_drvdata->attached_elm);
 	ctx_drvdata->attached_domain = NULL;
 
-	regulator_disable(iommu_drvdata->gdsc);
+	iommu_access_ops->iommu_power_off(iommu_drvdata);
 	BUG_ON(iommu_drvdata->ctx_attach_count == 0);
 	--iommu_drvdata->ctx_attach_count;
 fail:
-	mutex_unlock(&msm_iommu_lock);
+	iommu_access_ops->iommu_lock_release();
 }
 
 static int get_drvdata(struct iommu_domain *domain,
@@ -444,16 +430,18 @@
 	struct msm_iommu_ctx_drvdata *ctx_drvdata;
 	int ret = 0;
 
-	mutex_lock(&msm_iommu_lock);
+	iommu_access_ops->iommu_lock_acquire();
 
 	ret = get_drvdata(domain, &iommu_drvdata, &ctx_drvdata);
 	if (ret)
 		goto fail;
 
+	iommu_access_ops->iommu_clk_on(iommu_drvdata);
 	ret = msm_iommu_sec_ptbl_map(iommu_drvdata, ctx_drvdata,
 					va, pa, len);
+	iommu_access_ops->iommu_clk_off(iommu_drvdata);
 fail:
-	mutex_unlock(&msm_iommu_lock);
+	iommu_access_ops->iommu_lock_release();
 	return ret;
 }
 
@@ -464,16 +452,18 @@
 	struct msm_iommu_ctx_drvdata *ctx_drvdata;
 	int ret = -ENODEV;
 
-	mutex_lock(&msm_iommu_lock);
+	iommu_access_ops->iommu_lock_acquire();
 
 	ret = get_drvdata(domain, &iommu_drvdata, &ctx_drvdata);
 	if (ret)
 		goto fail;
 
+	iommu_access_ops->iommu_clk_on(iommu_drvdata);
 	ret = msm_iommu_sec_ptbl_unmap(iommu_drvdata, ctx_drvdata,
 					va, len);
+	iommu_access_ops->iommu_clk_off(iommu_drvdata);
 fail:
-	mutex_unlock(&msm_iommu_lock);
+	iommu_access_ops->iommu_lock_release();
 
 	/* the IOMMU API requires us to return how many bytes were unmapped */
 	len = ret ? 0 : len;
@@ -488,15 +478,17 @@
 	struct msm_iommu_drvdata *iommu_drvdata;
 	struct msm_iommu_ctx_drvdata *ctx_drvdata;
 
-	mutex_lock(&msm_iommu_lock);
+	iommu_access_ops->iommu_lock_acquire();
 
 	ret = get_drvdata(domain, &iommu_drvdata, &ctx_drvdata);
 	if (ret)
 		goto fail;
+	iommu_access_ops->iommu_clk_on(iommu_drvdata);
 	ret = msm_iommu_sec_ptbl_map_range(iommu_drvdata, ctx_drvdata,
 						va, sg, len);
+	iommu_access_ops->iommu_clk_off(iommu_drvdata);
 fail:
-	mutex_unlock(&msm_iommu_lock);
+	iommu_access_ops->iommu_lock_release();
 	return ret;
 }
 
@@ -508,16 +500,18 @@
 	struct msm_iommu_ctx_drvdata *ctx_drvdata;
 	int ret;
 
-	mutex_lock(&msm_iommu_lock);
+	iommu_access_ops->iommu_lock_acquire();
 
 	ret = get_drvdata(domain, &iommu_drvdata, &ctx_drvdata);
 	if (ret)
 		goto fail;
 
+	iommu_access_ops->iommu_clk_on(iommu_drvdata);
 	ret = msm_iommu_sec_ptbl_unmap(iommu_drvdata, ctx_drvdata, va, len);
+	iommu_access_ops->iommu_clk_off(iommu_drvdata);
 
 fail:
-	mutex_unlock(&msm_iommu_lock);
+	iommu_access_ops->iommu_lock_release();
 	return 0;
 }
 
diff --git a/drivers/leds/leds-qpnp.c b/drivers/leds/leds-qpnp.c
index ac06fc5..e88e574 100644
--- a/drivers/leds/leds-qpnp.c
+++ b/drivers/leds/leds-qpnp.c
@@ -991,6 +991,7 @@
 static struct attribute *led_attrs[] = {
 	&dev_attr_led_mode.attr,
 	&dev_attr_strobe.attr,
+	NULL
 };
 
 static const struct attribute_group led_attr_group = {
diff --git a/drivers/media/dvb/dvb-core/dvb_ringbuffer.c b/drivers/media/dvb/dvb-core/dvb_ringbuffer.c
index 92f7463..e8480f7 100644
--- a/drivers/media/dvb/dvb-core/dvb_ringbuffer.c
+++ b/drivers/media/dvb/dvb-core/dvb_ringbuffer.c
@@ -5,7 +5,7 @@
  * Copyright (C) 2003 Oliver Endriss
  * Copyright (C) 2004 Andrew de Quincey
  *
- * Copyright (c) 2012, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
  *
  * based on code originally found in av7110.c & dvb_ci.c:
  * Copyright (C) 1999-2003 Ralph  Metzler
@@ -334,7 +334,10 @@
 		idx = (idx + curpktlen + DVB_RINGBUFFER_PKTHDRSIZE) % rbuf->size;
 	}
 
-	consumed = (idx - rbuf->pread) % rbuf->size;
+	if (idx >= rbuf->pread)
+		consumed = idx - rbuf->pread;
+	else
+		consumed = rbuf->size - (rbuf->pread - idx);
 
 	while((dvb_ringbuffer_avail(rbuf) - consumed) > DVB_RINGBUFFER_PKTHDRSIZE) {
 
diff --git a/drivers/media/platform/msm/camera_v1/mercury/msm_mercury_platform.c b/drivers/media/platform/msm/camera_v1/mercury/msm_mercury_platform.c
index 3607f2e..cda36d9 100644
--- a/drivers/media/platform/msm/camera_v1/mercury/msm_mercury_platform.c
+++ b/drivers/media/platform/msm/camera_v1/mercury/msm_mercury_platform.c
@@ -16,7 +16,6 @@
 
 #include <mach/clk.h>
 #include <mach/camera.h>
-#include <mach/msm_subsystem_map.h>
 
 #include "msm_mercury_platform.h"
 #include "msm_mercury_sync.h"
diff --git a/drivers/media/platform/msm/camera_v2/Kconfig b/drivers/media/platform/msm/camera_v2/Kconfig
index 269e538..d9552e2 100644
--- a/drivers/media/platform/msm/camera_v2/Kconfig
+++ b/drivers/media/platform/msm/camera_v2/Kconfig
@@ -64,6 +64,15 @@
           based on cid which is mapped to a virtual channel
           and datatype.
 
+config MSM_EEPROM
+        bool "Qualcomm MSM Camera ROM Interface for Calibration support"
+        depends on MSMB_CAMERA
+        ---help---
+          Enable support for ROM Interface for Calibration
+          Provides interface for reading the Claibration data.
+          and also provides support for writing data in case of FLASH ROM.
+	  Currently supports I2C, CCI and SPI protocol
+
 config MSM_ISPIF
         bool "Qualcomm MSM Image Signal Processing interface support"
         depends on MSMB_CAMERA
diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp.c
index ff86aae..447c752 100644
--- a/drivers/media/platform/msm/camera_v2/isp/msm_isp.c
+++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp.c
@@ -113,7 +113,8 @@
 	vfe_dev->subdev.sd.flags |= V4L2_SUBDEV_FL_HAS_EVENTS;
 	v4l2_set_subdevdata(&vfe_dev->subdev.sd, vfe_dev);
 	platform_set_drvdata(pdev, &vfe_dev->subdev.sd);
-	mutex_init(&vfe_dev->mutex);
+	mutex_init(&vfe_dev->realtime_mutex);
+	mutex_init(&vfe_dev->core_mutex);
 	spin_lock_init(&vfe_dev->tasklet_lock);
 	spin_lock_init(&vfe_dev->shared_data_lock);
 	media_entity_init(&vfe_dev->subdev.sd.entity, 0, NULL, 0);
diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp.h b/drivers/media/platform/msm/camera_v2/isp/msm_isp.h
index cfbe29c..1b762ea 100644
--- a/drivers/media/platform/msm/camera_v2/isp/msm_isp.h
+++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp.h
@@ -33,7 +33,7 @@
 #define MAX_NUM_COMPOSITE_MASK 4
 #define MAX_NUM_STATS_COMP_MASK 2
 #define MAX_INIT_FRAME_DROP 31
-#define ISP_SUB(a) ((a > 0) ? a-1 : 0)
+#define ISP_Q2 (1 << 2)
 
 #define VFE_PING_FLAG 0xFFFFFFFF
 #define VFE_PONG_FLAG 0x0
@@ -183,6 +183,7 @@
 
 struct msm_vfe_hardware_info {
 	int num_iommu_ctx;
+	int vfe_clk_idx;
 	struct msm_vfe_ops vfe_ops;
 	struct msm_vfe_axi_hardware_info *axi_hw_info;
 	struct msm_vfe_stats_hardware_info *stats_hw_info;
@@ -206,6 +207,7 @@
 	PAUSE,
 	START_PENDING,
 	STOP_PENDING,
+	STARTING,
 	STOPPING,
 	PAUSE_PENDING,
 };
@@ -246,9 +248,16 @@
 	uint32_t burst_frame_count;/*number of sof before burst stop*/
 	uint8_t framedrop_update;
 
+	/*Bandwidth calculation info*/
+	uint32_t max_width;
+	/*Based on format plane size in Q2. e.g NV12 = 1.5*/
+	uint32_t format_factor;
+	uint32_t bandwidth;
+
 	/*Run time update variables*/
 	uint32_t runtime_init_frame_drop;
 	uint32_t runtime_burst_frame_count;/*number of sof before burst stop*/
+	uint32_t runtime_num_burst_capture;
 	uint8_t runtime_framedrop_update;
 };
 
@@ -263,6 +272,8 @@
 	uint8_t pix_stream_count;
 	uint8_t raw_stream_count;
 	enum msm_vfe_inputmux input_mux;
+	uint32_t width;
+	long pixel_clock;
 };
 
 enum msm_wm_ub_cfg_type {
@@ -369,7 +380,8 @@
 	struct completion reset_complete;
 	struct completion halt_complete;
 	struct completion stream_config_complete;
-	struct mutex mutex;
+	struct mutex realtime_mutex;
+	struct mutex core_mutex;
 
 	atomic_t irq_cnt;
 	uint8_t taskletq_idx;
diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp32.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp32.c
index b981653..31fa39e 100644
--- a/drivers/media/platform/msm/camera_v2/isp/msm_isp32.c
+++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp32.c
@@ -39,42 +39,7 @@
 	(VFE32_STATS_BASE(idx) + 0x4 * \
 	(~(ping_pong >> (idx + VFE32_STATS_PING_PONG_OFFSET)) & 0x1))
 
-/*Temporary use fixed bus vectors in VFE */
-static struct msm_bus_vectors msm_vfe32_init_vectors[] = {
-	{
-		.src = MSM_BUS_MASTER_VFE,
-		.dst = MSM_BUS_SLAVE_EBI_CH0,
-		.ab  = 0,
-		.ib  = 0,
-	},
-};
-
-static struct msm_bus_vectors msm_vfe32_preview_vectors[] = {
-	{
-		.src = MSM_BUS_MASTER_VFE,
-		.dst = MSM_BUS_SLAVE_EBI_CH0,
-		.ab  = 1027648000,
-		.ib  = 1105920000,
-	},
-};
-
-static struct msm_bus_paths msm_vfe32_bus_client_config[] = {
-	{
-		ARRAY_SIZE(msm_vfe32_init_vectors),
-		msm_vfe32_init_vectors,
-	},
-	{
-		ARRAY_SIZE(msm_vfe32_preview_vectors),
-		msm_vfe32_preview_vectors,
-	},
-};
-
-static struct msm_bus_scale_pdata msm_vfe32_bus_client_pdata = {
-		msm_vfe32_bus_client_config,
-		ARRAY_SIZE(msm_vfe32_bus_client_config),
-		.name = "msm_camera_vfe",
-};
-
+#define VFE32_CLK_IDX 0
 static struct msm_cam_clk_info msm_vfe32_clk_info[] = {
 	{"vfe_clk", 266667000},
 	{"vfe_pclk", -1},
@@ -84,15 +49,11 @@
 static int msm_vfe32_init_hardware(struct vfe_device *vfe_dev)
 {
 	int rc = -1;
-
-	vfe_dev->bus_perf_client =
-		msm_bus_scale_register_client(&msm_vfe32_bus_client_pdata);
-	if (!vfe_dev->bus_perf_client) {
-		pr_err("%s: Registration Failed!\n", __func__);
-		vfe_dev->bus_perf_client = 0;
+	rc = msm_isp_init_bandwidth_mgr(ISP_VFE0 + vfe_dev->pdev->id);
+	if (rc < 0) {
+		pr_err("%s: Bandwidth registration Failed!\n", __func__);
 		goto bus_scale_register_failed;
 	}
-	msm_bus_scale_client_update_request(vfe_dev->bus_perf_client, 1);
 
 	if (vfe_dev->fs_vfe) {
 		rc = regulator_enable(vfe_dev->fs_vfe);
@@ -131,8 +92,7 @@
 clk_enable_failed:
 	regulator_disable(vfe_dev->fs_vfe);
 fs_failed:
-	msm_bus_scale_client_update_request(vfe_dev->bus_perf_client, 0);
-	msm_bus_scale_unregister_client(vfe_dev->bus_perf_client);
+	msm_isp_deinit_bandwidth_mgr(ISP_VFE0 + vfe_dev->pdev->id);
 bus_scale_register_failed:
 	return rc;
 }
@@ -145,8 +105,7 @@
 	msm_cam_clk_enable(&vfe_dev->pdev->dev, msm_vfe32_clk_info,
 		 vfe_dev->vfe_clk, ARRAY_SIZE(msm_vfe32_clk_info), 0);
 	regulator_disable(vfe_dev->fs_vfe);
-	msm_bus_scale_client_update_request(vfe_dev->bus_perf_client, 0);
-	msm_bus_scale_unregister_client(vfe_dev->bus_perf_client);
+	msm_isp_deinit_bandwidth_mgr(ISP_VFE0 + vfe_dev->pdev->id);
 }
 
 static void msm_vfe32_init_hardware_reg(struct vfe_device *vfe_dev)
@@ -1021,6 +980,7 @@
 
 struct msm_vfe_hardware_info vfe32_hw_info = {
 	.num_iommu_ctx = 2,
+	.vfe_clk_idx = VFE32_CLK_IDX,
 	.vfe_ops = {
 		.irq_ops = {
 			.read_irq_status = msm_vfe32_read_irq_status,
diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp40.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp40.c
index a786750..256d136 100644
--- a/drivers/media/platform/msm/camera_v2/isp/msm_isp40.c
+++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp40.c
@@ -77,42 +77,7 @@
 #define VFE40_BUS_BDG_QOS_CFG_6     0x000002DC
 #define VFE40_BUS_BDG_QOS_CFG_7     0x000002E0
 
-/*Temporary use fixed bus vectors in VFE */
-static struct msm_bus_vectors msm_vfe40_init_vectors[] = {
-	{
-		.src = MSM_BUS_MASTER_VFE,
-		.dst = MSM_BUS_SLAVE_EBI_CH0,
-		.ab  = 0,
-		.ib  = 0,
-	},
-};
-
-static struct msm_bus_vectors msm_vfe40_preview_vectors[] = {
-	{
-		.src = MSM_BUS_MASTER_VFE,
-		.dst = MSM_BUS_SLAVE_EBI_CH0,
-		.ab  = 2027648000U,
-		.ib  = 2805920000U,
-	},
-};
-
-static struct msm_bus_paths msm_vfe40_bus_client_config[] = {
-	{
-		ARRAY_SIZE(msm_vfe40_init_vectors),
-		msm_vfe40_init_vectors,
-	},
-	{
-		ARRAY_SIZE(msm_vfe40_preview_vectors),
-		msm_vfe40_preview_vectors,
-	},
-};
-
-static struct msm_bus_scale_pdata msm_vfe40_bus_client_pdata = {
-	msm_vfe40_bus_client_config,
-	ARRAY_SIZE(msm_vfe40_bus_client_config),
-	.name = "msm_camera_vfe",
-};
-
+#define VFE40_CLK_IDX 1
 static struct msm_cam_clk_info msm_vfe40_clk_info[] = {
 	{"camss_top_ahb_clk", -1},
 	{"vfe_clk_src", 266670000},
@@ -223,16 +188,11 @@
 static int msm_vfe40_init_hardware(struct vfe_device *vfe_dev)
 {
 	int rc = -1;
-
-	vfe_dev->bus_perf_client =
-		msm_bus_scale_register_client(&msm_vfe40_bus_client_pdata);
-	if (!vfe_dev->bus_perf_client) {
-		pr_err("%s: Registration Failed!\n", __func__);
-		vfe_dev->bus_perf_client = 0;
+	rc = msm_isp_init_bandwidth_mgr(ISP_VFE0 + vfe_dev->pdev->id);
+	if (rc < 0) {
+		pr_err("%s: Bandwidth registration Failed!\n", __func__);
 		goto bus_scale_register_failed;
 	}
-	msm_bus_scale_client_update_request(
-		vfe_dev->bus_perf_client, 1);
 
 	if (vfe_dev->fs_vfe) {
 		rc = regulator_enable(vfe_dev->fs_vfe);
@@ -280,8 +240,7 @@
 clk_enable_failed:
 	regulator_disable(vfe_dev->fs_vfe);
 fs_failed:
-	msm_bus_scale_client_update_request(vfe_dev->bus_perf_client, 0);
-	msm_bus_scale_unregister_client(vfe_dev->bus_perf_client);
+	msm_isp_deinit_bandwidth_mgr(ISP_VFE0 + vfe_dev->pdev->id);
 bus_scale_register_failed:
 	return rc;
 }
@@ -295,8 +254,7 @@
 	msm_cam_clk_enable(&vfe_dev->pdev->dev, msm_vfe40_clk_info,
 		vfe_dev->vfe_clk, ARRAY_SIZE(msm_vfe40_clk_info), 0);
 	regulator_disable(vfe_dev->fs_vfe);
-	msm_bus_scale_client_update_request(vfe_dev->bus_perf_client, 0);
-	msm_bus_scale_unregister_client(vfe_dev->bus_perf_client);
+	msm_isp_deinit_bandwidth_mgr(ISP_VFE0 + vfe_dev->pdev->id);
 }
 
 static void msm_vfe40_init_hardware_reg(struct vfe_device *vfe_dev)
@@ -1288,6 +1246,7 @@
 
 struct msm_vfe_hardware_info vfe40_hw_info = {
 	.num_iommu_ctx = 1,
+	.vfe_clk_idx = VFE40_CLK_IDX,
 	.vfe_ops = {
 		.irq_ops = {
 			.read_irq_status = msm_vfe40_read_irq_status,
diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c
index f1bfd68..477985d 100644
--- a/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c
+++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c
@@ -18,6 +18,8 @@
 	((src < RDI_INTF_0) ? VFE_PIX_0 : \
 	(VFE_RAW_0 + src - RDI_INTF_0))
 
+#define HANDLE_TO_IDX(handle) (handle & 0xFF)
+
 int msm_isp_axi_create_stream(
 	struct msm_vfe_axi_shared_data *axi_data,
 	struct msm_vfe_axi_stream_request_cmd *stream_cfg_cmd)
@@ -67,7 +69,7 @@
 	int rc = -1, i;
 	struct msm_vfe_axi_stream *stream_info =
 		&axi_data->stream_info[
-			(stream_cfg_cmd->axi_stream_handle & 0xFF)];
+			HANDLE_TO_IDX(stream_cfg_cmd->axi_stream_handle)];
 
 	switch (stream_cfg_cmd->output_format) {
 	case V4L2_PIX_FMT_SBGGR8:
@@ -95,12 +97,14 @@
 	case V4L2_PIX_FMT_QGRBG12:
 	case V4L2_PIX_FMT_QRGGB12:
 		stream_info->num_planes = 1;
+		stream_info->format_factor = ISP_Q2;
 		break;
 	case V4L2_PIX_FMT_NV12:
 	case V4L2_PIX_FMT_NV21:
 	case V4L2_PIX_FMT_NV16:
 	case V4L2_PIX_FMT_NV61:
 		stream_info->num_planes = 2;
+		stream_info->format_factor = 1.5 * ISP_Q2;
 		break;
 	/*TD: Add more image format*/
 	default:
@@ -131,9 +135,12 @@
 		return rc;
 	}
 
-	for (i = 0; i < stream_info->num_planes; i++)
+	for (i = 0; i < stream_info->num_planes; i++) {
 		stream_info->plane_offset[i] =
 			stream_cfg_cmd->plane_cfg[i].plane_addr_offset;
+		stream_info->max_width = max(stream_info->max_width,
+			stream_cfg_cmd->plane_cfg[i].output_width);
+	}
 
 	stream_info->stream_src = stream_cfg_cmd->stream_src;
 	stream_info->frame_based = stream_cfg_cmd->frame_base;
@@ -209,7 +216,7 @@
 	int i, j;
 	struct msm_vfe_axi_stream *stream_info =
 		&axi_data->stream_info[
-			(stream_cfg_cmd->axi_stream_handle & 0xFF)];
+			HANDLE_TO_IDX(stream_cfg_cmd->axi_stream_handle)];
 
 	for (i = 0; i < stream_info->num_planes; i++) {
 		for (j = 0; j < axi_data->hw_info->num_wm; j++) {
@@ -245,7 +252,7 @@
 	uint8_t comp_mask = 0;
 	struct msm_vfe_axi_stream *stream_info =
 		&axi_data->stream_info[
-			(stream_cfg_cmd->axi_stream_handle & 0xFF)];
+			HANDLE_TO_IDX(stream_cfg_cmd->axi_stream_handle)];
 	for (i = 0; i < stream_info->num_planes; i++)
 		comp_mask |= 1 << stream_info->wm[i];
 
@@ -285,7 +292,7 @@
 
 	for (i = 0; i < stream_cfg_cmd->num_streams; i++) {
 		stream_info = &axi_data->stream_info[
-			(stream_cfg_cmd->stream_handle[i] & 0xFF)];
+			HANDLE_TO_IDX(stream_cfg_cmd->stream_handle[i])];
 		if (stream_info->state != valid_state) {
 			pr_err("%s: Invalid stream state\n", __func__);
 			rc = -EINVAL;
@@ -344,6 +351,8 @@
 	stream_info->runtime_init_frame_drop = stream_info->init_frame_drop;
 	stream_info->runtime_burst_frame_count =
 		stream_info->burst_frame_count;
+	stream_info->runtime_num_burst_capture =
+		stream_info->num_burst_capture;
 	stream_info->runtime_framedrop_update = stream_info->framedrop_update;
 	vfe_dev->hw_info->vfe_ops.axi_ops.cfg_framedrop(vfe_dev, stream_info);
 }
@@ -411,7 +420,7 @@
 {
 	struct msm_vfe_axi_stream *stream_info =
 		&axi_data->stream_info[
-		(stream_cfg_cmd->axi_stream_handle & 0xFF)];
+		HANDLE_TO_IDX(stream_cfg_cmd->axi_stream_handle)];
 	uint32_t framedrop_period = msm_isp_get_framedrop_period(
 	   stream_cfg_cmd->frame_skip_pattern);
 
@@ -443,6 +452,23 @@
 	}
 }
 
+void msm_isp_calculate_bandwidth(
+	struct msm_vfe_axi_shared_data *axi_data,
+	struct msm_vfe_axi_stream *stream_info)
+{
+	if (stream_info->stream_src < RDI_INTF_0) {
+		stream_info->bandwidth =
+			(axi_data->src_info[VFE_PIX_0].pixel_clock /
+			axi_data->src_info[VFE_PIX_0].width) *
+			stream_info->max_width;
+		stream_info->bandwidth = stream_info->bandwidth *
+			stream_info->format_factor / ISP_Q2;
+	} else {
+		int rdi = SRC_TO_INTF(stream_info->stream_src);
+		stream_info->bandwidth = axi_data->src_info[rdi].pixel_clock;
+	}
+}
+
 int msm_isp_request_axi_stream(struct vfe_device *vfe_dev, void *arg)
 {
 	int rc = 0, i;
@@ -461,13 +487,12 @@
 	if (rc) {
 		pr_err("%s: Request validation failed\n", __func__);
 		msm_isp_axi_destroy_stream(&vfe_dev->axi_data,
-			(stream_cfg_cmd->axi_stream_handle & 0xFF));
+			HANDLE_TO_IDX(stream_cfg_cmd->axi_stream_handle));
 		return rc;
 	}
 
-	stream_info =
-		&vfe_dev->axi_data.
-			stream_info[(stream_cfg_cmd->axi_stream_handle & 0xFF)];
+	stream_info = &vfe_dev->axi_data.
+		stream_info[HANDLE_TO_IDX(stream_cfg_cmd->axi_stream_handle)];
 	msm_isp_axi_reserve_wm(&vfe_dev->axi_data, stream_cfg_cmd);
 
 	if (stream_cfg_cmd->stream_src == CAMIF_RAW ||
@@ -504,7 +529,7 @@
 	struct msm_vfe_axi_shared_data *axi_data = &vfe_dev->axi_data;
 	struct msm_vfe_axi_stream *stream_info =
 		&axi_data->stream_info[
-		(stream_release_cmd->stream_handle & 0xFF)];
+		HANDLE_TO_IDX(stream_release_cmd->stream_handle)];
 	struct msm_vfe_axi_stream_cfg_cmd stream_cfg;
 
 	if (stream_info->state == AVALIABLE) {
@@ -538,79 +563,70 @@
 	msm_isp_axi_free_wm(axi_data, stream_info);
 
 	msm_isp_axi_destroy_stream(&vfe_dev->axi_data,
-		(stream_release_cmd->stream_handle & 0xFF));
+		HANDLE_TO_IDX(stream_release_cmd->stream_handle));
 
 	return rc;
 }
 
-void msm_isp_axi_stream_enable_cfg(
+static void msm_isp_axi_stream_enable_cfg(
 	struct vfe_device *vfe_dev,
-	struct msm_vfe_axi_stream *stream_info,
-	uint32_t *wm_reload_mask)
+	struct msm_vfe_axi_stream *stream_info)
 {
 	int i;
 	struct msm_vfe_axi_shared_data *axi_data = &vfe_dev->axi_data;
 	if (stream_info->state == INACTIVE)
 		return;
 	for (i = 0; i < stream_info->num_planes; i++) {
-		/*TD: Frame base command*/
 		if (stream_info->state == START_PENDING)
 			vfe_dev->hw_info->vfe_ops.axi_ops.
 				enable_wm(vfe_dev, stream_info->wm[i], 1);
 		else
 			vfe_dev->hw_info->vfe_ops.axi_ops.
 				enable_wm(vfe_dev, stream_info->wm[i], 0);
-
-		*wm_reload_mask |= (1 << stream_info->wm[i]);
 	}
 
-	if (stream_info->state == START_PENDING) {
+	if (stream_info->state == START_PENDING)
 		axi_data->num_active_stream++;
-		stream_info->state = ACTIVE;
-	} else {
+	else
 		axi_data->num_active_stream--;
-		stream_info->state = INACTIVE;
-	}
 }
 
 void msm_isp_axi_stream_update(struct vfe_device *vfe_dev)
 {
 	int i;
 	struct msm_vfe_axi_shared_data *axi_data = &vfe_dev->axi_data;
-	uint32_t wm_reload_mask = 0x0;
 	for (i = 0; i < MAX_NUM_STREAM; i++) {
 		if (axi_data->stream_info[i].state == START_PENDING ||
 				axi_data->stream_info[i].state ==
 					STOP_PENDING) {
 			msm_isp_axi_stream_enable_cfg(
-				vfe_dev, &axi_data->stream_info[i],
-				&wm_reload_mask);
-			if (axi_data->stream_info[i].state == STOP_PENDING)
-				axi_data->stream_info[i].state = STOPPING;
+				vfe_dev, &axi_data->stream_info[i]);
+			axi_data->stream_info[i].state =
+				axi_data->stream_info[i].state ==
+				START_PENDING ? STARTING : STOPPING;
+		} else if (axi_data->stream_info[i].state == STARTING ||
+			axi_data->stream_info[i].state == STOPPING) {
+			axi_data->stream_info[i].state =
+				axi_data->stream_info[i].state == STARTING ?
+				ACTIVE : INACTIVE;
 		}
 	}
-	/*Reload AXI*/
-	vfe_dev->hw_info->vfe_ops.axi_ops.
-		reload_wm(vfe_dev, wm_reload_mask);
-	if (vfe_dev->axi_data.stream_update) {
-		vfe_dev->hw_info->vfe_ops.core_ops.reg_update(vfe_dev);
-		ISP_DBG("%s: send update complete\n", __func__);
-		vfe_dev->axi_data.stream_update = 0;
+	vfe_dev->axi_data.stream_update--;
+	if (vfe_dev->axi_data.stream_update == 0)
 		complete(&vfe_dev->stream_config_complete);
-	}
 }
 
 static void msm_isp_cfg_pong_address(struct vfe_device *vfe_dev,
 		struct msm_vfe_axi_stream *stream_info)
 {
 	int i;
-	struct msm_isp_buffer *buf = stream_info->buf[1];
+	struct msm_isp_buffer *buf = stream_info->buf[0];
 	for (i = 0; i < stream_info->num_planes; i++)
 		vfe_dev->hw_info->vfe_ops.axi_ops.update_ping_pong_addr(
 			vfe_dev, stream_info->wm[i],
-			VFE_PING_FLAG, buf->mapped_info[i].paddr +
+			VFE_PONG_FLAG, buf->mapped_info[i].paddr +
 			stream_info->plane_offset[i]);
-	stream_info->buf[0] = buf;
+	stream_info->buf[1] = buf;
 }
 
 static void msm_isp_get_done_buf(struct vfe_device *vfe_dev,
@@ -636,7 +652,7 @@
 	struct msm_isp_buffer *buf = NULL;
 	uint32_t pingpong_bit = 0;
 	uint32_t bufq_handle = stream_info->bufq_handle;
-	uint32_t stream_idx = stream_info->stream_handle & 0xFF;
+	uint32_t stream_idx = HANDLE_TO_IDX(stream_info->stream_handle);
 
 	rc = vfe_dev->buf_mgr->ops->get_buf(vfe_dev->buf_mgr,
 			vfe_dev->pdev->id, bufq_handle, &buf);
@@ -673,7 +689,7 @@
 {
 	int rc;
 	struct msm_isp_event_data buf_event;
-	uint32_t stream_idx = stream_info->stream_handle & 0xFF;
+	uint32_t stream_idx = HANDLE_TO_IDX(stream_info->stream_handle);
 	uint32_t frame_id = vfe_dev->axi_data.
 		src_info[SRC_TO_INTF(stream_info->stream_src)].frame_id;
 
@@ -724,7 +740,7 @@
 	for (i = 0; i < stream_cfg_cmd->num_streams; i++) {
 		stream_info =
 			&axi_data->stream_info[
-			(stream_cfg_cmd->stream_handle[i] & 0xFF)];
+			HANDLE_TO_IDX(stream_cfg_cmd->stream_handle[i])];
 		if (stream_info->stream_src  < RDI_INTF_0)
 			pix_stream_cnt++;
 		if (stream_info->stream_src == PIX_ENCODER ||
@@ -793,16 +809,193 @@
 		ISP_DBG("%s\n", line_str);
 }
 
-int msm_isp_cfg_axi_stream(struct vfe_device *vfe_dev, void *arg)
+/*Factor in Q2 format*/
+#define ISP_DEFAULT_FORMAT_FACTOR 6
+#define ISP_BUS_UTILIZATION_FACTOR 6
+static int msm_isp_update_stream_bandwidth(struct vfe_device *vfe_dev)
 {
-	int rc = 0, i;
-	struct msm_vfe_axi_stream_cfg_cmd *stream_cfg_cmd = arg;
+	int i, rc = 0;
+	struct msm_vfe_axi_stream *stream_info;
+	struct msm_vfe_axi_shared_data *axi_data = &vfe_dev->axi_data;
+	uint32_t total_pix_bandwidth = 0, total_rdi_bandwidth = 0;
+	uint32_t num_pix_streams = 0;
+	uint64_t total_bandwidth = 0;
+
+	for (i = 0; i < MAX_NUM_STREAM; i++) {
+		stream_info = &axi_data->stream_info[i];
+		if (stream_info->state == ACTIVE ||
+			stream_info->state == START_PENDING) {
+			if (stream_info->stream_src < RDI_INTF_0) {
+				total_pix_bandwidth += stream_info->bandwidth;
+				num_pix_streams++;
+			} else {
+				total_rdi_bandwidth += stream_info->bandwidth;
+			}
+		}
+	}
+	if (num_pix_streams > 0)
+		total_pix_bandwidth = total_pix_bandwidth /
+			num_pix_streams * (num_pix_streams - 1) +
+			axi_data->src_info[VFE_PIX_0].pixel_clock *
+			ISP_DEFAULT_FORMAT_FACTOR / ISP_Q2;
+	total_bandwidth = total_pix_bandwidth + total_rdi_bandwidth;
+
+	rc = msm_isp_update_bandwidth(ISP_VFE0 + vfe_dev->pdev->id,
+		total_bandwidth, total_bandwidth *
+		ISP_BUS_UTILIZATION_FACTOR / ISP_Q2);
+	if (rc < 0)
+		pr_err("%s: update failed\n", __func__);
+
+	return rc;
+}
+
+static int msm_isp_axi_wait_for_cfg_done(struct vfe_device *vfe_dev)
+{
+	int rc;
+	unsigned long flags;
+	spin_lock_irqsave(&vfe_dev->shared_data_lock, flags);
+	init_completion(&vfe_dev->stream_config_complete);
+	vfe_dev->axi_data.stream_update = 2;
+	spin_unlock_irqrestore(&vfe_dev->shared_data_lock, flags);
+	rc = wait_for_completion_interruptible_timeout(
+		&vfe_dev->stream_config_complete,
+		msecs_to_jiffies(500));
+	if (rc == 0) {
+		pr_err("%s: wait timeout\n", __func__);
+		rc = -1;
+	} else {
+		rc = 0;
+	}
+	return rc;
+}
+
+static int msm_isp_init_stream_ping_pong_reg(
+	struct vfe_device *vfe_dev,
+	struct msm_vfe_axi_stream *stream_info)
+{
+	int rc = 0;
+	/*Set address for both PING & PONG register */
+	rc = msm_isp_cfg_ping_pong_address(vfe_dev,
+		stream_info, VFE_PING_FLAG);
+	if (rc < 0) {
+		pr_err("%s: No free buffer for ping\n",
+			   __func__);
+		return rc;
+	}
+
+	/* For burst stream of one capture, only one buffer
+	 * is allocated. Duplicate ping buffer address to pong
+	 * buffer to ensure hardware write to a valid address
+	 */
+	if (stream_info->stream_type == BURST_STREAM &&
+		stream_info->runtime_num_burst_capture <= 1) {
+		msm_isp_cfg_pong_address(vfe_dev, stream_info);
+	} else {
+		rc = msm_isp_cfg_ping_pong_address(vfe_dev,
+			stream_info, VFE_PONG_FLAG);
+		if (rc < 0) {
+			pr_err("%s: No free buffer for pong\n",
+				   __func__);
+			return rc;
+		}
+	}
+	return rc;
+}
+
+static void msm_isp_get_stream_wm_mask(
+	struct msm_vfe_axi_stream *stream_info,
+	uint32_t *wm_reload_mask)
+{
+	int i;
+	for (i = 0; i < stream_info->num_planes; i++)
+		*wm_reload_mask |= (1 << stream_info->wm[i]);
+}
+
+static int msm_isp_start_axi_stream(struct vfe_device *vfe_dev,
+			struct msm_vfe_axi_stream_cfg_cmd *stream_cfg_cmd,
+			enum msm_isp_camif_update_state camif_update)
+{
+	int i, rc = 0;
+	uint8_t src_state, wait_for_complete = 0;
 	uint32_t wm_reload_mask = 0x0;
 	struct msm_vfe_axi_stream *stream_info;
 	struct msm_vfe_axi_shared_data *axi_data = &vfe_dev->axi_data;
-	uint8_t src_state;
+	for (i = 0; i < stream_cfg_cmd->num_streams; i++) {
+		stream_info = &axi_data->stream_info[
+			HANDLE_TO_IDX(stream_cfg_cmd->stream_handle[i])];
+		src_state = axi_data->src_info[
+			SRC_TO_INTF(stream_info->stream_src)].active;
+
+		msm_isp_calculate_bandwidth(axi_data, stream_info);
+		msm_isp_reset_framedrop(vfe_dev, stream_info);
+		msm_isp_get_stream_wm_mask(stream_info, &wm_reload_mask);
+		rc = msm_isp_init_stream_ping_pong_reg(vfe_dev, stream_info);
+		if (rc < 0) {
+			pr_err("%s: No buffer for stream%d\n", __func__,
+				HANDLE_TO_IDX(
+				stream_cfg_cmd->stream_handle[i]));
+			return rc;
+		}
+
+		stream_info->state = START_PENDING;
+		if (src_state) {
+			wait_for_complete = 1;
+		} else {
+			if (vfe_dev->dump_reg)
+				msm_camera_io_dump_2(vfe_dev->vfe_base, 0x900);
+
+			/*Configure AXI start bits to start immediately*/
+			msm_isp_axi_stream_enable_cfg(vfe_dev, stream_info);
+			stream_info->state = ACTIVE;
+		}
+	}
+	msm_isp_update_stream_bandwidth(vfe_dev);
+	vfe_dev->hw_info->vfe_ops.axi_ops.reload_wm(vfe_dev, wm_reload_mask);
+	vfe_dev->hw_info->vfe_ops.core_ops.reg_update(vfe_dev);
+
+	if (camif_update == ENABLE_CAMIF)
+		vfe_dev->hw_info->vfe_ops.core_ops.
+			update_camif_state(vfe_dev, camif_update);
+
+	if (wait_for_complete)
+		rc = msm_isp_axi_wait_for_cfg_done(vfe_dev);
+
+	return rc;
+}
+
+static int msm_isp_stop_axi_stream(struct vfe_device *vfe_dev,
+			struct msm_vfe_axi_stream_cfg_cmd *stream_cfg_cmd,
+			enum msm_isp_camif_update_state camif_update)
+{
+	int i, rc = 0;
+	struct msm_vfe_axi_stream *stream_info;
+	struct msm_vfe_axi_shared_data *axi_data = &vfe_dev->axi_data;
+	for (i = 0; i < stream_cfg_cmd->num_streams; i++) {
+		stream_info = &axi_data->stream_info[
+			HANDLE_TO_IDX(stream_cfg_cmd->stream_handle[i])];
+		stream_info->state = STOP_PENDING;
+	}
+
+	rc = msm_isp_axi_wait_for_cfg_done(vfe_dev);
+	if (rc < 0) {
+		pr_err("%s: wait for config done failed\n", __func__);
+		return rc;
+	}
+	msm_isp_update_stream_bandwidth(vfe_dev);
+	if (camif_update == DISABLE_CAMIF)
+		vfe_dev->hw_info->vfe_ops.core_ops.
+			update_camif_state(vfe_dev, DISABLE_CAMIF);
+	return rc;
+}
+
+
+int msm_isp_cfg_axi_stream(struct vfe_device *vfe_dev, void *arg)
+{
+	int rc = 0;
+	struct msm_vfe_axi_stream_cfg_cmd *stream_cfg_cmd = arg;
+	struct msm_vfe_axi_shared_data *axi_data = &vfe_dev->axi_data;
 	enum msm_isp_camif_update_state camif_update;
-	uint8_t wait_for_complete = 0;
+
 	rc = msm_isp_axi_check_stream_state(vfe_dev, stream_cfg_cmd);
 	if (rc < 0) {
 		pr_err("%s: Invalid stream state\n", __func__);
@@ -813,104 +1006,18 @@
 		/*Configure UB*/
 		vfe_dev->hw_info->vfe_ops.axi_ops.cfg_ub(vfe_dev);
 	}
-
 	camif_update =
 		msm_isp_update_camif_output_count(vfe_dev, stream_cfg_cmd);
 
-	if (camif_update == DISABLE_CAMIF)
-		vfe_dev->hw_info->vfe_ops.core_ops.
-			update_camif_state(vfe_dev, DISABLE_CAMIF);
+	if (stream_cfg_cmd->cmd == START_STREAM)
+		rc = msm_isp_start_axi_stream(
+		   vfe_dev, stream_cfg_cmd, camif_update);
+	else
+		rc = msm_isp_stop_axi_stream(
+		   vfe_dev, stream_cfg_cmd, camif_update);
 
-	/*
-	* Stream start either immediately or at reg update
-	* Depends on whether the stream src is active
-	* If source is on, start and stop have to be done during reg update
-	* If source is off, start can happen immediately or during reg update
-	* stop has to be done immediately.
-	*/
-	for (i = 0; i < stream_cfg_cmd->num_streams; i++) {
-		stream_info =
-			&axi_data->stream_info[
-				(stream_cfg_cmd->stream_handle[i] & 0xFF)];
-
-		if (stream_info->stream_src < RDI_INTF_0)
-			src_state = axi_data->src_info[0].active;
-		else
-			src_state = axi_data->src_info[
-			(stream_info->stream_src - RDI_INTF_0)].active;
-
-		stream_info->state = (stream_cfg_cmd->cmd == START_STREAM) ?
-			START_PENDING : STOP_PENDING;
-
-		if (stream_cfg_cmd->cmd == START_STREAM) {
-			/*Configure framedrop*/
-			msm_isp_reset_framedrop(vfe_dev, stream_info);
-
-			/*Set address for both PING & PONG register */
-			rc = msm_isp_cfg_ping_pong_address(vfe_dev,
-				stream_info, VFE_PONG_FLAG);
-			if (rc < 0) {
-				pr_err("%s: No buffer for start stream\n",
-					   __func__);
-				return rc;
-			}
-			/* For burst stream of one capture, only one buffer
-			 * is allocated. Duplicate ping buffer address to pong
-			 * buffer to ensure hardware write to a valid address
-			 */
-			if (stream_info->stream_type == BURST_STREAM &&
-				stream_info->num_burst_capture <= 1) {
-				msm_isp_cfg_pong_address(vfe_dev, stream_info);
-			} else {
-				rc = msm_isp_cfg_ping_pong_address(vfe_dev,
-					stream_info, VFE_PING_FLAG);
-			}
-		}
-		if (src_state && camif_update != DISABLE_CAMIF) {
-			/*On the fly stream start/stop */
-			wait_for_complete = 1;
-		} else {
-			if (vfe_dev->dump_reg &&
-				stream_cfg_cmd->cmd == START_STREAM)
-				msm_camera_io_dump_2(vfe_dev->vfe_base, 0x900);
-			/*Configure AXI start bits to start immediately*/
-			msm_isp_axi_stream_enable_cfg(
-				vfe_dev, stream_info, &wm_reload_mask);
-		}
-	}
-	if (!wait_for_complete) {
-		/*Reload AXI*/
-		if (stream_cfg_cmd->cmd == START_STREAM)
-			vfe_dev->hw_info->vfe_ops.axi_ops.
-			reload_wm(vfe_dev, wm_reload_mask);
-
-		vfe_dev->hw_info->vfe_ops.core_ops.
-			reg_update(vfe_dev);
-
-		if (camif_update == ENABLE_CAMIF)
-			vfe_dev->hw_info->vfe_ops.core_ops.
-				update_camif_state(vfe_dev, camif_update);
-	} else {
-		unsigned long flags;
-		spin_lock_irqsave(&vfe_dev->shared_data_lock, flags);
-		init_completion(&vfe_dev->stream_config_complete);
-		axi_data->stream_update = 1;
-		spin_unlock_irqrestore(&vfe_dev->shared_data_lock, flags);
-		/*Reload AXI*/
-		if (stream_cfg_cmd->cmd == START_STREAM)
-			vfe_dev->hw_info->vfe_ops.axi_ops.
-			reload_wm(vfe_dev, wm_reload_mask);
-		vfe_dev->hw_info->vfe_ops.core_ops.reg_update(vfe_dev);
-		rc = wait_for_completion_interruptible_timeout(
-			&vfe_dev->stream_config_complete,
-			msecs_to_jiffies(500));
-		if (rc == 0) {
-			pr_err("%s: wait timeout\n", __func__);
-			rc = -1;
-		} else {
-			rc = 0;
-		}
-	}
+	if (rc < 0)
+		pr_err("%s: start/stop stream failed\n", __func__);
 	return rc;
 }
 
@@ -921,7 +1028,7 @@
 	struct msm_vfe_axi_shared_data *axi_data = &vfe_dev->axi_data;
 	struct msm_vfe_axi_stream_update_cmd *update_cmd = arg;
 	stream_info = &axi_data->stream_info[
-			(update_cmd->stream_handle & 0xFF)];
+			HANDLE_TO_IDX(update_cmd->stream_handle)];
 	if (stream_info->state != ACTIVE && stream_info->state != INACTIVE) {
 		pr_err("%s: Invalid stream state\n", __func__);
 		return -EINVAL;
@@ -984,18 +1091,25 @@
 				pr_err("%s: Invalid handle for composite irq\n",
 					__func__);
 			} else {
-				stream_idx = comp_info->stream_handle & 0xFF;
+				stream_idx =
+					HANDLE_TO_IDX(comp_info->stream_handle);
 				stream_info =
 					&axi_data->stream_info[stream_idx];
 				ISP_DBG("%s: stream%d frame id: 0x%x\n",
 					__func__,
 					stream_idx, stream_info->frame_id);
 				stream_info->frame_id++;
+
+				if (stream_info->stream_type == BURST_STREAM)
+					stream_info->
+						runtime_num_burst_capture--;
+
 				msm_isp_get_done_buf(vfe_dev, stream_info,
 					pingpong_status, &done_buf);
 				if (stream_info->stream_type ==
 					CONTINUOUS_STREAM ||
-					stream_info->num_burst_capture > 1) {
+					stream_info->
+					runtime_num_burst_capture > 1) {
 					rc = msm_isp_cfg_ping_pong_address(
 							vfe_dev, stream_info,
 							pingpong_status);
@@ -1015,16 +1129,20 @@
 					__func__);
 				continue;
 			}
-			stream_idx = axi_data->free_wm[i] & 0xFF;
+			stream_idx = HANDLE_TO_IDX(axi_data->free_wm[i]);
 			stream_info = &axi_data->stream_info[stream_idx];
 			ISP_DBG("%s: stream%d frame id: 0x%x\n",
 				__func__,
 				stream_idx, stream_info->frame_id);
 			stream_info->frame_id++;
+
+			if (stream_info->stream_type == BURST_STREAM)
+				stream_info->runtime_num_burst_capture--;
+
 			msm_isp_get_done_buf(vfe_dev, stream_info,
 						pingpong_status, &done_buf);
 			if (stream_info->stream_type == CONTINUOUS_STREAM ||
-				stream_info->num_burst_capture > 1) {
+				stream_info->runtime_num_burst_capture > 1) {
 				rc = msm_isp_cfg_ping_pong_address(vfe_dev,
 					stream_info, pingpong_status);
 			}
diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.h b/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.h
index ba845bc..f592a60 100644
--- a/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.h
+++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.h
@@ -46,10 +46,6 @@
 int msm_isp_release_axi_stream(struct vfe_device *vfe_dev, void *arg);
 int msm_isp_update_axi_stream(struct vfe_device *vfe_dev, void *arg);
 
-void msm_isp_axi_stream_enable_cfg(struct vfe_device *vfe_dev,
-	struct msm_vfe_axi_stream *stream_info,
-	uint32_t *wm_reload_mask);
-
 void msm_isp_axi_stream_update(struct vfe_device *vfe_dev);
 
 void msm_isp_update_framedrop_reg(struct vfe_device *vfe_dev);
diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c
index ae89500..9fd87f3 100644
--- a/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c
+++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c
@@ -9,6 +9,7 @@
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
  */
+#include <linux/mutex.h>
 #include <linux/io.h>
 #include <media/v4l2-subdev.h>
 
@@ -19,6 +20,139 @@
 #include "msm_camera_io_util.h"
 
 #define MAX_ISP_V4l2_EVENTS 100
+static DEFINE_MUTEX(bandwidth_mgr_mutex);
+static struct msm_isp_bandwidth_mgr isp_bandwidth_mgr;
+
+#define MSM_ISP_MIN_AB 300000000
+#define MSM_ISP_MIN_IB 450000000
+
+static struct msm_bus_vectors msm_isp_init_vectors[] = {
+	{
+		.src = MSM_BUS_MASTER_VFE,
+		.dst = MSM_BUS_SLAVE_EBI_CH0,
+		.ab  = 0,
+		.ib  = 0,
+	},
+};
+
+static struct msm_bus_vectors msm_isp_ping_vectors[] = {
+	{
+		.src = MSM_BUS_MASTER_VFE,
+		.dst = MSM_BUS_SLAVE_EBI_CH0,
+		.ab  = MSM_ISP_MIN_AB,
+		.ib  = MSM_ISP_MIN_IB,
+	},
+};
+
+static struct msm_bus_vectors msm_isp_pong_vectors[] = {
+	{
+		.src = MSM_BUS_MASTER_VFE,
+		.dst = MSM_BUS_SLAVE_EBI_CH0,
+		.ab  = MSM_ISP_MIN_AB,
+		.ib  = MSM_ISP_MIN_IB,
+	},
+};
+
+static struct msm_bus_paths msm_isp_bus_client_config[] = {
+	{
+		ARRAY_SIZE(msm_isp_init_vectors),
+		msm_isp_init_vectors,
+	},
+	{
+		ARRAY_SIZE(msm_isp_ping_vectors),
+		msm_isp_ping_vectors,
+	},
+	{
+		ARRAY_SIZE(msm_isp_pong_vectors),
+		msm_isp_pong_vectors,
+	},
+};
+
+static struct msm_bus_scale_pdata msm_isp_bus_client_pdata = {
+	msm_isp_bus_client_config,
+	ARRAY_SIZE(msm_isp_bus_client_config),
+	.name = "msm_camera_isp",
+};
+
+int msm_isp_init_bandwidth_mgr(enum msm_isp_hw_client client)
+{
+	int rc = 0;
+	mutex_lock(&bandwidth_mgr_mutex);
+	isp_bandwidth_mgr.client_info[client].active = 1;
+	if (isp_bandwidth_mgr.use_count++) {
+		mutex_unlock(&bandwidth_mgr_mutex);
+		return rc;
+	}
+	isp_bandwidth_mgr.bus_client =
+		msm_bus_scale_register_client(&msm_isp_bus_client_pdata);
+	if (!isp_bandwidth_mgr.bus_client) {
+		pr_err("%s: client register failed\n", __func__);
+		mutex_unlock(&bandwidth_mgr_mutex);
+		return -EINVAL;
+	}
+
+	isp_bandwidth_mgr.bus_vector_active_idx = 1;
+	msm_bus_scale_client_update_request(
+	   isp_bandwidth_mgr.bus_client,
+	   isp_bandwidth_mgr.bus_vector_active_idx);
+
+	mutex_unlock(&bandwidth_mgr_mutex);
+	return 0;
+}
+
+int msm_isp_update_bandwidth(enum msm_isp_hw_client client,
+	uint64_t ab, uint64_t ib)
+{
+	int i;
+	struct msm_bus_paths *path;
+	mutex_lock(&bandwidth_mgr_mutex);
+	if (!isp_bandwidth_mgr.use_count ||
+		!isp_bandwidth_mgr.bus_client) {
+		pr_err("%s: bandwidth manager inactive\n", __func__);
+		return -EINVAL;
+	}
+
+	isp_bandwidth_mgr.client_info[client].ab = ab;
+	isp_bandwidth_mgr.client_info[client].ib = ib;
+	ALT_VECTOR_IDX(isp_bandwidth_mgr.bus_vector_active_idx);
+	path =
+		&(msm_isp_bus_client_pdata.usecase[
+		  isp_bandwidth_mgr.bus_vector_active_idx]);
+	path->vectors[0].ab = MSM_ISP_MIN_AB;
+	path->vectors[0].ib = MSM_ISP_MIN_IB;
+	for (i = 0; i < MAX_ISP_CLIENT; i++) {
+		if (isp_bandwidth_mgr.client_info[client].active) {
+			path->vectors[0].ab +=
+				isp_bandwidth_mgr.client_info[i].ab;
+			path->vectors[0].ib +=
+				isp_bandwidth_mgr.client_info[i].ib;
+		}
+	}
+	msm_bus_scale_client_update_request(isp_bandwidth_mgr.bus_client,
+		isp_bandwidth_mgr.bus_vector_active_idx);
+	mutex_unlock(&bandwidth_mgr_mutex);
+	return 0;
+}
+
+void msm_isp_deinit_bandwidth_mgr(enum msm_isp_hw_client client)
+{
+	mutex_lock(&bandwidth_mgr_mutex);
+	memset(&isp_bandwidth_mgr.client_info[client], 0,
+		   sizeof(struct msm_isp_bandwidth_info));
+	if (--isp_bandwidth_mgr.use_count) {
+		mutex_unlock(&bandwidth_mgr_mutex);
+		return;
+	}
+
+	if (!isp_bandwidth_mgr.bus_client)
+		return;
+
+	msm_bus_scale_client_update_request(
+	   isp_bandwidth_mgr.bus_client, 0);
+	msm_bus_scale_unregister_client(isp_bandwidth_mgr.bus_client);
+	isp_bandwidth_mgr.bus_client = 0;
+	mutex_unlock(&bandwidth_mgr_mutex);
+}
 
 static inline void msm_isp_get_timestamp(struct msm_isp_timestamp *time_stamp)
 {
@@ -68,28 +202,67 @@
 	return rc;
 }
 
-int msm_isp_cfg_pix(struct vfe_device *vfe_dev,
-	struct msm_vfe_pix_cfg *pix_cfg)
+static int msm_isp_set_clk_rate(struct vfe_device *vfe_dev, uint32_t rate)
 {
 	int rc = 0;
-	/*TD Validate config info
-	 * should check if all streams are off */
+	int clk_idx = vfe_dev->hw_info->vfe_clk_idx;
+	long round_rate =
+		clk_round_rate(vfe_dev->vfe_clk[clk_idx], rate);
+	if (round_rate < 0) {
+		pr_err("%s: Invalid vfe clock rate\n", __func__);
+		return round_rate;
+	}
 
-	vfe_dev->axi_data.src_info[VFE_PIX_0].input_mux = pix_cfg->input_mux;
+	rc = clk_set_rate(vfe_dev->vfe_clk[clk_idx], round_rate);
+	if (rc < 0) {
+		pr_err("%s: Vfe set rate error\n", __func__);
+		return rc;
+	}
+	return 0;
+}
 
-	vfe_dev->hw_info->vfe_ops.core_ops.cfg_camif(vfe_dev, pix_cfg);
+int msm_isp_cfg_pix(struct vfe_device *vfe_dev,
+	struct msm_vfe_input_cfg *input_cfg)
+{
+	int rc = 0;
+	if (vfe_dev->axi_data.src_info[VFE_PIX_0].active) {
+		pr_err("%s: pixel path is active\n", __func__);
+		return -EINVAL;
+	}
+
+	vfe_dev->axi_data.src_info[VFE_PIX_0].pixel_clock =
+		input_cfg->input_pix_clk;
+	vfe_dev->axi_data.src_info[VFE_PIX_0].input_mux =
+		input_cfg->d.pix_cfg.input_mux;
+	vfe_dev->axi_data.src_info[VFE_PIX_0].width =
+		input_cfg->d.pix_cfg.camif_cfg.pixels_per_line;
+
+	rc = msm_isp_set_clk_rate(vfe_dev,
+		vfe_dev->axi_data.src_info[VFE_PIX_0].pixel_clock);
+	if (rc < 0) {
+		pr_err("%s: clock set rate failed\n", __func__);
+		return rc;
+	}
+
+	vfe_dev->hw_info->vfe_ops.core_ops.cfg_camif(
+		vfe_dev, &input_cfg->d.pix_cfg);
 	return rc;
 }
 
 int msm_isp_cfg_rdi(struct vfe_device *vfe_dev,
-	struct msm_vfe_rdi_cfg *rdi_cfg, enum msm_vfe_input_src input_src)
+	struct msm_vfe_input_cfg *input_cfg)
 {
 	int rc = 0;
-	/*TD Validate config info
-	 * should check if all streams are off */
+	if (vfe_dev->axi_data.src_info[input_cfg->input_src].active) {
+		pr_err("%s: RAW%d path is active\n", __func__,
+			   input_cfg->input_src - VFE_RAW_0);
+		return -EINVAL;
+	}
 
-	vfe_dev->hw_info->vfe_ops.core_ops.
-		cfg_rdi_reg(vfe_dev, rdi_cfg, input_src);
+	vfe_dev->axi_data.src_info[input_cfg->input_src].pixel_clock =
+		input_cfg->input_pix_clk;
+	vfe_dev->hw_info->vfe_ops.core_ops.cfg_rdi_reg(
+		vfe_dev, &input_cfg->d.rdi_cfg, input_cfg->input_src);
 	return rc;
 }
 
@@ -100,16 +273,16 @@
 
 	switch (input_cfg->input_src) {
 	case VFE_PIX_0:
-		msm_isp_cfg_pix(vfe_dev, &input_cfg->d.pix_cfg);
+		rc = msm_isp_cfg_pix(vfe_dev, input_cfg);
 		break;
 	case VFE_RAW_0:
 	case VFE_RAW_1:
 	case VFE_RAW_2:
-		msm_isp_cfg_rdi(vfe_dev, &input_cfg->d.rdi_cfg,
-						input_cfg->input_src);
+		rc = msm_isp_cfg_rdi(vfe_dev, input_cfg);
 		break;
-	case VFE_SRC_MAX:
-		break;
+	default:
+		pr_err("%s: Invalid input source\n", __func__);
+		rc = -EINVAL;
 	}
 	return rc;
 }
@@ -120,55 +293,82 @@
 	long rc = 0;
 	struct vfe_device *vfe_dev = v4l2_get_subdevdata(sd);
 
-	mutex_lock(&vfe_dev->mutex);
-	ISP_DBG("%s cmd: %d\n", __func__, cmd);
+	/* Use real time mutex for hard real-time ioctls such as
+	 * buffer operations and register updates.
+	 * Use core mutex for other ioctls that could take
+	 * longer time to complete such as start/stop ISP streams
+	 * which blocks until the hardware start/stop streaming
+	 */
+	ISP_DBG("%s cmd: %d\n", __func__, _IOC_TYPE(cmd));
 	switch (cmd) {
 	case VIDIOC_MSM_VFE_REG_CFG: {
+		mutex_lock(&vfe_dev->realtime_mutex);
 		rc = msm_isp_proc_cmd(vfe_dev, arg);
+		mutex_unlock(&vfe_dev->realtime_mutex);
 		break;
 	}
 	case VIDIOC_MSM_ISP_REQUEST_BUF:
 	case VIDIOC_MSM_ISP_ENQUEUE_BUF:
 	case VIDIOC_MSM_ISP_RELEASE_BUF: {
+		mutex_lock(&vfe_dev->realtime_mutex);
 		rc = msm_isp_proc_buf_cmd(vfe_dev->buf_mgr, cmd, arg);
+		mutex_unlock(&vfe_dev->realtime_mutex);
 		break;
 	}
 	case VIDIOC_MSM_ISP_REQUEST_STREAM:
+		mutex_lock(&vfe_dev->core_mutex);
 		rc = msm_isp_request_axi_stream(vfe_dev, arg);
+		mutex_unlock(&vfe_dev->core_mutex);
 		break;
 	case VIDIOC_MSM_ISP_RELEASE_STREAM:
+		mutex_lock(&vfe_dev->core_mutex);
 		rc = msm_isp_release_axi_stream(vfe_dev, arg);
+		mutex_unlock(&vfe_dev->core_mutex);
 		break;
 	case VIDIOC_MSM_ISP_CFG_STREAM:
+		mutex_lock(&vfe_dev->core_mutex);
 		rc = msm_isp_cfg_axi_stream(vfe_dev, arg);
+		mutex_unlock(&vfe_dev->core_mutex);
 		break;
 	case VIDIOC_MSM_ISP_INPUT_CFG:
+		mutex_lock(&vfe_dev->core_mutex);
 		rc = msm_isp_cfg_input(vfe_dev, arg);
+		mutex_unlock(&vfe_dev->core_mutex);
 		break;
 	case VIDIOC_MSM_ISP_SET_SRC_STATE:
+		mutex_lock(&vfe_dev->core_mutex);
 		msm_isp_set_src_state(vfe_dev, arg);
+		mutex_unlock(&vfe_dev->core_mutex);
 		break;
 	case VIDIOC_MSM_ISP_REQUEST_STATS_STREAM:
+		mutex_lock(&vfe_dev->core_mutex);
 		rc = msm_isp_request_stats_stream(vfe_dev, arg);
+		mutex_unlock(&vfe_dev->core_mutex);
 		break;
 	case VIDIOC_MSM_ISP_RELEASE_STATS_STREAM:
+		mutex_lock(&vfe_dev->core_mutex);
 		rc = msm_isp_release_stats_stream(vfe_dev, arg);
+		mutex_unlock(&vfe_dev->core_mutex);
 		break;
 	case VIDIOC_MSM_ISP_CFG_STATS_STREAM:
+		mutex_lock(&vfe_dev->core_mutex);
 		rc = msm_isp_cfg_stats_stream(vfe_dev, arg);
+		mutex_unlock(&vfe_dev->core_mutex);
 		break;
 	case VIDIOC_MSM_ISP_CFG_STATS_COMP_POLICY:
+		mutex_lock(&vfe_dev->core_mutex);
 		rc = msm_isp_cfg_stats_comp_policy(vfe_dev, arg);
+		mutex_unlock(&vfe_dev->core_mutex);
 		break;
 	case VIDIOC_MSM_ISP_UPDATE_STREAM:
+		mutex_lock(&vfe_dev->core_mutex);
 		rc = msm_isp_update_axi_stream(vfe_dev, arg);
+		mutex_unlock(&vfe_dev->core_mutex);
 		break;
 	default:
 		pr_err("%s: Invalid ISP command\n", __func__);
 		rc = -EINVAL;
 	}
-
-	mutex_unlock(&vfe_dev->mutex);
 	return rc;
 }
 
@@ -623,23 +823,27 @@
 	long rc;
 	ISP_DBG("%s\n", __func__);
 
-	mutex_lock(&vfe_dev->mutex);
+	mutex_lock(&vfe_dev->realtime_mutex);
+	mutex_lock(&vfe_dev->core_mutex);
 	if (vfe_dev->vfe_open_cnt == 1) {
 		pr_err("VFE already open\n");
-		mutex_unlock(&vfe_dev->mutex);
+		mutex_unlock(&vfe_dev->core_mutex);
+		mutex_unlock(&vfe_dev->realtime_mutex);
 		return -ENODEV;
 	}
 
 	if (vfe_dev->hw_info->vfe_ops.core_ops.init_hw(vfe_dev) < 0) {
 		pr_err("%s: init hardware failed\n", __func__);
-		mutex_unlock(&vfe_dev->mutex);
+		mutex_unlock(&vfe_dev->core_mutex);
+		mutex_unlock(&vfe_dev->realtime_mutex);
 		return -EBUSY;
 	}
 
 	rc = vfe_dev->hw_info->vfe_ops.core_ops.reset_hw(vfe_dev);
 	if (rc <= 0) {
 		pr_err("%s: reset timeout\n", __func__);
-		mutex_unlock(&vfe_dev->mutex);
+		mutex_unlock(&vfe_dev->core_mutex);
+		mutex_unlock(&vfe_dev->realtime_mutex);
 		return -EINVAL;
 	}
 	vfe_dev->vfe_hw_version = msm_camera_io_r(vfe_dev->vfe_base);
@@ -659,7 +863,8 @@
 	vfe_dev->axi_data.hw_info = vfe_dev->hw_info->axi_hw_info;
 	vfe_dev->vfe_open_cnt++;
 	vfe_dev->taskletq_idx = 0;
-	mutex_unlock(&vfe_dev->mutex);
+	mutex_unlock(&vfe_dev->core_mutex);
+	mutex_unlock(&vfe_dev->realtime_mutex);
 	return 0;
 }
 
@@ -669,10 +874,12 @@
 	long rc;
 	struct vfe_device *vfe_dev = v4l2_get_subdevdata(sd);
 	ISP_DBG("%s\n", __func__);
-	mutex_lock(&vfe_dev->mutex);
+	mutex_lock(&vfe_dev->realtime_mutex);
+	mutex_lock(&vfe_dev->core_mutex);
 	if (vfe_dev->vfe_open_cnt == 0) {
 		pr_err("%s: Invalid close\n", __func__);
-		mutex_unlock(&vfe_dev->mutex);
+		mutex_unlock(&vfe_dev->core_mutex);
+		mutex_unlock(&vfe_dev->realtime_mutex);
 		return -ENODEV;
 	}
 
@@ -689,6 +896,7 @@
 	vfe_dev->hw_info->vfe_ops.core_ops.release_hw(vfe_dev);
 
 	vfe_dev->vfe_open_cnt--;
-	mutex_unlock(&vfe_dev->mutex);
+	mutex_unlock(&vfe_dev->core_mutex);
+	mutex_unlock(&vfe_dev->realtime_mutex);
 	return 0;
 }
diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.h b/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.h
index 3dac7e0..7934f26 100644
--- a/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.h
+++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.h
@@ -22,6 +22,32 @@
 #define ISP_DBG(fmt, args...) pr_debug(fmt, ##args)
 #endif
 
+#define ALT_VECTOR_IDX(x) {x = 3 - x; }
+struct msm_isp_bandwidth_info {
+	uint32_t active;
+	uint64_t ab;
+	uint64_t ib;
+};
+
+enum msm_isp_hw_client {
+	ISP_VFE0,
+	ISP_VFE1,
+	ISP_CPP,
+	MAX_ISP_CLIENT,
+};
+
+struct msm_isp_bandwidth_mgr {
+	uint32_t bus_client;
+	uint32_t bus_vector_active_idx;
+	uint32_t use_count;
+	struct msm_isp_bandwidth_info client_info[MAX_ISP_CLIENT];
+};
+
+int msm_isp_init_bandwidth_mgr(enum msm_isp_hw_client client);
+int msm_isp_update_bandwidth(enum msm_isp_hw_client client,
+	uint64_t ab, uint64_t ib);
+void msm_isp_deinit_bandwidth_mgr(enum msm_isp_hw_client client);
+
 int msm_isp_subscribe_event(struct v4l2_subdev *sd, struct v4l2_fh *fh,
 	struct v4l2_event_subscription *sub);
 
diff --git a/drivers/media/platform/msm/camera_v2/ispif/msm_ispif.c b/drivers/media/platform/msm/camera_v2/ispif/msm_ispif.c
index 22ce35b..f209330 100644
--- a/drivers/media/platform/msm/camera_v2/ispif/msm_ispif.c
+++ b/drivers/media/platform/msm/camera_v2/ispif/msm_ispif.c
@@ -380,6 +380,8 @@
 
 	data = msm_camera_io_r(ispif->base + ISPIF_VFE_m_CTRL_0(vfe_intf));
 	data |= (1 << (intftype + 7));
+	if (intftype == PIX0)
+		data |= 1 << PIX0_LINE_BUF_EN_BIT;
 	msm_camera_io_w(data,
 		ispif->base + ISPIF_VFE_m_CTRL_0(vfe_intf));
 
@@ -503,6 +505,13 @@
 	BUG_ON(!ispif);
 	BUG_ON(!params);
 
+	if (ispif->ispif_state != ISPIF_POWER_UP) {
+		pr_err("%s: ispif invalid state %d\n", __func__,
+			ispif->ispif_state);
+		rc = -EPERM;
+		return rc;
+	}
+
 	rc = msm_ispif_clk_enable(ispif, params, 1);
 	if (rc < 0) {
 		pr_err("%s: unable to enable clocks", __func__);
@@ -653,6 +662,13 @@
 	BUG_ON(!ispif);
 	BUG_ON(!params);
 
+	if (ispif->ispif_state != ISPIF_POWER_UP) {
+		pr_err("%s: ispif invalid state %d\n", __func__,
+			ispif->ispif_state);
+		rc = -EPERM;
+		return rc;
+	}
+
 	msm_ispif_intf_cmd(ispif, ISPIF_INTF_CMD_DISABLE_IMMEDIATELY, params);
 
 	/* after stop the interface we need to unmask the CID enable bits */
@@ -671,6 +687,13 @@
 {
 	int rc;
 
+	if (ispif->ispif_state != ISPIF_POWER_UP) {
+		pr_err("%s: ispif invalid state %d\n", __func__,
+			ispif->ispif_state);
+		rc = -EPERM;
+		return rc;
+	}
+
 	rc = msm_ispif_clk_enable(ispif, params, 1);
 	if (rc < 0) {
 		pr_err("%s: unable to enable clocks", __func__);
@@ -703,6 +726,13 @@
 	BUG_ON(!params);
 
 
+	if (ispif->ispif_state != ISPIF_POWER_UP) {
+		pr_err("%s: ispif invalid state %d\n", __func__,
+			ispif->ispif_state);
+		rc = -EPERM;
+		return rc;
+	}
+
 	rc = msm_ispif_clk_enable(ispif, params, 1);
 	if (rc < 0) {
 		pr_err("%s: unable to enable clocks", __func__);
diff --git a/drivers/media/platform/msm/camera_v2/ispif/msm_ispif_hwreg_v1.h b/drivers/media/platform/msm/camera_v2/ispif/msm_ispif_hwreg_v1.h
index afd91d1..9f8b2fa 100644
--- a/drivers/media/platform/msm/camera_v2/ispif/msm_ispif_hwreg_v1.h
+++ b/drivers/media/platform/msm/camera_v2/ispif/msm_ispif_hwreg_v1.h
@@ -16,6 +16,7 @@
 /* common registers */
 #define ISPIF_RST_CMD_ADDR                       0x0000
 #define ISPIF_IRQ_GLOBAL_CLEAR_CMD_ADDR          0x0124
+#define PIX0_LINE_BUF_EN_BIT                     0
 
 #define ISPIF_VFE(m)                             (0x0)
 
diff --git a/drivers/media/platform/msm/camera_v2/ispif/msm_ispif_hwreg_v2.h b/drivers/media/platform/msm/camera_v2/ispif/msm_ispif_hwreg_v2.h
index 80b32d4..5e61a4d 100644
--- a/drivers/media/platform/msm/camera_v2/ispif/msm_ispif_hwreg_v2.h
+++ b/drivers/media/platform/msm/camera_v2/ispif/msm_ispif_hwreg_v2.h
@@ -17,6 +17,7 @@
 #define ISPIF_RST_CMD_ADDR                       0x008
 #define ISPIF_RST_CMD_1_ADDR                     0x00C
 #define ISPIF_IRQ_GLOBAL_CLEAR_CMD_ADDR          0x01C
+#define PIX0_LINE_BUF_EN_BIT                     6
 
 #define ISPIF_VFE(m)                             ((m) * 0x200)
 
diff --git a/drivers/media/platform/msm/camera_v2/pproc/cpp/Makefile b/drivers/media/platform/msm/camera_v2/pproc/cpp/Makefile
index 2f969d2..c793ef6 100644
--- a/drivers/media/platform/msm/camera_v2/pproc/cpp/Makefile
+++ b/drivers/media/platform/msm/camera_v2/pproc/cpp/Makefile
@@ -1,3 +1,4 @@
 ccflags-y += -Idrivers/media/platform/msm/camera_v2
+ccflags-y += -Idrivers/media/platform/msm/camera_v2/isp/
 ccflags-y += -Idrivers/media/platform/msm/camera_v2/sensor/io
 obj-$(CONFIG_MSM_CPP) += msm_cpp.o
diff --git a/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.c b/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.c
index c06b009..1203d17 100644
--- a/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.c
+++ b/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.c
@@ -34,6 +34,7 @@
 #include <media/msmb_pproc.h>
 #include <media/msmb_generic_buf_mgr.h>
 #include "msm_cpp.h"
+#include "msm_isp_util.h"
 #include "msm_camera_io_util.h"
 
 #define MSM_CPP_DRV_NAME "msm_cpp"
@@ -582,6 +583,12 @@
 static int cpp_init_hardware(struct cpp_device *cpp_dev)
 {
 	int rc = 0;
+	rc = msm_isp_init_bandwidth_mgr(ISP_CPP);
+	if (rc < 0) {
+		pr_err("%s: Bandwidth registration Failed!\n", __func__);
+		goto bus_scale_register_failed;
+	}
+	msm_isp_update_bandwidth(ISP_CPP, 981345600, 1600020000);
 
 	if (cpp_dev->fs_cpp == NULL) {
 		cpp_dev->fs_cpp =
@@ -667,6 +674,9 @@
 	regulator_disable(cpp_dev->fs_cpp);
 	regulator_put(cpp_dev->fs_cpp);
 fs_failed:
+	msm_isp_update_bandwidth(ISP_CPP, 0, 0);
+	msm_isp_deinit_bandwidth_mgr(ISP_CPP);
+bus_scale_register_failed:
 	return rc;
 }
 
@@ -688,6 +698,8 @@
 		regulator_put(cpp_dev->fs_cpp);
 		cpp_dev->fs_cpp = NULL;
 	}
+	msm_isp_update_bandwidth(ISP_CPP, 0, 0);
+	msm_isp_deinit_bandwidth_mgr(ISP_CPP);
 }
 
 static void cpp_load_fw(struct cpp_device *cpp_dev, char *fw_name_bin)
@@ -907,7 +919,7 @@
 	struct msm_queue_cmd *frame_qcmd)
 {
 	uint32_t i;
-	int32_t rc = -EINVAL;
+	int32_t rc = -EAGAIN;
 	struct msm_cpp_frame_info_t *process_frame;
 
 	if (cpp_dev->processing_q.len < MAX_CPP_PROCESSING_FRAME) {
@@ -921,6 +933,8 @@
 		do_gettimeofday(&(process_frame->in_time));
 		rc = 0;
 	}
+	if (rc < 0)
+		pr_err("process queue full. drop frame\n");
 	return rc;
 }
 
@@ -940,6 +954,9 @@
 	unsigned long in_phyaddr, out_phyaddr;
 	uint16_t num_stripes = 0;
 	struct msm_buf_mngr_info buff_mgr_info;
+	struct msm_cpp_frame_info_t *u_frame_info =
+		(struct msm_cpp_frame_info_t *)ioctl_ptr->ioctl_ptr;
+	int32_t status = 0;
 
 	int i = 0;
 	if (!new_frame) {
@@ -992,8 +1009,8 @@
 	rc = msm_cpp_buffer_ops(cpp_dev, VIDIOC_MSM_BUF_MNGR_GET_BUF,
 		&buff_mgr_info);
 	if (rc < 0) {
-		pr_err("error getting buffer\n");
-		rc = -EINVAL;
+		rc = -EAGAIN;
+		pr_err("error getting buffer rc:%d\n", rc);
 		goto ERROR2;
 	}
 
@@ -1036,6 +1053,15 @@
 		goto ERROR4;
 	}
 
+	ioctl_ptr->trans_code = rc;
+	status = rc;
+	rc = (copy_to_user((void __user *)u_frame_info->status, &status,
+		sizeof(int32_t)) ? -EFAULT : 0);
+	if (rc) {
+		ERR_COPY_FROM_USER();
+		rc = -EINVAL;
+		goto ERROR4;
+	}
 	return rc;
 ERROR4:
 	kfree(frame_qcmd);
@@ -1046,6 +1072,11 @@
 	kfree(cpp_frame_msg);
 ERROR1:
 	kfree(new_frame);
+	ioctl_ptr->trans_code = rc;
+	status = rc;
+	if (copy_to_user((void __user *)u_frame_info->status, &status,
+		sizeof(int32_t)))
+		pr_err("error cannot copy error\n");
 	return rc;
 }
 
diff --git a/drivers/media/platform/msm/camera_v2/sensor/Makefile b/drivers/media/platform/msm/camera_v2/sensor/Makefile
index b6708a3..5104bcb 100644
--- a/drivers/media/platform/msm/camera_v2/sensor/Makefile
+++ b/drivers/media/platform/msm/camera_v2/sensor/Makefile
@@ -3,7 +3,7 @@
 ccflags-y += -Idrivers/media/platform/msm/camera_v2/camera
 ccflags-y += -Idrivers/media/platform/msm/camera_v2/sensor/io
 ccflags-y += -Idrivers/media/platform/msm/camera_v2/sensor/cci
-obj-$(CONFIG_MSMB_CAMERA) += cci/ io/ csiphy/ csid/ actuator/ flash/
+obj-$(CONFIG_MSMB_CAMERA) += cci/ io/ csiphy/ csid/ actuator/ flash/ eeprom/
 obj-$(CONFIG_MSM_CAMERA_SENSOR) += msm_sensor.o
 obj-$(CONFIG_S5K3L1YX) += s5k3l1yx.o
 obj-$(CONFIG_IMX135) += imx135.o
diff --git a/drivers/media/platform/msm/camera_v2/sensor/cci/msm_cci.c b/drivers/media/platform/msm/camera_v2/sensor/cci/msm_cci.c
index 12ac4cb..9300ce0 100644
--- a/drivers/media/platform/msm/camera_v2/sensor/cci/msm_cci.c
+++ b/drivers/media/platform/msm/camera_v2/sensor/cci/msm_cci.c
@@ -39,6 +39,9 @@
 #define CDBG(fmt, args...) do { } while (0)
 #endif
 
+/* Max bytes that can be read per CCI read transaction */
+#define CCI_READ_MAX 12
+
 static struct v4l2_subdev *g_cci_subdev;
 
 static void msm_cci_set_clk_param(struct cci_device *cci_dev)
@@ -377,6 +380,61 @@
 	return rc;
 }
 
+static int32_t msm_cci_i2c_read_bytes(struct v4l2_subdev *sd,
+	struct msm_camera_cci_ctrl *c_ctrl)
+{
+	int32_t rc = 0;
+	struct cci_device *cci_dev = NULL;
+	enum cci_i2c_master_t master;
+	struct msm_camera_cci_i2c_read_cfg *read_cfg = NULL;
+	uint16_t read_bytes = 0;
+
+	if (!sd || !c_ctrl) {
+		pr_err("%s:%d sd %p c_ctrl %p\n", __func__,
+			__LINE__, sd, c_ctrl);
+		return -EINVAL;
+	}
+	if (!c_ctrl->cci_info) {
+		pr_err("%s:%d cci_info NULL\n", __func__, __LINE__);
+		return -EINVAL;
+	}
+	cci_dev = v4l2_get_subdevdata(sd);
+	if (!cci_dev) {
+		pr_err("%s:%d cci_dev NULL\n", __func__, __LINE__);
+		return -EINVAL;
+	}
+
+	master = c_ctrl->cci_info->cci_i2c_master;
+	read_cfg = &c_ctrl->cfg.cci_i2c_read_cfg;
+	if (!read_cfg->num_byte) {
+		pr_err("%s:%d read num bytes 0\n", __func__, __LINE__);
+		rc = -EINVAL;
+		goto ERROR;
+	}
+
+	read_bytes = read_cfg->num_byte;
+	do {
+		if (read_bytes > CCI_READ_MAX)
+			read_cfg->num_byte = CCI_READ_MAX;
+		else
+			read_cfg->num_byte = read_bytes;
+		rc = msm_cci_i2c_read(sd, c_ctrl);
+		if (rc < 0) {
+			pr_err("%s:%d failed rc %d\n", __func__, __LINE__, rc);
+			goto ERROR;
+		}
+		if (read_bytes > CCI_READ_MAX) {
+			read_cfg->addr += CCI_READ_MAX;
+			read_cfg->data += CCI_READ_MAX;
+			read_bytes -= CCI_READ_MAX;
+		} else {
+			read_bytes = 0;
+		}
+	} while (read_bytes);
+ERROR:
+	return rc;
+}
+
 static int32_t msm_cci_i2c_write(struct v4l2_subdev *sd,
 	struct msm_camera_cci_ctrl *c_ctrl)
 {
@@ -589,7 +647,7 @@
 		rc = msm_cci_i2c_config_sync_timer(sd, cci_ctrl);
 		break;
 	case MSM_CCI_I2C_READ:
-		rc = msm_cci_i2c_read(sd, cci_ctrl);
+		rc = msm_cci_i2c_read_bytes(sd, cci_ctrl);
 		break;
 	case MSM_CCI_I2C_WRITE:
 		rc = msm_cci_i2c_write(sd, cci_ctrl);
diff --git a/drivers/media/platform/msm/camera_v2/sensor/eeprom/Makefile b/drivers/media/platform/msm/camera_v2/sensor/eeprom/Makefile
new file mode 100644
index 0000000..de843fb
--- /dev/null
+++ b/drivers/media/platform/msm/camera_v2/sensor/eeprom/Makefile
@@ -0,0 +1,4 @@
+ccflags-y += -Idrivers/media/platform/msm/camera_v2
+ccflags-y += -Idrivers/media/platform/msm/camera_v2/sensor/io
+ccflags-y += -Idrivers/media/platform/msm/camera_v2/sensor/cci
+obj-$(CONFIG_MSM_EEPROM) += msm_eeprom.o
diff --git a/drivers/media/platform/msm/camera_v2/sensor/eeprom/msm_eeprom.c b/drivers/media/platform/msm/camera_v2/sensor/eeprom/msm_eeprom.c
new file mode 100644
index 0000000..47e672d
--- /dev/null
+++ b/drivers/media/platform/msm/camera_v2/sensor/eeprom/msm_eeprom.c
@@ -0,0 +1,932 @@
+/* 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
+ * 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/of_gpio.h>
+#include <linux/delay.h>
+#include "msm_sd.h"
+#include "msm_cci.h"
+#include "msm_eeprom.h"
+
+#undef CDBG
+#ifdef MSM_EEPROM_DEBUG
+#define CDBG(fmt, args...) pr_err(fmt, ##args)
+#else
+#define CDBG(fmt, args...) pr_debug(fmt, ##args)
+#endif
+
+DEFINE_MSM_MUTEX(msm_eeprom_mutex);
+
+int32_t msm_eeprom_config(struct msm_eeprom_ctrl_t *e_ctrl,
+	void __user *argp)
+{
+	struct msm_eeprom_cfg_data *cdata =
+		(struct msm_eeprom_cfg_data *)argp;
+	int32_t rc = 0;
+
+	CDBG("%s E\n", __func__);
+	switch (cdata->cfgtype) {
+	case CFG_EEPROM_GET_INFO:
+	CDBG("%s E CFG_EEPROM_GET_INFO\n", __func__);
+		cdata->is_supported = e_ctrl->is_supported;
+		memcpy(cdata->cfg.eeprom_name,
+			e_ctrl->eboard_info->eeprom_name,
+			sizeof(cdata->cfg.eeprom_name));
+		break;
+	case CFG_EEPROM_GET_DATA:
+		CDBG("%s E CFG_EEPROM_GET_DATA\n", __func__);
+		cdata->cfg.get_data.num_bytes =
+			e_ctrl->num_bytes;
+		break;
+	case CFG_EEPROM_READ_DATA:
+		CDBG("%s E CFG_EEPROM_READ_DATA\n", __func__);
+		rc = copy_to_user(cdata->cfg.read_data.dbuffer,
+			e_ctrl->memory_data,
+			cdata->cfg.read_data.num_bytes);
+		break;
+	default:
+		break;
+	}
+
+	CDBG("%s X\n", __func__);
+	return rc;
+}
+static int32_t msm_eeprom_get_subdev_id(
+	struct msm_eeprom_ctrl_t *e_ctrl, void *arg)
+{
+	uint32_t *subdev_id = (uint32_t *)arg;
+	CDBG("%s E\n", __func__);
+	if (!subdev_id) {
+		pr_err("%s failed\n", __func__);
+		return -EINVAL;
+	}
+	*subdev_id = e_ctrl->subdev_id;
+	CDBG("subdev_id %d\n", *subdev_id);
+	CDBG("%s X\n", __func__);
+	return 0;
+}
+
+static long msm_eeprom_subdev_ioctl(struct v4l2_subdev *sd,
+		unsigned int cmd, void *arg)
+{
+	struct msm_eeprom_ctrl_t *e_ctrl = v4l2_get_subdevdata(sd);
+	void __user *argp = (void __user *)arg;
+	CDBG("%s E\n", __func__);
+	CDBG("%s:%d a_ctrl %p argp %p\n", __func__, __LINE__, e_ctrl, argp);
+	switch (cmd) {
+	case VIDIOC_MSM_SENSOR_GET_SUBDEV_ID:
+		return msm_eeprom_get_subdev_id(e_ctrl, argp);
+	case VIDIOC_MSM_EEPROM_CFG:
+		return msm_eeprom_config(e_ctrl, argp);
+	default:
+		return -ENOIOCTLCMD;
+	}
+
+	CDBG("%s X\n", __func__);
+}
+
+static struct msm_camera_i2c_fn_t msm_eeprom_cci_func_tbl = {
+	.i2c_read = msm_camera_cci_i2c_read,
+	.i2c_read_seq = msm_camera_cci_i2c_read_seq,
+	.i2c_write = msm_camera_cci_i2c_write,
+	.i2c_write_table = msm_camera_cci_i2c_write_table,
+	.i2c_write_seq_table = msm_camera_cci_i2c_write_seq_table,
+	.i2c_write_table_w_microdelay =
+	msm_camera_cci_i2c_write_table_w_microdelay,
+	.i2c_util = msm_sensor_cci_i2c_util,
+	.i2c_poll = msm_camera_cci_i2c_poll,
+};
+
+static struct msm_camera_i2c_fn_t msm_eeprom_qup_func_tbl = {
+	.i2c_read = msm_camera_qup_i2c_read,
+	.i2c_read_seq = msm_camera_qup_i2c_read_seq,
+	.i2c_write = msm_camera_qup_i2c_write,
+	.i2c_write_table = msm_camera_qup_i2c_write_table,
+	.i2c_write_seq_table = msm_camera_qup_i2c_write_seq_table,
+	.i2c_write_table_w_microdelay =
+	msm_camera_qup_i2c_write_table_w_microdelay,
+};
+
+static struct msm_camera_i2c_fn_t msm_eeprom_spi_func_tbl = {
+	.i2c_read = msm_camera_spi_read,
+	.i2c_read_seq = msm_camera_spi_read_seq,
+};
+
+static int msm_eeprom_open(struct v4l2_subdev *sd,
+	struct v4l2_subdev_fh *fh) {
+	int rc = 0;
+	struct msm_eeprom_ctrl_t *e_ctrl =  v4l2_get_subdevdata(sd);
+	CDBG("%s E\n", __func__);
+	if (!e_ctrl) {
+		pr_err("%s failed e_ctrl is NULL\n", __func__);
+		return -EINVAL;
+	}
+	if (e_ctrl->eeprom_device_type == MSM_CAMERA_PLATFORM_DEVICE) {
+		rc = e_ctrl->i2c_client.i2c_func_tbl->i2c_util(
+		&e_ctrl->i2c_client, MSM_CCI_INIT);
+		if (rc < 0)
+			pr_err("%s cci_init failed\n", __func__);
+	}
+	CDBG("%s X\n", __func__);
+	return rc;
+}
+
+static int msm_eeprom_close(struct v4l2_subdev *sd,
+	struct v4l2_subdev_fh *fh) {
+	int rc = 0;
+	struct msm_eeprom_ctrl_t *e_ctrl =  v4l2_get_subdevdata(sd);
+	CDBG("%s E\n", __func__);
+	if (!e_ctrl) {
+		pr_err("%s failed e_ctrl is NULL\n", __func__);
+		return -EINVAL;
+	}
+	if (e_ctrl->eeprom_device_type == MSM_CAMERA_PLATFORM_DEVICE) {
+		rc = e_ctrl->i2c_client.i2c_func_tbl->i2c_util(
+			&e_ctrl->i2c_client, MSM_CCI_RELEASE);
+		if (rc < 0)
+			pr_err("%s cci_init failed\n", __func__);
+	}
+	CDBG("%s X\n", __func__);
+	return rc;
+}
+
+static const struct v4l2_subdev_internal_ops msm_eeprom_internal_ops = {
+	.open = msm_eeprom_open,
+	.close = msm_eeprom_close,
+};
+
+int32_t read_eeprom_memory(struct msm_eeprom_ctrl_t *e_ctrl)
+{
+	int rc = 0;
+	int j;
+	uint8_t *memptr = NULL;
+	struct msm_eeprom_board_info *eb_info = NULL;
+	struct eeprom_memory_map_t *emap = NULL;
+	if (!e_ctrl) {
+		pr_err("%s e_ctrl is NULL", __func__);
+		rc = -1;
+		return rc;
+	}
+	memptr = e_ctrl->memory_data;
+	eb_info = e_ctrl->eboard_info;
+	emap = eb_info->eeprom_map;
+
+	for (j = 0; j < eb_info->num_blocks; j++) {
+		if (emap[j].page.valid_size) {
+			e_ctrl->i2c_client.addr_type = emap[j].page.addr_t;
+			rc = e_ctrl->i2c_client.i2c_func_tbl->i2c_write(
+				&(e_ctrl->i2c_client), emap[j].page.addr,
+				emap[j].page.data, emap[j].page.data_t);
+				msleep(emap[j].page.delay);
+			if (rc < 0) {
+				pr_err("%s: page write failed\n", __func__);
+				return rc;
+			}
+		}
+
+		if (emap[j].poll.valid_size) {
+			e_ctrl->i2c_client.addr_type = emap[j].poll.addr_t;
+			rc = e_ctrl->i2c_client.i2c_func_tbl->i2c_poll(
+				&(e_ctrl->i2c_client), emap[j].poll.addr,
+				emap[j].poll.data, emap[j].poll.data_t);
+				msleep(emap[j].poll.delay);
+			if (rc < 0) {
+				pr_err("%s: poll failed\n", __func__);
+				return rc;
+			}
+		}
+
+		if (emap[j].mem.valid_size) {
+			e_ctrl->i2c_client.addr_type = emap[j].mem.addr_t;
+			rc = e_ctrl->i2c_client.i2c_func_tbl->i2c_read_seq(
+				&(e_ctrl->i2c_client), emap[j].mem.addr,
+				memptr, emap[j].mem.valid_size);
+			if (rc < 0) {
+				pr_err("%s: read failed\n", __func__);
+				return rc;
+			}
+			memptr += emap[j].mem.valid_size;
+		}
+	}
+	return rc;
+}
+
+static int msm_eeprom_alloc_memory_map(struct msm_eeprom_ctrl_t *e_ctrl,
+				       struct device_node *of)
+{
+	int i, rc = 0;
+	char property[12];
+	uint32_t count = 6;
+	struct msm_eeprom_board_info *eb = e_ctrl->eboard_info;
+
+	rc = of_property_read_u32(of, "qcom,num-blocks", &eb->num_blocks);
+	CDBG("%s: qcom,num_blocks %d\n", __func__, eb->num_blocks);
+	if (rc < 0) {
+		pr_err("%s failed rc %d\n", __func__, rc);
+		return rc;
+	}
+
+	eb->eeprom_map = kzalloc((sizeof(struct eeprom_memory_map_t)
+				 * eb->num_blocks), GFP_KERNEL);
+
+	if (!eb->eeprom_map) {
+		pr_err("%s failed line %d\n", __func__, __LINE__);
+		return -ENOMEM;
+	}
+
+	for (i = 0; i < eb->num_blocks; i++) {
+		snprintf(property, 12, "qcom,page%d", i);
+		rc = of_property_read_u32_array(of, property,
+			(uint32_t *) &eb->eeprom_map[i].page, count);
+		if (rc < 0) {
+			pr_err("%s: failed %d\n", __func__, __LINE__);
+			goto out;
+		}
+
+		snprintf(property, 12, "qcom,poll%d", i);
+		rc = of_property_read_u32_array(of, property,
+			(uint32_t *) &eb->eeprom_map[i].poll, count);
+		if (rc < 0) {
+			pr_err("%s failed %d\n", __func__, __LINE__);
+			goto out;
+		}
+
+		snprintf(property, 12, "qcom,mem%d", i);
+		rc = of_property_read_u32_array(of, property,
+			(uint32_t *) &eb->eeprom_map[i].mem, count);
+		if (rc < 0) {
+			pr_err("%s failed %d\n", __func__, __LINE__);
+			goto out;
+		}
+		e_ctrl->num_bytes += eb->eeprom_map[i].mem.valid_size;
+	}
+
+	CDBG("%s num_bytes %d\n", __func__, e_ctrl->num_bytes);
+
+	e_ctrl->memory_data = kzalloc(e_ctrl->num_bytes, GFP_KERNEL);
+	if (!e_ctrl->memory_data) {
+		pr_err("%s failed line %d\n", __func__, __LINE__);
+		rc = -ENOMEM;
+		goto out;
+	}
+	return rc;
+
+out:
+	kfree(eb->eeprom_map);
+	return rc;
+}
+
+static struct msm_cam_clk_info cam_8960_clk_info[] = {
+	[SENSOR_CAM_MCLK] = {"cam_clk", 24000000},
+};
+
+static struct msm_cam_clk_info cam_8974_clk_info[] = {
+	[SENSOR_CAM_MCLK] = {"cam_src_clk", 19200000},
+	[SENSOR_CAM_CLK] = {"cam_clk", 0},
+};
+
+static struct v4l2_subdev_core_ops msm_eeprom_subdev_core_ops = {
+	.ioctl = msm_eeprom_subdev_ioctl,
+};
+
+static struct v4l2_subdev_ops msm_eeprom_subdev_ops = {
+	.core = &msm_eeprom_subdev_core_ops,
+};
+
+int32_t msm_eeprom_i2c_probe(struct i2c_client *client,
+	const struct i2c_device_id *id) {
+	int rc = 0;
+	struct msm_eeprom_ctrl_t *e_ctrl = NULL;
+	struct msm_camera_power_ctrl_t *power_info = NULL;
+	CDBG("%s E\n", __func__);
+
+	if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
+		pr_err("%s i2c_check_functionality failed\n", __func__);
+		goto probe_failure;
+	}
+
+	e_ctrl = kzalloc(sizeof(struct msm_eeprom_ctrl_t), GFP_KERNEL);
+	if (!e_ctrl) {
+		pr_err("%s:%d kzalloc failed\n", __func__, __LINE__);
+		return -ENOMEM;
+	}
+	e_ctrl->eeprom_v4l2_subdev_ops = &msm_eeprom_subdev_ops;
+	e_ctrl->eeprom_mutex = &msm_eeprom_mutex;
+	CDBG("%s client = %x\n", __func__, (unsigned int)client);
+	e_ctrl->eboard_info = (struct msm_eeprom_board_info *)(id->driver_data);
+	if (!e_ctrl->eboard_info) {
+		pr_err("%s:%d board info NULL\n", __func__, __LINE__);
+		return -EINVAL;
+	}
+	power_info = &e_ctrl->eboard_info->power_info;
+	e_ctrl->i2c_client.client = client;
+
+	/* Set device type as I2C */
+	e_ctrl->eeprom_device_type = MSM_CAMERA_I2C_DEVICE;
+	e_ctrl->i2c_client.i2c_func_tbl = &msm_eeprom_qup_func_tbl;
+
+	if (e_ctrl->eboard_info->i2c_slaveaddr != 0)
+		e_ctrl->i2c_client.client->addr =
+					e_ctrl->eboard_info->i2c_slaveaddr;
+	power_info->clk_info = cam_8960_clk_info;
+	power_info->clk_info_size = ARRAY_SIZE(cam_8960_clk_info);
+	power_info->dev = &client->dev;
+
+	/*IMPLEMENT READING PART*/
+	/* Initialize sub device */
+	v4l2_i2c_subdev_init(&e_ctrl->msm_sd.sd,
+		e_ctrl->i2c_client.client,
+		e_ctrl->eeprom_v4l2_subdev_ops);
+	v4l2_set_subdevdata(&e_ctrl->msm_sd.sd, e_ctrl);
+	e_ctrl->msm_sd.sd.internal_ops = &msm_eeprom_internal_ops;
+	e_ctrl->msm_sd.sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
+	media_entity_init(&e_ctrl->msm_sd.sd.entity, 0, NULL, 0);
+	e_ctrl->msm_sd.sd.entity.type = MEDIA_ENT_T_V4L2_SUBDEV;
+	e_ctrl->msm_sd.sd.entity.group_id = MSM_CAMERA_SUBDEV_EEPROM;
+	msm_sd_register(&e_ctrl->msm_sd);
+	CDBG("%s success result=%d X\n", __func__, rc);
+	return rc;
+
+probe_failure:
+	pr_err("%s failed! rc = %d\n", __func__, rc);
+	return rc;
+}
+
+static int32_t msm_eeprom_i2c_remove(struct i2c_client *client)
+{
+	struct v4l2_subdev *sd = i2c_get_clientdata(client);
+	struct msm_eeprom_ctrl_t  *e_ctrl;
+	if (!sd) {
+		pr_err("%s: Subdevice is NULL\n", __func__);
+		return 0;
+	}
+
+	e_ctrl = (struct msm_eeprom_ctrl_t *)v4l2_get_subdevdata(sd);
+	if (!e_ctrl) {
+		pr_err("%s: eeprom device is NULL\n", __func__);
+		return 0;
+	}
+
+	kfree(e_ctrl->memory_data);
+	if (e_ctrl->eboard_info) {
+		kfree(e_ctrl->eboard_info->power_info.gpio_conf);
+		kfree(e_ctrl->eboard_info->eeprom_map);
+	}
+	kfree(e_ctrl->eboard_info);
+	kfree(e_ctrl);
+	return 0;
+}
+
+#define msm_eeprom_spi_parse_cmd(spic, str, name, out, size)		\
+	{								\
+		if (of_property_read_u32_array(				\
+			spic->spi_master->dev.of_node,			\
+			str, out, size)) {				\
+			return -EFAULT;					\
+		} else {						\
+			spic->cmd_tbl.name.opcode = out[0];		\
+			spic->cmd_tbl.name.addr_len = out[1];		\
+			spic->cmd_tbl.name.dummy_len = out[2];		\
+		}							\
+	}
+
+static int msm_eeprom_spi_parse_of(struct msm_camera_spi_client *spic)
+{
+	int rc = -EFAULT;
+	uint32_t tmp[3];
+	msm_eeprom_spi_parse_cmd(spic, "qcom,spiop,read", read, tmp, 3);
+	msm_eeprom_spi_parse_cmd(spic, "qcom,spiop,readseq", read_seq, tmp, 3);
+	msm_eeprom_spi_parse_cmd(spic, "qcom,spiop,queryid", query_id, tmp, 3);
+
+	rc = of_property_read_u32_array(spic->spi_master->dev.of_node,
+					"qcom,eeprom-id", tmp, 2);
+	if (rc) {
+		pr_err("%s: Failed to get eeprom id\n", __func__);
+		return rc;
+	}
+	spic->mfr_id = tmp[0];
+	spic->device_id = tmp[1];
+
+	return 0;
+}
+
+static int msm_eeprom_check_id(struct msm_eeprom_ctrl_t *e_ctrl)
+{
+	int rc;
+	struct msm_camera_i2c_client *client = &e_ctrl->i2c_client;
+	uint8_t id[2];
+
+	rc = msm_camera_spi_query_id(client, 0, &id[0], 2);
+	if (rc)
+		return rc;
+	if (id[0] != client->spi_client->mfr_id
+		    || id[1] != client->spi_client->device_id) {
+		CDBG("%s: read 0x%x 0x%x, check 0x%x 0x%x\n", __func__, id[0],
+		     id[1], client->spi_client->mfr_id,
+		     client->spi_client->device_id);
+		return -ENODEV;
+	}
+
+	return 0;
+}
+
+static int msm_eeprom_get_dt_data(struct msm_eeprom_ctrl_t *e_ctrl)
+{
+	int rc = 0, i = 0;
+	struct msm_eeprom_board_info *eb_info;
+	struct msm_camera_power_ctrl_t *power_info =
+		&e_ctrl->eboard_info->power_info;
+	struct spi_device *spi = e_ctrl->i2c_client.spi_client->spi_master;
+	struct device_node *of_node = spi->dev.of_node;
+	struct msm_camera_gpio_conf *gconf = NULL;
+	uint16_t gpio_array_size = 0;
+	uint16_t *gpio_array = NULL;
+
+	eb_info = e_ctrl->eboard_info;
+	rc = msm_camera_get_dt_power_setting_data(spi->dev.of_node,
+		  &power_info->power_setting, &power_info->power_setting_size);
+	if (rc)
+		return rc;
+
+	rc = msm_camera_get_dt_vreg_data(of_node, &power_info->cam_vreg,
+					     &power_info->num_vreg);
+	if (rc)
+		goto ERROR1;
+
+	power_info->gpio_conf = kzalloc(sizeof(struct msm_camera_gpio_conf),
+					GFP_KERNEL);
+	if (!power_info->gpio_conf) {
+		rc = -ENOMEM;
+		goto ERROR2;
+	}
+	gconf = power_info->gpio_conf;
+	gpio_array_size = of_gpio_count(of_node);
+	CDBG("%s gpio count %d\n", __func__, gpio_array_size);
+
+	if (gpio_array_size) {
+		gpio_array = kzalloc(sizeof(uint16_t) * gpio_array_size,
+			GFP_KERNEL);
+		if (!gpio_array) {
+			pr_err("%s failed %d\n", __func__, __LINE__);
+			goto ERROR3;
+		}
+		for (i = 0; i < gpio_array_size; i++) {
+			gpio_array[i] = of_get_gpio(of_node, i);
+			CDBG("%s gpio_array[%d] = %d\n", __func__, i,
+				gpio_array[i]);
+		}
+
+		rc = msm_camera_get_dt_gpio_req_tbl(of_node, gconf,
+			gpio_array, gpio_array_size);
+		if (rc < 0) {
+			pr_err("%s failed %d\n", __func__, __LINE__);
+			goto ERROR4;
+		}
+
+		rc = msm_camera_init_gpio_pin_tbl(of_node, gconf,
+			gpio_array, gpio_array_size);
+		if (rc < 0) {
+			pr_err("%s failed %d\n", __func__, __LINE__);
+			goto ERROR4;
+		}
+		kfree(gpio_array);
+	}
+
+	return rc;
+ERROR4:
+	kfree(gpio_array);
+ERROR3:
+	kfree(power_info->gpio_conf);
+ERROR2:
+	kfree(power_info->cam_vreg);
+ERROR1:
+	kfree(power_info->power_setting);
+	return rc;
+}
+
+static int msm_eeprom_spi_setup(struct spi_device *spi)
+{
+	struct msm_eeprom_ctrl_t *e_ctrl = NULL;
+	struct msm_camera_i2c_client *client = NULL;
+	struct msm_camera_spi_client *spi_client;
+	struct msm_eeprom_board_info *eb_info;
+	struct msm_camera_power_ctrl_t *power_info = NULL;
+	int rc = 0;
+
+	e_ctrl = kzalloc(sizeof(struct msm_eeprom_ctrl_t), GFP_KERNEL);
+	if (!e_ctrl) {
+		pr_err("%s:%d kzalloc failed\n", __func__, __LINE__);
+		return -ENOMEM;
+	}
+	e_ctrl->eeprom_v4l2_subdev_ops = &msm_eeprom_subdev_ops;
+	e_ctrl->eeprom_mutex = &msm_eeprom_mutex;
+	client = &e_ctrl->i2c_client;
+	e_ctrl->is_supported = 0;
+
+	spi_client = kzalloc(sizeof(spi_client), GFP_KERNEL);
+	if (!spi_client) {
+		pr_err("%s:%d kzalloc failed\n", __func__, __LINE__);
+		kfree(e_ctrl);
+		return -ENOMEM;
+	}
+
+	rc = of_property_read_u32(spi->dev.of_node, "cell-index",
+				  &e_ctrl->subdev_id);
+	CDBG("cell-index %d, rc %d\n", e_ctrl->subdev_id, rc);
+	if (rc) {
+		pr_err("failed rc %d\n", rc);
+		return rc;
+	}
+
+	e_ctrl->eeprom_device_type = MSM_CAMERA_SPI_DEVICE;
+	client->spi_client = spi_client;
+	spi_client->spi_master = spi;
+	client->i2c_func_tbl = &msm_eeprom_spi_func_tbl;
+	client->addr_type = MSM_CAMERA_I2C_3B_ADDR;
+
+	eb_info = kzalloc(sizeof(eb_info), GFP_KERNEL);
+	if (!eb_info)
+		goto spi_free;
+	e_ctrl->eboard_info = eb_info;
+	rc = of_property_read_string(spi->dev.of_node, "qcom,eeprom-name",
+		&eb_info->eeprom_name);
+	CDBG("%s qcom,eeprom-name %s, rc %d\n", __func__,
+		eb_info->eeprom_name, rc);
+	if (rc < 0) {
+		pr_err("%s failed %d\n", __func__, __LINE__);
+		goto board_free;
+	}
+	power_info = &eb_info->power_info;
+
+	power_info->clk_info = cam_8974_clk_info;
+	power_info->clk_info_size = ARRAY_SIZE(cam_8974_clk_info);
+	power_info->dev = &spi->dev;
+
+	rc = msm_eeprom_get_dt_data(e_ctrl);
+	if (rc)
+		goto board_free;
+
+	/* set spi instruction info */
+	spi_client->retry_delay = 1;
+	spi_client->retries = 0;
+
+	if (msm_eeprom_spi_parse_of(spi_client)) {
+		dev_err(&spi->dev,
+			"%s: Error parsing device properties\n", __func__);
+		goto board_free;
+	}
+
+	rc = msm_eeprom_alloc_memory_map(e_ctrl, spi->dev.of_node);
+	if (rc)
+		goto board_free;
+
+	rc = msm_camera_power_up(power_info, e_ctrl->eeprom_device_type,
+		&e_ctrl->i2c_client);
+	if (rc) {
+		pr_err("failed rc %d\n", rc);
+		goto memmap_free;
+	}
+
+	/* check eeprom id */
+	rc = msm_eeprom_check_id(e_ctrl);
+	if (rc) {
+		CDBG("%s: eeprom not matching %d\n", __func__, rc);
+		goto power_down;
+	}
+	/* read eeprom */
+	rc = read_eeprom_memory(e_ctrl);
+	if (rc) {
+		dev_err(&spi->dev, "%s: read eeprom memory failed\n", __func__);
+		goto power_down;
+	}
+
+	rc = msm_camera_power_down(power_info, e_ctrl->eeprom_device_type,
+		&e_ctrl->i2c_client);
+	if (rc) {
+		pr_err("failed rc %d\n", rc);
+		goto memmap_free;
+	}
+
+	/* initiazlie subdev */
+	v4l2_spi_subdev_init(&e_ctrl->msm_sd.sd,
+		e_ctrl->i2c_client.spi_client->spi_master,
+		e_ctrl->eeprom_v4l2_subdev_ops);
+	v4l2_set_subdevdata(&e_ctrl->msm_sd.sd, e_ctrl);
+	e_ctrl->msm_sd.sd.internal_ops = &msm_eeprom_internal_ops;
+	e_ctrl->msm_sd.sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
+	media_entity_init(&e_ctrl->msm_sd.sd.entity, 0, NULL, 0);
+	e_ctrl->msm_sd.sd.entity.type = MEDIA_ENT_T_V4L2_SUBDEV;
+	e_ctrl->msm_sd.sd.entity.group_id = MSM_CAMERA_SUBDEV_EEPROM;
+	msm_sd_register(&e_ctrl->msm_sd);
+	e_ctrl->is_supported = 1;
+	CDBG("%s success result=%d X\n", __func__, rc);
+
+	return 0;
+
+power_down:
+	msm_camera_power_down(power_info, e_ctrl->eeprom_device_type,
+		&e_ctrl->i2c_client);
+memmap_free:
+	kfree(e_ctrl->eboard_info->eeprom_map);
+	kfree(e_ctrl->memory_data);
+board_free:
+	kfree(e_ctrl->eboard_info);
+spi_free:
+	kfree(spi_client);
+	return rc;
+}
+
+static int msm_eeprom_spi_probe(struct spi_device *spi)
+{
+	int irq, cs, cpha, cpol, cs_high;
+
+	CDBG("%s\n", __func__);
+	spi->bits_per_word = 8;
+	spi->mode = SPI_MODE_0;
+	spi_setup(spi);
+
+	irq = spi->irq;
+	cs = spi->chip_select;
+	cpha = (spi->mode & SPI_CPHA) ? 1 : 0;
+	cpol = (spi->mode & SPI_CPOL) ? 1 : 0;
+	cs_high = (spi->mode & SPI_CS_HIGH) ? 1 : 0;
+	dev_info(&spi->dev, "irq[%d] cs[%x] CPHA[%x] CPOL[%x] CS_HIGH[%x]\n",
+			irq, cs, cpha, cpol, cs_high);
+	dev_info(&spi->dev, "max_speed[%u]\n", spi->max_speed_hz);
+
+	return msm_eeprom_spi_setup(spi);
+}
+
+static int32_t msm_eeprom_spi_remove(struct spi_device *sdev)
+{
+	struct v4l2_subdev *sd = spi_get_drvdata(sdev);
+	struct msm_eeprom_ctrl_t  *e_ctrl;
+	if (!sd) {
+		pr_err("%s: Subdevice is NULL\n", __func__);
+		return 0;
+	}
+
+	e_ctrl = (struct msm_eeprom_ctrl_t *)v4l2_get_subdevdata(sd);
+	if (!e_ctrl) {
+		pr_err("%s: eeprom device is NULL\n", __func__);
+		return 0;
+	}
+
+	kfree(e_ctrl->i2c_client.spi_client);
+	kfree(e_ctrl->memory_data);
+	if (e_ctrl->eboard_info) {
+		kfree(e_ctrl->eboard_info->power_info.gpio_conf);
+		kfree(e_ctrl->eboard_info->eeprom_map);
+	}
+	kfree(e_ctrl->eboard_info);
+	kfree(e_ctrl);
+	return 0;
+}
+
+static int32_t msm_eeprom_platform_probe(struct platform_device *pdev)
+{
+	int32_t rc = 0;
+	int32_t j = 0;
+	uint32_t temp;
+
+	struct msm_camera_cci_client *cci_client = NULL;
+	struct msm_eeprom_ctrl_t *e_ctrl = NULL;
+	struct msm_eeprom_board_info *eb_info = NULL;
+	struct device_node *of_node = pdev->dev.of_node;
+	struct msm_camera_power_ctrl_t *power_info = NULL;
+
+	CDBG("%s E\n", __func__);
+
+	e_ctrl = kzalloc(sizeof(struct msm_eeprom_ctrl_t), GFP_KERNEL);
+	if (!e_ctrl) {
+		pr_err("%s:%d kzalloc failed\n", __func__, __LINE__);
+		return -ENOMEM;
+	}
+	e_ctrl->eeprom_v4l2_subdev_ops = &msm_eeprom_subdev_ops;
+	e_ctrl->eeprom_mutex = &msm_eeprom_mutex;
+
+	e_ctrl->is_supported = 0;
+	if (!of_node) {
+		pr_err("%s dev.of_node NULL\n", __func__);
+		return -EINVAL;
+	}
+
+	rc = of_property_read_u32(of_node, "cell-index",
+		&pdev->id);
+	CDBG("cell-index %d, rc %d\n", pdev->id, rc);
+	if (rc < 0) {
+		pr_err("failed rc %d\n", rc);
+		return rc;
+	}
+	e_ctrl->subdev_id = pdev->id;
+
+	rc = of_property_read_u32(of_node, "qcom,cci-master",
+		&e_ctrl->cci_master);
+	CDBG("qcom,cci-master %d, rc %d\n", e_ctrl->cci_master, rc);
+	if (rc < 0) {
+		pr_err("%s failed rc %d\n", __func__, rc);
+		return rc;
+	}
+	rc = of_property_read_u32(of_node, "qcom,slave-addr",
+		&temp);
+	if (rc < 0) {
+		pr_err("%s failed rc %d\n", __func__, rc);
+		return rc;
+	}
+
+	/* Set platform device handle */
+	e_ctrl->pdev = pdev;
+	/* Set device type as platform device */
+	e_ctrl->eeprom_device_type = MSM_CAMERA_PLATFORM_DEVICE;
+	e_ctrl->i2c_client.i2c_func_tbl = &msm_eeprom_cci_func_tbl;
+	e_ctrl->i2c_client.cci_client = kzalloc(sizeof(
+		struct msm_camera_cci_client), GFP_KERNEL);
+	if (!e_ctrl->i2c_client.cci_client) {
+		pr_err("%s failed no memory\n", __func__);
+		return -ENOMEM;
+	}
+
+	e_ctrl->eboard_info = kzalloc(sizeof(
+		struct msm_eeprom_board_info), GFP_KERNEL);
+	if (!e_ctrl->eboard_info) {
+		pr_err("%s failed line %d\n", __func__, __LINE__);
+		rc = -ENOMEM;
+		goto cciclient_free;
+	}
+	eb_info = e_ctrl->eboard_info;
+	power_info = &eb_info->power_info;
+	eb_info->i2c_slaveaddr = temp;
+
+	power_info->clk_info = cam_8974_clk_info;
+	power_info->clk_info_size = ARRAY_SIZE(cam_8974_clk_info);
+	power_info->dev = &pdev->dev;
+
+	CDBG("qcom,slave-addr = 0x%X\n", eb_info->i2c_slaveaddr);
+	cci_client = e_ctrl->i2c_client.cci_client;
+	cci_client->cci_subdev = msm_cci_get_subdev();
+	cci_client->cci_i2c_master = e_ctrl->cci_master;
+	cci_client->sid = eb_info->i2c_slaveaddr >> 1;
+	cci_client->retries = 3;
+	cci_client->id_map = 0;
+
+	rc = of_property_read_string(of_node, "qcom,eeprom-name",
+		&eb_info->eeprom_name);
+	CDBG("%s qcom,eeprom-name %s, rc %d\n", __func__,
+		eb_info->eeprom_name, rc);
+	if (rc < 0) {
+		pr_err("%s failed %d\n", __func__, __LINE__);
+		goto board_free;
+	}
+
+	if (e_ctrl->eeprom_device_type == MSM_CAMERA_PLATFORM_DEVICE) {
+		rc = e_ctrl->i2c_client.i2c_func_tbl->i2c_util(
+		&e_ctrl->i2c_client, MSM_CCI_INIT);
+		if (rc < 0)
+			pr_err("%s cci_init failed\n", __func__);
+	}
+
+	rc = msm_eeprom_alloc_memory_map(e_ctrl, of_node);
+	if (rc)
+		goto board_free;
+
+	rc = read_eeprom_memory(e_ctrl);
+	if (rc < 0) {
+		pr_err("%s read_eeprom_memory failed\n", __func__);
+		goto memdata_free;
+	}
+		pr_err("%s line %d\n", __func__, __LINE__);
+	for (j = 0; j < e_ctrl->num_bytes; j++)
+		CDBG("memory_data[%d] = 0x%X\n", j, e_ctrl->memory_data[j]);
+
+	v4l2_subdev_init(&e_ctrl->msm_sd.sd,
+		e_ctrl->eeprom_v4l2_subdev_ops);
+	v4l2_set_subdevdata(&e_ctrl->msm_sd.sd, e_ctrl);
+	platform_set_drvdata(pdev, &e_ctrl->msm_sd.sd);
+	e_ctrl->msm_sd.sd.internal_ops = &msm_eeprom_internal_ops;
+	e_ctrl->msm_sd.sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
+	snprintf(e_ctrl->msm_sd.sd.name,
+		ARRAY_SIZE(e_ctrl->msm_sd.sd.name), "msm_eeprom");
+	media_entity_init(&e_ctrl->msm_sd.sd.entity, 0, NULL, 0);
+	e_ctrl->msm_sd.sd.entity.type = MEDIA_ENT_T_V4L2_SUBDEV;
+	e_ctrl->msm_sd.sd.entity.group_id = MSM_CAMERA_SUBDEV_EEPROM;
+	msm_sd_register(&e_ctrl->msm_sd);
+
+
+	if (e_ctrl->eeprom_device_type == MSM_CAMERA_PLATFORM_DEVICE) {
+		rc = e_ctrl->i2c_client.i2c_func_tbl->i2c_util(
+			&e_ctrl->i2c_client, MSM_CCI_RELEASE);
+		if (rc < 0)
+			pr_err("%s cci_init failed\n", __func__);
+	}
+	e_ctrl->is_supported = 1;
+	CDBG("%s X\n", __func__);
+	return rc;
+
+memdata_free:
+	kfree(e_ctrl->memory_data);
+	kfree(eb_info->eeprom_map);
+board_free:
+	kfree(e_ctrl->eboard_info);
+cciclient_free:
+	kfree(e_ctrl->i2c_client.cci_client);
+	return rc;
+}
+
+static int32_t msm_eeprom_platform_remove(struct platform_device *pdev)
+{
+	struct v4l2_subdev *sd = platform_get_drvdata(pdev);
+	struct msm_eeprom_ctrl_t  *e_ctrl;
+	if (!sd) {
+		pr_err("%s: Subdevice is NULL\n", __func__);
+		return 0;
+	}
+
+	e_ctrl = (struct msm_eeprom_ctrl_t *)v4l2_get_subdevdata(sd);
+	if (!e_ctrl) {
+		pr_err("%s: eeprom device is NULL\n", __func__);
+		return 0;
+	}
+
+	kfree(e_ctrl->i2c_client.cci_client);
+	kfree(e_ctrl->memory_data);
+	if (e_ctrl->eboard_info) {
+		kfree(e_ctrl->eboard_info->power_info.gpio_conf);
+		kfree(e_ctrl->eboard_info->eeprom_map);
+	}
+	kfree(e_ctrl->eboard_info);
+	kfree(e_ctrl);
+	return 0;
+}
+
+static const struct of_device_id msm_eeprom_dt_match[] = {
+	{ .compatible = "qcom,eeprom" },
+	{ }
+};
+
+MODULE_DEVICE_TABLE(of, msm_eeprom_dt_match);
+
+static struct platform_driver msm_eeprom_platform_driver = {
+	.driver = {
+		.name = "qcom,eeprom",
+		.owner = THIS_MODULE,
+		.of_match_table = msm_eeprom_dt_match,
+	},
+	.remove = __devexit_p(msm_eeprom_platform_remove),
+};
+
+static const struct i2c_device_id msm_eeprom_i2c_id[] = {
+	{ "msm_eeprom", (kernel_ulong_t)NULL},
+	{ }
+};
+
+static struct i2c_driver msm_eeprom_i2c_driver = {
+	.id_table = msm_eeprom_i2c_id,
+	.probe  = msm_eeprom_i2c_probe,
+	.remove = __devexit_p(msm_eeprom_i2c_remove),
+	.driver = {
+		.name = "msm_eeprom",
+	},
+};
+
+static struct spi_driver msm_eeprom_spi_driver = {
+	.driver = {
+		.name = "qcom_eeprom",
+		.owner = THIS_MODULE,
+		.of_match_table = msm_eeprom_dt_match,
+	},
+	.probe = msm_eeprom_spi_probe,
+	.remove = __devexit_p(msm_eeprom_spi_remove),
+};
+
+static int __init msm_eeprom_init_module(void)
+{
+	int32_t rc = 0;
+	CDBG("%s E\n", __func__);
+	rc = platform_driver_probe(&msm_eeprom_platform_driver,
+		msm_eeprom_platform_probe);
+	CDBG("%s:%d platform rc %d\n", __func__, __LINE__, rc);
+	rc = spi_register_driver(&msm_eeprom_spi_driver);
+	CDBG("%s:%d spi rc %d\n", __func__, __LINE__, rc);
+	return i2c_add_driver(&msm_eeprom_i2c_driver);
+}
+
+static void __exit msm_eeprom_exit_module(void)
+{
+	platform_driver_unregister(&msm_eeprom_platform_driver);
+	spi_unregister_driver(&msm_eeprom_spi_driver);
+	i2c_del_driver(&msm_eeprom_i2c_driver);
+}
+
+module_init(msm_eeprom_init_module);
+module_exit(msm_eeprom_exit_module);
+MODULE_DESCRIPTION("MSM EEPROM driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/media/platform/msm/camera_v2/sensor/eeprom/msm_eeprom.h b/drivers/media/platform/msm/camera_v2/sensor/eeprom/msm_eeprom.h
new file mode 100644
index 0000000..cebe585
--- /dev/null
+++ b/drivers/media/platform/msm/camera_v2/sensor/eeprom/msm_eeprom.h
@@ -0,0 +1,48 @@
+/* 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
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+#ifndef MSM_EEPROM_H
+#define MSM_EEPROM_H
+
+#include <linux/i2c.h>
+#include <linux/gpio.h>
+#include <mach/camera2.h>
+#include <media/v4l2-subdev.h>
+#include <media/msmb_camera.h>
+#include "msm_camera_i2c.h"
+#include "msm_camera_spi.h"
+#include "msm_camera_io_util.h"
+#include "msm_camera_dt_util.h"
+
+struct msm_eeprom_ctrl_t;
+
+#define DEFINE_MSM_MUTEX(mutexname) \
+	static struct mutex mutexname = __MUTEX_INITIALIZER(mutexname)
+
+struct msm_eeprom_ctrl_t {
+	struct platform_device *pdev;
+	struct mutex *eeprom_mutex;
+
+	struct v4l2_subdev sdev;
+	struct v4l2_subdev_ops *eeprom_v4l2_subdev_ops;
+	enum msm_camera_device_type_t eeprom_device_type;
+	struct msm_sd_subdev msm_sd;
+	enum cci_i2c_master_t cci_master;
+
+	struct msm_camera_i2c_client i2c_client;
+	uint32_t num_bytes;
+	uint8_t *memory_data;
+	uint8_t is_supported;
+	struct msm_eeprom_board_info *eboard_info;
+	uint32_t subdev_id;
+};
+
+#endif
diff --git a/drivers/media/platform/msm/camera_v2/sensor/io/Makefile b/drivers/media/platform/msm/camera_v2/sensor/io/Makefile
index f71b09d..0c7c191 100644
--- a/drivers/media/platform/msm/camera_v2/sensor/io/Makefile
+++ b/drivers/media/platform/msm/camera_v2/sensor/io/Makefile
@@ -1,3 +1,4 @@
 ccflags-y += -Idrivers/media/platform/msm/camera_v2/
+ccflags-y += -Idrivers/media/platform/msm/camera_v2/sensor
 ccflags-y += -Idrivers/media/platform/msm/camera_v2/sensor/cci
-obj-$(CONFIG_MSMB_CAMERA)   += msm_camera_io_util.o msm_camera_cci_i2c.o msm_camera_qup_i2c.o msm_camera_i2c_mux.o
+obj-$(CONFIG_MSMB_CAMERA)   += msm_camera_io_util.o msm_camera_cci_i2c.o msm_camera_qup_i2c.o msm_camera_i2c_mux.o msm_camera_spi.o msm_camera_dt_util.o
diff --git a/drivers/media/platform/msm/camera_v2/sensor/io/msm_camera_cci_i2c.c b/drivers/media/platform/msm/camera_v2/sensor/io/msm_camera_cci_i2c.c
index b07f04f..80b1ccb 100644
--- a/drivers/media/platform/msm/camera_v2/sensor/io/msm_camera_cci_i2c.c
+++ b/drivers/media/platform/msm/camera_v2/sensor/io/msm_camera_cci_i2c.c
@@ -28,7 +28,7 @@
 #define I2C_POLL_MAX_ITERATION 20
 
 int32_t msm_camera_cci_i2c_read(struct msm_camera_i2c_client *client,
-	uint16_t addr, uint16_t *data,
+	uint32_t addr, uint16_t *data,
 	enum msm_camera_i2c_data_type data_type)
 {
 	int32_t rc = -EFAULT;
@@ -64,10 +64,10 @@
 }
 
 int32_t msm_camera_cci_i2c_read_seq(struct msm_camera_i2c_client *client,
-	uint16_t addr, uint8_t *data, uint16_t num_byte)
+	uint32_t addr, uint8_t *data, uint16_t num_byte)
 {
 	int32_t rc = -EFAULT;
-	unsigned char buf[client->addr_type+num_byte];
+	unsigned char *buf = NULL;
 	int i;
 	struct msm_camera_cci_ctrl cci_ctrl;
 
@@ -76,6 +76,11 @@
 		|| num_byte == 0)
 		return rc;
 
+	buf = kzalloc(num_byte, GFP_KERNEL);
+	if (!buf) {
+		pr_err("%s:%d no memory\n", __func__, __LINE__);
+		return -ENOMEM;
+	}
 	cci_ctrl.cmd = MSM_CCI_I2C_READ;
 	cci_ctrl.cci_info = client->cci_client;
 	cci_ctrl.cfg.cci_i2c_read_cfg.addr = addr;
@@ -93,11 +98,12 @@
 		S_I2C_DBG("Byte %d: 0x%x\n", i, buf[i]);
 		S_I2C_DBG("Data: 0x%x\n", data[i]);
 	}
+	kfree(buf);
 	return rc;
 }
 
 int32_t msm_camera_cci_i2c_write(struct msm_camera_i2c_client *client,
-	uint16_t addr, uint16_t data,
+	uint32_t addr, uint16_t data,
 	enum msm_camera_i2c_data_type data_type)
 {
 	int32_t rc = -EFAULT;
@@ -131,7 +137,7 @@
 }
 
 int32_t msm_camera_cci_i2c_write_seq(struct msm_camera_i2c_client *client,
-	uint16_t addr, uint8_t *data, uint16_t num_byte)
+	uint32_t addr, uint8_t *data, uint16_t num_byte)
 {
 	int32_t rc = -EFAULT;
 	uint8_t i = 0;
@@ -272,7 +278,7 @@
 }
 
 static int32_t msm_camera_cci_i2c_compare(struct msm_camera_i2c_client *client,
-	uint16_t addr, uint16_t data,
+	uint32_t addr, uint16_t data,
 	enum msm_camera_i2c_data_type data_type)
 {
 	int32_t rc;
@@ -327,8 +333,8 @@
 	return rc;
 }
 
-static int32_t msm_camera_cci_i2c_poll(struct msm_camera_i2c_client *client,
-	uint16_t addr, uint16_t data,
+int32_t msm_camera_cci_i2c_poll(struct msm_camera_i2c_client *client,
+	uint32_t addr, uint16_t data,
 	enum msm_camera_i2c_data_type data_type)
 {
 	int32_t rc;
@@ -347,7 +353,7 @@
 }
 
 static int32_t msm_camera_cci_i2c_set_mask(struct msm_camera_i2c_client *client,
-	uint16_t addr, uint16_t mask,
+	uint32_t addr, uint16_t mask,
 	enum msm_camera_i2c_data_type data_type, uint16_t set_mask)
 {
 	int32_t rc;
@@ -376,7 +382,7 @@
 
 static int32_t msm_camera_cci_i2c_set_write_mask_data(
 	struct msm_camera_i2c_client *client,
-	uint16_t addr, uint16_t data, int16_t mask,
+	uint32_t addr, uint16_t data, int16_t mask,
 	enum msm_camera_i2c_data_type data_type)
 {
 	int32_t rc;
diff --git a/drivers/media/platform/msm/camera_v2/sensor/io/msm_camera_dt_util.c b/drivers/media/platform/msm/camera_v2/sensor/io/msm_camera_dt_util.c
new file mode 100644
index 0000000..2511651
--- /dev/null
+++ b/drivers/media/platform/msm/camera_v2/sensor/io/msm_camera_dt_util.c
@@ -0,0 +1,662 @@
+/* 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 <mach/gpiomux.h>
+#include "msm_camera_dt_util.h"
+#include "msm_camera_io_util.h"
+#include "msm_camera_i2c_mux.h"
+#include "msm_cci.h"
+
+#undef CDBG
+#ifdef CONFIG_MSM_CAMERA_DT_DEBUG
+#define CDBG(fmt, args...) pr_err(fmt, ##args)
+#else
+#define CDBG(fmt, args...) do { } while (0)
+#endif
+
+int32_t msm_camera_get_dt_power_setting_data(struct device_node *of_node,
+	struct msm_sensor_power_setting **power_setting,
+	uint16_t *power_setting_size)
+{
+	int32_t rc = 0, i = 0;
+	int32_t count = 0;
+	const char *seq_name = NULL;
+	uint32_t *array = NULL;
+	struct msm_sensor_power_setting *ps;
+
+	if (!power_setting || !power_setting_size)
+		return -EINVAL;
+
+	count = of_property_count_strings(of_node, "qcom,cam-power-seq-type");
+	*power_setting_size = count;
+	CDBG("%s qcom,cam-power-seq-type count %d\n", __func__, count);
+
+	if (count <= 0)
+		return 0;
+
+	ps = kzalloc(sizeof(struct msm_sensor_power_setting) * count,
+		GFP_KERNEL);
+	if (!ps) {
+		pr_err("%s failed %d\n", __func__, __LINE__);
+		return -ENOMEM;
+	}
+	*power_setting = ps;
+
+	for (i = 0; i < count; i++) {
+		rc = of_property_read_string_index(of_node,
+			"qcom,cam-power-seq-type", i,
+			&seq_name);
+		CDBG("%s seq_name[%d] = %s\n", __func__, i,
+			seq_name);
+		if (rc < 0) {
+			pr_err("%s failed %d\n", __func__, __LINE__);
+			goto ERROR1;
+		}
+		if (!strcmp(seq_name, "sensor_vreg")) {
+			ps[i].seq_type = SENSOR_VREG;
+			CDBG("%s:%d seq_type[%d] %d\n", __func__, __LINE__,
+				i, ps[i].seq_type);
+		} else if (!strcmp(seq_name, "sensor_gpio")) {
+			ps[i].seq_type = SENSOR_GPIO;
+			CDBG("%s:%d seq_type[%d] %d\n", __func__, __LINE__,
+				i, ps[i].seq_type);
+		} else if (!strcmp(seq_name, "sensor_clk")) {
+			ps[i].seq_type = SENSOR_CLK;
+			CDBG("%s:%d seq_type[%d] %d\n", __func__, __LINE__,
+				i, ps[i].seq_type);
+		} else if (!strcmp(seq_name, "sensor_i2c_mux")) {
+			ps[i].seq_type = SENSOR_I2C_MUX;
+			CDBG("%s:%d seq_type[%d] %d\n", __func__, __LINE__,
+				i, ps[i].seq_type);
+		}
+	}
+
+
+	for (i = 0; i < count; i++) {
+		rc = of_property_read_string_index(of_node,
+			"qcom,cam-power-seq-val", i,
+			&seq_name);
+		CDBG("%s seq_name[%d] = %s\n", __func__, i,
+			seq_name);
+		if (rc < 0) {
+			pr_err("%s failed %d\n", __func__, __LINE__);
+			goto ERROR1;
+		}
+		if (!strcmp(seq_name, "cam_vdig"))
+			ps[i].seq_val = CAM_VDIG;
+		else if (!strcmp(seq_name, "cam_vio"))
+			ps[i].seq_val = CAM_VIO;
+		else if (!strcmp(seq_name, "cam_vana"))
+			ps[i].seq_val = CAM_VANA;
+		else if (!strcmp(seq_name, "cam_vaf"))
+			ps[i].seq_val = CAM_VAF;
+		else if (!strcmp(seq_name, "sensor_gpio_reset"))
+			ps[i].seq_val = SENSOR_GPIO_RESET;
+		else if (!strcmp(seq_name, "sensor_gpio_standby"))
+			ps[i].seq_val = SENSOR_GPIO_STANDBY;
+		else if (!strcmp(seq_name, "sensor_cam_mclk"))
+			ps[i].seq_val = SENSOR_CAM_MCLK;
+		else if (!strcmp(seq_name, "sensor_cam_clk"))
+			ps[i].seq_val = SENSOR_CAM_CLK;
+		else if (!strcmp(seq_name, "none"))
+			ps[i].seq_val = 0;
+	}
+
+	array = kzalloc(sizeof(uint32_t) * count, GFP_KERNEL);
+	if (!array) {
+		pr_err("%s failed %d\n", __func__, __LINE__);
+		rc = -ENOMEM;
+		goto ERROR1;
+	}
+
+
+	rc = of_property_read_u32_array(of_node, "qcom,cam-power-seq-cfg-val",
+		array, count);
+	if (rc < 0) {
+		pr_err("%s failed %d\n", __func__, __LINE__);
+		goto ERROR2;
+	}
+	for (i = 0; i < count; i++) {
+		if (ps[i].seq_type == SENSOR_GPIO) {
+			if (array[i] == 0)
+				ps[i].config_val = GPIO_OUT_LOW;
+			else if (array[i] == 1)
+				ps[i].config_val = GPIO_OUT_HIGH;
+		} else {
+			ps[i].config_val = array[i];
+		}
+		CDBG("%s power_setting[%d].config_val = %ld\n", __func__, i,
+			ps[i].config_val);
+	}
+
+	rc = of_property_read_u32_array(of_node, "qcom,cam-power-seq-delay",
+		array, count);
+	if (rc < 0) {
+		pr_err("%s failed %d\n", __func__, __LINE__);
+		goto ERROR2;
+	}
+	for (i = 0; i < count; i++) {
+		ps[i].delay = array[i];
+		CDBG("%s power_setting[%d].delay = %d\n", __func__,
+			i, ps[i].delay);
+	}
+	kfree(array);
+	return rc;
+ERROR2:
+	kfree(array);
+ERROR1:
+	kfree(ps);
+	power_setting_size = 0;
+	return rc;
+}
+
+int32_t msm_camera_get_dt_gpio_req_tbl(struct device_node *of_node,
+	struct msm_camera_gpio_conf *gconf, uint16_t *gpio_array,
+	uint16_t gpio_array_size)
+{
+	int32_t rc = 0, i = 0;
+	uint32_t count = 0;
+	uint32_t *val_array = NULL;
+
+	if (!of_get_property(of_node, "qcom,gpio-req-tbl-num", &count))
+		return 0;
+
+	count /= sizeof(uint32_t);
+	if (!count) {
+		pr_err("%s qcom,gpio-req-tbl-num 0\n", __func__);
+		return 0;
+	}
+
+	val_array = kzalloc(sizeof(uint32_t) * count, GFP_KERNEL);
+	if (!val_array) {
+		pr_err("%s failed %d\n", __func__, __LINE__);
+		return -ENOMEM;
+	}
+
+	gconf->cam_gpio_req_tbl = kzalloc(sizeof(struct gpio) * count,
+		GFP_KERNEL);
+	if (!gconf->cam_gpio_req_tbl) {
+		pr_err("%s failed %d\n", __func__, __LINE__);
+		rc = -ENOMEM;
+		goto ERROR1;
+	}
+	gconf->cam_gpio_req_tbl_size = count;
+
+	rc = of_property_read_u32_array(of_node, "qcom,gpio-req-tbl-num",
+		val_array, count);
+	if (rc < 0) {
+		pr_err("%s failed %d\n", __func__, __LINE__);
+		goto ERROR2;
+	}
+	for (i = 0; i < count; i++) {
+		if (val_array[i] >= gpio_array_size) {
+			pr_err("%s gpio req tbl index %d invalid\n",
+				__func__, val_array[i]);
+			return -EINVAL;
+		}
+		gconf->cam_gpio_req_tbl[i].gpio = gpio_array[val_array[i]];
+		CDBG("%s cam_gpio_req_tbl[%d].gpio = %d\n", __func__, i,
+			gconf->cam_gpio_req_tbl[i].gpio);
+	}
+
+	rc = of_property_read_u32_array(of_node, "qcom,gpio-req-tbl-flags",
+		val_array, count);
+	if (rc < 0) {
+		pr_err("%s failed %d\n", __func__, __LINE__);
+		goto ERROR2;
+	}
+	for (i = 0; i < count; i++) {
+		gconf->cam_gpio_req_tbl[i].flags = val_array[i];
+		CDBG("%s cam_gpio_req_tbl[%d].flags = %ld\n", __func__, i,
+			gconf->cam_gpio_req_tbl[i].flags);
+	}
+
+	for (i = 0; i < count; i++) {
+		rc = of_property_read_string_index(of_node,
+			"qcom,gpio-req-tbl-label", i,
+			&gconf->cam_gpio_req_tbl[i].label);
+		CDBG("%s cam_gpio_req_tbl[%d].label = %s\n", __func__, i,
+			gconf->cam_gpio_req_tbl[i].label);
+		if (rc < 0) {
+			pr_err("%s failed %d\n", __func__, __LINE__);
+			goto ERROR2;
+		}
+	}
+
+	kfree(val_array);
+	return rc;
+
+ERROR2:
+	kfree(gconf->cam_gpio_req_tbl);
+ERROR1:
+	kfree(val_array);
+	gconf->cam_gpio_req_tbl_size = 0;
+	return rc;
+}
+
+int32_t msm_camera_init_gpio_pin_tbl(struct device_node *of_node,
+	struct msm_camera_gpio_conf *gconf, uint16_t *gpio_array,
+	uint16_t gpio_array_size)
+{
+	int32_t rc = 0;
+	int32_t val = 0;
+
+	gconf->gpio_num_info = kzalloc(sizeof(struct msm_camera_gpio_num_info),
+		GFP_KERNEL);
+	if (!gconf->gpio_num_info) {
+		pr_err("%s failed %d\n", __func__, __LINE__);
+		rc = -ENOMEM;
+		return rc;
+	}
+
+	if (of_property_read_bool(of_node, "qcom,gpio-reset") == true) {
+		rc = of_property_read_u32(of_node, "qcom,gpio-reset", &val);
+		if (rc < 0) {
+			pr_err("%s:%d read qcom,gpio-reset failed rc %d\n",
+				__func__, __LINE__, rc);
+			goto ERROR;
+		} else if (val >= gpio_array_size) {
+			pr_err("%s:%d qcom,gpio-reset invalid %d\n",
+				__func__, __LINE__, val);
+			goto ERROR;
+		}
+		gconf->gpio_num_info->gpio_num[SENSOR_GPIO_RESET] =
+			gpio_array[val];
+		CDBG("%s qcom,gpio-reset %d\n", __func__,
+			gconf->gpio_num_info->gpio_num[SENSOR_GPIO_RESET]);
+	}
+
+	if (of_property_read_bool(of_node, "qcom,gpio-standby") == true) {
+		rc = of_property_read_u32(of_node, "qcom,gpio-standby", &val);
+		if (rc < 0) {
+			pr_err("%s:%d read qcom,gpio-standby failed rc %d\n",
+				__func__, __LINE__, rc);
+			goto ERROR;
+		} else if (val >= gpio_array_size) {
+			pr_err("%s:%d qcom,gpio-standby invalid %d\n",
+				__func__, __LINE__, val);
+			goto ERROR;
+		}
+		gconf->gpio_num_info->gpio_num[SENSOR_GPIO_STANDBY] =
+			gpio_array[val];
+		CDBG("%s qcom,gpio-reset %d\n", __func__,
+			gconf->gpio_num_info->gpio_num[SENSOR_GPIO_STANDBY]);
+	}
+	return rc;
+
+ERROR:
+	kfree(gconf->gpio_num_info);
+	gconf->gpio_num_info = NULL;
+	return rc;
+}
+
+int32_t msm_camera_get_dt_vreg_data(struct device_node *of_node,
+	struct camera_vreg_t **cam_vreg, int *num_vreg)
+{
+	int32_t rc = 0, i = 0;
+	uint32_t count = 0;
+	uint32_t *vreg_array = NULL;
+	struct camera_vreg_t *vreg = NULL;
+
+	count = of_property_count_strings(of_node, "qcom,cam-vreg-name");
+	CDBG("%s qcom,cam-vreg-name count %d\n", __func__, count);
+
+	if (!count)
+		return 0;
+
+	vreg = kzalloc(sizeof(struct camera_vreg_t) * count,
+		GFP_KERNEL);
+	if (!vreg) {
+		pr_err("%s failed %d\n", __func__, __LINE__);
+		return -ENOMEM;
+	}
+	*cam_vreg = vreg;
+	*num_vreg = count;
+	for (i = 0; i < count; i++) {
+		rc = of_property_read_string_index(of_node,
+			"qcom,cam-vreg-name", i,
+			&vreg[i].reg_name);
+		CDBG("%s reg_name[%d] = %s\n", __func__, i,
+			vreg[i].reg_name);
+		if (rc < 0) {
+			pr_err("%s failed %d\n", __func__, __LINE__);
+			goto ERROR1;
+		}
+	}
+
+	vreg_array = kzalloc(sizeof(uint32_t) * count, GFP_KERNEL);
+	if (!vreg_array) {
+		pr_err("%s failed %d\n", __func__, __LINE__);
+		rc = -ENOMEM;
+		goto ERROR1;
+	}
+
+	rc = of_property_read_u32_array(of_node, "qcom,cam-vreg-type",
+		vreg_array, count);
+	if (rc < 0) {
+		pr_err("%s failed %d\n", __func__, __LINE__);
+		goto ERROR2;
+	}
+	for (i = 0; i < count; i++) {
+		vreg[i].type = vreg_array[i];
+		CDBG("%s cam_vreg[%d].type = %d\n", __func__, i,
+			vreg[i].type);
+	}
+
+	rc = of_property_read_u32_array(of_node, "qcom,cam-vreg-min-voltage",
+		vreg_array, count);
+	if (rc < 0) {
+		pr_err("%s failed %d\n", __func__, __LINE__);
+		goto ERROR2;
+	}
+	for (i = 0; i < count; i++) {
+		vreg[i].min_voltage = vreg_array[i];
+		CDBG("%s cam_vreg[%d].min_voltage = %d\n", __func__,
+			i, vreg[i].min_voltage);
+	}
+
+	rc = of_property_read_u32_array(of_node, "qcom,cam-vreg-max-voltage",
+		vreg_array, count);
+	if (rc < 0) {
+		pr_err("%s failed %d\n", __func__, __LINE__);
+		goto ERROR2;
+	}
+	for (i = 0; i < count; i++) {
+		vreg[i].max_voltage = vreg_array[i];
+		CDBG("%s cam_vreg[%d].max_voltage = %d\n", __func__,
+			i, vreg[i].max_voltage);
+	}
+
+	rc = of_property_read_u32_array(of_node, "qcom,cam-vreg-op-mode",
+		vreg_array, count);
+	if (rc < 0) {
+		pr_err("%s failed %d\n", __func__, __LINE__);
+		goto ERROR2;
+	}
+	for (i = 0; i < count; i++) {
+		vreg[i].op_mode = vreg_array[i];
+		CDBG("%s cam_vreg[%d].op_mode = %d\n", __func__, i,
+			vreg[i].op_mode);
+	}
+
+	kfree(vreg_array);
+	return rc;
+ERROR2:
+	kfree(vreg_array);
+ERROR1:
+	kfree(vreg);
+	*num_vreg = 0;
+	return rc;
+}
+
+static int32_t msm_camera_enable_i2c_mux(struct msm_camera_i2c_conf *i2c_conf)
+{
+	struct v4l2_subdev *i2c_mux_sd =
+		dev_get_drvdata(&i2c_conf->mux_dev->dev);
+	v4l2_subdev_call(i2c_mux_sd, core, ioctl,
+		VIDIOC_MSM_I2C_MUX_INIT, NULL);
+	v4l2_subdev_call(i2c_mux_sd, core, ioctl,
+		VIDIOC_MSM_I2C_MUX_CFG, (void *)&i2c_conf->i2c_mux_mode);
+	return 0;
+}
+
+static int32_t msm_camera_disable_i2c_mux(struct msm_camera_i2c_conf *i2c_conf)
+{
+	struct v4l2_subdev *i2c_mux_sd =
+		dev_get_drvdata(&i2c_conf->mux_dev->dev);
+	v4l2_subdev_call(i2c_mux_sd, core, ioctl,
+		VIDIOC_MSM_I2C_MUX_RELEASE, NULL);
+	return 0;
+}
+
+int32_t msm_camera_power_up(struct msm_camera_power_ctrl_t *ctrl,
+	enum msm_camera_device_type_t device_type,
+	struct msm_camera_i2c_client *sensor_i2c_client)
+{
+	int32_t rc = 0, index = 0, no_gpio = 0;
+	struct msm_sensor_power_setting *power_setting = NULL;
+
+	CDBG("%s:%d\n", __func__, __LINE__);
+	if (!ctrl || !sensor_i2c_client) {
+		pr_err("failed ctrl %p sensor_i2c_client %p\n", ctrl,
+			sensor_i2c_client);
+		return -EINVAL;
+	}
+	if (ctrl->gpio_conf->cam_gpiomux_conf_tbl != NULL) {
+		pr_err("%s:%d mux install\n", __func__, __LINE__);
+		msm_gpiomux_install(
+			(struct msm_gpiomux_config *)
+			ctrl->gpio_conf->cam_gpiomux_conf_tbl,
+			ctrl->gpio_conf->cam_gpiomux_conf_tbl_size);
+	}
+
+	rc = msm_camera_request_gpio_table(
+		ctrl->gpio_conf->cam_gpio_req_tbl,
+		ctrl->gpio_conf->cam_gpio_req_tbl_size, 1);
+	if (rc < 0)
+		no_gpio = rc;
+
+	for (index = 0; index < ctrl->power_setting_size; index++) {
+		CDBG("%s index %d\n", __func__, index);
+		power_setting = &ctrl->power_setting[index];
+		CDBG("%s type %d\n", __func__, power_setting->seq_type);
+		switch (power_setting->seq_type) {
+		case SENSOR_CLK:
+			if (power_setting->seq_val >= ctrl->clk_info_size) {
+				pr_err("%s clk index %d >= max %d\n", __func__,
+					power_setting->seq_val,
+					ctrl->clk_info_size);
+				goto power_up_failed;
+			}
+			if (power_setting->config_val)
+				ctrl->clk_info[power_setting->seq_val].
+					clk_rate = power_setting->config_val;
+
+			rc = msm_cam_clk_enable(ctrl->dev,
+				&ctrl->clk_info[0],
+				(struct clk **)&power_setting->data[0],
+				ctrl->clk_info_size,
+				1);
+			if (rc < 0) {
+				pr_err("%s: clk enable failed\n",
+					__func__);
+				goto power_up_failed;
+			}
+			break;
+		case SENSOR_GPIO:
+			if (no_gpio) {
+				pr_err("%s: request gpio failed\n", __func__);
+				return no_gpio;
+			}
+			if (power_setting->seq_val >= SENSOR_GPIO_MAX ||
+				!ctrl->gpio_conf->gpio_num_info) {
+				pr_err("%s gpio index %d >= max %d\n", __func__,
+					power_setting->seq_val,
+					SENSOR_GPIO_MAX);
+				goto power_up_failed;
+			}
+			pr_debug("%s:%d gpio set val %d\n", __func__, __LINE__,
+				ctrl->gpio_conf->gpio_num_info->gpio_num
+				[power_setting->seq_val]);
+			gpio_set_value_cansleep(
+				ctrl->gpio_conf->gpio_num_info->gpio_num
+				[power_setting->seq_val],
+				power_setting->config_val);
+			break;
+		case SENSOR_VREG:
+			if (power_setting->seq_val >= CAM_VREG_MAX) {
+				pr_err("%s vreg index %d >= max %d\n", __func__,
+					power_setting->seq_val,
+					SENSOR_GPIO_MAX);
+				goto power_up_failed;
+			}
+			msm_camera_config_single_vreg(ctrl->dev,
+				&ctrl->cam_vreg[power_setting->seq_val],
+				(struct regulator **)&power_setting->data[0],
+				1);
+			break;
+		case SENSOR_I2C_MUX:
+			if (ctrl->i2c_conf && ctrl->i2c_conf->use_i2c_mux)
+				msm_camera_enable_i2c_mux(ctrl->i2c_conf);
+			break;
+		default:
+			pr_err("%s error power seq type %d\n", __func__,
+				power_setting->seq_type);
+			break;
+		}
+		if (power_setting->delay > 20) {
+			msleep(power_setting->delay);
+		} else if (power_setting->delay) {
+			usleep_range(power_setting->delay * 1000,
+				(power_setting->delay * 1000) + 1000);
+		}
+	}
+
+	if (device_type == MSM_CAMERA_PLATFORM_DEVICE) {
+		rc = sensor_i2c_client->i2c_func_tbl->i2c_util(
+			sensor_i2c_client, MSM_CCI_INIT);
+		if (rc < 0) {
+			pr_err("%s cci_init failed\n", __func__);
+			goto power_up_failed;
+		}
+	}
+
+	CDBG("%s exit\n", __func__);
+	return 0;
+power_up_failed:
+	pr_err("%s:%d failed\n", __func__, __LINE__);
+	if (device_type == MSM_CAMERA_PLATFORM_DEVICE) {
+		sensor_i2c_client->i2c_func_tbl->i2c_util(
+			sensor_i2c_client, MSM_CCI_RELEASE);
+	}
+
+	for (index--; index >= 0; index--) {
+		CDBG("%s index %d\n", __func__, index);
+		power_setting = &ctrl->power_setting[index];
+		CDBG("%s type %d\n", __func__, power_setting->seq_type);
+		switch (power_setting->seq_type) {
+		case SENSOR_CLK:
+			msm_cam_clk_enable(ctrl->dev,
+				&ctrl->clk_info[0],
+				(struct clk **)&power_setting->data[0],
+				ctrl->clk_info_size,
+				0);
+			break;
+		case SENSOR_GPIO:
+			gpio_set_value_cansleep(
+				ctrl->gpio_conf->gpio_num_info->gpio_num
+				[power_setting->seq_val], GPIOF_OUT_INIT_LOW);
+			break;
+		case SENSOR_VREG:
+			msm_camera_config_single_vreg(ctrl->dev,
+				&ctrl->cam_vreg[power_setting->seq_val],
+				(struct regulator **)&power_setting->data[0],
+				0);
+			break;
+		case SENSOR_I2C_MUX:
+			if (ctrl->i2c_conf && ctrl->i2c_conf->use_i2c_mux)
+				msm_camera_disable_i2c_mux(ctrl->i2c_conf);
+			break;
+		default:
+			pr_err("%s error power seq type %d\n", __func__,
+				power_setting->seq_type);
+			break;
+		}
+		if (power_setting->delay > 20) {
+			msleep(power_setting->delay);
+		} else if (power_setting->delay) {
+			usleep_range(power_setting->delay * 1000,
+				(power_setting->delay * 1000) + 1000);
+		}
+	}
+	msm_camera_request_gpio_table(
+		ctrl->gpio_conf->cam_gpio_req_tbl,
+		ctrl->gpio_conf->cam_gpio_req_tbl_size, 0);
+	return rc;
+}
+
+int32_t msm_camera_power_down(struct msm_camera_power_ctrl_t *ctrl,
+	enum msm_camera_device_type_t device_type,
+	struct msm_camera_i2c_client *sensor_i2c_client)
+{
+	int32_t index = 0;
+	struct msm_sensor_power_setting *power_setting = NULL;
+
+	CDBG("%s:%d\n", __func__, __LINE__);
+	if (!ctrl || !sensor_i2c_client) {
+		pr_err("failed ctrl %p sensor_i2c_client %p\n", ctrl,
+			sensor_i2c_client);
+		return -EINVAL;
+	}
+
+	if (device_type == MSM_CAMERA_PLATFORM_DEVICE)
+		sensor_i2c_client->i2c_func_tbl->i2c_util(
+			sensor_i2c_client, MSM_CCI_RELEASE);
+
+	for (index = (ctrl->power_setting_size - 1); index >= 0; index--) {
+		CDBG("%s index %d\n", __func__, index);
+		power_setting = &ctrl->power_setting[index];
+		CDBG("%s type %d\n", __func__, power_setting->seq_type);
+		switch (power_setting->seq_type) {
+		case SENSOR_CLK:
+			msm_cam_clk_enable(ctrl->dev,
+				&ctrl->clk_info[0],
+				(struct clk **)&power_setting->data[0],
+				ctrl->clk_info_size,
+				0);
+			break;
+		case SENSOR_GPIO:
+			if (power_setting->seq_val >= SENSOR_GPIO_MAX ||
+				!ctrl->gpio_conf->gpio_num_info) {
+				pr_err("%s gpio index %d >= max %d\n", __func__,
+					power_setting->seq_val,
+					SENSOR_GPIO_MAX);
+				continue;
+			}
+			gpio_set_value_cansleep(
+				ctrl->gpio_conf->gpio_num_info->gpio_num
+				[power_setting->seq_val], GPIOF_OUT_INIT_LOW);
+			break;
+		case SENSOR_VREG:
+			if (power_setting->seq_val >= CAM_VREG_MAX) {
+				pr_err("%s vreg index %d >= max %d\n", __func__,
+					power_setting->seq_val,
+					SENSOR_GPIO_MAX);
+				continue;
+			}
+			msm_camera_config_single_vreg(ctrl->dev,
+				&ctrl->cam_vreg[power_setting->seq_val],
+				(struct regulator **)&power_setting->data[0],
+				0);
+			break;
+		case SENSOR_I2C_MUX:
+			if (ctrl->i2c_conf && ctrl->i2c_conf->use_i2c_mux)
+				msm_camera_disable_i2c_mux(ctrl->i2c_conf);
+			break;
+		default:
+			pr_err("%s error power seq type %d\n", __func__,
+				power_setting->seq_type);
+			break;
+		}
+		if (power_setting->delay > 20) {
+			msleep(power_setting->delay);
+		} else if (power_setting->delay) {
+			usleep_range(power_setting->delay * 1000,
+				(power_setting->delay * 1000) + 1000);
+		}
+	}
+	msm_camera_request_gpio_table(
+		ctrl->gpio_conf->cam_gpio_req_tbl,
+		ctrl->gpio_conf->cam_gpio_req_tbl_size, 0);
+	CDBG("%s exit\n", __func__);
+	return 0;
+}
diff --git a/drivers/media/platform/msm/camera_v2/sensor/io/msm_camera_dt_util.h b/drivers/media/platform/msm/camera_v2/sensor/io/msm_camera_dt_util.h
new file mode 100644
index 0000000..5a35747
--- /dev/null
+++ b/drivers/media/platform/msm/camera_v2/sensor/io/msm_camera_dt_util.h
@@ -0,0 +1,44 @@
+/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef MSM_CAMERA_DT_UTIL_H__
+#define MSM_CAMERA_DT_UTIL_H__
+
+#include <mach/camera2.h>
+#include <linux/gpio.h>
+#include <linux/of.h>
+#include "msm_camera_i2c.h"
+
+int32_t msm_camera_get_dt_power_setting_data(struct device_node *of_node,
+	struct msm_sensor_power_setting **power_setting,
+	uint16_t *power_setting_size);
+
+int32_t msm_camera_get_dt_gpio_req_tbl(struct device_node *of_node,
+	struct msm_camera_gpio_conf *gconf, uint16_t *gpio_array,
+	uint16_t gpio_array_size);
+
+int32_t msm_camera_init_gpio_pin_tbl(struct device_node *of_node,
+	struct msm_camera_gpio_conf *gconf, uint16_t *gpio_array,
+	uint16_t gpio_array_size);
+
+int32_t msm_camera_get_dt_vreg_data(struct device_node *of_node,
+	struct camera_vreg_t **cam_vreg, int *num_vreg);
+
+int32_t msm_camera_power_up(struct msm_camera_power_ctrl_t *ctrl,
+	enum msm_camera_device_type_t device_type,
+	struct msm_camera_i2c_client *sensor_i2c_client);
+
+int32_t msm_camera_power_down(struct msm_camera_power_ctrl_t *ctrl,
+	enum msm_camera_device_type_t device_type,
+	struct msm_camera_i2c_client *sensor_i2c_client);
+
+#endif
diff --git a/drivers/media/platform/msm/camera_v2/sensor/io/msm_camera_i2c.h b/drivers/media/platform/msm/camera_v2/sensor/io/msm_camera_i2c.h
index 26f1c4f..b1331ab 100644
--- a/drivers/media/platform/msm/camera_v2/sensor/io/msm_camera_i2c.h
+++ b/drivers/media/platform/msm/camera_v2/sensor/io/msm_camera_i2c.h
@@ -21,6 +21,7 @@
 	struct msm_camera_i2c_fn_t *i2c_func_tbl;
 	struct i2c_client *client;
 	struct msm_camera_cci_client *cci_client;
+	struct msm_camera_spi_client *spi_client;
 	enum msm_camera_i2c_reg_addr_type addr_type;
 };
 
@@ -31,13 +32,13 @@
 };
 
 struct msm_camera_i2c_fn_t {
-	int (*i2c_read) (struct msm_camera_i2c_client *, uint16_t, uint16_t *,
+	int (*i2c_read) (struct msm_camera_i2c_client *, uint32_t, uint16_t *,
 		enum msm_camera_i2c_data_type);
-	int32_t (*i2c_read_seq)(struct msm_camera_i2c_client *, uint16_t,
+	int32_t (*i2c_read_seq)(struct msm_camera_i2c_client *, uint32_t,
 		uint8_t *, uint16_t);
-	int (*i2c_write) (struct msm_camera_i2c_client *, uint16_t, uint16_t,
+	int (*i2c_write) (struct msm_camera_i2c_client *, uint32_t, uint16_t,
 		enum msm_camera_i2c_data_type);
-	int (*i2c_write_seq) (struct msm_camera_i2c_client *, uint16_t ,
+	int (*i2c_write_seq) (struct msm_camera_i2c_client *, uint32_t ,
 		uint8_t *, uint16_t);
 	int32_t (*i2c_write_table)(struct msm_camera_i2c_client *,
 		struct msm_camera_i2c_reg_setting *);
@@ -51,21 +52,24 @@
 	int32_t (*i2c_write_conf_tbl)(struct msm_camera_i2c_client *client,
 		struct msm_camera_i2c_reg_conf *reg_conf_tbl, uint16_t size,
 		enum msm_camera_i2c_data_type data_type);
+	int32_t (*i2c_poll)(struct msm_camera_i2c_client *client,
+		uint32_t addr, uint16_t data,
+		enum msm_camera_i2c_data_type data_type);
 };
 
 int32_t msm_camera_cci_i2c_read(struct msm_camera_i2c_client *client,
-	uint16_t addr, uint16_t *data,
+	uint32_t addr, uint16_t *data,
 	enum msm_camera_i2c_data_type data_type);
 
 int32_t msm_camera_cci_i2c_read_seq(struct msm_camera_i2c_client *client,
-	uint16_t addr, uint8_t *data, uint16_t num_byte);
+	uint32_t addr, uint8_t *data, uint16_t num_byte);
 
 int32_t msm_camera_cci_i2c_write(struct msm_camera_i2c_client *client,
-	uint16_t addr, uint16_t data,
+	uint32_t addr, uint16_t data,
 	enum msm_camera_i2c_data_type data_type);
 
 int32_t msm_camera_cci_i2c_write_seq(struct msm_camera_i2c_client *client,
-	uint16_t addr, uint8_t *data, uint16_t num_byte);
+	uint32_t addr, uint8_t *data, uint16_t num_byte);
 
 int32_t msm_camera_cci_i2c_write_table(
 	struct msm_camera_i2c_client *client,
@@ -88,19 +92,23 @@
 int32_t msm_sensor_cci_i2c_util(struct msm_camera_i2c_client *client,
 	uint16_t cci_cmd);
 
+int32_t msm_camera_cci_i2c_poll(struct msm_camera_i2c_client *client,
+	uint32_t addr, uint16_t data,
+	enum msm_camera_i2c_data_type data_type);
+
 int32_t msm_camera_qup_i2c_read(struct msm_camera_i2c_client *client,
-	uint16_t addr, uint16_t *data,
+	uint32_t addr, uint16_t *data,
 	enum msm_camera_i2c_data_type data_type);
 
 int32_t msm_camera_qup_i2c_read_seq(struct msm_camera_i2c_client *client,
-	uint16_t addr, uint8_t *data, uint16_t num_byte);
+	uint32_t addr, uint8_t *data, uint16_t num_byte);
 
 int32_t msm_camera_qup_i2c_write(struct msm_camera_i2c_client *client,
-	uint16_t addr, uint16_t data,
+	uint32_t addr, uint16_t data,
 	enum msm_camera_i2c_data_type data_type);
 
 int32_t msm_camera_qup_i2c_write_seq(struct msm_camera_i2c_client *client,
-	uint16_t addr, uint8_t *data, uint16_t num_byte);
+	uint32_t addr, uint8_t *data, uint16_t num_byte);
 
 int32_t msm_camera_qup_i2c_write_table(struct msm_camera_i2c_client *client,
 	struct msm_camera_i2c_reg_setting *write_setting);
diff --git a/drivers/media/platform/msm/camera_v2/sensor/io/msm_camera_qup_i2c.c b/drivers/media/platform/msm/camera_v2/sensor/io/msm_camera_qup_i2c.c
index 55f27e0..9222bb5 100644
--- a/drivers/media/platform/msm/camera_v2/sensor/io/msm_camera_qup_i2c.c
+++ b/drivers/media/platform/msm/camera_v2/sensor/io/msm_camera_qup_i2c.c
@@ -69,7 +69,7 @@
 }
 
 int32_t msm_camera_qup_i2c_read(struct msm_camera_i2c_client *client,
-	uint16_t addr, uint16_t *data,
+	uint32_t addr, uint16_t *data,
 	enum msm_camera_i2c_data_type data_type)
 {
 	int32_t rc = -EFAULT;
@@ -103,7 +103,7 @@
 }
 
 int32_t msm_camera_qup_i2c_read_seq(struct msm_camera_i2c_client *client,
-	uint16_t addr, uint8_t *data, uint16_t num_byte)
+	uint32_t addr, uint8_t *data, uint16_t num_byte)
 {
 	int32_t rc = -EFAULT;
 	unsigned char buf[client->addr_type+num_byte];
@@ -136,7 +136,7 @@
 }
 
 int32_t msm_camera_qup_i2c_write(struct msm_camera_i2c_client *client,
-	uint16_t addr, uint16_t data,
+	uint32_t addr, uint16_t data,
 	enum msm_camera_i2c_data_type data_type)
 {
 	int32_t rc = -EFAULT;
@@ -184,7 +184,7 @@
 }
 
 int32_t msm_camera_qup_i2c_write_seq(struct msm_camera_i2c_client *client,
-	uint16_t addr, uint8_t *data, uint16_t num_byte)
+	uint32_t addr, uint8_t *data, uint16_t num_byte)
 {
 	int32_t rc = -EFAULT;
 	unsigned char buf[client->addr_type+num_byte];
diff --git a/drivers/media/platform/msm/camera_v2/sensor/io/msm_camera_spi.c b/drivers/media/platform/msm/camera_v2/sensor/io/msm_camera_spi.c
new file mode 100644
index 0000000..d1d5f23
--- /dev/null
+++ b/drivers/media/platform/msm/camera_v2/sensor/io/msm_camera_spi.c
@@ -0,0 +1,154 @@
+/* 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 <mach/camera2.h>
+#include "msm_camera_spi.h"
+
+#undef SPIDBG
+#ifdef CONFIG_MSMB_CAMERA_DEBUG
+#define SPIDBG(fmt, args...) pr_debug(fmt, ##args)
+#define S_I2C_DBG(fmt, args...) pr_debug(fmt, ##args)
+#else
+#define SPIDBG(fmt, args...) do { } while (0)
+#define S_I2C_DBG(fmt, args...) do { } while (0)
+#endif
+
+static int msm_camera_spi_txfr(struct spi_device *spi, char *txbuf,
+			       char *rxbuf, int num_byte)
+{
+	struct spi_transfer t;
+	struct spi_message m;
+
+	memset(&t, 0, sizeof(t));
+	t.tx_buf = txbuf;
+	t.rx_buf = rxbuf;
+	t.len = num_byte;
+	spi_message_init(&m);
+	spi_message_add_tail(&t, &m);
+
+	return spi_sync(spi, &m);
+}
+
+/**
+  * msm_camera_set_addr() - helper function to set transfer address
+  * @addr:	device address
+  * @addr_len:	the addr field length of an instruction
+  * @type:	type (i.e. byte-length) of @addr
+  * @str:	shifted address output, must be zeroed when passed in
+  *
+  * This helper function sets @str based on the addr field length of an
+  * instruction and the data length.
+  */
+static void msm_camera_set_addr(uint32_t addr, uint8_t addr_len,
+				enum msm_camera_i2c_reg_addr_type type,
+				char *str)
+{
+	int i, len;
+
+	if (addr_len < type)
+		SPIDBG("%s: omitting higher bits in address\n", __func__);
+
+	/* only support transfer MSB first for now */
+	len = addr_len - type;
+	for (i = len; i < addr_len; i++) {
+		if (i >= 0)
+			str[i] = (addr >> (BITS_PER_BYTE * (addr_len - i - 1)))
+				& 0xFF;
+	}
+
+}
+
+static int32_t msm_camera_spi_read_helper(struct msm_camera_i2c_client *client,
+		struct msm_camera_spi_inst *inst, uint32_t addr, uint8_t *data,
+		uint16_t num_byte)
+{
+	int32_t rc = -EFAULT;
+	struct spi_device *spi = client->spi_client->spi_master;
+	char *tx, *rx;
+	uint16_t len;
+	int8_t retries = client->spi_client->retries;
+
+	if ((client->addr_type != MSM_CAMERA_I2C_BYTE_ADDR)
+	    && (client->addr_type != MSM_CAMERA_I2C_WORD_ADDR)
+	    && (client->addr_type != MSM_CAMERA_I2C_3B_ADDR))
+		return rc;
+
+	len = sizeof(inst->opcode) + inst->addr_len + inst->dummy_len
+		+ num_byte;
+
+	tx = kmalloc(len, GFP_KERNEL | GFP_DMA);
+	if (!tx)
+		return -ENOMEM;
+	rx = kmalloc(len, GFP_KERNEL | GFP_DMA);
+	if (!rx) {
+		kfree(tx);
+		return -ENOMEM;
+	}
+	memset(tx, 0, len);
+	memset(rx, 0, len);
+
+	tx[0] = inst->opcode;
+	msm_camera_set_addr(addr, inst->addr_len, client->addr_type, tx + 1);
+	while ((rc = msm_camera_spi_txfr(spi, tx, rx, len)) && retries) {
+		retries--;
+		msleep(client->spi_client->retry_delay);
+	}
+	if (rc) {
+		SPIDBG("%s: failed %d\n", __func__, rc);
+		goto out;
+	}
+	len = sizeof(inst->opcode) + inst->addr_len + inst->dummy_len;
+	memcpy(data, rx + len, num_byte);
+out:
+	kfree(tx);
+	kfree(rx);
+	return rc;
+}
+
+int32_t msm_camera_spi_read(struct msm_camera_i2c_client *client,
+	uint32_t addr, uint16_t *data,
+	enum msm_camera_i2c_data_type data_type)
+{
+	int32_t rc = -EFAULT;
+	uint8_t temp[2];
+
+	if ((data_type != MSM_CAMERA_I2C_BYTE_DATA)
+	    && (data_type != MSM_CAMERA_I2C_WORD_DATA))
+		return rc;
+
+	rc = msm_camera_spi_read_helper(client,
+		&client->spi_client->cmd_tbl.read, addr, &temp[0], data_type);
+	if (rc)
+		return rc;
+
+	if (data_type == MSM_CAMERA_I2C_BYTE_DATA)
+		*data = temp[0];
+	else
+		*data = (temp[0] << BITS_PER_BYTE) | temp[1];
+
+	SPIDBG("%s: addr 0x%x, data %u\n", __func__, addr, *data);
+	return rc;
+}
+
+int32_t msm_camera_spi_read_seq(struct msm_camera_i2c_client *client,
+	uint32_t addr, uint8_t *data, uint16_t num_byte)
+{
+	return msm_camera_spi_read_helper(client,
+		&client->spi_client->cmd_tbl.read_seq, addr, data, num_byte);
+}
+
+int32_t msm_camera_spi_query_id(struct msm_camera_i2c_client *client,
+	uint32_t addr, uint8_t *data, uint16_t num_byte)
+{
+	return msm_camera_spi_read_helper(client,
+		&client->spi_client->cmd_tbl.query_id, addr, data, num_byte);
+}
diff --git a/drivers/media/platform/msm/camera_v2/sensor/io/msm_camera_spi.h b/drivers/media/platform/msm/camera_v2/sensor/io/msm_camera_spi.h
new file mode 100644
index 0000000..564e470
--- /dev/null
+++ b/drivers/media/platform/msm/camera_v2/sensor/io/msm_camera_spi.h
@@ -0,0 +1,51 @@
+/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __MSM_CAMERA_SPI_H
+#define __MSM_CAMERA_SPI_H
+
+#include <linux/spi/spi.h>
+#include <media/msm_cam_sensor.h>
+#include "msm_camera_i2c.h"
+
+struct msm_camera_spi_inst {
+	uint8_t opcode;		/* one-byte opcode */
+	uint8_t addr_len;	/* addr len in bytes */
+	uint8_t dummy_len;	/* setup cycles */
+};
+
+struct msm_camera_spi_inst_tbl {
+	struct msm_camera_spi_inst read;
+	struct msm_camera_spi_inst read_seq;
+	struct msm_camera_spi_inst query_id;
+};
+
+struct msm_camera_spi_client {
+	struct spi_device *spi_master;
+	struct msm_camera_spi_inst_tbl cmd_tbl;
+	uint8_t device_id;
+	uint8_t mfr_id;
+	uint8_t retry_delay;	/* ms */
+	uint8_t retries;	/* retry times upon failure */
+};
+
+int32_t msm_camera_spi_read(struct msm_camera_i2c_client *client,
+	uint32_t addr, uint16_t *data,
+	enum msm_camera_i2c_data_type data_type);
+
+int32_t msm_camera_spi_read_seq(struct msm_camera_i2c_client *client,
+	uint32_t addr, uint8_t *data, uint16_t num_byte);
+
+int32_t msm_camera_spi_query_id(struct msm_camera_i2c_client *client,
+	uint32_t addr, uint8_t *data, uint16_t num_byte);
+
+#endif
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 453b14a..fa63e2b 100644
--- a/drivers/media/platform/msm/camera_v2/sensor/msm_sensor.c
+++ b/drivers/media/platform/msm/camera_v2/sensor/msm_sensor.c
@@ -78,6 +78,23 @@
 		src_node = NULL;
 	}
 
+	src_node = of_parse_phandle(of_node, "qcom,eeprom-src", 0);
+	if (!src_node) {
+		CDBG("%s:%d eeprom src_node NULL\n", __func__, __LINE__);
+	} else {
+		rc = of_property_read_u32(src_node, "cell-index", &val);
+		CDBG("%s qcom,eeprom cell index %d, rc %d\n", __func__,
+			val, rc);
+		if (rc < 0) {
+			pr_err("%s failed %d\n", __func__, __LINE__);
+			goto ERROR;
+		}
+		sensordata->sensor_info->
+			subdev_id[SUB_MODULE_EEPROM] = val;
+		of_node_put(src_node);
+		src_node = NULL;
+	}
+
 	if (of_property_read_bool(of_node, "qcom,eeprom-sd-index") ==
 		true) {
 		rc = of_property_read_u32(of_node, "qcom,eeprom-sd-index",
diff --git a/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_common.c b/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_common.c
index b6bc0d7..6775a23 100644
--- a/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_common.c
+++ b/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_common.c
@@ -1220,6 +1220,8 @@
 {
 	struct mpq_demux *mpq_demux = feed->demux->priv;
 
+	MPQ_DVB_DBG_PRINT("%s: cookie=%d\n", __func__, cookie);
+
 	if (cookie < 0) {
 		MPQ_DVB_ERR_PRINT("%s: invalid cookie parameter\n", __func__);
 		return -EINVAL;
@@ -2441,9 +2443,15 @@
 
 	data->data_length = 0;
 	data->buf.handle = packet->raw_data_handle;
+
 	/* this has to succeed when called here, after packet was written */
 	data->buf.cookie = mpq_streambuffer_pkt_next(stream_buffer,
 				feed_data->last_pkt_index, &len);
+	if (data->buf.cookie < 0)
+		MPQ_DVB_DBG_PRINT(
+			"%s: received invalid packet index %d\n",
+			__func__, data->buf.cookie);
+
 	data->buf.offset = packet->raw_data_offset;
 	data->buf.len = packet->raw_data_len;
 	data->buf.pts_exists = pts_dts->pts_exist;
@@ -2459,6 +2467,8 @@
 	/* save for next time: */
 	feed_data->last_pkt_index = data->buf.cookie;
 
+	MPQ_DVB_DBG_PRINT("%s: cookie=%d\n", __func__, data->buf.cookie);
+
 	/* reset counters */
 	feed_data->ts_packets_num = 0;
 	feed_data->ts_dropped_bytes = 0;
@@ -4235,7 +4245,12 @@
 				__func__, ret);
 		}
 		mpq_dmx_update_decoder_stat(mpq_demux);
-		mpq_streambuffer_pkt_write(sbuf, &packet, (u8 *)&meta_data);
+		if (mpq_streambuffer_pkt_write(sbuf,
+				&packet,
+				(u8 *)&meta_data) < 0)
+			MPQ_DVB_ERR_PRINT(
+				"%s: Couldn't write packet. Should never happen\n",
+				__func__);
 
 		mpq_dmx_prepare_es_event_data(
 			&packet, &meta_data, &mpq_feed->video_info,
diff --git a/drivers/media/platform/msm/dvb/video/mpq_dvb_video.c b/drivers/media/platform/msm/dvb/video/mpq_dvb_video.c
index b9fdc5e..45a9dd5 100644
--- a/drivers/media/platform/msm/dvb/video/mpq_dvb_video.c
+++ b/drivers/media/platform/msm/dvb/video/mpq_dvb_video.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2010-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -31,7 +31,7 @@
 
 #include <linux/clk.h>
 #include <linux/timer.h>
-#include <mach/msm_subsystem_map.h>
+#include <mach/iommu_domains.h>
 #include <media/msm/vidc_type.h>
 #include <media/msm/vcd_api.h>
 #include <media/msm/vidc_init.h>
@@ -1188,9 +1188,6 @@
 
 	if (!client_ctx)
 		return -EINVAL;
-	if (client_ctx->vcd_h264_mv_buffer.client_data)
-		msm_subsystem_unmap_buffer((struct msm_mapped_buffer *)
-		client_ctx->vcd_h264_mv_buffer.client_data);
 
 	vcd_property_hdr.prop_id = VCD_I_FREE_H264_MV_BUFFER;
 	vcd_property_hdr.sz = sizeof(struct vcd_property_buffer_size);
diff --git a/drivers/media/platform/msm/vidc/Kconfig b/drivers/media/platform/msm/vidc/Kconfig
index 3fc2b9e..4a27fd3 100644
--- a/drivers/media/platform/msm/vidc/Kconfig
+++ b/drivers/media/platform/msm/vidc/Kconfig
@@ -4,4 +4,4 @@
 
 menuconfig MSM_VIDC_V4L2
 	bool "Qualcomm MSM V4L2 based video driver"
-		depends on (ARCH_MSM8974 || ARCH_MSM8610) && VIDEO_V4L2
+		depends on (ARCH_MSM8974 || ARCH_MSM8610 || ARCH_MSM8226) && VIDEO_V4L2
diff --git a/drivers/media/platform/msm/vidc/hfi_response_handler.c b/drivers/media/platform/msm/vidc/hfi_response_handler.c
index 102e1ec..91fb514 100644
--- a/drivers/media/platform/msm/vidc/hfi_response_handler.c
+++ b/drivers/media/platform/msm/vidc/hfi_response_handler.c
@@ -1003,12 +1003,6 @@
 		return;
 	}
 
-	sess_close = (struct hal_session *)pkt->session_id;
-	dprintk(VIDC_INFO, "deleted the session: 0x%x",
-			sess_close->session_id);
-	list_del(&sess_close->list);
-	kfree(sess_close);
-
 	memset(&cmd_done, 0, sizeof(struct msm_vidc_cb_cmd_done));
 	cmd_done.device_id = device_id;
 	cmd_done.session_id =
@@ -1016,6 +1010,11 @@
 	cmd_done.status = hfi_map_err_status((u32)pkt->error_type);
 	cmd_done.data = NULL;
 	cmd_done.size = 0;
+	sess_close = (struct hal_session *)pkt->session_id;
+	dprintk(VIDC_INFO, "deleted the session: 0x%x",
+		sess_close->session_id);
+	list_del(&sess_close->list);
+	kfree(sess_close);
 	callback(SESSION_END_DONE, &cmd_done);
 }
 
diff --git a/drivers/media/platform/msm/vidc/msm_smem.c b/drivers/media/platform/msm/vidc/msm_smem.c
index b3bce5f..79a492e 100644
--- a/drivers/media/platform/msm/vidc/msm_smem.c
+++ b/drivers/media/platform/msm/vidc/msm_smem.c
@@ -80,12 +80,18 @@
 			goto mem_domain_get_failed;
 		}
 	}
-	rc = ion_map_iommu(clnt, hndl, domain, partition, align,
-			0, iova, buffer_size, 0, 0);
+	if (is_iommu_present(smem_client->res)) {
+		dprintk(VIDC_DBG,
+				"Calling ion_map_iommu - domain: %d, partition: %d",
+				domain, partition);
+		rc = ion_map_iommu(clnt, hndl, domain, partition, align,
+				0, iova, buffer_size, 0, 0);
+	} else {
+		dprintk(VIDC_DBG, "Using physical memory address");
+		rc = ion_phys(clnt, hndl, iova, (size_t *)buffer_size);
+	}
 	if (rc) {
-		dprintk(VIDC_ERR,
-		"ion_map_iommu failed(%d).domain: %d,partition: %d\n",
-		rc, domain, partition);
+		dprintk(VIDC_ERR, "ion memory map failed - %d", rc);
 		goto mem_map_failed;
 	}
 
@@ -97,10 +103,28 @@
 	return rc;
 }
 
-static void put_device_address(struct ion_client *clnt,
+static void put_device_address(struct smem_client *smem_client,
 	struct ion_handle *hndl, int domain_num, int partition_num, u32 flags)
 {
-	ion_unmap_iommu(clnt, hndl, domain_num, partition_num);
+	struct ion_client *clnt = NULL;
+
+	if (!hndl || !smem_client) {
+		dprintk(VIDC_WARN, "Invalid params: %p, %p\n",
+				smem_client, hndl);
+		return;
+	}
+
+	clnt = smem_client->clnt;
+	if (!clnt) {
+		dprintk(VIDC_WARN, "Invalid client");
+		return;
+	}
+	if (is_iommu_present(smem_client->res)) {
+		dprintk(VIDC_DBG,
+				"Calling ion_unmap_iommu - domain: %d, parition: %d",
+				domain_num, partition_num);
+		ion_unmap_iommu(clnt, hndl, domain_num, partition_num);
+	}
 	if (flags & SMEM_SECURE) {
 		if (msm_ion_unsecure_buffer(clnt, hndl))
 			dprintk(VIDC_ERR, "Failed to unsecure memory\n");
@@ -128,16 +152,7 @@
 	rc = ion_handle_get_flags(client->clnt, hndl, &ionflags);
 	if (rc) {
 		dprintk(VIDC_ERR, "Failed to get ion flags: %d\n", rc);
-		goto fail_map;
-	}
-	if (ION_IS_CACHED(ionflags)) {
-		mem->kvaddr = ion_map_kernel(client->clnt, hndl);
-		if (!mem->kvaddr) {
-			dprintk(VIDC_ERR,
-					"Failed to map shared mem in kernel\n");
-			rc = -EIO;
-			goto fail_map;
-		}
+		goto fail_device_address;
 	}
 
 	mem->flags = ionflags;
@@ -160,9 +175,6 @@
 		mem->device_addr, mem->size);
 	return rc;
 fail_device_address:
-	if (mem->kvaddr)
-		ion_unmap_kernel(client->clnt, hndl);
-fail_map:
 	ion_free(client->clnt, hndl);
 fail_import_fd:
 	return rc;
@@ -186,7 +198,15 @@
 		align = ALIGN(align, SZ_1M);
 	}
 
-	heap_mask = ION_HEAP(ION_IOMMU_HEAP_ID);
+	if (is_iommu_present(client->res)) {
+		heap_mask = ION_HEAP(ION_IOMMU_HEAP_ID);
+	} else {
+		dprintk(VIDC_DBG,
+			"allocate shared memory from adsp heap size %d align %d\n",
+			size, align);
+		heap_mask = ION_HEAP(ION_ADSP_HEAP_ID);
+	}
+
 	if (flags & SMEM_SECURE)
 		heap_mask = ION_HEAP(ION_CP_MM_HEAP_ID);
 
@@ -246,7 +266,7 @@
 	}
 
 	if (mem->device_addr)
-		put_device_address(client->clnt,
+		put_device_address(client,
 			mem->smem_priv, domain, partition, mem->flags);
 	if (mem->kvaddr)
 		ion_unmap_kernel(client->clnt, mem->smem_priv);
@@ -334,20 +354,14 @@
 			rc = -EINVAL;
 			goto cache_op_failed;
 		}
-		if (mem->kvaddr) {
-			rc = msm_ion_do_cache_op(client->clnt,
-					(struct ion_handle *)mem->smem_priv,
-					(unsigned long *) mem->kvaddr,
-					(unsigned long)mem->size,
-					msm_cache_ops);
-			if (rc) {
-				dprintk(VIDC_ERR,
+		rc = msm_ion_do_cache_op(client->clnt,
+				(struct ion_handle *)mem->smem_priv,
+				0, (unsigned long)mem->size,
+				msm_cache_ops);
+		if (rc) {
+			dprintk(VIDC_ERR,
 					"cache operation failed %d\n", rc);
-				goto cache_op_failed;
-			}
-		} else {
-			dprintk(VIDC_WARN,
-				"cache operation failed as no kernel mapping\n");
+			goto cache_op_failed;
 		}
 	}
 cache_op_failed:
diff --git a/drivers/media/platform/msm/vidc/msm_v4l2_vidc.c b/drivers/media/platform/msm/vidc/msm_v4l2_vidc.c
index 50adb13..687bd71 100644
--- a/drivers/media/platform/msm/vidc/msm_v4l2_vidc.c
+++ b/drivers/media/platform/msm/vidc/msm_v4l2_vidc.c
@@ -1061,10 +1061,9 @@
 
 	if (!of_get_property(pdev->dev.of_node, "qcom,iommu-groups",
 				&array_size)) {
-		dprintk(VIDC_ERR, "Could not find iommu_groups property\n");
+		dprintk(VIDC_DBG, "iommu_groups property not present\n");
 		iommu_group_set->count = 0;
-		rc = -ENOENT;
-		goto err_no_of_node;
+		return 0;
 	}
 
 	iommu_group_set->count = array_size / sizeof(u32);
@@ -1359,10 +1358,37 @@
 	return rc;
 }
 
+static ssize_t msm_vidc_link_name_show(struct device *dev,
+		struct device_attribute *attr,
+		char *buf)
+{
+	struct msm_vidc_core *core = dev_get_drvdata(dev);
+	if (core)
+		if (dev == &core->vdev[MSM_VIDC_DECODER].vdev.dev)
+			if (core->hfi_type == VIDC_HFI_Q6)
+				return snprintf(buf, PAGE_SIZE, "q6_dec");
+			else
+				return snprintf(buf, PAGE_SIZE, "venus_dec");
+		else if (dev == &core->vdev[MSM_VIDC_ENCODER].vdev.dev)
+			if (core->hfi_type == VIDC_HFI_Q6)
+				return snprintf(buf, PAGE_SIZE, "q6_enc");
+			else
+				return snprintf(buf, PAGE_SIZE, "venus_enc");
+		else
+			return 0;
+	else
+		return 0;
+}
+
+static DEVICE_ATTR(link_name, 0644, msm_vidc_link_name_show, NULL);
+
 static int __devinit msm_vidc_probe(struct platform_device *pdev)
 {
 	int rc = 0;
 	struct msm_vidc_core *core;
+	struct device *dev;
+	int nr = BASE_DEVICE_NUMBER;
+
 	core = kzalloc(sizeof(*core), GFP_KERNEL);
 	if (!core || !vidc_driver) {
 		dprintk(VIDC_ERR,
@@ -1375,6 +1401,10 @@
 		dprintk(VIDC_ERR, "Failed to init core\n");
 		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;
+	}
 	rc = v4l2_device_register(&pdev->dev, &core->v4l2_dev);
 	if (rc) {
 		dprintk(VIDC_ERR, "Failed to register v4l2 device\n");
@@ -1386,12 +1416,19 @@
 	core->vdev[MSM_VIDC_DECODER].vdev.ioctl_ops = &msm_v4l2_ioctl_ops;
 	core->vdev[MSM_VIDC_DECODER].type = MSM_VIDC_DECODER;
 	rc = video_register_device(&core->vdev[MSM_VIDC_DECODER].vdev,
-					VFL_TYPE_GRABBER, BASE_DEVICE_NUMBER);
+					VFL_TYPE_GRABBER, nr);
 	if (rc) {
 		dprintk(VIDC_ERR, "Failed to register video decoder device");
 		goto err_dec_register;
 	}
 	video_set_drvdata(&core->vdev[MSM_VIDC_DECODER].vdev, core);
+	dev = &core->vdev[MSM_VIDC_DECODER].vdev.dev;
+	rc = device_create_file(dev, &dev_attr_link_name);
+	if (rc) {
+		dprintk(VIDC_ERR,
+				"Failed to create link name sysfs for decoder");
+		goto err_dec_attr_link_name;
+	}
 
 	core->vdev[MSM_VIDC_ENCODER].vdev.release =
 		msm_vidc_release_video_device;
@@ -1399,19 +1436,20 @@
 	core->vdev[MSM_VIDC_ENCODER].vdev.ioctl_ops = &msm_v4l2_ioctl_ops;
 	core->vdev[MSM_VIDC_ENCODER].type = MSM_VIDC_ENCODER;
 	rc = video_register_device(&core->vdev[MSM_VIDC_ENCODER].vdev,
-				VFL_TYPE_GRABBER, BASE_DEVICE_NUMBER + 1);
+				VFL_TYPE_GRABBER, nr + 1);
 	if (rc) {
 		dprintk(VIDC_ERR, "Failed to register video encoder device");
 		goto err_enc_register;
 	}
 	video_set_drvdata(&core->vdev[MSM_VIDC_ENCODER].vdev, core);
-
-	core->device = vidc_hfi_initialize(core->hfi_type, core->id,
-				&core->resources, &handle_cmd_response);
-	if (!core->device) {
-		dprintk(VIDC_ERR, "Failed to create HFI device\n");
-		goto err_cores_exceeded;
+	dev = &core->vdev[MSM_VIDC_ENCODER].vdev.dev;
+	rc = device_create_file(dev, &dev_attr_link_name);
+	if (rc) {
+		dprintk(VIDC_ERR,
+				"Failed to create link name sysfs for encoder");
+		goto err_enc_attr_link_name;
 	}
+
 	mutex_lock(&vidc_driver->lock);
 	if (vidc_driver->num_cores  + 1 > MSM_VIDC_CORES_MAX) {
 		mutex_unlock(&vidc_driver->lock);
@@ -1419,8 +1457,20 @@
 				vidc_driver->num_cores);
 		goto err_cores_exceeded;
 	}
-
 	core->id = vidc_driver->num_cores++;
+	mutex_unlock(&vidc_driver->lock);
+
+	core->device = vidc_hfi_initialize(core->hfi_type, core->id,
+				&core->resources, &handle_cmd_response);
+	if (!core->device) {
+		dprintk(VIDC_ERR, "Failed to create HFI device\n");
+		mutex_lock(&vidc_driver->lock);
+		vidc_driver->num_cores--;
+		mutex_unlock(&vidc_driver->lock);
+		goto err_cores_exceeded;
+	}
+
+	mutex_lock(&vidc_driver->lock);
 	list_add_tail(&core->list, &vidc_driver->cores);
 	mutex_unlock(&vidc_driver->lock);
 	core->debugfs_root = msm_vidc_debugfs_init_core(
@@ -1429,8 +1479,14 @@
 	return rc;
 
 err_cores_exceeded:
+	device_remove_file(&core->vdev[MSM_VIDC_ENCODER].vdev.dev,
+			&dev_attr_link_name);
+err_enc_attr_link_name:
 	video_unregister_device(&core->vdev[MSM_VIDC_ENCODER].vdev);
 err_enc_register:
+	device_remove_file(&core->vdev[MSM_VIDC_DECODER].vdev.dev,
+			&dev_attr_link_name);
+err_dec_attr_link_name:
 	video_unregister_device(&core->vdev[MSM_VIDC_DECODER].vdev);
 err_dec_register:
 	v4l2_device_unregister(&core->v4l2_dev);
@@ -1457,7 +1513,11 @@
 	}
 
 	vidc_hfi_deinitialize(core->hfi_type, core->device);
+	device_remove_file(&core->vdev[MSM_VIDC_ENCODER].vdev.dev,
+				&dev_attr_link_name);
 	video_unregister_device(&core->vdev[MSM_VIDC_ENCODER].vdev);
+	device_remove_file(&core->vdev[MSM_VIDC_DECODER].vdev.dev,
+				&dev_attr_link_name);
 	video_unregister_device(&core->vdev[MSM_VIDC_DECODER].vdev);
 	v4l2_device_unregister(&core->v4l2_dev);
 
diff --git a/drivers/media/platform/msm/vidc/msm_vdec.c b/drivers/media/platform/msm/vidc/msm_vdec.c
index 2ca5008..eca8091 100644
--- a/drivers/media/platform/msm/vidc/msm_vdec.c
+++ b/drivers/media/platform/msm/vidc/msm_vdec.c
@@ -24,7 +24,7 @@
 #define MAX_NUM_OUTPUT_BUFFERS 6
 
 enum msm_vdec_ctrl_cluster {
-	MSM_VDEC_CTRL_CLUSTER_MAX = 1,
+	MSM_VDEC_CTRL_CLUSTER_MAX = 1 << 0,
 };
 
 static const char *const mpeg_video_vidc_divx_format[] = {
@@ -621,13 +621,6 @@
 		frame_sz.height = inst->prop.height;
 		dprintk(VIDC_DBG, "width = %d, height = %d\n",
 				frame_sz.width, frame_sz.height);
-		rc = msm_comm_try_set_prop(inst,
-			HAL_PARAM_FRAME_SIZE, &frame_sz);
-		if (rc) {
-			dprintk(VIDC_ERR,
-				"%s: Failed : Frame size setting\n", __func__);
-			goto exit;
-		}
 		rc = msm_comm_try_get_bufreqs(inst);
 		if (rc) {
 			dprintk(VIDC_ERR,
@@ -1364,7 +1357,7 @@
 		return NULL;
 
 	for (c = 0; c < NUM_CTRLS; c++) {
-		if (msm_vdec_ctrls[c].cluster == type) {
+		if (msm_vdec_ctrls[c].cluster & type) {
 			cluster[sz] = msm_vdec_ctrls[c].priv;
 			++sz;
 		}
diff --git a/drivers/media/platform/msm/vidc/msm_venc.c b/drivers/media/platform/msm/vidc/msm_venc.c
index bf29a95..bbd56fb 100644
--- a/drivers/media/platform/msm/vidc/msm_venc.c
+++ b/drivers/media/platform/msm/vidc/msm_venc.c
@@ -107,16 +107,17 @@
 };
 
 enum msm_venc_ctrl_cluster {
-	MSM_VENC_CTRL_CLUSTER_QP = 1,
-	MSM_VENC_CTRL_CLUSTER_INTRA_PERIOD,
-	MSM_VENC_CTRL_CLUSTER_H264_PROFILE_LEVEL,
-	MSM_VENC_CTRL_CLUSTER_MPEG_PROFILE_LEVEL,
-	MSM_VENC_CTRL_CLUSTER_H263_PROFILE_LEVEL,
-	MSM_VENC_CTRL_CLUSTER_H264_ENTROPY,
-	MSM_VENC_CTRL_CLUSTER_SLICING,
-	MSM_VENC_CTRL_CLUSTER_INTRA_REFRESH,
-	MSM_VENC_CTRL_CLUSTER_BITRATE,
-	MSM_VENC_CTRL_CLUSTER_MAX,
+	MSM_VENC_CTRL_CLUSTER_QP = 1 << 0,
+	MSM_VENC_CTRL_CLUSTER_INTRA_PERIOD = 1 << 1,
+	MSM_VENC_CTRL_CLUSTER_H264_PROFILE_LEVEL = 1 << 2,
+	MSM_VENC_CTRL_CLUSTER_MPEG_PROFILE_LEVEL = 1 << 3,
+	MSM_VENC_CTRL_CLUSTER_H263_PROFILE_LEVEL = 1 << 4,
+	MSM_VENC_CTRL_CLUSTER_H264_ENTROPY = 1 << 5,
+	MSM_VENC_CTRL_CLUSTER_SLICING = 1 << 6,
+	MSM_VENC_CTRL_CLUSTER_INTRA_REFRESH = 1 << 7,
+	MSM_VENC_CTRL_CLUSTER_BITRATE = 1 << 8,
+	MSM_VENC_CTRL_CLUSTER_TIMING = 1 << 9,
+	MSM_VENC_CTRL_CLUSTER_MAX = 1 << 10,
 };
 
 static struct msm_vidc_ctrl msm_venc_ctrls[] = {
@@ -2187,7 +2188,7 @@
 		return NULL;
 
 	for (c = 0; c < NUM_CTRLS; c++) {
-		if (msm_venc_ctrls[c].cluster == type) {
+		if (msm_venc_ctrls[c].cluster & type) {
 			cluster[sz] = msm_venc_ctrls[c].priv;
 			++sz;
 		}
diff --git a/drivers/media/platform/msm/vidc/msm_vidc_common.c b/drivers/media/platform/msm/vidc/msm_vidc_common.c
index 8eecb98..adf6dec 100644
--- a/drivers/media/platform/msm/vidc/msm_vidc_common.c
+++ b/drivers/media/platform/msm/vidc/msm_vidc_common.c
@@ -375,7 +375,7 @@
 	struct msm_vidc_inst *inst;
 	struct v4l2_control control = {0};
 	struct msm_vidc_cb_event *event_notify;
-	int event = 0;
+	int event = V4L2_EVENT_SEQ_CHANGED_INSUFFICIENT;
 	int rc = 0;
 	if (response) {
 		inst = (struct msm_vidc_inst *)response->session_id;
@@ -398,11 +398,14 @@
 		default:
 			break;
 		}
-
-		inst->reconfig_height = event_notify->height;
-		inst->reconfig_width = event_notify->width;
-		inst->in_reconfig = true;
-
+		if (event == V4L2_EVENT_SEQ_CHANGED_INSUFFICIENT) {
+			inst->reconfig_height = event_notify->height;
+			inst->reconfig_width = event_notify->width;
+			inst->in_reconfig = true;
+		} else {
+			inst->prop.height = event_notify->height;
+			inst->prop.width = event_notify->width;
+		}
 		rc = msm_vidc_check_session_supported(inst);
 		if (!rc) {
 			queue_v4l2_event(inst, event);
@@ -821,6 +824,7 @@
 	vb->v4l2_planes[0].bytesused = fill_buf_done->filled_len1;
 
 	vb->v4l2_buf.flags = V4L2_QCOM_BUF_FLAG_CODECCONFIG;
+	vb->v4l2_buf.timestamp = ns_to_timeval(0);
 
 	dprintk(VIDC_DBG, "Filled length = %d; flags %x\n",
 				vb->v4l2_planes[0].bytesused,
@@ -1445,7 +1449,7 @@
 			"Failed to send close\n");
 		goto exit;
 	}
-	change_inst_state(inst, MSM_VIDC_OPEN);
+	change_inst_state(inst, MSM_VIDC_CLOSE);
 exit:
 	return rc;
 }
diff --git a/drivers/media/platform/msm/vidc/msm_vidc_resources.h b/drivers/media/platform/msm/vidc/msm_vidc_resources.h
index 693c1a5..43af909 100644
--- a/drivers/media/platform/msm/vidc/msm_vidc_resources.h
+++ b/drivers/media/platform/msm/vidc/msm_vidc_resources.h
@@ -78,5 +78,13 @@
 	struct platform_device *pdev;
 };
 
+static inline int is_iommu_present(struct msm_vidc_platform_resources *res)
+{
+	if (res)
+		return (res->iommu_group_set.count > 0 &&
+				res->iommu_group_set.iommu_maps != NULL);
+	return 0;
+}
+
 #endif
 
diff --git a/drivers/media/platform/msm/wfd/enc-venus-subdev.c b/drivers/media/platform/msm/wfd/enc-venus-subdev.c
index 9ebf763..b719b3f 100644
--- a/drivers/media/platform/msm/wfd/enc-venus-subdev.c
+++ b/drivers/media/platform/msm/wfd/enc-venus-subdev.c
@@ -767,6 +767,7 @@
 	if (inst->secure)
 		msm_ion_unsecure_buffer(venc_ion_client, mregion->ion_handle);
 
+	ion_free(venc_ion_client, mregion->ion_handle);
 	return rc;
 }
 
@@ -1286,9 +1287,11 @@
 		return rc;
 	}
 
-	if (mregion->paddr)
+	if (mregion->paddr) {
 		ion_unmap_iommu(mmap->ion_client, mregion->ion_handle,
 			domain, partition);
+		mregion->paddr = NULL;
+	}
 
 	if (inst->secure)
 		msm_ion_unsecure_buffer(mmap->ion_client, mregion->ion_handle);
diff --git a/drivers/media/platform/msm/wfd/mdp-5-subdev.c b/drivers/media/platform/msm/wfd/mdp-5-subdev.c
index 4089a99..16de0d4 100644
--- a/drivers/media/platform/msm/wfd/mdp-5-subdev.c
+++ b/drivers/media/platform/msm/wfd/mdp-5-subdev.c
@@ -127,9 +127,9 @@
 		if (inst->secure)
 			msm_fb_writeback_set_secure(inst->mdp, false);
 		msm_fb_writeback_terminate(fbi);
-		kfree(inst);
 		/* Unregister wfd node from switch driver */
 		switch_dev_unregister(&inst->sdev);
+		kfree(inst);
 	}
 	return 0;
 }
diff --git a/drivers/media/platform/msm/wfd/wfd-ioctl.c b/drivers/media/platform/msm/wfd/wfd-ioctl.c
index cd54449..e589878 100644
--- a/drivers/media/platform/msm/wfd/wfd-ioctl.c
+++ b/drivers/media/platform/msm/wfd/wfd-ioctl.c
@@ -166,11 +166,15 @@
 	unsigned int alloc_regions = 0, ion_flags = 0, align = 0;
 	int rc = 0;
 
-	alloc_regions = ION_HEAP(ION_CP_MM_HEAP_ID);
-	alloc_regions |= secure ? 0 :
-				ION_HEAP(ION_IOMMU_HEAP_ID);
-	ion_flags |= secure ? ION_SECURE : 0;
-	align = secure ? SZ_1M : SZ_4K;
+	if (secure) {
+		alloc_regions = ION_HEAP(ION_CP_MM_HEAP_ID);
+		ion_flags = ION_SECURE;
+		align = SZ_1M;
+	} else {
+		alloc_regions = ION_HEAP(ION_IOMMU_HEAP_ID);
+		align = SZ_4K;
+	}
+
 	handle = ion_alloc(client, mregion->size, align,
 			alloc_regions, ion_flags);
 
@@ -1546,10 +1550,10 @@
 			WFD_MSG_ERR("Failed to CLOSE vsg subdev: %d\n", rc);
 
 		wfd_stats_deinit(&inst->stats);
+		v4l2_fh_del(&inst->event_handler);
 		kfree(inst);
 	}
 
-	v4l2_fh_del(&inst->event_handler);
 
 	mutex_lock(&wfd_dev->dev_lock);
 	wfd_dev->in_use = false;
diff --git a/drivers/mfd/wcd9xxx-core.c b/drivers/mfd/wcd9xxx-core.c
index ff8234e..7c73d6c 100644
--- a/drivers/mfd/wcd9xxx-core.c
+++ b/drivers/mfd/wcd9xxx-core.c
@@ -1153,6 +1153,7 @@
 	char **codec_supplies;
 	u32 num_of_supplies = 0;
 	u32 mclk_rate = 0;
+	u32 dmic_sample_rate = 0;
 
 	pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
 	if (!pdata) {
@@ -1212,6 +1213,38 @@
 		goto err;
 	}
 	pdata->mclk_rate = mclk_rate;
+
+	ret = of_property_read_u32(dev->of_node,
+				"qcom,cdc-dmic-sample-rate",
+				&dmic_sample_rate);
+	if (ret) {
+		dev_err(dev, "Looking up %s property in node %s failed",
+			"qcom,cdc-dmic-sample-rate",
+			dev->of_node->full_name);
+		dmic_sample_rate = TAIKO_DMIC_SAMPLE_RATE_UNDEFINED;
+	}
+	if (pdata->mclk_rate == TAIKO_MCLK_CLK_9P6HZ) {
+		if ((dmic_sample_rate != TAIKO_DMIC_SAMPLE_RATE_2P4MHZ) &&
+		    (dmic_sample_rate != TAIKO_DMIC_SAMPLE_RATE_3P2MHZ) &&
+		    (dmic_sample_rate != TAIKO_DMIC_SAMPLE_RATE_4P8MHZ) &&
+		    (dmic_sample_rate != TAIKO_DMIC_SAMPLE_RATE_UNDEFINED)) {
+			dev_err(dev, "Invalid dmic rate %d for mclk %d\n",
+				dmic_sample_rate, pdata->mclk_rate);
+			ret = -EINVAL;
+			goto err;
+		}
+	} else if (pdata->mclk_rate == TAIKO_MCLK_CLK_12P288MHZ) {
+		if ((dmic_sample_rate != TAIKO_DMIC_SAMPLE_RATE_3P072MHZ) &&
+		    (dmic_sample_rate != TAIKO_DMIC_SAMPLE_RATE_4P096MHZ) &&
+		    (dmic_sample_rate != TAIKO_DMIC_SAMPLE_RATE_6P144MHZ) &&
+		    (dmic_sample_rate != TAIKO_DMIC_SAMPLE_RATE_UNDEFINED)) {
+			dev_err(dev, "Invalid dmic rate %d for mclk %d\n",
+				dmic_sample_rate, pdata->mclk_rate);
+			ret = -EINVAL;
+			goto err;
+		}
+	}
+	pdata->dmic_sample_rate = dmic_sample_rate;
 	return pdata;
 err:
 	devm_kfree(dev, pdata);
diff --git a/drivers/misc/qseecom.c b/drivers/misc/qseecom.c
index 7d76b43..188ac32 100644
--- a/drivers/misc/qseecom.c
+++ b/drivers/misc/qseecom.c
@@ -52,6 +52,7 @@
 #define QSEEE_VERSION_00		0x400000
 #define QSEE_VERSION_01			0x401000
 #define QSEE_VERSION_02			0x402000
+#define QSEE_VERSION_03			0x403000
 
 
 #define QSEOS_CHECK_VERSION_CMD		0x00001803
@@ -59,12 +60,20 @@
 #define QSEE_CE_CLK_100MHZ		100000000
 
 #define QSEECOM_MAX_SG_ENTRY	512
+#define QSEECOM_DISK_ENCRYTPION_KEY_ID 0
 
 enum qseecom_clk_definitions {
 	CLK_DFAB = 0,
 	CLK_SFPB,
 };
 
+enum qseecom_client_handle_type {
+	QSEECOM_CLIENT_APP = 0,
+	QSEECOM_LISTENER_SERVICE,
+	QSEECOM_SECURE_SERVICE,
+	QSEECOM_GENERIC,
+};
+
 static struct class *driver_class;
 static dev_t qseecom_device_no;
 static struct cdev qseecom_cdev;
@@ -101,6 +110,12 @@
 	struct qseecom_handle *handle;
 };
 
+struct ce_hw_usage_info {
+	uint32_t  qsee_ce_hw_instance;
+	uint32_t  hlos_ce_hw_instance;
+	uint32_t  disk_encrypt_pipe;
+};
+
 struct qseecom_clk {
 	struct clk *ce_core_clk;
 	struct clk *ce_clk;
@@ -126,6 +141,7 @@
 	uint32_t          qsee_version;
 	struct device *pdev;
 	bool  commonlib_loaded;
+	struct ce_hw_usage_info ce_info;
 
 	int qsee_bw_count;
 	int qsee_sfpb_bw_count;
@@ -152,7 +168,7 @@
 static struct qseecom_control qseecom;
 
 struct qseecom_dev_handle {
-	bool               service;
+	enum qseecom_client_handle_type type;
 	union {
 		struct qseecom_client_handle client;
 		struct qseecom_listener_handle listener;
@@ -163,6 +179,20 @@
 	atomic_t          ioctl_count;
 };
 
+enum qseecom_set_clear_key_flag {
+	QSEECOM_CLEAR_CE_KEY_CMD = 0,
+	QSEECOM_SET_CE_KEY_CMD,
+};
+
+struct qseecom_set_key_parameter {
+	uint32_t ce_hw;
+	uint32_t pipe;
+	uint32_t flags;
+	uint8_t key_id[QSEECOM_KEY_ID_SIZE];
+	unsigned char hash32[QSEECOM_HASH_SIZE];
+	enum qseecom_set_clear_key_flag set_clear_key_flag;
+};
+
 struct qseecom_sg_entry {
 	uint32_t phys_addr;
 	uint32_t len;
@@ -307,7 +337,7 @@
 		return ret;
 	}
 	data->listener.id = 0;
-	data->service = true;
+	data->type = QSEECOM_LISTENER_SERVICE;
 	if (!__qseecom_is_svc_unique(data, &rcvd_lstnr)) {
 		pr_err("Service is not unique and is already registered\n");
 		data->released = true;
@@ -495,7 +525,6 @@
 	struct qseecom_client_listener_data_irsp send_data_rsp;
 	struct qseecom_registered_listener_list *ptr_svc = NULL;
 
-
 	while (resp->result == QSEOS_RESULT_INCOMPLETE) {
 		lstnr = resp->data;
 		/*
@@ -544,13 +573,14 @@
 					sizeof(*resp));
 		if (ret) {
 			pr_err("scm_call() failed with err: %d (app_id = %d)\n",
-					ret, data->client.app_id);
+				ret, data->client.app_id);
 			return ret;
 		}
-		if (resp->result == QSEOS_RESULT_FAILURE) {
-			pr_err("Response result %d FAIL (app_id = %d)\n",
-					resp->result, data->client.app_id);
-			return -EINVAL;
+		if ((resp->result != QSEOS_RESULT_SUCCESS) &&
+			(resp->result != QSEOS_RESULT_INCOMPLETE)) {
+			pr_err("fail:resp res= %d,app_id = %d,lstr = %d\n",
+				resp->result, data->client.app_id, lstnr);
+			ret = -EINVAL;
 		}
 	}
 	if (rc)
@@ -754,6 +784,17 @@
 	return 1;
 }
 
+static int qseecom_unmap_ion_allocated_memory(struct qseecom_dev_handle *data)
+{
+	int ret = 0;
+	if (!IS_ERR_OR_NULL(data->client.ihandle)) {
+		ion_unmap_kernel(qseecom.ion_clnt, data->client.ihandle);
+		ion_free(qseecom.ion_clnt, data->client.ihandle);
+		data->client.ihandle = NULL;
+	}
+	return ret;
+}
+
 static int qseecom_unload_app(struct qseecom_dev_handle *data)
 {
 	unsigned long flags;
@@ -836,11 +877,7 @@
 			}
 		}
 	}
-	if (!IS_ERR_OR_NULL(data->client.ihandle)) {
-		ion_unmap_kernel(qseecom.ion_clnt, data->client.ihandle);
-		ion_free(qseecom.ion_clnt, data->client.ihandle);
-		data->client.ihandle = NULL;
-	}
+	qseecom_unmap_ion_allocated_memory(data);
 	data->released = true;
 	return ret;
 }
@@ -943,6 +980,96 @@
 	return ret;
 }
 
+int __qseecom_process_rpmb_svc_cmd(struct qseecom_dev_handle *data_ptr,
+		struct qseecom_send_svc_cmd_req *req_ptr,
+		struct qseecom_client_send_service_ireq *send_svc_ireq_ptr)
+{
+	int ret = 0;
+	if ((req_ptr == NULL) || (send_svc_ireq_ptr == NULL)) {
+		pr_err("Error with pointer: req_ptr = %p, send_svc_ptr = %p\n",
+			req_ptr, send_svc_ireq_ptr);
+		return -EINVAL;
+	}
+	send_svc_ireq_ptr->qsee_cmd_id = req_ptr->cmd_id;
+	send_svc_ireq_ptr->key_type =
+	((struct qseecom_rpmb_provision_key *)req_ptr->cmd_req_buf)->key_type;
+	send_svc_ireq_ptr->req_len = req_ptr->cmd_req_len;
+	send_svc_ireq_ptr->rsp_ptr = (void *)(__qseecom_uvirt_to_kphys(data_ptr,
+					(uint32_t)req_ptr->resp_buf));
+	send_svc_ireq_ptr->rsp_len = req_ptr->resp_len;
+
+	pr_debug("CMD ID (%x), KEY_TYPE (%d)\n", send_svc_ireq_ptr->qsee_cmd_id,
+	((struct qseecom_rpmb_provision_key *)req_ptr->cmd_req_buf)->key_type);
+	return ret;
+}
+
+static int qseecom_send_service_cmd(struct qseecom_dev_handle *data,
+				void __user *argp)
+{
+	int ret = 0;
+	struct qseecom_client_send_service_ireq send_svc_ireq;
+	struct qseecom_command_scm_resp resp;
+	struct qseecom_send_svc_cmd_req req;
+	/*struct qseecom_command_scm_resp resp;*/
+
+	if (__copy_from_user(&req,
+				(void __user *)argp,
+				sizeof(req))) {
+		pr_err("copy_from_user failed\n");
+		return -EFAULT;
+	}
+
+	if (req.resp_buf == NULL) {
+		pr_err("cmd buffer or response buffer is null\n");
+		return -EINVAL;
+	}
+
+	data->type = QSEECOM_SECURE_SERVICE;
+
+	switch (req.cmd_id) {
+	case QSEE_RPMB_PROVISION_KEY_COMMAND:
+	case QSEE_RPMB_ERASE_COMMAND:
+		if (__qseecom_process_rpmb_svc_cmd(data, &req,
+				&send_svc_ireq))
+			return -EINVAL;
+		break;
+	default:
+		pr_err("Unsupported cmd_id %d\n", req.cmd_id);
+		return -EINVAL;
+	}
+
+	ret = scm_call(SCM_SVC_TZSCHEDULER, 1, (const void *) &send_svc_ireq,
+					sizeof(send_svc_ireq),
+					&resp, sizeof(resp));
+	if (ret) {
+		pr_err("qseecom_scm_call failed with err: %d\n", ret);
+		return ret;
+	}
+
+	switch (resp.result) {
+	case QSEOS_RESULT_SUCCESS:
+		break;
+	case QSEOS_RESULT_INCOMPLETE:
+		pr_err("qseos_result_incomplete\n");
+		ret = __qseecom_process_incomplete_cmd(data, &resp);
+		if (ret) {
+			pr_err("process_incomplete_cmd fail: err: %d\n",
+				ret);
+		}
+		break;
+	case QSEOS_RESULT_FAILURE:
+		pr_err("process_incomplete_cmd failed err: %d\n", ret);
+		break;
+	default:
+		pr_err("Response result %d not supported\n",
+				resp.result);
+		ret = -EINVAL;
+		break;
+	}
+	return ret;
+
+}
+
 static int __qseecom_send_cmd(struct qseecom_dev_handle *data,
 				struct qseecom_send_cmd_req *req)
 {
@@ -1504,7 +1631,7 @@
 		return -ENOMEM;
 	}
 	data->abort = 0;
-	data->service = false;
+	data->type = QSEECOM_CLIENT_APP;
 	data->released = false;
 	data->client.app_id = ret;
 	data->client.sb_length = size;
@@ -1769,7 +1896,7 @@
 	int rc = 0;
 	struct qseecom_clk *qclk;
 
-	qclk = &qseecom.qsee;
+		qclk = &qseecom.qsee;
 	/* Enable CE core clk */
 	rc = clk_prepare_enable(qclk->ce_core_clk);
 	if (rc) {
@@ -2176,6 +2303,273 @@
 	}
 }
 
+static int __qseecom_get_ce_pipe_info(
+			enum qseecom_key_management_usage_type usage,
+			uint32_t *pipe, uint32_t *ce_hw)
+{
+	int ret;
+	switch (usage) {
+	case QSEOS_KM_USAGE_DISK_ENCRYPTION:
+		if (qseecom.ce_info.disk_encrypt_pipe == 0xFF ||
+			qseecom.ce_info.hlos_ce_hw_instance == 0xFF) {
+			pr_err("nfo unavailable: disk encr pipe %d ce_hw %d\n",
+				qseecom.ce_info.disk_encrypt_pipe,
+				qseecom.ce_info.hlos_ce_hw_instance);
+			ret = -EINVAL;
+		} else {
+			*pipe = qseecom.ce_info.disk_encrypt_pipe;
+			*ce_hw = qseecom.ce_info.hlos_ce_hw_instance;
+			ret = 0;
+		}
+		break;
+	default:
+		ret = -EINVAL;
+		break;
+	}
+	return ret;
+}
+
+static int __qseecom_generate_and_save_key(struct qseecom_dev_handle *data,
+			enum qseecom_key_management_usage_type usage,
+			uint8_t *key_id, uint32_t flags)
+{
+	struct qseecom_key_generate_ireq ireq;
+	struct qseecom_command_scm_resp resp;
+	int ret;
+
+	if (usage != QSEOS_KM_USAGE_DISK_ENCRYPTION) {
+		pr_err("Error:: unsupported usage %d\n", usage);
+		return -EFAULT;
+	}
+
+	memcpy(ireq.key_id, key_id, QSEECOM_KEY_ID_SIZE);
+	ireq.flags = flags;
+
+	ret = scm_call(SCM_SVC_CRYPTO, QSEOS_GENERATE_KEY,
+				&ireq, sizeof(struct qseecom_key_generate_ireq),
+				&resp, sizeof(resp));
+	if (ret) {
+		pr_err("scm call to generate key failed : %d\n", ret);
+		return ret;
+	}
+
+	switch (resp.result) {
+	case QSEOS_RESULT_SUCCESS:
+		break;
+	case QSEOS_RESULT_INCOMPLETE:
+		ret = __qseecom_process_incomplete_cmd(data, &resp);
+		if (ret)
+			pr_err("process_incomplete_cmd FAILED\n");
+		break;
+	case QSEOS_RESULT_FAILURE:
+	default:
+		pr_err("gen key scm call failed resp.result %d\n", resp.result);
+		ret = -EINVAL;
+		break;
+	}
+	return ret;
+}
+
+static int __qseecom_delete_saved_key(struct qseecom_dev_handle *data,
+			enum qseecom_key_management_usage_type usage,
+			uint8_t *key_id, uint32_t flags)
+{
+	struct qseecom_key_delete_ireq ireq;
+	struct qseecom_command_scm_resp resp;
+	int ret;
+
+	if (usage != QSEOS_KM_USAGE_DISK_ENCRYPTION) {
+		pr_err("Error:: unsupported usage %d\n", usage);
+		return -EFAULT;
+	}
+
+	memcpy(ireq.key_id, key_id, QSEECOM_KEY_ID_SIZE);
+	ireq.flags = flags;
+
+	ret = scm_call(SCM_SVC_CRYPTO, QSEOS_DELETE_KEY,
+				&ireq, sizeof(struct qseecom_key_delete_ireq),
+				&resp, sizeof(struct qseecom_command_scm_resp));
+	if (ret) {
+		pr_err("scm call to delete key failed : %d\n", ret);
+		return ret;
+	}
+
+	switch (resp.result) {
+	case QSEOS_RESULT_SUCCESS:
+		break;
+	case QSEOS_RESULT_INCOMPLETE:
+		ret = __qseecom_process_incomplete_cmd(data, &resp);
+		if (ret)
+			pr_err("process_incomplete_cmd FAILED\n");
+		break;
+	case QSEOS_RESULT_FAILURE:
+	default:
+		pr_err("Delete key scm call failed resp.result %d\n",
+							resp.result);
+		ret = -EINVAL;
+		break;
+	}
+	return ret;
+}
+
+static int __qseecom_set_clear_ce_key(struct qseecom_dev_handle *data,
+			enum qseecom_key_management_usage_type usage,
+			struct qseecom_set_key_parameter *set_key_para)
+{
+	struct qseecom_key_select_ireq ireq;
+	struct qseecom_command_scm_resp resp;
+	int ret;
+
+	if (usage != QSEOS_KM_USAGE_DISK_ENCRYPTION) {
+			pr_err("Error:: unsupported usage %d\n", usage);
+			return -EFAULT;
+	}
+	memcpy(ireq.key_id, set_key_para->key_id, QSEECOM_KEY_ID_SIZE);
+	ireq.ce = set_key_para->ce_hw;
+	ireq.pipe = set_key_para->pipe;
+	ireq.flags = set_key_para->flags;
+
+	if (set_key_para->set_clear_key_flag ==
+			QSEECOM_SET_CE_KEY_CMD)
+		memcpy((void *)ireq.hash, (void *)set_key_para->hash32,
+				QSEECOM_HASH_SIZE);
+	else
+		memset((void *)ireq.hash, 0, QSEECOM_HASH_SIZE);
+
+	ret = scm_call(SCM_SVC_CRYPTO, QSEOS_SET_KEY,
+				&ireq, sizeof(struct qseecom_key_select_ireq),
+				&resp, sizeof(struct qseecom_command_scm_resp));
+	if (ret) {
+		pr_err("scm call to set key failed : %d\n", ret);
+		return ret;
+	}
+
+	switch (resp.result) {
+	case QSEOS_RESULT_SUCCESS:
+		break;
+	case QSEOS_RESULT_INCOMPLETE:
+		ret = __qseecom_process_incomplete_cmd(data, &resp);
+		if (ret)
+			pr_err("process_incomplete_cmd FAILED\n");
+		break;
+	case QSEOS_RESULT_FAILURE:
+	default:
+		pr_err("Set key scm call failed resp.result %d\n", resp.result);
+		ret = -EINVAL;
+		break;
+	}
+
+	return ret;
+}
+
+static int qseecom_create_key(struct qseecom_dev_handle *data,
+			void __user *argp)
+{
+	uint32_t ce_hw = 0;
+	uint32_t pipe = 0;
+	uint8_t key_id[QSEECOM_KEY_ID_SIZE] = {0};
+	int ret = 0;
+	uint32_t flags = 0;
+	struct qseecom_set_key_parameter set_key_para;
+	struct qseecom_create_key_req create_key_req;
+
+	ret = copy_from_user(&create_key_req, argp, sizeof(create_key_req));
+	if (ret) {
+		pr_err("copy_from_user failed\n");
+		return ret;
+	}
+
+	if (create_key_req.usage != QSEOS_KM_USAGE_DISK_ENCRYPTION) {
+		pr_err("Error:: unsupported usage %d\n", create_key_req.usage);
+		return -EFAULT;
+	}
+
+	ret = __qseecom_get_ce_pipe_info(create_key_req.usage, &pipe, &ce_hw);
+	if (ret) {
+		pr_err("Failed to retrieve pipe/ce_hw info: %d\n", ret);
+		return -EINVAL;
+	}
+
+	ret = __qseecom_generate_and_save_key(data, create_key_req.usage,
+								key_id, flags);
+	if (ret) {
+		pr_err("Failed to generate key on storage: %d\n", ret);
+		return -EFAULT;
+	}
+
+	set_key_para.ce_hw = ce_hw;
+	set_key_para.pipe = pipe;
+	memcpy(set_key_para.key_id, key_id, QSEECOM_KEY_ID_SIZE);
+	set_key_para.flags = flags;
+	set_key_para.set_clear_key_flag = QSEECOM_SET_CE_KEY_CMD;
+	memcpy((void *)set_key_para.hash32, (void *)create_key_req.hash32,
+				QSEECOM_HASH_SIZE);
+
+	ret = __qseecom_set_clear_ce_key(data, create_key_req.usage,
+								&set_key_para);
+	if (ret) {
+		pr_err("Failed to create key: pipe %d, ce %d: %d\n",
+			pipe, ce_hw, ret);
+		return -EFAULT;
+	}
+
+	return ret;
+}
+
+static int qseecom_wipe_key(struct qseecom_dev_handle *data,
+				void __user *argp)
+{
+	uint32_t ce_hw = 0;
+	uint32_t pipe = 0;
+	uint8_t key_id[QSEECOM_KEY_ID_SIZE] = {0};
+	int ret = 0;
+	uint32_t flags = 0;
+	int i;
+	struct qseecom_wipe_key_req wipe_key_req;
+	struct qseecom_set_key_parameter clear_key_para;
+
+	ret = copy_from_user(&wipe_key_req, argp, sizeof(wipe_key_req));
+	if (ret) {
+		pr_err("copy_from_user failed\n");
+		return ret;
+	}
+
+	if (wipe_key_req.usage != QSEOS_KM_USAGE_DISK_ENCRYPTION) {
+		pr_err("Error:: unsupported usage %d\n", wipe_key_req.usage);
+		return -EFAULT;
+	}
+
+	ret = __qseecom_get_ce_pipe_info(wipe_key_req.usage, &pipe, &ce_hw);
+	if (ret) {
+		pr_err("Failed to retrieve pipe/ce_hw info: %d\n", ret);
+		return -EINVAL;
+	}
+
+	ret = __qseecom_delete_saved_key(data, wipe_key_req.usage, key_id,
+									flags);
+	if (ret) {
+		pr_err("Failed to delete key from ssd storage: %d\n", ret);
+		return -EFAULT;
+	}
+
+	/* an invalid key_id 0xff is used to indicate clear key*/
+	for (i = 0; i < QSEECOM_KEY_ID_SIZE; i++)
+		clear_key_para.key_id[i] = 0xff;
+	clear_key_para.ce_hw = ce_hw;
+	clear_key_para.pipe = pipe;
+	clear_key_para.flags = flags;
+	clear_key_para.set_clear_key_flag = QSEECOM_CLEAR_CE_KEY_CMD;
+	ret = __qseecom_set_clear_ce_key(data, wipe_key_req.usage,
+							&clear_key_para);
+	if (ret) {
+		pr_err("Failed to wipe key: pipe %d, ce %d: %d\n",
+			pipe, ce_hw, ret);
+		return -EFAULT;
+	}
+
+	return ret;
+}
+
 static long qseecom_ioctl(struct file *file, unsigned cmd,
 		unsigned long arg)
 {
@@ -2352,6 +2746,42 @@
 		mutex_unlock(&app_access_lock);
 		break;
 	}
+	case QSEECOM_IOCTL_SEND_CMD_SERVICE_REQ: {
+		if (qseecom.qsee_version < QSEE_VERSION_03) {
+			pr_err("SEND_CMD_SERVICE_REQ: Invalid qsee version %u\n",
+				qseecom.qsee_version);
+			return -EINVAL;
+		}
+		mutex_lock(&app_access_lock);
+		atomic_inc(&data->ioctl_count);
+		ret = qseecom_send_service_cmd(data, argp);
+		atomic_dec(&data->ioctl_count);
+		mutex_unlock(&app_access_lock);
+		break;
+	}
+	case QSEECOM_IOCTL_CREATE_KEY_REQ: {
+		data->released = true;
+		mutex_lock(&app_access_lock);
+		atomic_inc(&data->ioctl_count);
+		ret = qseecom_create_key(data, argp);
+		if (ret)
+			pr_err("failed to create encryption key: %d\n", ret);
+
+		atomic_dec(&data->ioctl_count);
+		mutex_unlock(&app_access_lock);
+		break;
+	}
+	case QSEECOM_IOCTL_WIPE_KEY_REQ: {
+		data->released = true;
+		mutex_lock(&app_access_lock);
+		atomic_inc(&data->ioctl_count);
+		ret = qseecom_wipe_key(data, argp);
+		if (ret)
+			pr_err("failed to wipe encryption key: %d\n", ret);
+		atomic_dec(&data->ioctl_count);
+		mutex_unlock(&app_access_lock);
+		break;
+	}
 	default:
 		return -EINVAL;
 	}
@@ -2370,7 +2800,7 @@
 	}
 	file->private_data = data;
 	data->abort = 0;
-	data->service = false;
+	data->type = QSEECOM_GENERIC;
 	data->released = false;
 	init_waitqueue_head(&data->abort_wq);
 	atomic_set(&data->ioctl_count, 0);
@@ -2401,15 +2831,28 @@
 
 	if (data->released == false) {
 		pr_warn("data->released == false\n");
-		if (data->service)
+		switch (data->type) {
+		case QSEECOM_LISTENER_SERVICE:
 			ret = qseecom_unregister_listener(data);
-		else
+			break;
+		case QSEECOM_CLIENT_APP:
 			ret = qseecom_unload_app(data);
-		if (ret) {
-			pr_err("Close failed\n");
-			return ret;
+			break;
+		case QSEECOM_SECURE_SERVICE:
+		case QSEECOM_GENERIC:
+			ret = qseecom_unmap_ion_allocated_memory(data);
+			if (ret) {
+				pr_err("Close failed\n");
+				return ret;
+			}
+			break;
+		default:
+			pr_err("Unsupported clnt_handle_type %d",
+				data->type);
+			break;
 		}
 	}
+
 	if (data->client.fast_load_enabled == true)
 		qsee_disable_clock_vote(data, CLK_SFPB);
 	if (data->client.perf_enabled == true)
@@ -2610,6 +3053,42 @@
 
 	/* register client for bus scaling */
 	if (pdev->dev.of_node) {
+		if (of_property_read_u32((&pdev->dev)->of_node,
+				"qcom,disk-encrypt-pipe-pair",
+				&qseecom.ce_info.disk_encrypt_pipe)) {
+			pr_err("Fail to get disk-encrypt pipe pair information.\n");
+			qseecom.ce_info.disk_encrypt_pipe = 0xff;
+			rc = -EINVAL;
+			goto err;
+		} else {
+			pr_warn("bam_pipe_pair=0x%x",
+			qseecom.ce_info.disk_encrypt_pipe);
+		}
+
+		if (of_property_read_u32((&pdev->dev)->of_node,
+				"qcom,qsee-ce-hw-instance",
+				&qseecom.ce_info.qsee_ce_hw_instance)) {
+			pr_err("Fail to get qsee ce hw instance information.\n");
+			qseecom.ce_info.qsee_ce_hw_instance = 0xff;
+			rc = -EINVAL;
+			goto err;
+		} else {
+			pr_warn("qsee-ce-hw-instance=0x%x",
+			qseecom.ce_info.qsee_ce_hw_instance);
+		}
+
+		if (of_property_read_u32((&pdev->dev)->of_node,
+				"qcom,hlos-ce-hw-instance",
+				&qseecom.ce_info.hlos_ce_hw_instance)) {
+			pr_err("Fail to get hlos ce hw instance information.\n");
+			qseecom.ce_info.hlos_ce_hw_instance = 0xff;
+			rc = -EINVAL;
+			goto err;
+		} else {
+			pr_warn("hlos-ce-hw-instance=0x%x",
+			qseecom.ce_info.hlos_ce_hw_instance);
+		}
+
 		ret = __qseecom_init_clk();
 		if (ret)
 			goto err;
diff --git a/drivers/misc/tsif.c b/drivers/misc/tsif.c
index 05f6c86..f80fbcc 100644
--- a/drivers/misc/tsif.c
+++ b/drivers/misc/tsif.c
@@ -216,8 +216,6 @@
 		tsif_device->tsif_clk = clk_get(&tsif_device->pdev->dev,
 						pdata->tsif_clk);
 		if (IS_ERR(tsif_device->tsif_clk)) {
-			dev_err(&tsif_device->pdev->dev, "failed to get %s\n",
-				pdata->tsif_clk);
 			rc = PTR_ERR(tsif_device->tsif_clk);
 			tsif_device->tsif_clk = NULL;
 			goto ret;
@@ -227,8 +225,6 @@
 		tsif_device->tsif_pclk = clk_get(&tsif_device->pdev->dev,
 						 pdata->tsif_pclk);
 		if (IS_ERR(tsif_device->tsif_pclk)) {
-			dev_err(&tsif_device->pdev->dev, "failed to get %s\n",
-				pdata->tsif_pclk);
 			rc = PTR_ERR(tsif_device->tsif_pclk);
 			tsif_device->tsif_pclk = NULL;
 			goto ret;
@@ -238,8 +234,6 @@
 		tsif_device->tsif_ref_clk = clk_get(&tsif_device->pdev->dev,
 						    pdata->tsif_ref_clk);
 		if (IS_ERR(tsif_device->tsif_ref_clk)) {
-			dev_err(&tsif_device->pdev->dev, "failed to get %s\n",
-				pdata->tsif_ref_clk);
 			rc = PTR_ERR(tsif_device->tsif_ref_clk);
 			tsif_device->tsif_ref_clk = NULL;
 			goto ret;
@@ -1431,7 +1425,8 @@
 		     (unsigned long)tsif_device);
 	tasklet_init(&tsif_device->clocks_off, tsif_clocks_off,
 		     (unsigned long)tsif_device);
-	if (tsif_get_clocks(tsif_device))
+	rc = tsif_get_clocks(tsif_device);
+	if (rc)
 		goto err_clocks;
 /* map I/O memory */
 	tsif_device->memres = platform_get_resource(pdev, IORESOURCE_MEM, 0);
diff --git a/drivers/misc/tspp.c b/drivers/misc/tspp.c
index 9ef86a7..dbb4f5e 100644
--- a/drivers/misc/tspp.c
+++ b/drivers/misc/tspp.c
@@ -1569,6 +1569,7 @@
 {
 	int i;
 	int id;
+	int table_idx;
 	u32 val;
 
 	struct sps_connect *config;
@@ -1606,16 +1607,18 @@
 	wmb();
 
 	/* unregister all filters for this channel */
-	for (i = 0; i < TSPP_NUM_PRIORITIES; i++) {
-		struct tspp_pid_filter *tspp_filter =
-			&pdev->filters[channel->src]->filter[i];
-		id = FILTER_GET_PIPE_NUMBER0(tspp_filter);
-		if (id == channel->id) {
-			if (FILTER_HAS_ENCRYPTION(tspp_filter))
-				tspp_free_key_entry(
-					FILTER_GET_KEY_NUMBER(tspp_filter));
-			tspp_filter->config = 0;
-			tspp_filter->filter = 0;
+	for (table_idx = 0; table_idx < TSPP_FILTER_TABLES; table_idx++) {
+		for (i = 0; i < TSPP_NUM_PRIORITIES; i++) {
+			struct tspp_pid_filter *filter =
+				&pdev->filters[table_idx]->filter[i];
+			id = FILTER_GET_PIPE_NUMBER0(filter);
+			if (id == channel->id) {
+				if (FILTER_HAS_ENCRYPTION(filter))
+					tspp_free_key_entry(
+						FILTER_GET_KEY_NUMBER(filter));
+				filter->config = 0;
+				filter->filter = 0;
+			}
 		}
 	}
 	channel->filter_count = 0;
@@ -2836,8 +2839,6 @@
 	if (data->tsif_pclk) {
 		device->tsif_pclk = clk_get(&pdev->dev, data->tsif_pclk);
 		if (IS_ERR(device->tsif_pclk)) {
-			pr_err("tspp: failed to get %s",
-				data->tsif_pclk);
 			rc = PTR_ERR(device->tsif_pclk);
 			device->tsif_pclk = NULL;
 			goto err_pclock;
@@ -2846,8 +2847,6 @@
 	if (data->tsif_ref_clk) {
 		device->tsif_ref_clk = clk_get(&pdev->dev, data->tsif_ref_clk);
 		if (IS_ERR(device->tsif_ref_clk)) {
-			pr_err("tspp: failed to get %s",
-				data->tsif_ref_clk);
 			rc = PTR_ERR(device->tsif_ref_clk);
 			device->tsif_ref_clk = NULL;
 			goto err_refclock;
diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
index ae47975..fc7c399 100644
--- a/drivers/mmc/core/core.c
+++ b/drivers/mmc/core/core.c
@@ -2823,7 +2823,13 @@
 	u32 status;
 	bool ret = false;
 
-	if (!card)
+	/*
+	 * If the current partition type is RPMB, clock switching may not
+	 * work properly as sending tuning command (CMD21) is illegal in
+	 * this mode.
+	 */
+	if (!card || (mmc_card_mmc(card) &&
+			card->part_curr == EXT_CSD_PART_CONFIG_ACC_RPMB))
 		goto out;
 
 	if (mmc_send_status(card, &status)) {
@@ -3594,6 +3600,20 @@
 EXPORT_SYMBOL(mmc_set_embedded_sdio_data);
 #endif
 
+#ifdef CONFIG_PM_RUNTIME
+void mmc_dump_dev_pm_state(struct mmc_host *host, struct device *dev)
+{
+	pr_err("%s: %s: err: runtime_error: %d\n", dev_name(dev),
+	       mmc_hostname(host), dev->power.runtime_error);
+	pr_err("%s: %s: disable_depth: %d runtime_status: %d idle_notification: %d\n",
+	       dev_name(dev), mmc_hostname(host), dev->power.disable_depth,
+	       dev->power.runtime_status,
+	       dev->power.idle_notification);
+	pr_err("%s: %s: request_pending: %d, request: %d\n",
+	       dev_name(dev), mmc_hostname(host),
+	       dev->power.request_pending, dev->power.request);
+}
+
 void mmc_rpm_hold(struct mmc_host *host, struct device *dev)
 {
 	int ret = 0;
@@ -3602,13 +3622,16 @@
 		return;
 
 	ret = pm_runtime_get_sync(dev);
-	if (ret < 0) {
-		pr_err("%s: %s: %s: error resuming device: %d\n",
+	if ((ret < 0) &&
+	    (dev->power.runtime_error || (dev->power.disable_depth > 0))) {
+		pr_err("%s: %s: %s: pm_runtime_get_sync: err: %d\n",
 		       dev_name(dev), mmc_hostname(host), __func__, ret);
+		mmc_dump_dev_pm_state(host, dev);
 		if (pm_runtime_suspended(dev))
 			BUG_ON(1);
 	}
 }
+
 EXPORT_SYMBOL(mmc_rpm_hold);
 
 void mmc_rpm_release(struct mmc_host *host, struct device *dev)
@@ -3619,11 +3642,22 @@
 		return;
 
 	ret = pm_runtime_put_sync(dev);
-	if (ret < 0 && ret != -EBUSY)
-		pr_err("%s: %s: %s: put sync ret: %d\n",
+	if ((ret < 0) &&
+	    (dev->power.runtime_error || (dev->power.disable_depth > 0))) {
+		pr_err("%s: %s: %s: pm_runtime_put_sync: err: %d\n",
 		       dev_name(dev), mmc_hostname(host), __func__, ret);
+		mmc_dump_dev_pm_state(host, dev);
+	}
 }
+
 EXPORT_SYMBOL(mmc_rpm_release);
+#else
+void mmc_rpm_hold(struct mmc_host *host, struct device *dev) {}
+EXPORT_SYMBOL(mmc_rpm_hold);
+
+void mmc_rpm_release(struct mmc_host *host, struct device *dev) {}
+EXPORT_SYMBOL(mmc_rpm_release);
+#endif
 
 /**
  * mmc_init_context_info() - init synchronization context
diff --git a/drivers/mmc/host/sdhci-msm.c b/drivers/mmc/host/sdhci-msm.c
index 5090eea..2038d3d 100644
--- a/drivers/mmc/host/sdhci-msm.c
+++ b/drivers/mmc/host/sdhci-msm.c
@@ -1187,9 +1187,12 @@
 static unsigned int sdhci_get_bw_required(struct sdhci_host *host,
 					struct mmc_ios *ios)
 {
+	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+	struct sdhci_msm_host *msm_host = pltfm_host->priv;
+
 	unsigned int bw;
 
-	bw = host->clock;
+	bw = msm_host->clk_rate;
 	/*
 	 * For DDR mode, SDCC controller clock will be at
 	 * the double rate than the actual clock that goes to card.
@@ -2184,6 +2187,7 @@
 	host->quirks |= SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN;
 	host->quirks2 |= SDHCI_QUIRK2_ALWAYS_USE_BASE_CLOCK;
 	host->quirks2 |= SDHCI_QUIRK2_IGNORE_CMDCRC_FOR_TUNING;
+	host->quirks2 |= SDHCI_QUIRK2_USE_MAX_DISCARD_SIZE;
 
 	host_version = readl_relaxed((host->ioaddr + SDHCI_HOST_VERSION));
 	dev_dbg(&pdev->dev, "Host Version: 0x%x Vendor Version 0x%x\n",
diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
index c247ae9..d58379f 100644
--- a/drivers/mmc/host/sdhci.c
+++ b/drivers/mmc/host/sdhci.c
@@ -66,53 +66,67 @@
 }
 #endif
 
+static void sdhci_dump_state(struct sdhci_host *host)
+{
+	struct mmc_host *mmc = host->mmc;
+
+	pr_info("%s: clk: %d clk-gated: %d claimer: %s pwr: %d\n",
+		mmc_hostname(mmc), host->clock, mmc->clk_gated,
+		mmc->claimer->comm, host->pwr);
+	pr_info("%s: rpmstatus[pltfm](runtime-suspend:usage_count:disable_depth)(%d:%d:%d)\n",
+		mmc_hostname(mmc), mmc->parent->power.runtime_status,
+		atomic_read(&mmc->parent->power.usage_count),
+		mmc->parent->power.disable_depth);
+}
+
 static void sdhci_dumpregs(struct sdhci_host *host)
 {
-	pr_debug(DRIVER_NAME ": =========== REGISTER DUMP (%s)===========\n",
+	pr_info(DRIVER_NAME ": =========== REGISTER DUMP (%s)===========\n",
 		mmc_hostname(host->mmc));
 
-	pr_debug(DRIVER_NAME ": Sys addr: 0x%08x | Version:  0x%08x\n",
+	pr_info(DRIVER_NAME ": Sys addr: 0x%08x | Version:  0x%08x\n",
 		sdhci_readl(host, SDHCI_DMA_ADDRESS),
 		sdhci_readw(host, SDHCI_HOST_VERSION));
-	pr_debug(DRIVER_NAME ": Blk size: 0x%08x | Blk cnt:  0x%08x\n",
+	pr_info(DRIVER_NAME ": Blk size: 0x%08x | Blk cnt:  0x%08x\n",
 		sdhci_readw(host, SDHCI_BLOCK_SIZE),
 		sdhci_readw(host, SDHCI_BLOCK_COUNT));
-	pr_debug(DRIVER_NAME ": Argument: 0x%08x | Trn mode: 0x%08x\n",
+	pr_info(DRIVER_NAME ": Argument: 0x%08x | Trn mode: 0x%08x\n",
 		sdhci_readl(host, SDHCI_ARGUMENT),
 		sdhci_readw(host, SDHCI_TRANSFER_MODE));
-	pr_debug(DRIVER_NAME ": Present:  0x%08x | Host ctl: 0x%08x\n",
+	pr_info(DRIVER_NAME ": Present:  0x%08x | Host ctl: 0x%08x\n",
 		sdhci_readl(host, SDHCI_PRESENT_STATE),
 		sdhci_readb(host, SDHCI_HOST_CONTROL));
-	pr_debug(DRIVER_NAME ": Power:    0x%08x | Blk gap:  0x%08x\n",
+	pr_info(DRIVER_NAME ": Power:    0x%08x | Blk gap:  0x%08x\n",
 		sdhci_readb(host, SDHCI_POWER_CONTROL),
 		sdhci_readb(host, SDHCI_BLOCK_GAP_CONTROL));
-	pr_debug(DRIVER_NAME ": Wake-up:  0x%08x | Clock:    0x%08x\n",
+	pr_info(DRIVER_NAME ": Wake-up:  0x%08x | Clock:    0x%08x\n",
 		sdhci_readb(host, SDHCI_WAKE_UP_CONTROL),
 		sdhci_readw(host, SDHCI_CLOCK_CONTROL));
-	pr_debug(DRIVER_NAME ": Timeout:  0x%08x | Int stat: 0x%08x\n",
+	pr_info(DRIVER_NAME ": Timeout:  0x%08x | Int stat: 0x%08x\n",
 		sdhci_readb(host, SDHCI_TIMEOUT_CONTROL),
 		sdhci_readl(host, SDHCI_INT_STATUS));
-	pr_debug(DRIVER_NAME ": Int enab: 0x%08x | Sig enab: 0x%08x\n",
+	pr_info(DRIVER_NAME ": Int enab: 0x%08x | Sig enab: 0x%08x\n",
 		sdhci_readl(host, SDHCI_INT_ENABLE),
 		sdhci_readl(host, SDHCI_SIGNAL_ENABLE));
-	pr_debug(DRIVER_NAME ": AC12 err: 0x%08x | Slot int: 0x%08x\n",
+	pr_info(DRIVER_NAME ": AC12 err: 0x%08x | Slot int: 0x%08x\n",
 		sdhci_readw(host, SDHCI_ACMD12_ERR),
 		sdhci_readw(host, SDHCI_SLOT_INT_STATUS));
-	pr_debug(DRIVER_NAME ": Caps:     0x%08x | Caps_1:   0x%08x\n",
+	pr_info(DRIVER_NAME ": Caps:     0x%08x | Caps_1:   0x%08x\n",
 		sdhci_readl(host, SDHCI_CAPABILITIES),
 		sdhci_readl(host, SDHCI_CAPABILITIES_1));
-	pr_debug(DRIVER_NAME ": Cmd:      0x%08x | Max curr: 0x%08x\n",
+	pr_info(DRIVER_NAME ": Cmd:      0x%08x | Max curr: 0x%08x\n",
 		sdhci_readw(host, SDHCI_COMMAND),
 		sdhci_readl(host, SDHCI_MAX_CURRENT));
-	pr_debug(DRIVER_NAME ": Host ctl2: 0x%08x\n",
+	pr_info(DRIVER_NAME ": Host ctl2: 0x%08x\n",
 		sdhci_readw(host, SDHCI_HOST_CONTROL2));
 
 	if (host->flags & SDHCI_USE_ADMA)
-		pr_debug(DRIVER_NAME ": ADMA Err: 0x%08x | ADMA Ptr: 0x%08x\n",
+		pr_info(DRIVER_NAME ": ADMA Err: 0x%08x | ADMA Ptr: 0x%08x\n",
 		       readl(host->ioaddr + SDHCI_ADMA_ERROR),
 		       readl(host->ioaddr + SDHCI_ADMA_ADDRESS));
 
-	pr_debug(DRIVER_NAME ": ===========================================\n");
+	sdhci_dump_state(host);
+	pr_info(DRIVER_NAME ": ===========================================\n");
 }
 
 /*****************************************************************************\
@@ -1372,6 +1386,17 @@
 	}
 }
 
+static bool sdhci_check_state(struct sdhci_host *host)
+{
+	struct mmc_host *mmc = host->mmc;
+
+	if (!host->clock || !host->pwr ||
+	    pm_runtime_suspended(mmc->parent))
+		return true;
+	else
+		return false;
+}
+
 static void sdhci_request(struct mmc_host *mmc, struct mmc_request *mrq)
 {
 	struct sdhci_host *host;
@@ -1381,6 +1406,15 @@
 	host = mmc_priv(mmc);
 
 	sdhci_runtime_pm_get(host);
+	if (sdhci_check_state(host)) {
+		sdhci_dump_state(host);
+		WARN(1, "sdhci in bad state");
+		mrq->cmd->error = -EIO;
+		if (mrq->data)
+			mrq->data->error = -EIO;
+		tasklet_schedule(&host->finish_tasklet);
+		return;
+	}
 
 	spin_lock_irqsave(&host->lock, flags);
 
@@ -2217,6 +2251,11 @@
 		sdhci_dumpregs(host);
 
 		if (host->data) {
+			pr_info("%s: bytes to transfer: %d transferred: %d\n",
+				mmc_hostname(host->mmc),
+				(host->data->blksz * host->data->blocks),
+				(sdhci_readw(host, SDHCI_BLOCK_SIZE) & 0xFFF) *
+				sdhci_readw(host, SDHCI_BLOCK_COUNT));
 			host->data->error = -ETIMEDOUT;
 			sdhci_finish_data(host);
 		} else {
@@ -2354,6 +2393,7 @@
 static void sdhci_data_irq(struct sdhci_host *host, u32 intmask)
 {
 	u32 command;
+	bool pr_msg = false;
 	BUG_ON(intmask == 0);
 
 	/* CMD19 generates _only_ Buffer Read Ready interrupt */
@@ -2401,10 +2441,25 @@
 		sdhci_show_adma_error(host);
 		host->data->error = -EIO;
 	}
-
-	if (host->data->error)
+	if (host->data->error) {
+		if ((intmask & (SDHCI_INT_DATA_CRC | SDHCI_INT_DATA_TIMEOUT)) &&
+		    (host->quirks2 & SDHCI_QUIRK2_IGNORE_CMDCRC_FOR_TUNING)) {
+			command = SDHCI_GET_CMD(sdhci_readw(host,
+							    SDHCI_COMMAND));
+			if ((command != MMC_SEND_TUNING_BLOCK_HS200) &&
+			    (command != MMC_SEND_TUNING_BLOCK))
+				pr_msg = true;
+		} else {
+			pr_msg = true;
+		}
+		if (pr_msg) {
+			pr_err("%s: data txfr (0x%08x) error: %d\n",
+			       mmc_hostname(host->mmc), intmask,
+			       host->data->error);
+			sdhci_dumpregs(host);
+		}
 		sdhci_finish_data(host);
-	else {
+	} else {
 		if (intmask & (SDHCI_INT_DATA_AVAIL | SDHCI_INT_SPACE_AVAIL))
 			sdhci_transfer_pio(host);
 
@@ -2962,7 +3017,8 @@
 	if (host->quirks & SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK)
 		host->timeout_clk = mmc->f_max / 1000;
 
-	mmc->max_discard_to = (1 << 27) / host->timeout_clk;
+	if (!(host->quirks2 & SDHCI_QUIRK2_USE_MAX_DISCARD_SIZE))
+		mmc->max_discard_to = (1 << 27) / host->timeout_clk;
 
 	mmc->caps |= MMC_CAP_SDIO_IRQ | MMC_CAP_ERASE | MMC_CAP_CMD23;
 
diff --git a/drivers/mtd/devices/msm_qpic_nand.c b/drivers/mtd/devices/msm_qpic_nand.c
index c37a4a4..570c257 100644
--- a/drivers/mtd/devices/msm_qpic_nand.c
+++ b/drivers/mtd/devices/msm_qpic_nand.c
@@ -28,8 +28,9 @@
 #include <linux/bitrev.h>
 #include <linux/mutex.h>
 #include <linux/of.h>
+#include <linux/ctype.h>
 #include <mach/sps.h>
-
+#include <mach/msm_smsm.h>
 #define PAGE_SIZE_2K 2048
 #define PAGE_SIZE_4K 4096
 #define WRITE 1
@@ -285,6 +286,34 @@
 	uint16_t integrity_crc;
 } __attribute__((__packed__));
 
+#define FLASH_PART_MAGIC1	0x55EE73AA
+#define FLASH_PART_MAGIC2	0xE35EBDDB
+#define FLASH_PTABLE_V3		3
+#define FLASH_PTABLE_V4		4
+#define FLASH_PTABLE_MAX_PARTS_V3 16
+#define FLASH_PTABLE_MAX_PARTS_V4 32
+#define FLASH_PTABLE_HDR_LEN (4*sizeof(uint32_t))
+#define FLASH_PTABLE_ENTRY_NAME_SIZE 16
+
+struct flash_partition_entry {
+	char name[FLASH_PTABLE_ENTRY_NAME_SIZE];
+	u32 offset;     /* Offset in blocks from beginning of device */
+	u32 length;     /* Length of the partition in blocks */
+	u8 attr;	/* Flags for this partition */
+};
+
+struct flash_partition_table {
+	u32 magic1;
+	u32 magic2;
+	u32 version;
+	u32 numparts;
+	struct flash_partition_entry part_entry[FLASH_PTABLE_MAX_PARTS_V4];
+};
+
+static struct flash_partition_table ptable;
+
+static struct mtd_partition mtd_part[FLASH_PTABLE_MAX_PARTS_V4];
+
 /*
  * Get the DMA memory for requested amount of size. It returns the pointer
  * to free memory available from the allocated pool. Returns NULL if there
@@ -660,6 +689,14 @@
 	if (ret < 0)
 		goto free_dma;
 
+	/* Lookup the 'APPS' partition's first page address */
+	for (i = 0; i < FLASH_PTABLE_MAX_PARTS_V4; i++) {
+		if (!strncmp("apps", ptable.part_entry[i].name,
+				strlen(ptable.part_entry[i].name))) {
+			page_address = ptable.part_entry[i].offset << 6;
+			break;
+		}
+	}
 	data.cfg.cmd = MSM_NAND_CMD_PAGE_READ_ALL;
 	data.exec = 1;
 	data.cfg.addr0 = (page_address << 16) |
@@ -2338,6 +2375,75 @@
 
 }
 
+#ifdef CONFIG_MSM_SMD
+static int msm_nand_parse_smem_ptable(int *nr_parts)
+{
+
+	uint32_t  i, j;
+	uint32_t len = FLASH_PTABLE_HDR_LEN;
+	struct flash_partition_entry *pentry;
+	char *delimiter = ":";
+
+	pr_info("Parsing partition table info from SMEM\n");
+	/* Read only the header portion of ptable */
+	ptable = *(struct flash_partition_table *)
+			(smem_get_entry(SMEM_AARM_PARTITION_TABLE, &len));
+	/* Verify ptable magic */
+	if (ptable.magic1 != FLASH_PART_MAGIC1 ||
+			ptable.magic2 != FLASH_PART_MAGIC2) {
+		pr_err("Partition table magic verification failed\n");
+		goto out;
+	}
+	/* Ensure that # of partitions is less than the max we have allocated */
+	if (ptable.numparts > FLASH_PTABLE_MAX_PARTS_V4) {
+		pr_err("Partition numbers exceed the max limit\n");
+		goto out;
+	}
+	/* Find out length of partition data based on table version. */
+	if (ptable.version <= FLASH_PTABLE_V3) {
+		len = FLASH_PTABLE_HDR_LEN + FLASH_PTABLE_MAX_PARTS_V3 *
+			sizeof(struct flash_partition_entry);
+	} else if (ptable.version == FLASH_PTABLE_V4) {
+		len = FLASH_PTABLE_HDR_LEN + FLASH_PTABLE_MAX_PARTS_V4 *
+			sizeof(struct flash_partition_entry);
+	} else {
+		pr_err("Unknown ptable version (%d)", ptable.version);
+		goto out;
+	}
+
+	*nr_parts = ptable.numparts;
+	ptable = *(struct flash_partition_table *)
+			(smem_get_entry(SMEM_AARM_PARTITION_TABLE, &len));
+	for (i = 0; i < ptable.numparts; i++) {
+		pentry = &ptable.part_entry[i];
+		if (pentry->name == '\0')
+			continue;
+		/* Convert name to lower case and discard the initial chars */
+		mtd_part[i].name        = pentry->name;
+		for (j = 0; j < strlen(mtd_part[i].name); j++)
+			*(mtd_part[i].name + j) =
+				tolower(*(mtd_part[i].name + j));
+		strsep(&(mtd_part[i].name), delimiter);
+		mtd_part[i].offset      = pentry->offset;
+		mtd_part[i].mask_flags  = pentry->attr;
+		mtd_part[i].size        = pentry->length;
+		pr_debug("%d: %s offs=0x%08x size=0x%08x attr:0x%08x\n",
+			i, pentry->name, pentry->offset, pentry->length,
+			pentry->attr);
+	}
+	pr_info("SMEM partition table found: ver: %d len: %d\n",
+		ptable.version, ptable.numparts);
+	return 0;
+out:
+	return -EINVAL;
+}
+#else
+static int msm_nand_parse_smem_ptable(int *nr_parts)
+{
+	return -ENODEV;
+}
+#endif
+
 /*
  * This function gets called when its device named msm-nand is added to
  * device tree .dts file with all its resources such as physical addresses
@@ -2352,26 +2458,13 @@
 {
 	struct msm_nand_info *info;
 	struct resource *res;
-	int err;
-	struct device_node *pnode;
-	struct mtd_part_parser_data parser_data;
-
-	if (!pdev->dev.of_node) {
-		pr_err("No valid device tree info for NANDc\n");
-		err = -ENODEV;
-		goto out;
-	}
+	int i, err, nr_parts;
 
 	/*
 	 * The partition information can also be passed from kernel command
 	 * line. Also, the MTD core layer supports adding the whole device as
 	 * one MTD device when no partition information is available at all.
-	 * Hence, do not bail out when partition information is not availabe
-	 * in device tree.
 	 */
-	pnode = of_find_node_by_path("/qcom,mtd-partitions");
-	if (!pnode)
-		pr_info("No partition info available in device tree\n");
 	info = devm_kzalloc(&pdev->dev, sizeof(struct msm_nand_info),
 				GFP_KERNEL);
 	if (!info) {
@@ -2379,7 +2472,6 @@
 		err = -ENOMEM;
 		goto out;
 	}
-
 	res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
 						"nand_phys");
 	if (!res || !res->start) {
@@ -2438,14 +2530,22 @@
 		pr_err("Failed to enable DMA in NANDc\n");
 		goto free_bam;
 	}
+	err = msm_nand_parse_smem_ptable(&nr_parts);
+	if (err < 0) {
+		pr_err("Failed to parse partition table in SMEM\n");
+		goto free_bam;
+	}
 	if (msm_nand_scan(&info->mtd)) {
 		pr_err("No nand device found\n");
 		err = -ENXIO;
 		goto free_bam;
 	}
-	parser_data.of_node = pnode;
-	err = mtd_device_parse_register(&info->mtd, NULL, &parser_data,
-					NULL, 0);
+	for (i = 0; i < nr_parts; i++) {
+		mtd_part[i].offset *= info->mtd.erasesize;
+		mtd_part[i].size *= info->mtd.erasesize;
+	}
+	err = mtd_device_parse_register(&info->mtd, NULL, NULL,
+		&mtd_part[0], nr_parts);
 	if (err < 0) {
 		pr_err("Unable to register MTD partitions %d\n", err);
 		goto free_bam;
diff --git a/drivers/net/ethernet/msm/msm_rmnet_smux.c b/drivers/net/ethernet/msm/msm_rmnet_smux.c
index 7b27b73..5fe724e 100644
--- a/drivers/net/ethernet/msm/msm_rmnet_smux.c
+++ b/drivers/net/ethernet/msm/msm_rmnet_smux.c
@@ -804,7 +804,7 @@
 	for (i = 0; i < RMNET_SMUX_DEVICE_COUNT; i++) {
 		p = netdev_priv(netdevs[i]);
 
-		if ((p != NULL) && (p->device_state == DEVICE_INACTIVE)) {
+		if (p != NULL) {
 			r =  msm_smux_open(p->ch_id,
 					   netdevs[i],
 					   rmnet_smux_notify,
@@ -828,7 +828,7 @@
 	for (i = 0; i < RMNET_SMUX_DEVICE_COUNT; i++) {
 		p = netdev_priv(netdevs[i]);
 
-		if ((p != NULL) && (p->device_state == DEVICE_ACTIVE)) {
+		if (p != NULL) {
 			r =  msm_smux_close(p->ch_id);
 
 			if (r < 0) {
diff --git a/drivers/platform/msm/ipa/ipa_bridge.c b/drivers/platform/msm/ipa/ipa_bridge.c
index eeb98e9..dd00081 100644
--- a/drivers/platform/msm/ipa/ipa_bridge.c
+++ b/drivers/platform/msm/ipa/ipa_bridge.c
@@ -403,7 +403,7 @@
 		sys->connection.dest_pipe_index = ipa_ctx->a5_pipe_index++;
 		sys->connection.mode = SPS_MODE_SRC;
 		sys->connection.options = SPS_O_AUTO_ENABLE | SPS_O_EOT |
-		      SPS_O_ACK_TRANSFERS;
+		      SPS_O_ACK_TRANSFERS | SPS_O_NO_DISABLE;
 	}
 
 	sys->desc_mem_buf.size = props->desc_fifo_sz;
diff --git a/drivers/platform/msm/ipa/ipa_client.c b/drivers/platform/msm/ipa/ipa_client.c
index a4b7e22..f2f80bf 100644
--- a/drivers/platform/msm/ipa/ipa_client.c
+++ b/drivers/platform/msm/ipa/ipa_client.c
@@ -33,17 +33,56 @@
 
 static int ipa_disable_data_path(u32 clnt_hdl)
 {
+	DECLARE_COMPLETION_ONSTACK(tag_rsp);
+	struct ipa_desc desc = {0};
+	struct ipa_ip_packet_tag cmd;
 	struct ipa_ep_context *ep = &ipa_ctx->ep[clnt_hdl];
+	struct ipa_tree_node *node;
+	int result = 0;
 
 	if (ipa_ctx->ipa_hw_mode == IPA_HW_MODE_VIRTUAL) {
 		/* IPA_HW_MODE_VIRTUAL lacks support for TAG IC & EP suspend */
 		return 0;
 	}
 
+	node = kmem_cache_zalloc(ipa_ctx->tree_node_cache, GFP_KERNEL);
+	if (!node) {
+		IPAERR("failed to alloc tree node object\n");
+		result = -ENOMEM;
+		goto fail_alloc;
+	}
+
 	if (ipa_ctx->ipa_hw_type == IPA_HW_v1_1 && !ep->suspended) {
 		ipa_write_reg(ipa_ctx->mmio,
 				IPA_ENDP_INIT_CTRL_n_OFST(clnt_hdl), 1);
 
+		cmd.tag = (u32) &tag_rsp;
+
+		desc.pyld = &cmd;
+		desc.len = sizeof(struct ipa_ip_packet_tag);
+		desc.type = IPA_IMM_CMD_DESC;
+		desc.opcode = IPA_IP_PACKET_TAG;
+
+		IPADBG("Wait on TAG %p clnt=%d\n", &tag_rsp, clnt_hdl);
+
+		node->hdl = cmd.tag;
+		mutex_lock(&ipa_ctx->lock);
+		if (ipa_insert(&ipa_ctx->tag_tree, node)) {
+			IPAERR("failed to add to tree\n");
+			result = -EINVAL;
+			mutex_unlock(&ipa_ctx->lock);
+			goto fail_insert;
+		}
+		mutex_unlock(&ipa_ctx->lock);
+
+		if (ipa_send_cmd(1, &desc)) {
+			ipa_write_reg(ipa_ctx->mmio,
+				IPA_ENDP_INIT_CTRL_n_OFST(clnt_hdl), 0);
+			IPAERR("fail to send TAG command\n");
+			result = -EPERM;
+			goto fail_send;
+		}
+		wait_for_completion(&tag_rsp);
 		if (IPA_CLIENT_IS_CONS(ep->client) &&
 				ep->cfg.aggr.aggr_en == IPA_ENABLE_AGGR &&
 				ep->cfg.aggr.aggr_time_limit)
@@ -52,6 +91,13 @@
 	}
 
 	return 0;
+
+fail_send:
+	rb_erase(&node->node, &ipa_ctx->tag_tree);
+fail_insert:
+	kmem_cache_free(ipa_ctx->tree_node_cache, node);
+fail_alloc:
+	return result;
 }
 
 static int ipa_connect_configure_sps(const struct ipa_connect_params *in,
@@ -238,6 +284,9 @@
 	ep->connect.event_thresh = IPA_EVENT_THRESHOLD;
 	ep->connect.options = SPS_O_AUTO_ENABLE;    /* BAM-to-BAM */
 
+	if (IPA_CLIENT_IS_CONS(in->client))
+		ep->connect.options |= SPS_O_NO_DISABLE;
+
 	result = sps_connect(ep->ep_hdl, &ep->connect);
 	if (result) {
 		IPAERR("sps_connect fails.\n");
diff --git a/drivers/platform/msm/ipa/ipa_dp.c b/drivers/platform/msm/ipa/ipa_dp.c
index bd1da2c..5f7f3d9 100644
--- a/drivers/platform/msm/ipa/ipa_dp.c
+++ b/drivers/platform/msm/ipa/ipa_dp.c
@@ -259,7 +259,7 @@
 	if (unlikely(!in_atomic))
 		mem_flag = GFP_KERNEL;
 
-	transfer.iovec = dma_alloc_coherent(NULL, size, &dma_addr, 0);
+	transfer.iovec = dma_alloc_coherent(NULL, size, &dma_addr, mem_flag);
 	transfer.iovec_phys = dma_addr;
 	transfer.iovec_count = num_desc;
 	spin_lock_irqsave(&sys->spinlock, irq_flags);
@@ -528,6 +528,8 @@
 	struct ipa_sys_context *sys = &ipa_ctx->sys[IPA_A5_LAN_WAN_IN];
 	struct ipa_ep_context *ep;
 	int cnt = 0;
+	struct completion *compl;
+	struct ipa_tree_node *node;
 	unsigned int src_pipe;
 
 	while ((in_poll_state ? atomic_read(&ipa_ctx->curr_polling_state) :
@@ -582,6 +584,35 @@
 		IPA_STATS_INC_CNT(ipa_ctx->stats.rx_pkts);
 		IPA_STATS_EXCP_CNT(mux_hdr->flags, ipa_ctx->stats.rx_excp_pkts);
 
+		if (unlikely(mux_hdr->flags & IPA_A5_MUX_HDR_EXCP_FLAG_TAG)) {
+			if (ipa_ctx->ipa_hw_mode != IPA_HW_MODE_VIRTUAL) {
+				/* retrieve the compl object from tag value */
+				mux_hdr++;
+				compl = (struct completion *)
+					ntohl(*((u32 *)mux_hdr));
+				IPADBG("%x %x %p\n", *(u32 *)mux_hdr,
+						*((u32 *)mux_hdr + 1), compl);
+
+				mutex_lock(&ipa_ctx->lock);
+				node = ipa_search(&ipa_ctx->tag_tree,
+						(u32)compl);
+				if (node) {
+					complete_all(compl);
+					rb_erase(&node->node,
+							&ipa_ctx->tag_tree);
+					kmem_cache_free(
+						ipa_ctx->tree_node_cache, node);
+				} else {
+					WARN_ON(1);
+				}
+				mutex_unlock(&ipa_ctx->lock);
+			}
+			dev_kfree_skb(rx_skb);
+			ipa_replenish_rx_cache();
+			++cnt;
+			continue;
+		}
+
 		/*
 		 * Any packets arriving over AMPDU_TX should be dispatched
 		 * to the regular WLAN RX data-path.
@@ -791,7 +822,8 @@
 			ipa_ctx->a5_pipe_index++;
 		ipa_ctx->ep[ipa_ep_idx].connect.src_pipe_index = ipa_ep_idx;
 		ipa_ctx->ep[ipa_ep_idx].connect.options =
-			SPS_O_AUTO_ENABLE | SPS_O_EOT | SPS_O_ACK_TRANSFERS;
+			SPS_O_AUTO_ENABLE | SPS_O_EOT | SPS_O_ACK_TRANSFERS |
+			SPS_O_NO_DISABLE;
 		if (ipa_ctx->polling_mode)
 			ipa_ctx->ep[ipa_ep_idx].connect.options |= SPS_O_POLL;
 	} else {
@@ -943,7 +975,6 @@
 
 static void ipa_tx_cmd_comp(void *user1, void *user2)
 {
-	IPA_STATS_INC_CNT(ipa_ctx->stats.imm_cmds[IPA_IP_PACKET_INIT]);
 	kfree(user1);
 }
 
@@ -1022,6 +1053,7 @@
 			IPAERR("fail to send immediate command\n");
 			goto fail_send;
 		}
+		IPA_STATS_INC_CNT(ipa_ctx->stats.imm_cmds[IPA_IP_PACKET_INIT]);
 	} else if (dst == IPA_CLIENT_A5_WLAN_AMPDU_PROD) {
 		desc[0].pyld = skb->data;
 		desc[0].len = skb->len;
diff --git a/drivers/platform/msm/sps/sps_bam.c b/drivers/platform/msm/sps/sps_bam.c
index 31d1a78..3ebb1cd 100644
--- a/drivers/platform/msm/sps/sps_bam.c
+++ b/drivers/platform/msm/sps/sps_bam.c
@@ -827,9 +827,14 @@
 	}
 
 	if (bam_pipe_is_enabled(dev->base, pipe_index)) {
-		SPS_ERR("sps:BAM 0x%x pipe %d sharing violation",
-			BAM_ID(dev), pipe_index);
-		return SPS_ERROR;
+		if (params->options & SPS_O_NO_DISABLE)
+			SPS_DBG("sps:BAM 0x%x pipe %d is already enabled\n",
+				BAM_ID(dev), pipe_index);
+		else {
+			SPS_ERR("sps:BAM 0x%x pipe %d sharing violation\n",
+				BAM_ID(dev), pipe_index);
+			return SPS_ERROR;
+		}
 	}
 
 	if (bam_pipe_init(dev->base, pipe_index, &hw_params, dev->props.ee)) {
@@ -882,8 +887,13 @@
 	bam_pipe->state |= BAM_STATE_INIT;
 	result = 0;
 exit_err:
-	if (result)
-		bam_pipe_exit(dev->base, pipe_index, dev->props.ee);
+	if (result) {
+		if (params->options & SPS_O_NO_DISABLE)
+			SPS_DBG("sps:BAM 0x%x pipe %d connection exits\n",
+				BAM_ID(dev), pipe_index);
+		else
+			bam_pipe_exit(dev->base, pipe_index, dev->props.ee);
+	}
 exit_init_err:
 	if (result) {
 		/* Clear the client pipe state */
@@ -916,7 +926,11 @@
 			dev->pipe_active_mask &= ~(1UL << pipe_index);
 		}
 		dev->pipe_remote_mask &= ~(1UL << pipe_index);
-		bam_pipe_exit(dev->base, pipe_index, dev->props.ee);
+		if (pipe->connect.options & SPS_O_NO_DISABLE)
+			SPS_DBG("sps:BAM 0x%x pipe %d exits\n", BAM_ID(dev),
+				pipe_index);
+		else
+			bam_pipe_exit(dev->base, pipe_index, dev->props.ee);
 		if (pipe->sys.desc_cache != NULL) {
 			u32 size = pipe->num_descs * sizeof(void *);
 			if (pipe->desc_size + size <= PAGE_SIZE)
@@ -1114,7 +1128,12 @@
 	struct sps_pipe *pipe = dev->pipes[pipe_index];
 
 	/* Disable the BAM pipe */
-	bam_pipe_disable(dev->base, pipe_index);
+	if (pipe->connect.options & SPS_O_NO_DISABLE)
+		SPS_DBG("sps:BAM 0x%x pipe %d enters disable state\n",
+			BAM_ID(dev), pipe_index);
+	else
+		bam_pipe_disable(dev->base, pipe_index);
+
 	pipe->state &= ~BAM_STATE_ENABLED;
 
 	return 0;
diff --git a/drivers/platform/msm/usb_bam.c b/drivers/platform/msm/usb_bam.c
index a5fac9e..1d0fb5d 100644
--- a/drivers/platform/msm/usb_bam.c
+++ b/drivers/platform/msm/usb_bam.c
@@ -177,8 +177,8 @@
 		*usb_pipe_idx = pipe_connect->dst_pipe_index;
 	}
 
-	/* If BAM is using dedicated SPS pipe memory, get it */
-	if (pipe_connect->mem_type == SPS_PIPE_MEM) {
+	switch (pipe_connect->mem_type) {
+	case SPS_PIPE_MEM:
 		pr_debug("%s: USB BAM using SPS pipe memory\n", __func__);
 		ret = sps_setup_bam2bam_fifo(
 			data_buf,
@@ -199,7 +199,8 @@
 				ret);
 			goto free_sps_endpoint;
 		}
-	} else if (pipe_connect->mem_type == USB_PRIVATE_MEM) {
+		break;
+	case USB_PRIVATE_MEM:
 		pr_debug("%s: USB BAM using private memory\n", __func__);
 
 		if (IS_ERR(ctx.mem_clk) || IS_ERR(ctx.mem_iface_clk)) {
@@ -227,10 +228,12 @@
 
 		pr_debug("Writing 0x%x to QSCRATCH_RAM1\n", ram1_value);
 		writel_relaxed(ram1_value, ctx.qscratch_ram1_reg);
-
+		/* fall through */
+	case OCI_MEM:
+		pr_debug("%s: USB BAM using oci memory\n", __func__);
 		data_buf->phys_base =
 			pipe_connect->data_fifo_base_offset +
-				pdata->usb_base_address;
+				pdata->usb_bam_fifo_baseaddr;
 		data_buf->size = pipe_connect->data_fifo_size;
 		data_buf->base =
 			ioremap(data_buf->phys_base, data_buf->size);
@@ -238,12 +241,13 @@
 
 		desc_buf->phys_base =
 			pipe_connect->desc_fifo_base_offset +
-				pdata->usb_base_address;
+				pdata->usb_bam_fifo_baseaddr;
 		desc_buf->size = pipe_connect->desc_fifo_size;
 		desc_buf->base =
 			ioremap(desc_buf->phys_base, desc_buf->size);
 		memset(desc_buf->base, 0, desc_buf->size);
-	} else {
+		break;
+	case SYSTEM_MEM:
 		pr_debug("%s: USB BAM using system memory\n", __func__);
 		/* BAM would use system memory, allocate FIFOs */
 		data_buf->size = pipe_connect->data_fifo_size;
@@ -261,6 +265,10 @@
 			&(desc_buf->phys_base),
 			0);
 		memset(desc_buf->base, 0, pipe_connect->desc_fifo_size);
+		break;
+	default:
+		pr_err("%s: invalid mem type\n", __func__);
+		goto free_sps_endpoint;
 	}
 
 	sps_connection->data = *data_buf;
@@ -436,7 +444,8 @@
 	sps_disconnect(pipe);
 	sps_free_endpoint(pipe);
 
-	if (pipe_connect->mem_type == SYSTEM_MEM) {
+	switch (pipe_connect->mem_type) {
+	case SYSTEM_MEM:
 		pr_debug("%s: Freeing system memory used by PIPE\n", __func__);
 		if (sps_connection->data.phys_base)
 			dma_free_coherent(&ctx.usb_bam_pdev->dev,
@@ -448,13 +457,20 @@
 					sps_connection->desc.size,
 					sps_connection->desc.base,
 					sps_connection->desc.phys_base);
-	} else if (pipe_connect->mem_type == USB_PRIVATE_MEM) {
-		pr_debug("Freeing USB private memory used by BAM PIPE\n");
+		break;
+	case USB_PRIVATE_MEM:
+		pr_debug("Freeing private memory used by BAM PIPE\n");
 		writel_relaxed(0x0, ctx.qscratch_ram1_reg);
-		iounmap(sps_connection->data.base);
-		iounmap(sps_connection->desc.base);
 		clk_disable_unprepare(ctx.mem_clk);
 		clk_disable_unprepare(ctx.mem_iface_clk);
+	case OCI_MEM:
+		pr_debug("Freeing oci memory used by BAM PIPE\n");
+		iounmap(sps_connection->data.base);
+		iounmap(sps_connection->desc.base);
+		break;
+	case SPS_PIPE_MEM:
+		pr_debug("%s: nothing to be be\n", __func__);
+		break;
 	}
 
 	sps_connection->options &= ~SPS_O_AUTO_ENABLE;
@@ -973,8 +989,8 @@
 		return NULL;
 	}
 
-	rc = of_property_read_u32(node, "qcom,usb-base-address",
-		&pdata->usb_base_address);
+	rc = of_property_read_u32(node, "qcom,usb-bam-fifo-baseaddr",
+		&pdata->usb_bam_fifo_baseaddr);
 	if (rc)
 		pr_debug("%s: Invalid usb base address property\n", __func__);
 
@@ -1012,11 +1028,13 @@
 		if (rc)
 			goto err;
 
-		if (usb_bam_connections[i].mem_type == USB_PRIVATE_MEM &&
-			!pdata->usb_base_address) {
-			pr_err("%s: base address is missing for private mem\n",
-				__func__);
-			goto err;
+		if (usb_bam_connections[i].mem_type == USB_PRIVATE_MEM ||
+				usb_bam_connections[i].mem_type == OCI_MEM) {
+			if (!pdata->usb_bam_fifo_baseaddr) {
+				pr_err("%s: base address is missing\n",
+					__func__);
+				goto err;
+			}
 		}
 
 		rc = of_property_read_u32(node, "qcom,bam-type",
@@ -1148,6 +1166,7 @@
 			goto free_bam_regs;
 		}
 	}
+
 	props.phys_addr = res->start;
 	props.virt_addr = usb_virt_addr;
 	props.virt_size = resource_size(res);
diff --git a/drivers/power/pm8xxx-ccadc.c b/drivers/power/pm8xxx-ccadc.c
index 7e37daa..5313593 100644
--- a/drivers/power/pm8xxx-ccadc.c
+++ b/drivers/power/pm8xxx-ccadc.c
@@ -81,6 +81,7 @@
 	int			r_sense_uohm;
 	struct delayed_work	calib_ccadc_work;
 	struct mutex		calib_mutex;
+	bool			periodic_wakeup;
 };
 
 static struct pm8xxx_ccadc_chip *the_chip;
@@ -367,7 +368,7 @@
 	return 0;
 }
 
-void pm8xxx_calib_ccadc(void)
+static void __pm8xxx_calib_ccadc(int sample_count)
 {
 	u8 data_msb, data_lsb, sec_cntrl;
 	int result_offset, result_gain;
@@ -379,6 +380,8 @@
 		return;
 	}
 
+	pr_debug("sample_count = %d\n", sample_count);
+
 	mutex_lock(&the_chip->calib_mutex);
 	rc = pm8xxx_readb(the_chip->dev->parent,
 					ADC_ARB_SECP_CNTRL, &sec_cntrl);
@@ -405,7 +408,7 @@
 	}
 
 	result_offset = 0;
-	for (i = 0; i < SAMPLE_COUNT; i++) {
+	for (i = 0; i < sample_count; i++) {
 		/* Short analog inputs to CCADC internally to ground */
 		rc = pm8xxx_writeb(the_chip->dev->parent, ADC_ARB_SECP_RSV,
 							CCADC_CALIB_RSV_GND);
@@ -431,7 +434,7 @@
 		result_offset += result;
 	}
 
-	result_offset = result_offset / SAMPLE_COUNT;
+	result_offset = result_offset / sample_count;
 
 
 	pr_debug("offset result_offset = 0x%x, voltage = %llduV\n",
@@ -470,7 +473,7 @@
 	}
 
 	result_gain = 0;
-	for (i = 0; i < SAMPLE_COUNT; i++) {
+	for (i = 0; i < sample_count; i++) {
 		rc = pm8xxx_writeb(the_chip->dev->parent,
 					ADC_ARB_SECP_RSV, CCADC_CALIB_RSV_25MV);
 		if (rc < 0) {
@@ -494,7 +497,7 @@
 
 		result_gain += result;
 	}
-	result_gain = result_gain / SAMPLE_COUNT;
+	result_gain = result_gain / sample_count;
 
 	/*
 	 * result_offset includes INTRINSIC OFFSET
@@ -519,6 +522,16 @@
 calibration_unlock:
 	mutex_unlock(&the_chip->calib_mutex);
 }
+
+static void pm8xxx_calib_ccadc_quick(void)
+{
+	__pm8xxx_calib_ccadc(2);
+}
+
+void pm8xxx_calib_ccadc(void)
+{
+	__pm8xxx_calib_ccadc(SAMPLE_COUNT);
+}
 EXPORT_SYMBOL(pm8xxx_calib_ccadc);
 
 static void calibrate_ccadc_work(struct work_struct *work)
@@ -737,6 +750,7 @@
 	chip->r_sense_uohm = pdata->r_sense_uohm;
 	chip->calib_delay_ms = pdata->calib_delay_ms;
 	chip->batt_temp_channel = pdata->ccadc_cdata.batt_temp_channel;
+	chip->periodic_wakeup = pdata->periodic_wakeup;
 	mutex_init(&chip->calib_mutex);
 
 	calib_ccadc_read_offset_and_gain(chip,
@@ -793,6 +807,12 @@
 		pr_err("unable to get current time: %d\n", rc);
 		return 0;
 	}
+
+	if (the_chip->periodic_wakeup) {
+		pm8xxx_calib_ccadc_quick();
+		return 0;
+	}
+
 	if (current_time_sec > the_chip->last_calib_time) {
 		time_since_last_calib = current_time_sec -
 					the_chip->last_calib_time;
@@ -803,9 +823,11 @@
 				|| delta_temp > CCADC_CALIB_TEMP_THRESH) {
 			the_chip->last_calib_time = current_time_sec;
 			the_chip->last_calib_temp = batt_temp;
-			pm8xxx_calib_ccadc();
+			cancel_delayed_work(&the_chip->calib_ccadc_work);
+			schedule_delayed_work(&the_chip->calib_ccadc_work, 0);
 		}
 	}
+
 	return 0;
 }
 
diff --git a/drivers/power/qpnp-bms.c b/drivers/power/qpnp-bms.c
index cb5be3d..210964e 100644
--- a/drivers/power/qpnp-bms.c
+++ b/drivers/power/qpnp-bms.c
@@ -71,9 +71,9 @@
 #define BMS1_VBAT_AVG_DATA0		0x9E
 #define BMS1_VBAT_AVG_DATA1		0x9F
 /* Extra bms registers */
-#define BMS1_BMS_DATA_REG_0		0xB0
+#define SOC_STORAGE_REG			0xB0
 #define IAVG_STORAGE_REG		0xB1
-#define SOC_STORAGE_REG			0xB2
+#define BMS1_BMS_DATA_REG_2		0xB2
 #define BMS1_BMS_DATA_REG_3		0xB3
 /* IADC Channel Select */
 #define IADC1_BMS_ADC_CH_SEL_CTL	0x48
@@ -83,7 +83,7 @@
 #define IAVG_STEP_SIZE_MA		50
 #define IAVG_START			600
 #define IAVG_INVALID			0xFF
-#define SOC_ZERO			0xFF
+#define SOC_INVALID			0xFF
 
 #define IAVG_SAMPLES 16
 
@@ -135,6 +135,7 @@
 	struct sf_lut			*pc_sf_lut;
 	struct sf_lut			*rbatt_sf_lut;
 	int				default_rbatt_mohm;
+	int				rbatt_capacitive_mohm;
 
 	struct delayed_work		calculate_soc_delayed_work;
 	struct work_struct		recalc_work;
@@ -184,7 +185,6 @@
 	unsigned int			vadc_v1250;
 
 	int				ibat_max_ua;
-	int				prev_iavg_ua;
 	int				prev_uuc_iavg_ma;
 	int				prev_pc_unusable;
 	int				ibat_at_cv_ua;
@@ -194,6 +194,8 @@
 	int				prev_voltage_based_soc;
 	bool				use_voltage_soc;
 
+	int				prev_batt_terminal_uv;
+
 	int				ocv_high_threshold_uv;
 	int				ocv_low_threshold_uv;
 	unsigned long			last_recalc_time;
@@ -624,7 +626,8 @@
 {
 	int ibat_ua, vbat_uv, ocv_est_uv;
 	int rc;
-	int rbatt_mohm = chip->default_rbatt_mohm + chip->r_conn_mohm;
+	int rbatt_mohm = chip->default_rbatt_mohm + chip->r_conn_mohm
+					+ chip->rbatt_capacitive_mohm;
 
 	rc = get_simultaneous_batt_v_and_i(chip, &ibat_ua, &vbat_uv);
 	if (rc) {
@@ -650,6 +653,7 @@
 	chip->last_cc_uah = INT_MIN;
 	chip->last_ocv_temp = batt_temp;
 	chip->last_soc_invalid = true;
+	chip->prev_batt_terminal_uv = 0;
 }
 
 #define OCV_RAW_UNINITIALIZED	0xFFFF
@@ -844,38 +848,35 @@
 	rbatt_mohm += chip->r_conn_mohm;
 	pr_debug("adding r_conn_mohm = %d rbatt = %d\n",
 				chip->r_conn_mohm, rbatt_mohm);
+	rbatt_mohm += chip->rbatt_capacitive_mohm;
+	pr_debug("adding rbatt_capacitive_mohm = %d rbatt = %d\n",
+				chip->rbatt_capacitive_mohm, rbatt_mohm);
 
 	pr_debug("RBATT = %d\n", rbatt_mohm);
 	return rbatt_mohm;
 }
 
+#define IAVG_MINIMAL_TIME	2
 static void calculate_iavg(struct qpnp_bms_chip *chip, int cc_uah,
 				int *iavg_ua, int delta_time_s)
 {
 	int delta_cc_uah = 0;
 
-	/* if anything fails report the previous iavg_ua */
-	*iavg_ua = chip->prev_iavg_ua;
-
-	if (chip->last_cc_uah == INT_MIN) {
+	/*
+	 * use the battery current if called too quickly
+	 */
+	if (delta_time_s < IAVG_MINIMAL_TIME
+			|| chip->last_cc_uah == INT_MIN) {
 		get_battery_current(chip, iavg_ua);
 		goto out;
 	}
 
-	/* use the previous iavg if called within 15 seconds */
-	if (delta_time_s < 15) {
-		*iavg_ua = chip->prev_iavg_ua;
-		goto out;
-	}
-
 	delta_cc_uah = cc_uah - chip->last_cc_uah;
 
 	*iavg_ua = div_s64((s64)delta_cc_uah * 3600, delta_time_s);
 
 out:
 	pr_debug("delta_cc = %d iavg_ua = %d\n", delta_cc_uah, (int)*iavg_ua);
-	/* remember the iavg */
-	chip->prev_iavg_ua = *iavg_ua;
 
 	/* remember cc_uah */
 	chip->last_cc_uah = cc_uah;
@@ -1228,6 +1229,10 @@
 
 	rc = get_simultaneous_batt_v_and_i(chip, &ibat_ua, &vbat_uv);
 
+	/*
+	 * Don't include rbatt and rbatt_capacitative since we expect this to
+	 * be used with a fake battery which does not have internal resistances
+	 */
 	ocv_est_uv = vbat_uv + (ibat_ua * chip->r_conn_mohm) / 1000;
 	pr_debug("forcing ocv to be %d due to bms reset mode\n", ocv_est_uv);
 	chip->last_ocv_uv = ocv_est_uv;
@@ -1294,11 +1299,13 @@
 			pr_debug("CC_TO_CV ibat_ua = %d CHG SOC %d\n",
 					ibat_ua, soc);
 		}
+
+		chip->prev_batt_terminal_uv = batt_terminal_uv;
 		return soc;
 	}
 
 	/*
-	 * battery is in CV phase - begin liner inerpolation of soc based on
+	 * battery is in CV phase - begin linear interpolation of soc based on
 	 * battery charge current
 	 */
 
@@ -1306,10 +1313,11 @@
 	 * if voltage lessened (possibly because of a system load)
 	 * keep reporting the prev chg soc
 	 */
-	if (batt_terminal_uv <= chip->max_voltage_uv - 10000) {
+	if (batt_terminal_uv <= chip->prev_batt_terminal_uv) {
 		pr_debug("batt_terminal_uv %d < (max = %d - 10000); CC CHG SOC %d\n",
-			batt_terminal_uv,
-			chip->max_voltage_uv, chip->prev_chg_soc);
+			batt_terminal_uv, chip->prev_batt_terminal_uv,
+			chip->prev_chg_soc);
+		chip->prev_batt_terminal_uv = batt_terminal_uv;
 		return chip->prev_chg_soc;
 	}
 
@@ -1332,6 +1340,7 @@
 	}
 
 	pr_debug("Reporting CHG SOC %d\n", chip->prev_chg_soc);
+	chip->prev_batt_terminal_uv = batt_terminal_uv;
 	return chip->prev_chg_soc;
 }
 
@@ -1734,10 +1743,7 @@
 	rc = qpnp_write_wrapper(chip, &temp,
 			chip->base + IAVG_STORAGE_REG, 1);
 
-	if (soc == 0)
-		temp = SOC_ZERO;
-	else
-		temp = soc;
+	temp = soc;
 
 	/* don't store soc if temperature is below 5degC */
 	if (batt_temp > IGNORE_SOC_TEMP_DECIDEG)
@@ -2069,12 +2075,10 @@
 		} else {
 			chip->shutdown_soc = temp;
 
-			if (chip->shutdown_soc == 0) {
+			if (chip->shutdown_soc == SOC_INVALID) {
 				pr_debug("No shutdown soc available\n");
 				chip->shutdown_soc_invalid = true;
 				chip->shutdown_iavg_ma = 0;
-			} else if (chip->shutdown_soc == SOC_ZERO) {
-				chip->shutdown_soc = 0;
 			}
 		}
 	}
@@ -2145,6 +2149,7 @@
 	chip->pc_sf_lut = batt_data->pc_sf_lut;
 	chip->rbatt_sf_lut = batt_data->rbatt_sf_lut;
 	chip->default_rbatt_mohm = batt_data->default_rbatt_mohm;
+	chip->rbatt_capacitive_mohm = batt_data->rbatt_capacitive_mohm;
 
 	if (chip->pc_temp_ocv_lut == NULL) {
 		pr_err("temp ocv lut table is NULL\n");
diff --git a/drivers/power/qpnp-charger.c b/drivers/power/qpnp-charger.c
index b479477..f4efa756 100644
--- a/drivers/power/qpnp-charger.c
+++ b/drivers/power/qpnp-charger.c
@@ -24,6 +24,7 @@
 #include <linux/qpnp/qpnp-adc.h>
 #include <linux/power_supply.h>
 #include <linux/bitops.h>
+#include <linux/ratelimit.h>
 
 /* Interrupt offsets */
 #define INT_RT_STS(base)			(base + 0x10)
@@ -949,6 +950,7 @@
 get_prop_capacity(struct qpnp_chg_chip *chip)
 {
 	union power_supply_propval ret = {0,};
+	bool usb_online, dc_online;
 
 	if (chip->use_default_batt_values || !get_prop_batt_present(chip))
 		return DEFAULT_CAPACITY;
@@ -956,6 +958,14 @@
 	if (chip->bms_psy) {
 		chip->bms_psy->get_property(chip->bms_psy,
 			  POWER_SUPPLY_PROP_CAPACITY, &ret);
+		if (ret.intval == 0) {
+			usb_online = chip->usb_psy->get_property(chip->usb_psy,
+					  POWER_SUPPLY_PROP_ONLINE, &ret);
+			dc_online = chip->dc_psy.get_property(&chip->dc_psy,
+					  POWER_SUPPLY_PROP_ONLINE, &ret);
+			if (!usb_online && !dc_online)
+				pr_warn_ratelimited("Battery 0, CHG absent\n");
+		}
 		return ret.intval;
 	} else {
 		pr_debug("No BMS supply registered return 50\n");
diff --git a/drivers/staging/android/switch/switch_class.c b/drivers/staging/android/switch/switch_class.c
index 7468044..3852c2c 100644
--- a/drivers/staging/android/switch/switch_class.c
+++ b/drivers/staging/android/switch/switch_class.c
@@ -151,8 +151,8 @@
 {
 	device_remove_file(sdev->dev, &dev_attr_name);
 	device_remove_file(sdev->dev, &dev_attr_state);
-	device_destroy(switch_class, MKDEV(0, sdev->index));
 	dev_set_drvdata(sdev->dev, NULL);
+	device_destroy(switch_class, MKDEV(0, sdev->index));
 }
 EXPORT_SYMBOL_GPL(switch_dev_unregister);
 
diff --git a/drivers/thermal/msm8974-tsens.c b/drivers/thermal/msm8974-tsens.c
index f7e5eee..ee80975 100644
--- a/drivers/thermal/msm8974-tsens.c
+++ b/drivers/thermal/msm8974-tsens.c
@@ -280,10 +280,13 @@
 	num = ((adc_code * tmdev->tsens_factor) -
 				tmdev->sensor[sensor_num].offset);
 	den = (int) tmdev->sensor[sensor_num].slope_mul_tsens_factor;
-	degc = num/den;
 
-	if ((degc >= 0) && (num % den != 0))
-		degc++;
+	if (num > 0)
+		degc = ((num + (den/2))/den);
+	else if (num < 0)
+		degc = ((num - (den/2))/den);
+	else
+		degc = num/den;
 
 	return degc;
 }
@@ -344,6 +347,17 @@
 }
 EXPORT_SYMBOL(tsens_get_temp);
 
+int tsens_get_max_sensor_num(uint32_t *tsens_num_sensors)
+{
+	if (!tmdev)
+		return -ENODEV;
+
+	*tsens_num_sensors = tmdev->tsens_num_sensor;
+
+	return 0;
+}
+EXPORT_SYMBOL(tsens_get_max_sensor_num);
+
 static int tsens_tz_get_mode(struct thermal_zone_device *thermal,
 			      enum thermal_device_mode *mode)
 {
diff --git a/drivers/tty/serial/msm_serial_hs_lite.c b/drivers/tty/serial/msm_serial_hs_lite.c
index 8069b35..7aa14de 100644
--- a/drivers/tty/serial/msm_serial_hs_lite.c
+++ b/drivers/tty/serial/msm_serial_hs_lite.c
@@ -982,10 +982,6 @@
 			}
 		}
 	}
-#ifndef CONFIG_PM_RUNTIME
-	msm_hsl_init_clock(port);
-#endif
-	pm_runtime_get_sync(port->dev);
 
 	/*
 	 * Set RFR Level as 3/4 of UARTDM FIFO Size
@@ -1038,10 +1034,6 @@
 
 	free_irq(port->irq, port);
 
-#ifndef CONFIG_PM_RUNTIME
-	msm_hsl_deinit_clock(port);
-#endif
-	pm_runtime_put_sync(port->dev);
 	if (!(is_console(port)) || (!port->cons) ||
 		(port->cons && (!(port->cons->flags & CON_ENABLED)))) {
 		/* Free UART GPIOs */
@@ -1714,6 +1706,30 @@
 	port->uartclk = 7372800;
 	msm_hsl_port = UART_TO_MSM(port);
 
+	msm_hsl_port->clk = clk_get(&pdev->dev, "core_clk");
+	if (unlikely(IS_ERR(msm_hsl_port->clk))) {
+		ret = PTR_ERR(msm_hsl_port->clk);
+		if (ret != -EPROBE_DEFER)
+			pr_err("Error getting clk\n");
+		return ret;
+	}
+
+	/* Interface clock is not required by all UART configurations.
+	 * GSBI UART and BLSP UART needs interface clock but Legacy UART
+	 * do not require interface clock. Hence, do not fail probe with
+	 * iface clk_get failure.
+	 */
+	msm_hsl_port->pclk = clk_get(&pdev->dev, "iface_clk");
+	if (unlikely(IS_ERR(msm_hsl_port->pclk))) {
+		ret = PTR_ERR(msm_hsl_port->pclk);
+		if (ret == -EPROBE_DEFER) {
+			clk_put(msm_hsl_port->clk);
+			return ret;
+		} else {
+			msm_hsl_port->pclk = NULL;
+		}
+	}
+
 	/* Identify UART functional mode as 2-wire or 4-wire. */
 	if (pdata && pdata->config_gpio == 4)
 		msm_hsl_port->func_mode = UART_FOUR_WIRE;
@@ -1751,22 +1767,12 @@
 						     "gsbi_resource");
 	if (!gsbi_resource)
 		gsbi_resource = platform_get_resource(pdev, IORESOURCE_MEM, 1);
-	msm_hsl_port->clk = clk_get(&pdev->dev, "core_clk");
-	msm_hsl_port->pclk = clk_get(&pdev->dev, "iface_clk");
 
 	if (gsbi_resource)
 		msm_hsl_port->uart_type = GSBI_HSUART;
 	else
 		msm_hsl_port->uart_type = LEGACY_HSUART;
 
-	if (unlikely(IS_ERR(msm_hsl_port->clk))) {
-		pr_err("Error getting clk\n");
-		return PTR_ERR(msm_hsl_port->clk);
-	}
-	if (unlikely(IS_ERR(msm_hsl_port->pclk))) {
-		pr_err("Error getting pclk\n");
-		return PTR_ERR(msm_hsl_port->pclk);
-	}
 
 	uart_resource = platform_get_resource_byname(pdev,
 						     IORESOURCE_MEM,
diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c
index f9a26cf..6619e96 100644
--- a/drivers/usb/dwc3/core.c
+++ b/drivers/usb/dwc3/core.c
@@ -461,6 +461,7 @@
 
 #define DWC3_ALIGN_MASK		(16 - 1)
 
+static u64 dwc3_dma_mask = DMA_BIT_MASK(64);
 static int __devinit dwc3_probe(struct platform_device *pdev)
 {
 	struct device_node	*node = pdev->dev.of_node;
@@ -483,6 +484,11 @@
 	dwc = PTR_ALIGN(mem, DWC3_ALIGN_MASK + 1);
 	dwc->mem = mem;
 
+	if (!dev->dma_mask)
+		dev->dma_mask = &dwc3_dma_mask;
+	if (!dev->coherent_dma_mask)
+		dev->coherent_dma_mask = DMA_BIT_MASK(32);
+
 	res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
 	if (!res) {
 		dev_err(dev, "missing IRQ\n");
diff --git a/drivers/usb/dwc3/dwc3-msm.c b/drivers/usb/dwc3/dwc3-msm.c
index 9fad90c..435ef3b 100644
--- a/drivers/usb/dwc3/dwc3-msm.c
+++ b/drivers/usb/dwc3/dwc3-msm.c
@@ -26,6 +26,7 @@
 #include <linux/types.h>
 #include <linux/delay.h>
 #include <linux/of.h>
+#include <linux/of_platform.h>
 #include <linux/list.h>
 #include <linux/debugfs.h>
 #include <linux/uaccess.h>
@@ -63,6 +64,11 @@
 module_param(override_phy_init, int, S_IRUGO|S_IWUSR);
 MODULE_PARM_DESC(override_phy_init, "Override HSPHY Init Seq");
 
+/* Enable Proprietary charger detection */
+static bool prop_chg_detect;
+module_param(prop_chg_detect, bool, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(prop_chg_detect, "Enable Proprietary charger detection");
+
 /**
  *  USB DBM Hardware registers.
  *
@@ -152,7 +158,6 @@
 };
 
 struct dwc3_msm {
-	struct platform_device *dwc3;
 	struct device *dev;
 	void __iomem *base;
 	u32 resource_size;
@@ -220,7 +225,6 @@
 #define USB_SSPHY_1P8_HPM_LOAD		23000	/* uA */
 
 static struct dwc3_msm *context;
-static u64 dwc3_msm_dma_mask = DMA_BIT_MASK(64);
 
 static struct usb_ext_notification *usb_ext;
 
@@ -1391,12 +1395,12 @@
 static bool dwc3_chg_det_check_linestate(struct dwc3_msm *mdwc)
 {
 	u32 chg_det;
-	bool ret = false;
+
+	if (!prop_chg_detect)
+		return false;
 
 	chg_det = dwc3_msm_read_reg(mdwc->base, CHARGING_DET_OUTPUT_REG);
-	ret = chg_det & (3 << 8);
-
-	return ret;
+	return chg_det & (3 << 8);
 }
 
 static bool dwc3_chg_det_check_output(struct dwc3_msm *mdwc)
@@ -2214,10 +2218,10 @@
 static int __devinit dwc3_msm_probe(struct platform_device *pdev)
 {
 	struct device_node *node = pdev->dev.of_node;
-	struct platform_device *dwc3;
 	struct dwc3_msm *msm;
 	struct resource *res;
 	void __iomem *tcsr;
+	unsigned long flags;
 	int ret = 0;
 	int len = 0;
 	u32 tmp[3];
@@ -2430,6 +2434,11 @@
 					dev_err(&pdev->dev, "irqreq IDINT failed\n");
 					goto disable_hs_ldo;
 				}
+				local_irq_save(flags);
+				/* Update initial ID state */
+				msm->id_state = msm->ext_xceiv.id =
+					!!irq_read_line(msm->pmic_id_irq);
+				local_irq_restore(flags);
 				enable_irq_wake(msm->pmic_id_irq);
 			}
 		}
@@ -2476,19 +2485,7 @@
 		goto disable_hs_ldo;
 	}
 
-	dwc3 = platform_device_alloc("dwc3", -1);
-	if (!dwc3) {
-		dev_err(&pdev->dev, "couldn't allocate dwc3 device\n");
-		ret = -ENODEV;
-		goto disable_hs_ldo;
-	}
-
-	dwc3->dev.parent = &pdev->dev;
-	dwc3->dev.coherent_dma_mask = DMA_BIT_MASK(32);
-	dwc3->dev.dma_mask = &dwc3_msm_dma_mask;
-	dwc3->dev.dma_parms = pdev->dev.dma_parms;
 	msm->resource_size = resource_size(res);
-	msm->dwc3 = dwc3;
 
 	if (of_property_read_u32(node, "qcom,dwc-hsphy-init",
 						&msm->hsphy_init_seq))
@@ -2514,7 +2511,7 @@
 			"max: %d, dbm_num_eps: %d\n",
 			DBM_MAX_EPS, msm->dbm_num_eps);
 		ret = -ENODEV;
-		goto put_pdev;
+		goto disable_hs_ldo;
 	}
 
 	msm->usb_psy.name = "usb";
@@ -2534,20 +2531,16 @@
 		dev_err(&pdev->dev,
 				"%s:power_supply_register usb failed\n",
 					__func__);
-		goto put_pdev;
+		goto disable_hs_ldo;
 	}
 
-	ret = platform_device_add_resources(dwc3, pdev->resource,
-		pdev->num_resources);
-	if (ret) {
-		dev_err(&pdev->dev, "couldn't add resources to dwc3 device\n");
-		goto put_psupply;
-	}
-
-	ret = platform_device_add(dwc3);
-	if (ret) {
-		dev_err(&pdev->dev, "failed to register dwc3 device\n");
-		goto put_psupply;
+	if (node) {
+		ret = of_platform_populate(node, NULL, NULL, &pdev->dev);
+		if (ret) {
+			dev_err(&pdev->dev,
+				"failed to add create dwc3 core\n");
+			goto put_psupply;
+		}
 	}
 
 	msm->bus_scale_table = msm_bus_cl_get_pdata(pdev);
@@ -2592,11 +2585,8 @@
 
 put_xcvr:
 	usb_put_transceiver(msm->otg_xceiv);
-	platform_device_del(dwc3);
 put_psupply:
 	power_supply_unregister(&msm->usb_psy);
-put_pdev:
-	platform_device_put(dwc3);
 disable_hs_ldo:
 	dwc3_hsusb_ldo_enable(0);
 free_hs_ldo_init:
@@ -2647,7 +2637,6 @@
 	}
 
 	pm_runtime_disable(msm->dev);
-	platform_device_unregister(msm->dwc3);
 	wake_lock_destroy(&msm->wlock);
 
 	dwc3_hsusb_ldo_enable(0);
diff --git a/drivers/usb/dwc3/dwc3_otg.c b/drivers/usb/dwc3/dwc3_otg.c
index ca1f817..1d67cee 100644
--- a/drivers/usb/dwc3/dwc3_otg.c
+++ b/drivers/usb/dwc3/dwc3_otg.c
@@ -216,6 +216,8 @@
 						ext_xceiv->ext_block_reset)
 			ext_xceiv->ext_block_reset(true);
 
+		dwc3_otg_set_peripheral_regs(dotg);
+
 		/* re-init core and OTG registers as block reset clears these */
 		dwc3_post_host_reset_core_init(dwc);
 		if (ext_xceiv && !ext_xceiv->otg_capability)
diff --git a/drivers/usb/dwc3/ep0.c b/drivers/usb/dwc3/ep0.c
index a1d7a87..66854b2 100644
--- a/drivers/usb/dwc3/ep0.c
+++ b/drivers/usb/dwc3/ep0.c
@@ -756,6 +756,7 @@
 		dwc3_ep0_stall_and_restart(dwc);
 }
 
+bool zlp_required;
 static void dwc3_ep0_complete_data(struct dwc3 *dwc,
 		const struct dwc3_event_depevt *event)
 {
@@ -775,12 +776,18 @@
 
 	r = next_request(&ep0->request_list);
 	ur = &r->request;
+	if ((epnum & 1) && ur->zero &&
+		(ur->length % ep0->endpoint.maxpacket == 0)) {
+		zlp_required = true;
+		ur->zero = false;
+	}
 
 	trb = dwc->ep0_trb;
 
 	status = DWC3_TRB_SIZE_TRBSTS(trb->size);
 	if (status == DWC3_TRBSTS_SETUP_PENDING) {
 		dev_dbg(dwc->dev, "Setup Pending received\n");
+		zlp_required = false;
 
 		if (r)
 			dwc3_gadget_giveback(ep0, r, -ECONNRESET);
@@ -788,6 +795,9 @@
 		return;
 	}
 
+	if (zlp_required)
+		return;
+
 	length = trb->size & DWC3_TRB_SIZE_MASK;
 
 	if (dwc->ep0_bounced) {
@@ -930,6 +940,10 @@
 			return;
 		}
 
+		if (dep->number &&
+			!(req->request.length % dwc->gadget.ep0->maxpacket))
+			req->request.zero = true;
+
 		ret = dwc3_ep0_start_trans(dwc, dep->number, req->request.dma,
 				req->request.length, DWC3_TRBCTL_CONTROL_DATA);
 	}
@@ -993,7 +1007,11 @@
 static void dwc3_ep0_xfernotready(struct dwc3 *dwc,
 		const struct dwc3_event_depevt *event)
 {
+	u8			epnum;
+	int			ret;
+
 	dwc->setup_packet_pending = true;
+	epnum = event->endpoint_number;
 
 	switch (event->status) {
 	case DEPEVT_STATUS_CONTROL_DATA:
@@ -1017,6 +1035,15 @@
 			return;
 		}
 
+		if (zlp_required) {
+			zlp_required = false;
+			ret = dwc3_ep0_start_trans(dwc, epnum,
+					dwc->ctrl_req_addr, 0,
+					DWC3_TRBCTL_CONTROL_DATA);
+			dbg_event(epnum, "ZLP", ret);
+			WARN_ON(ret < 0);
+		}
+
 		break;
 
 	case DEPEVT_STATUS_CONTROL_STATUS:
@@ -1025,6 +1052,7 @@
 
 		dev_vdbg(dwc->dev, "Control Status\n");
 
+		zlp_required = false;
 		dwc->ep0state = EP0_STATUS_PHASE;
 
 		if (dwc->delayed_status &&
diff --git a/drivers/usb/gadget/f_uac1.c b/drivers/usb/gadget/f_uac1.c
index 8c74381..e8c9667 100644
--- a/drivers/usb/gadget/f_uac1.c
+++ b/drivers/usb/gadget/f_uac1.c
@@ -463,6 +463,8 @@
 	struct list_head		capture_queue;
 	struct usb_request		*capture_req;
 
+	u8				alt_intf[F_AUDIO_NUM_INTERFACES];
+
 	/* Control Set command */
 	struct list_head		fu_cs;
 	struct list_head		ep_cs;
@@ -881,6 +883,18 @@
 	return value;
 }
 
+static int f_audio_get_alt(struct usb_function *f, unsigned intf)
+{
+	struct f_audio	*audio = func_to_audio(f);
+
+	if (intf == ac_header_desc.baInterfaceNr[0])
+		return audio->alt_intf[0];
+	if (intf == ac_header_desc.baInterfaceNr[1])
+		return audio->alt_intf[1];
+
+	return 0;
+}
+
 static int f_audio_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
 {
 	struct f_audio		*audio = func_to_audio(f);
@@ -938,6 +952,7 @@
 			}
 			spin_unlock_irqrestore(&audio->capture_lock, flags);
 		}
+		audio->alt_intf[0] = alt;
 	} else if (intf == ac_header_desc.baInterfaceNr[1]) {
 		if (alt == 1) {
 			err = usb_ep_enable(out_ep);
@@ -986,10 +1001,12 @@
 				list_add_tail(&playback_copy_buf->list,
 						&audio->play_queue);
 				schedule_work(&audio->playback_work);
+				audio->playback_copy_buf = NULL;
 			} else {
 				pr_err("playback_buf is empty. Stop.");
 			}
 		}
+		audio->alt_intf[1] = alt;
 	} else {
 		pr_err("Interface %d. Do nothing. Return %d\n", intf, err);
 	}
@@ -1066,6 +1083,7 @@
 	microphone_as_interface_alt_0_desc.bInterfaceNumber = status;
 	microphone_as_interface_alt_1_desc.bInterfaceNumber = status;
 	ac_header_desc.baInterfaceNr[0] = status;
+	audio->alt_intf[0] = 0;
 
 	status = -ENODEV;
 
@@ -1077,6 +1095,7 @@
 	speaker_as_interface_alt_0_desc.bInterfaceNumber = status;
 	speaker_as_interface_alt_1_desc.bInterfaceNumber = status;
 	ac_header_desc.baInterfaceNr[1] = status;
+	audio->alt_intf[1] = 0;
 
 	status = -ENODEV;
 
@@ -1225,6 +1244,7 @@
 	audio->card.func.strings = audio_strings;
 	audio->card.func.bind = f_audio_bind;
 	audio->card.func.unbind = f_audio_unbind;
+	audio->card.func.get_alt = f_audio_get_alt;
 	audio->card.func.set_alt = f_audio_set_alt;
 	audio->card.func.setup = f_audio_setup;
 	audio->card.func.disable = f_audio_disable;
diff --git a/drivers/usb/gadget/u_rmnet_ctrl_smd.c b/drivers/usb/gadget/u_rmnet_ctrl_smd.c
index 5817779..161634e 100644
--- a/drivers/usb/gadget/u_rmnet_ctrl_smd.c
+++ b/drivers/usb/gadget/u_rmnet_ctrl_smd.c
@@ -408,6 +408,11 @@
 	struct platform_driver *pdrv;
 
 	c = &port->ctrl_ch;
+	if (c->ch) {
+		smd_close(c->ch);
+		c->ch = NULL;
+	}
+
 	if (test_bit(CH_READY, &c->flags) ||
 	    test_bit(CH_PREPARE_READY, &c->flags)) {
 		clear_bit(CH_PREPARE_READY, &c->flags);
@@ -422,6 +427,7 @@
 	unsigned long		flags;
 	struct smd_ch_info	*c;
 	struct rmnet_ctrl_pkt	*cpkt;
+	int clear_bits;
 
 	pr_debug("%s: grmnet:%p port#%d\n", __func__, gr, port_num);
 
@@ -453,13 +459,10 @@
 
 	spin_unlock_irqrestore(&port->port_lock, flags);
 
-	if (test_and_clear_bit(CH_OPENED, &c->flags))
+	if (test_and_clear_bit(CH_OPENED, &c->flags)) {
+		clear_bits = ~(c->cbits_tomodem | TIOCM_RTS);
 		/* send dtr zero */
-		smd_tiocmset(c->ch, c->cbits_tomodem, ~c->cbits_tomodem);
-
-	if (c->ch) {
-		smd_close(c->ch);
-		c->ch = NULL;
+		smd_tiocmset(c->ch, c->cbits_tomodem, clear_bits);
 	}
 
 	queue_delayed_work(grmnet_ctrl_wq, &port->disconnect_w, 0);
diff --git a/drivers/usb/host/ehci-msm-hsic.c b/drivers/usb/host/ehci-msm-hsic.c
index 9879122..4a085aa 100644
--- a/drivers/usb/host/ehci-msm-hsic.c
+++ b/drivers/usb/host/ehci-msm-hsic.c
@@ -1332,44 +1332,48 @@
 	if (pdata->resume_gpio)
 		gpio_direction_output(pdata->resume_gpio, 1);
 
-	mehci->resume_status = 0;
-	resume_thread = kthread_run(msm_hsic_resume_thread,
-			mehci, "hsic_resume_thread");
-	if (IS_ERR(resume_thread)) {
-		pr_err("Error creating resume thread:%lu\n",
-				PTR_ERR(resume_thread));
-		return PTR_ERR(resume_thread);
+	if (!mehci->ehci.resume_sof_bug) {
+		ehci_bus_resume(hcd);
+	} else {
+		mehci->resume_status = 0;
+		resume_thread = kthread_run(msm_hsic_resume_thread,
+				mehci, "hsic_resume_thread");
+		if (IS_ERR(resume_thread)) {
+			pr_err("Error creating resume thread:%lu\n",
+					PTR_ERR(resume_thread));
+			return PTR_ERR(resume_thread);
+		}
+
+		wait_for_completion(&mehci->rt_completion);
+
+		if (mehci->resume_status < 0)
+			return mehci->resume_status;
+
+		dbg_log_event(NULL, "FPR: Wokeup", 0);
+		spin_lock_irq(&ehci->lock);
+		(void) ehci_readl(ehci, &ehci->regs->command);
+
+		temp = 0;
+		if (ehci->async->qh_next.qh)
+			temp |= CMD_ASE;
+		if (ehci->periodic_sched)
+			temp |= CMD_PSE;
+		if (temp) {
+			ehci->command |= temp;
+			ehci_writel(ehci, ehci->command, &ehci->regs->command);
+		}
+
+		ehci->next_statechange = jiffies + msecs_to_jiffies(5);
+		hcd->state = HC_STATE_RUNNING;
+		ehci->rh_state = EHCI_RH_RUNNING;
+		ehci->command |= CMD_RUN;
+
+		/* Now we can safely re-enable irqs */
+		ehci_writel(ehci, INTR_MASK, &ehci->regs->intr_enable);
+
+		spin_unlock_irq(&ehci->lock);
 	}
 
-	wait_for_completion(&mehci->rt_completion);
-
-	if (mehci->resume_status < 0)
-		return mehci->resume_status;
-
-	dbg_log_event(NULL, "FPR: Wokeup", 0);
-	spin_lock_irq(&ehci->lock);
-	(void) ehci_readl(ehci, &ehci->regs->command);
-
-	temp = 0;
-	if (ehci->async->qh_next.qh)
-		temp |= CMD_ASE;
-	if (ehci->periodic_sched)
-		temp |= CMD_PSE;
-	if (temp) {
-		ehci->command |= temp;
-		ehci_writel(ehci, ehci->command, &ehci->regs->command);
-	}
-
-	ehci->next_statechange = jiffies + msecs_to_jiffies(5);
-	hcd->state = HC_STATE_RUNNING;
-	ehci->rh_state = EHCI_RH_RUNNING;
-	ehci->command |= CMD_RUN;
-
-	/* Now we can safely re-enable irqs */
-	ehci_writel(ehci, INTR_MASK, &ehci->regs->intr_enable);
-
-	spin_unlock_irq(&ehci->lock);
-
 	if (pdata->resume_gpio)
 		gpio_direction_output(pdata->resume_gpio, 0);
 
@@ -1808,6 +1812,8 @@
 		res_gpio = 0;
 	pdata->resume_gpio = res_gpio;
 
+	pdata->phy_sof_workaround = of_property_read_bool(node,
+					"qcom,phy-sof-workaround");
 	pdata->ignore_cal_pad_config = of_property_read_bool(node,
 					"hsic,ignore-cal-pad-config");
 	of_property_read_u32(node, "hsic,strobe-pad-offset",
@@ -1899,10 +1905,12 @@
 
 	spin_lock_init(&mehci->wakeup_lock);
 
-	mehci->ehci.susp_sof_bug = 1;
-	mehci->ehci.reset_sof_bug = 1;
+	if (pdata->phy_sof_workaround) {
+		mehci->ehci.susp_sof_bug = 1;
+		mehci->ehci.reset_sof_bug = 1;
+		mehci->ehci.resume_sof_bug = 1;
+	}
 
-	mehci->ehci.resume_sof_bug = 1;
 	mehci->ehci.pool_64_bit_align = pdata->pool_64_bit_align;
 	mehci->enable_hbm = pdata->enable_hbm;
 
diff --git a/drivers/usb/otg/msm_otg.c b/drivers/usb/otg/msm_otg.c
index 5750e0d..cae2c17 100644
--- a/drivers/usb/otg/msm_otg.c
+++ b/drivers/usb/otg/msm_otg.c
@@ -3897,7 +3897,20 @@
 		ret = PTR_ERR(motg->core_clk);
 		goto put_clk;
 	}
-	clk_set_rate(motg->core_clk, INT_MAX);
+
+	/*
+	 * Get Max supported clk frequency for USB Core CLK and request
+	 * to set the same.
+	 */
+	motg->core_clk_rate = clk_round_rate(motg->core_clk, LONG_MAX);
+	if (IS_ERR_VALUE(motg->core_clk_rate)) {
+		dev_err(&pdev->dev, "fail to get core clk max freq.\n");
+	} else {
+		ret = clk_set_rate(motg->core_clk, motg->core_clk_rate);
+		if (ret)
+			dev_err(&pdev->dev, "fail to set core_clk freq:%d\n",
+									ret);
+	}
 
 	motg->pclk = clk_get(&pdev->dev, "iface_clk");
 	if (IS_ERR(motg->pclk)) {
diff --git a/drivers/video/msm/mdss/Makefile b/drivers/video/msm/mdss/Makefile
index 7fafbc64..fd680e6 100644
--- a/drivers/video/msm/mdss/Makefile
+++ b/drivers/video/msm/mdss/Makefile
@@ -1,3 +1,6 @@
+mdss-mdp3-objs = mdp3.o mdp3_dma.o mdp3_ctrl.o
+obj-$(CONFIG_FB_MSM_MDSS) += mdss-mdp3.o
+
 mdss-mdp-objs := mdss_mdp.o mdss_mdp_ctl.o mdss_mdp_pipe.o mdss_mdp_util.o
 mdss-mdp-objs += mdss_mdp_pp.o
 mdss-mdp-objs += mdss_mdp_intf_video.o
@@ -7,12 +10,14 @@
 mdss-mdp-objs += mdss_mdp_overlay.o
 mdss-mdp-objs += mdss_mdp_wb.o
 obj-$(CONFIG_FB_MSM_MDSS) += mdss-mdp.o
-obj-$(CONFIG_FB_MSM_MDSS) += mdss_fb.o
 
 ifeq ($(CONFIG_FB_MSM_MDSS),y)
 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
+obj-$(CONFIG_FB_MSM_MDSS) += dsi-v2.o
+
 mdss-dsi-objs := mdss_dsi.o mdss_dsi_host.o
 mdss-dsi-objs += mdss_dsi_panel.o
 mdss-dsi-objs += msm_mdss_io_8974.o
@@ -31,3 +36,5 @@
 mdss-qpic-objs := mdss_qpic.o mdss_fb.o mdss_qpic_panel.o
 obj-$(CONFIG_FB_MSM_QPIC) += mdss-qpic.o
 obj-$(CONFIG_FB_MSM_QPIC_ILI_QVGA_PANEL) += qpic_panel_ili_qvga.o
+
+obj-$(CONFIG_FB_MSM_MDSS) += mdss_fb.o
diff --git a/drivers/video/msm/mdss/dsi_host_v2.c b/drivers/video/msm/mdss/dsi_host_v2.c
new file mode 100644
index 0000000..453cbaa
--- /dev/null
+++ b/drivers/video/msm/mdss/dsi_host_v2.c
@@ -0,0 +1,1034 @@
+/* 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/spinlock.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/dma-mapping.h>
+#include <linux/slab.h>
+#include <linux/iopoll.h>
+#include <linux/interrupt.h>
+#include <linux/of_device.h>
+
+#include "dsi_v2.h"
+#include "dsi_io_v2.h"
+#include "dsi_host_v2.h"
+
+#define DSI_POLL_SLEEP_US 1000
+#define DSI_POLL_TIMEOUT_US 16000
+#define DSI_ESC_CLK_RATE 19200000
+
+struct dsi_host_v2_private {
+	struct completion dma_comp;
+	int irq_enabled;
+	spinlock_t irq_lock;
+	spinlock_t mdp_lock;
+	int mdp_busy;
+	int irq_no;
+	unsigned char *dsi_base;
+	struct device dis_dev;
+};
+
+static struct dsi_host_v2_private *dsi_host_private;
+
+int msm_dsi_init(void)
+{
+	if (!dsi_host_private) {
+		dsi_host_private = kzalloc(sizeof(struct dsi_host_v2_private),
+					GFP_KERNEL);
+		if (!dsi_host_private) {
+			pr_err("fail to alloc dsi host private data\n");
+			return -ENOMEM;
+		}
+	}
+
+	init_completion(&dsi_host_private->dma_comp);
+	spin_lock_init(&dsi_host_private->irq_lock);
+	spin_lock_init(&dsi_host_private->mdp_lock);
+	return 0;
+}
+
+void msm_dsi_deinit(void)
+{
+	kfree(dsi_host_private);
+	dsi_host_private = NULL;
+}
+
+void msm_dsi_ack_err_status(unsigned char *ctrl_base)
+{
+	u32 status;
+
+	status = MIPI_INP(ctrl_base + DSI_ACK_ERR_STATUS);
+
+	if (status) {
+		MIPI_OUTP(ctrl_base + DSI_ACK_ERR_STATUS, status);
+		pr_debug("%s: status=%x\n", __func__, status);
+	}
+}
+
+void msm_dsi_timeout_status(unsigned char *ctrl_base)
+{
+	u32 status;
+
+	status = MIPI_INP(ctrl_base + DSI_TIMEOUT_STATUS);
+	if (status & 0x0111) {
+		MIPI_OUTP(ctrl_base + DSI_TIMEOUT_STATUS, status);
+		pr_debug("%s: status=%x\n", __func__, status);
+	}
+}
+
+void msm_dsi_dln0_phy_err(unsigned char *ctrl_base)
+{
+	u32 status;
+
+	status = MIPI_INP(ctrl_base + DSI_DLN0_PHY_ERR);
+
+	if (status & 0x011111) {
+		MIPI_OUTP(ctrl_base + DSI_DLN0_PHY_ERR, status);
+		pr_debug("%s: status=%x\n", __func__, status);
+	}
+}
+
+void msm_dsi_fifo_status(unsigned char *ctrl_base)
+{
+	u32 status;
+
+	status = MIPI_INP(ctrl_base + DSI_FIFO_STATUS);
+
+	if (status & 0x44444489) {
+		MIPI_OUTP(ctrl_base + DSI_FIFO_STATUS, status);
+		pr_debug("%s: status=%x\n", __func__, status);
+	}
+}
+
+void msm_dsi_status(unsigned char *ctrl_base)
+{
+	u32 status;
+
+	status = MIPI_INP(ctrl_base + DSI_STATUS);
+
+	if (status & 0x80000000) {
+		MIPI_OUTP(ctrl_base + DSI_STATUS, status);
+		pr_debug("%s: status=%x\n", __func__, status);
+	}
+}
+
+void msm_dsi_error(unsigned char *ctrl_base)
+{
+	msm_dsi_ack_err_status(ctrl_base);
+	msm_dsi_timeout_status(ctrl_base);
+	msm_dsi_fifo_status(ctrl_base);
+	msm_dsi_status(ctrl_base);
+	msm_dsi_dln0_phy_err(ctrl_base);
+}
+
+void msm_dsi_enable_irq(void)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&dsi_host_private->irq_lock, flags);
+	if (dsi_host_private->irq_enabled) {
+		pr_debug("%s: IRQ aleady enabled\n", __func__);
+		spin_unlock_irqrestore(&dsi_host_private->irq_lock, flags);
+		return;
+	}
+
+	enable_irq(dsi_host_private->irq_no);
+	dsi_host_private->irq_enabled = 1;
+	spin_unlock_irqrestore(&dsi_host_private->irq_lock, flags);
+}
+
+void msm_dsi_disable_irq(void)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&dsi_host_private->irq_lock, flags);
+	if (dsi_host_private->irq_enabled == 0) {
+		pr_debug("%s: IRQ already disabled\n", __func__);
+		spin_unlock_irqrestore(&dsi_host_private->irq_lock, flags);
+		return;
+	}
+	disable_irq(dsi_host_private->irq_no);
+	dsi_host_private->irq_enabled = 0;
+	spin_unlock_irqrestore(&dsi_host_private->irq_lock, flags);
+}
+
+void msm_dsi_disable_irq_nosync(void)
+{
+	spin_lock(&dsi_host_private->irq_lock);
+	if (dsi_host_private->irq_enabled == 0) {
+		pr_debug("%s: IRQ cannot be disabled\n", __func__);
+		spin_unlock(&dsi_host_private->irq_lock);
+		return;
+	}
+	disable_irq_nosync(dsi_host_private->irq_no);
+	dsi_host_private->irq_enabled = 0;
+	spin_unlock(&dsi_host_private->irq_lock);
+}
+
+irqreturn_t msm_dsi_isr(int irq, void *ptr)
+{
+	u32 isr;
+
+	isr = MIPI_INP(dsi_host_private->dsi_base + DSI_INT_CTRL);
+	MIPI_OUTP(dsi_host_private->dsi_base + DSI_INT_CTRL, isr);
+
+	if (isr & DSI_INTR_ERROR)
+		msm_dsi_error(dsi_host_private->dsi_base);
+
+	if (isr & DSI_INTR_CMD_DMA_DONE)
+		complete(&dsi_host_private->dma_comp);
+
+	if (isr & DSI_INTR_CMD_MDP_DONE) {
+		spin_lock(&dsi_host_private->mdp_lock);
+		dsi_host_private->mdp_busy = false;
+		msm_dsi_disable_irq_nosync();
+		spin_unlock(&dsi_host_private->mdp_lock);
+	}
+
+	return IRQ_HANDLED;
+}
+
+int msm_dsi_irq_init(struct device *dev, int irq_no)
+{
+	int ret;
+
+	ret = devm_request_irq(dev, irq_no, msm_dsi_isr,
+				IRQF_DISABLED, "DSI", NULL);
+	if (ret) {
+		pr_err("msm_dsi_irq_init request_irq() failed!\n");
+		return ret;
+	}
+	dsi_host_private->irq_no = irq_no;
+	disable_irq(irq_no);
+	return 0;
+}
+
+void msm_dsi_host_init(struct mipi_panel_info *pinfo)
+{
+	u32 dsi_ctrl, intr_ctrl, data;
+	unsigned char *ctrl_base = dsi_host_private->dsi_base;
+
+	pr_debug("msm_dsi_host_init\n");
+	pinfo->rgb_swap = DSI_RGB_SWAP_RGB;
+
+	if (pinfo->mode == DSI_VIDEO_MODE) {
+		data = 0;
+		if (pinfo->pulse_mode_hsa_he)
+			data |= BIT(28);
+		if (pinfo->hfp_power_stop)
+			data |= BIT(24);
+		if (pinfo->hbp_power_stop)
+			data |= BIT(20);
+		if (pinfo->hsa_power_stop)
+			data |= BIT(16);
+		if (pinfo->eof_bllp_power_stop)
+			data |= BIT(15);
+		if (pinfo->bllp_power_stop)
+			data |= BIT(12);
+		data |= ((pinfo->traffic_mode & 0x03) << 8);
+		data |= ((pinfo->dst_format & 0x03) << 4); /* 2 bits */
+		data |= (pinfo->vc & 0x03);
+		MIPI_OUTP(ctrl_base + DSI_VIDEO_MODE_CTRL, data);
+
+		data = 0;
+		data |= ((pinfo->rgb_swap & 0x07) << 12);
+		if (pinfo->b_sel)
+			data |= BIT(8);
+		if (pinfo->g_sel)
+			data |= BIT(4);
+		if (pinfo->r_sel)
+			data |= BIT(0);
+		MIPI_OUTP(ctrl_base + DSI_VIDEO_MODE_DATA_CTRL, data);
+	} else if (pinfo->mode == DSI_CMD_MODE) {
+		data = 0;
+		data |= ((pinfo->interleave_max & 0x0f) << 20);
+		data |= ((pinfo->rgb_swap & 0x07) << 16);
+		if (pinfo->b_sel)
+			data |= BIT(12);
+		if (pinfo->g_sel)
+			data |= BIT(8);
+		if (pinfo->r_sel)
+			data |= BIT(4);
+		data |= (pinfo->dst_format & 0x0f); /* 4 bits */
+		MIPI_OUTP(ctrl_base + DSI_COMMAND_MODE_MDP_CTRL, data);
+
+		/* DSI_COMMAND_MODE_MDP_DCS_CMD_CTRL */
+		data = pinfo->wr_mem_continue & 0x0ff;
+		data <<= 8;
+		data |= (pinfo->wr_mem_start & 0x0ff);
+		if (pinfo->insert_dcs_cmd)
+			data |= BIT(16);
+		MIPI_OUTP(ctrl_base + DSI_COMMAND_MODE_MDP_DCS_CMD_CTRL,
+				data);
+	} else
+		pr_err("%s: Unknown DSI mode=%d\n", __func__, pinfo->mode);
+
+	dsi_ctrl = BIT(8) | BIT(2); /* clock enable & cmd mode */
+	intr_ctrl = 0;
+	intr_ctrl = (DSI_INTR_CMD_DMA_DONE_MASK | DSI_INTR_CMD_MDP_DONE_MASK);
+
+	if (pinfo->crc_check)
+		dsi_ctrl |= BIT(24);
+	if (pinfo->ecc_check)
+		dsi_ctrl |= BIT(20);
+	if (pinfo->data_lane3)
+		dsi_ctrl |= BIT(7);
+	if (pinfo->data_lane2)
+		dsi_ctrl |= BIT(6);
+	if (pinfo->data_lane1)
+		dsi_ctrl |= BIT(5);
+	if (pinfo->data_lane0)
+		dsi_ctrl |= BIT(4);
+
+	/* from frame buffer, low power mode */
+	/* DSI_COMMAND_MODE_DMA_CTRL */
+	MIPI_OUTP(ctrl_base + DSI_COMMAND_MODE_DMA_CTRL, 0x14000000);
+
+	data = 0;
+	if (pinfo->te_sel)
+		data |= BIT(31);
+	data |= pinfo->mdp_trigger << 4;/* cmd mdp trigger */
+	data |= pinfo->dma_trigger;	/* cmd dma trigger */
+	data |= (pinfo->stream & 0x01) << 8;
+	MIPI_OUTP(ctrl_base + DSI_TRIG_CTRL, data);
+
+	/* DSI_LAN_SWAP_CTRL */
+	MIPI_OUTP(ctrl_base + DSI_LANE_SWAP_CTRL, pinfo->dlane_swap);
+
+	/* clock out ctrl */
+	data = pinfo->t_clk_post & 0x3f;	/* 6 bits */
+	data <<= 8;
+	data |= pinfo->t_clk_pre & 0x3f;	/*  6 bits */
+	/* DSI_CLKOUT_TIMING_CTRL */
+	MIPI_OUTP(ctrl_base + DSI_CLKOUT_TIMING_CTRL, data);
+
+	data = 0;
+	if (pinfo->rx_eot_ignore)
+		data |= BIT(4);
+	if (pinfo->tx_eot_append)
+		data |= BIT(0);
+	MIPI_OUTP(ctrl_base + DSI_EOT_PACKET_CTRL, data);
+
+
+	/* allow only ack-err-status  to generate interrupt */
+	/* DSI_ERR_INT_MASK0 */
+	MIPI_OUTP(ctrl_base + DSI_ERR_INT_MASK0, 0x13ff3fe0);
+
+	intr_ctrl |= DSI_INTR_ERROR_MASK;
+	MIPI_OUTP(ctrl_base + DSI_INT_CTRL, intr_ctrl);
+
+	/* turn esc, byte, dsi, pclk, sclk, hclk on */
+	MIPI_OUTP(ctrl_base + DSI_CLK_CTRL, 0x23f);
+
+	dsi_ctrl |= BIT(0);	/* enable dsi */
+	MIPI_OUTP(ctrl_base + DSI_CTRL, dsi_ctrl);
+
+	wmb();
+}
+
+void msm_dsi_set_tx_power_mode(int mode)
+{
+	u32 data;
+	unsigned char *ctrl_base = dsi_host_private->dsi_base;
+
+	data = MIPI_INP(ctrl_base + DSI_COMMAND_MODE_DMA_CTRL);
+
+	if (mode == 0)
+		data &= ~BIT(26);
+	else
+		data |= BIT(26);
+
+	MIPI_OUTP(ctrl_base + DSI_COMMAND_MODE_DMA_CTRL, data);
+}
+
+void msm_dsi_sw_reset(void)
+{
+	u32 dsi_ctrl;
+	unsigned char *ctrl_base = dsi_host_private->dsi_base;
+
+	pr_debug("msm_dsi_sw_reset\n");
+
+	dsi_ctrl = MIPI_INP(ctrl_base + DSI_CTRL);
+	dsi_ctrl &= ~0x01;
+	MIPI_OUTP(ctrl_base + DSI_CTRL, dsi_ctrl);
+	wmb();
+
+	/* turn esc, byte, dsi, pclk, sclk, hclk on */
+	MIPI_OUTP(ctrl_base + DSI_CLK_CTRL, 0x23f);
+	wmb();
+
+	MIPI_OUTP(ctrl_base + DSI_SOFT_RESET, 0x01);
+	wmb();
+	MIPI_OUTP(ctrl_base + DSI_SOFT_RESET, 0x00);
+	wmb();
+}
+
+void msm_dsi_controller_cfg(int enable)
+{
+	u32 dsi_ctrl, status;
+	unsigned char *ctrl_base = dsi_host_private->dsi_base;
+
+	pr_debug("msm_dsi_controller_cfg\n");
+
+	/* Check for CMD_MODE_DMA_BUSY */
+	if (readl_poll_timeout((ctrl_base + DSI_STATUS),
+				status,
+				((status & 0x02) == 0),
+				DSI_POLL_SLEEP_US, DSI_POLL_TIMEOUT_US))
+		pr_err("%s: DSI status=%x failed\n", __func__, status);
+
+	/* Check for x_HS_FIFO_EMPTY */
+	if (readl_poll_timeout((ctrl_base + DSI_FIFO_STATUS),
+				status,
+				((status & 0x11111000) == 0x11111000),
+				DSI_POLL_SLEEP_US, DSI_POLL_TIMEOUT_US))
+		pr_err("%s: FIFO status=%x failed\n", __func__, status);
+
+	/* Check for VIDEO_MODE_ENGINE_BUSY */
+	if (readl_poll_timeout((ctrl_base + DSI_STATUS),
+				status,
+				((status & 0x08) == 0),
+				DSI_POLL_SLEEP_US, DSI_POLL_TIMEOUT_US)) {
+		pr_err("%s: DSI status=%x\n", __func__, status);
+		pr_err("%s: Doing sw reset\n", __func__);
+		msm_dsi_sw_reset();
+	}
+
+	dsi_ctrl = MIPI_INP(ctrl_base + DSI_CTRL);
+	if (enable)
+		dsi_ctrl |= 0x01;
+	else
+		dsi_ctrl &= ~0x01;
+
+	MIPI_OUTP(ctrl_base + DSI_CTRL, dsi_ctrl);
+	wmb();
+}
+
+void msm_dsi_op_mode_config(int mode, struct mdss_panel_data *pdata)
+{
+	u32 dsi_ctrl, intr_ctrl;
+	unsigned char *ctrl_base = dsi_host_private->dsi_base;
+
+	pr_debug("msm_dsi_op_mode_config\n");
+
+	dsi_ctrl = MIPI_INP(ctrl_base + DSI_CTRL);
+	/*If Video enabled, Keep Video and Cmd mode ON */
+	if (dsi_ctrl & 0x02)
+		dsi_ctrl &= ~0x05;
+	else
+		dsi_ctrl &= ~0x07;
+
+	if (mode == DSI_VIDEO_MODE) {
+		dsi_ctrl |= 0x03;
+		intr_ctrl = DSI_INTR_CMD_DMA_DONE_MASK;
+	} else {		/* command mode */
+		dsi_ctrl |= 0x05;
+		if (pdata->panel_info.type == MIPI_VIDEO_PANEL)
+			dsi_ctrl |= 0x02;
+
+		intr_ctrl = DSI_INTR_CMD_DMA_DONE_MASK | DSI_INTR_ERROR_MASK |
+				DSI_INTR_CMD_MDP_DONE_MASK;
+	}
+
+	pr_debug("%s: dsi_ctrl=%x intr=%x\n", __func__, dsi_ctrl, intr_ctrl);
+
+	MIPI_OUTP(ctrl_base + DSI_INT_CTRL, intr_ctrl);
+	MIPI_OUTP(ctrl_base + DSI_CTRL, dsi_ctrl);
+	wmb();
+}
+
+void msm_dsi_cmd_mdp_start(void)
+{
+	unsigned long flag;
+
+	spin_lock_irqsave(&dsi_host_private->mdp_lock, flag);
+	msm_dsi_enable_irq();
+	dsi_host_private->mdp_busy = true;
+	spin_unlock_irqrestore(&dsi_host_private->mdp_lock, flag);
+}
+
+int msm_dsi_cmd_reg_tx(u32 data)
+{
+	unsigned char *ctrl_base = dsi_host_private->dsi_base;
+
+	MIPI_OUTP(ctrl_base + DSI_TRIG_CTRL, 0x04);/* sw trigger */
+	MIPI_OUTP(ctrl_base + DSI_CTRL, 0x135);
+	wmb();
+
+	MIPI_OUTP(ctrl_base + DSI_COMMAND_MODE_DMA_CTRL, data);
+	wmb();
+	MIPI_OUTP(ctrl_base + DSI_CMD_MODE_DMA_SW_TRIGGER, 0x01);
+	wmb();
+
+	udelay(300); /*per spec*/
+
+	return 0;
+}
+
+int msm_dsi_cmd_dma_tx(struct dsi_buf *tp)
+{
+	int len;
+	unsigned long size, addr;
+	unsigned char *ctrl_base = dsi_host_private->dsi_base;
+
+	len = ALIGN(tp->len, 4);
+	size = ALIGN(tp->len, SZ_4K);
+
+	tp->dmap = dma_map_single(&dsi_host_private->dis_dev, tp->data, size,
+				DMA_TO_DEVICE);
+	if (dma_mapping_error(&dsi_host_private->dis_dev, tp->dmap)) {
+		pr_err("%s: dmap mapp failed\n", __func__);
+		return -ENOMEM;
+	}
+
+	addr = tp->dmap;
+
+	INIT_COMPLETION(dsi_host_private->dma_comp);
+
+	MIPI_OUTP(ctrl_base + DSI_DMA_CMD_OFFSET, addr);
+	MIPI_OUTP(ctrl_base + DSI_DMA_CMD_LENGTH, len);
+	wmb();
+
+	MIPI_OUTP(ctrl_base + DSI_CMD_MODE_DMA_SW_TRIGGER, 0x01);
+	wmb();
+
+	wait_for_completion_interruptible(&dsi_host_private->dma_comp);
+
+	dma_unmap_single(&dsi_host_private->dis_dev, tp->dmap, size,
+			DMA_TO_DEVICE);
+	tp->dmap = 0;
+	return 0;
+}
+
+int msm_dsi_cmd_dma_rx(struct dsi_buf *rp, int rlen)
+{
+	u32 *lp, data;
+	int i, off, cnt;
+	unsigned char *ctrl_base = dsi_host_private->dsi_base;
+
+	lp = (u32 *)rp->data;
+	cnt = rlen;
+	cnt += 3;
+	cnt >>= 2;
+
+	if (cnt > 4)
+		cnt = 4; /* 4 x 32 bits registers only */
+
+	off = DSI_RDBK_DATA0;
+	off += ((cnt - 1) * 4);
+
+	for (i = 0; i < cnt; i++) {
+		data = (u32)MIPI_INP(ctrl_base + off);
+		*lp++ = ntohl(data); /* to network byte order */
+		pr_debug("%s: data = 0x%x and ntohl(data) = 0x%x\n",
+					 __func__, data, ntohl(data));
+		off -= 4;
+		rp->len += sizeof(*lp);
+	}
+
+	return 0;
+}
+
+int msm_dsi_cmds_tx(struct mdss_panel_data *pdata,
+			struct dsi_buf *tp, struct dsi_cmd_desc *cmds, int cnt)
+{
+	struct dsi_cmd_desc *cm;
+	u32 dsi_ctrl, ctrl;
+	int i, video_mode;
+	unsigned long flag;
+	unsigned char *ctrl_base = dsi_host_private->dsi_base;
+
+	/* turn on cmd mode
+	* for video mode, do not send cmds more than
+	* one pixel line, since it only transmit it
+	* during BLLP.
+	*/
+	dsi_ctrl = MIPI_INP(ctrl_base + DSI_CTRL);
+	video_mode = dsi_ctrl & 0x02; /* VIDEO_MODE_EN */
+	if (video_mode) {
+		ctrl = dsi_ctrl | 0x04; /* CMD_MODE_EN */
+		MIPI_OUTP(ctrl_base + DSI_CTRL, ctrl);
+	}
+
+	spin_lock_irqsave(&dsi_host_private->mdp_lock, flag);
+	msm_dsi_enable_irq();
+	dsi_host_private->mdp_busy = true;
+	spin_unlock_irqrestore(&dsi_host_private->mdp_lock, flag);
+
+	cm = cmds;
+	dsi_buf_init(tp);
+	for (i = 0; i < cnt; i++) {
+		dsi_buf_init(tp);
+		dsi_cmd_dma_add(tp, cm);
+		msm_dsi_cmd_dma_tx(tp);
+		if (cm->wait)
+			msleep(cm->wait);
+		cm++;
+	}
+
+	spin_lock_irqsave(&dsi_host_private->mdp_lock, flag);
+	dsi_host_private->mdp_busy = false;
+	msm_dsi_disable_irq();
+	spin_unlock_irqrestore(&dsi_host_private->mdp_lock, flag);
+
+	if (video_mode)
+		MIPI_OUTP(ctrl_base + DSI_CTRL, dsi_ctrl);
+	return 0;
+}
+
+/* MDSS_DSI_MRPS, Maximum Return Packet Size */
+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}
+};
+
+/*
+ * DSI panel reply with  MAX_RETURN_PACKET_SIZE bytes of data
+ * plus DCS header, ECC and CRC for DCS long read response
+ * mdss_dsi_controller only have 4x32 bits register ( 16 bytes) to
+ * hold data per transaction.
+ * MDSS_DSI_LEN equal to 8
+ * len should be either 4 or 8
+ * any return data more than MDSS_DSI_LEN need to be break down
+ * to multiple transactions.
+ *
+ * ov_mutex need to be acquired before call this function.
+ */
+int msm_dsi_cmds_rx(struct mdss_panel_data *pdata,
+			struct dsi_buf *tp, struct dsi_buf *rp,
+			struct dsi_cmd_desc *cmds, int rlen)
+{
+	int cnt, len, diff, pkt_size;
+	unsigned long flag;
+	char cmd;
+
+	if (pdata->panel_info.mipi.no_max_pkt_size)
+		rlen = ALIGN(rlen, 4); /* Only support rlen = 4*n */
+
+	len = rlen;
+	diff = 0;
+
+	if (len <= 2) {
+		cnt = 4;	/* short read */
+	} else {
+		if (len > DSI_LEN)
+			len = DSI_LEN;	/* 8 bytes at most */
+
+		len = ALIGN(len, 4); /* len 4 bytes align */
+		diff = len - rlen;
+		/*
+		 * add extra 2 bytes to len to have overall
+		 * packet size is multipe by 4. This also make
+		 * sure 4 bytes dcs headerlocates within a
+		 * 32 bits register after shift in.
+		 * after all, len should be either 6 or 10.
+		 */
+		len += 2;
+		cnt = len + 6; /* 4 bytes header + 2 bytes crc */
+	}
+
+	spin_lock_irqsave(&dsi_host_private->mdp_lock, flag);
+	msm_dsi_enable_irq();
+	dsi_host_private->mdp_busy = true;
+	spin_unlock_irqrestore(&dsi_host_private->mdp_lock, flag);
+
+	if (!pdata->panel_info.mipi.no_max_pkt_size) {
+		/* packet size need to be set at every read */
+		pkt_size = len;
+		max_pktsize[0] = pkt_size;
+		dsi_buf_init(tp);
+		dsi_cmd_dma_add(tp, pkt_size_cmd);
+		msm_dsi_cmd_dma_tx(tp);
+		pr_debug("%s: Max packet size sent\n", __func__);
+	}
+
+	dsi_buf_init(tp);
+	dsi_cmd_dma_add(tp, cmds);
+
+	/* transmit read comamnd to client */
+	msm_dsi_cmd_dma_tx(tp);
+	/*
+	 * once cmd_dma_done interrupt received,
+	 * return data from client is ready and stored
+	 * at RDBK_DATA register already
+	 */
+	dsi_buf_init(rp);
+	if (pdata->panel_info.mipi.no_max_pkt_size) {
+		/*
+		 * expect rlen = n * 4
+		 * short alignement for start addr
+		 */
+		rp->data += 2;
+	}
+
+	msm_dsi_cmd_dma_rx(rp, cnt);
+
+	spin_lock_irqsave(&dsi_host_private->mdp_lock, flag);
+	dsi_host_private->mdp_busy = false;
+	msm_dsi_disable_irq();
+	spin_unlock_irqrestore(&dsi_host_private->mdp_lock, flag);
+
+	if (pdata->panel_info.mipi.no_max_pkt_size) {
+		/*
+		 * remove extra 2 bytes from previous
+		 * rx transaction at shift register
+		 * which was inserted during copy
+		 * shift registers to rx buffer
+		 * rx payload start from long alignment addr
+		 */
+		rp->data += 2;
+	}
+
+	cmd = rp->data[0];
+	switch (cmd) {
+	case DTYPE_ACK_ERR_RESP:
+		pr_debug("%s: rx ACK_ERR_PACLAGE\n", __func__);
+		break;
+	case DTYPE_GEN_READ1_RESP:
+	case DTYPE_DCS_READ1_RESP:
+		dsi_short_read1_resp(rp);
+		break;
+	case DTYPE_GEN_READ2_RESP:
+	case DTYPE_DCS_READ2_RESP:
+		dsi_short_read2_resp(rp);
+		break;
+	case DTYPE_GEN_LREAD_RESP:
+	case DTYPE_DCS_LREAD_RESP:
+		dsi_long_read_resp(rp);
+		rp->len -= 2; /* extra 2 bytes added */
+		rp->len -= diff; /* align bytes */
+		break;
+	default:
+		pr_debug("%s: Unknown cmd received\n", __func__);
+		break;
+	}
+
+	return rp->len;
+}
+
+static int msm_dsi_cal_clk_rate(struct mdss_panel_data *pdata,
+				u32 *bitclk_rate,
+				u32 *byteclk_rate,
+				u32 *pclk_rate)
+{
+	struct mdss_panel_info *pinfo;
+	struct mipi_panel_info *mipi;
+	u32 hbp, hfp, vbp, vfp, hspw, vspw, width, height;
+	int lanes;
+
+	pinfo = &pdata->panel_info;
+	mipi  = &pdata->panel_info.mipi;
+
+	hbp = pdata->panel_info.lcdc.h_back_porch;
+	hfp = pdata->panel_info.lcdc.h_front_porch;
+	vbp = pdata->panel_info.lcdc.v_back_porch;
+	vfp = pdata->panel_info.lcdc.v_front_porch;
+	hspw = pdata->panel_info.lcdc.h_pulse_width;
+	vspw = pdata->panel_info.lcdc.v_pulse_width;
+	width = pdata->panel_info.xres;
+	height = pdata->panel_info.yres;
+
+	lanes = 0;
+	if (mipi->data_lane0)
+		lanes++;
+	if (mipi->data_lane1)
+		lanes++;
+	if (mipi->data_lane2)
+		lanes++;
+	if (mipi->data_lane3)
+		lanes++;
+	if (lanes == 0)
+		return -EINVAL;
+
+	*bitclk_rate = (width + hbp + hfp + hspw) * (height + vbp + vfp + vspw);
+	*bitclk_rate *= mipi->frame_rate;
+	*bitclk_rate *= pdata->panel_info.bpp;
+	*bitclk_rate /= lanes;
+
+	*byteclk_rate = *bitclk_rate / 8;
+	*pclk_rate = *byteclk_rate * lanes * 8 / pdata->panel_info.bpp;
+
+	pr_debug("bitclk=%u, byteclk=%u, pck_=%u\n",
+		*bitclk_rate, *byteclk_rate, *pclk_rate);
+	return 0;
+}
+
+static int msm_dsi_on(struct mdss_panel_data *pdata)
+{
+	int ret = 0;
+	u32 clk_rate;
+	struct mdss_panel_info *pinfo;
+	struct mipi_panel_info *mipi;
+	u32 hbp, hfp, vbp, vfp, hspw, vspw, width, height;
+	u32 ystride, bpp, data;
+	u32 dummy_xres, dummy_yres;
+	u32 bitclk_rate = 0, byteclk_rate = 0, pclk_rate = 0;
+	unsigned char *ctrl_base = dsi_host_private->dsi_base;
+
+	pr_debug("msm_dsi_on\n");
+
+	pinfo = &pdata->panel_info;
+
+	ret = msm_dsi_regulator_enable();
+	if (ret) {
+		pr_err("%s: DSI power on failed\n", __func__);
+		return ret;
+	}
+
+	msm_dsi_ahb_ctrl(1);
+	msm_dsi_phy_sw_reset(dsi_host_private->dsi_base);
+	msm_dsi_phy_init(dsi_host_private->dsi_base, pdata);
+
+	msm_dsi_cal_clk_rate(pdata, &bitclk_rate, &byteclk_rate, &pclk_rate);
+	msm_dsi_clk_set_rate(DSI_ESC_CLK_RATE, byteclk_rate, pclk_rate);
+	msm_dsi_prepare_clocks();
+	msm_dsi_clk_enable();
+
+	clk_rate = pdata->panel_info.clk_rate;
+	clk_rate = min(clk_rate, pdata->panel_info.clk_max);
+
+	hbp = pdata->panel_info.lcdc.h_back_porch;
+	hfp = pdata->panel_info.lcdc.h_front_porch;
+	vbp = pdata->panel_info.lcdc.v_back_porch;
+	vfp = pdata->panel_info.lcdc.v_front_porch;
+	hspw = pdata->panel_info.lcdc.h_pulse_width;
+	vspw = pdata->panel_info.lcdc.v_pulse_width;
+	width = pdata->panel_info.xres;
+	height = pdata->panel_info.yres;
+
+	mipi  = &pdata->panel_info.mipi;
+	if (pdata->panel_info.type == MIPI_VIDEO_PANEL) {
+		dummy_xres = pdata->panel_info.lcdc.xres_pad;
+		dummy_yres = pdata->panel_info.lcdc.yres_pad;
+
+		MIPI_OUTP(ctrl_base + DSI_VIDEO_MODE_ACTIVE_H,
+			((hspw + hbp + width + dummy_xres) << 16 |
+			(hspw + hbp)));
+		MIPI_OUTP(ctrl_base + DSI_VIDEO_MODE_ACTIVE_V,
+			((vspw + vbp + height + dummy_yres) << 16 |
+			(vspw + vbp)));
+		MIPI_OUTP(ctrl_base + DSI_VIDEO_MODE_TOTAL,
+			(vspw + vbp + height + dummy_yres +
+				vfp - 1) << 16 | (hspw + hbp +
+				width + dummy_xres + hfp - 1));
+
+		MIPI_OUTP(ctrl_base + DSI_VIDEO_MODE_HSYNC, (hspw << 16));
+		MIPI_OUTP(ctrl_base + DSI_VIDEO_MODE_VSYNC, 0);
+		MIPI_OUTP(ctrl_base + DSI_VIDEO_MODE_VSYNC_VPOS,
+				(vspw << 16));
+
+	} else {		/* command mode */
+		if (mipi->dst_format == DSI_CMD_DST_FORMAT_RGB888)
+			bpp = 3;
+		else if (mipi->dst_format == DSI_CMD_DST_FORMAT_RGB666)
+			bpp = 3;
+		else if (mipi->dst_format == DSI_CMD_DST_FORMAT_RGB565)
+			bpp = 2;
+		else
+			bpp = 3;	/* Default format set to RGB888 */
+
+		ystride = width * bpp + 1;
+
+		data = (ystride << 16) | (mipi->vc << 8) | DTYPE_DCS_LWRITE;
+		MIPI_OUTP(ctrl_base + DSI_COMMAND_MODE_MDP_STREAM0_CTRL,
+			data);
+		MIPI_OUTP(ctrl_base + DSI_COMMAND_MODE_MDP_STREAM1_CTRL,
+			data);
+
+		data = height << 16 | width;
+		MIPI_OUTP(ctrl_base + DSI_COMMAND_MODE_MDP_STREAM1_TOTAL,
+			data);
+		MIPI_OUTP(ctrl_base + DSI_COMMAND_MODE_MDP_STREAM0_TOTAL,
+			data);
+	}
+
+	msm_dsi_sw_reset();
+	msm_dsi_host_init(mipi);
+
+	if (mipi->force_clk_lane_hs) {
+		u32 tmp;
+
+		tmp = MIPI_INP(ctrl_base + DSI_LANE_CTRL);
+		tmp |= (1<<28);
+		MIPI_OUTP(ctrl_base + DSI_LANE_CTRL, tmp);
+		wmb();
+	}
+
+	msm_dsi_op_mode_config(mipi->mode, pdata);
+
+	return ret;
+}
+
+static int msm_dsi_off(struct mdss_panel_data *pdata)
+{
+	int ret = 0;
+
+	pr_debug("msm_dsi_off\n");
+	msm_dsi_clk_set_rate(0, 0, 0);
+	msm_dsi_clk_disable();
+	msm_dsi_unprepare_clocks();
+
+	/* disable DSI controller */
+	msm_dsi_controller_cfg(0);
+	msm_dsi_ahb_ctrl(0);
+
+	ret = msm_dsi_regulator_disable();
+	if (ret) {
+		pr_err("%s: Panel power off failed\n", __func__);
+		return ret;
+	}
+
+	return ret;
+}
+
+static int __devinit msm_dsi_probe(struct platform_device *pdev)
+{
+	struct dsi_interface intf;
+	int rc = 0;
+
+	pr_debug("%s\n", __func__);
+
+	rc = msm_dsi_init();
+	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_base = ioremap(
+						mdss_dsi_mres->start,
+						resource_size(mdss_dsi_mres));
+			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;
+		}
+
+	}
+
+	dsi_host_private->dis_dev = pdev->dev;
+	intf.on = msm_dsi_on;
+	intf.off = msm_dsi_off;
+	intf.op_mode_config = msm_dsi_op_mode_config;
+	intf.tx = msm_dsi_cmds_tx;
+	intf.rx = msm_dsi_cmds_rx;
+	intf.index = 0;
+	intf.private = NULL;
+	dsi_register_interface(&intf);
+	pr_debug("%s success\n", __func__);
+	return 0;
+dsi_probe_error:
+	if (dsi_host_private->dsi_base) {
+		iounmap(dsi_host_private->dsi_base);
+		dsi_host_private->dsi_base = NULL;
+	}
+	msm_dsi_io_deinit();
+	msm_dsi_deinit();
+	return rc;
+}
+
+static int __devexit msm_dsi_remove(struct platform_device *pdev)
+{
+	msm_dsi_disable_irq();
+	msm_dsi_io_deinit();
+	iounmap(dsi_host_private->dsi_base);
+	dsi_host_private->dsi_base = NULL;
+	msm_dsi_deinit();
+	return 0;
+}
+
+static const struct of_device_id msm_dsi_v2_dt_match[] = {
+	{.compatible = "qcom,msm-dsi-v2"},
+	{}
+};
+MODULE_DEVICE_TABLE(of, msm_dsi_v2_dt_match);
+
+static struct platform_driver msm_dsi_v2_driver = {
+	.probe = msm_dsi_probe,
+	.remove = __devexit_p(msm_dsi_remove),
+	.shutdown = NULL,
+	.driver = {
+		.name = "msm_dsi_v2",
+		.of_match_table = msm_dsi_v2_dt_match,
+	},
+};
+
+static int msm_dsi_v2_register_driver(void)
+{
+	return platform_driver_register(&msm_dsi_v2_driver);
+}
+
+static int __init msm_dsi_v2_driver_init(void)
+{
+	int ret;
+
+	ret = msm_dsi_v2_register_driver();
+	if (ret) {
+		pr_err("msm_dsi_v2_register_driver() failed!\n");
+		return ret;
+	}
+
+	return ret;
+}
+module_init(msm_dsi_v2_driver_init);
+
+static void __exit msm_dsi_v2_driver_cleanup(void)
+{
+	platform_driver_unregister(&msm_dsi_v2_driver);
+}
+module_exit(msm_dsi_v2_driver_cleanup);
diff --git a/drivers/video/msm/mdss/dsi_host_v2.h b/drivers/video/msm/mdss/dsi_host_v2.h
new file mode 100644
index 0000000..cec9774
--- /dev/null
+++ b/drivers/video/msm/mdss/dsi_host_v2.h
@@ -0,0 +1,169 @@
+/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+#ifndef DSI_HOST_V2_H
+#define DSI_HOST_V2_H
+
+#include <linux/bitops.h>
+
+#define DSI_INTR_ERROR_MASK			BIT(25)
+#define DSI_INTR_ERROR				BIT(24)
+#define DSI_INTR_VIDEO_DONE_MASK		BIT(17)
+#define DSI_INTR_VIDEO_DONE			BIT(16)
+#define DSI_INTR_CMD_MDP_DONE_MASK		BIT(9)
+#define DSI_INTR_CMD_MDP_DONE			BIT(8)
+#define DSI_INTR_CMD_DMA_DONE_MASK		BIT(1)
+#define DSI_INTR_CMD_DMA_DONE			BIT(0)
+
+#define DSI_CTRL				0x0000
+#define DSI_STATUS				0x0004
+#define DSI_FIFO_STATUS			0x0008
+#define DSI_VIDEO_MODE_CTRL			0x000C
+#define DSI_VIDEO_MODE_DATA_CTRL		0x001C
+#define DSI_VIDEO_MODE_ACTIVE_H			0x0020
+#define DSI_VIDEO_MODE_ACTIVE_V		0x0024
+#define DSI_VIDEO_MODE_TOTAL		0x0028
+#define DSI_VIDEO_MODE_HSYNC			0x002C
+#define DSI_VIDEO_MODE_VSYNC			0x0030
+#define DSI_VIDEO_MODE_VSYNC_VPOS		0x0034
+#define DSI_COMMAND_MODE_DMA_CTRL		0x0038
+#define DSI_COMMAND_MODE_MDP_CTRL		0x003C
+#define DSI_COMMAND_MODE_MDP_DCS_CMD_CTRL	0x0040
+#define DSI_DMA_CMD_OFFSET			0x0044
+#define DSI_DMA_CMD_LENGTH			0x0048
+#define DSI_DMA_FIFO_CTRL			0x004C
+#define DSI_COMMAND_MODE_MDP_STREAM0_CTRL	0x0054
+#define DSI_COMMAND_MODE_MDP_STREAM0_TOTAL	0x0058
+#define DSI_COMMAND_MODE_MDP_STREAM1_CTRL	0x005C
+#define DSI_COMMAND_MODE_MDP_STREAM1_TOTAL	0x0060
+#define DSI_ACK_ERR_STATUS			0x0064
+#define DSI_RDBK_DATA0				0x0068
+#define DSI_RDBK_DATA1				0x006C
+#define DSI_RDBK_DATA2				0x0070
+#define DSI_RDBK_DATA3				0x0074
+#define DSI_RDBK_DATATYPE0			0x0078
+#define DSI_RDBK_DATATYPE1			0x007C
+#define DSI_TRIG_CTRL				0x0080
+#define DSI_EXT_MUX				0x0084
+#define DSI_EXT_TE_PULSE_DETECT_CTRL		0x0088
+#define DSI_CMD_MODE_DMA_SW_TRIGGER		0x008C
+#define DSI_CMD_MODE_MDP_SW_TRIGGER		0x0090
+#define DSI_CMD_MODE_BTA_SW_TRIGGER		0x0094
+#define DSI_RESET_SW_TRIGGER			0x0098
+#define DSI_LANE_CTRL				0x00A8
+#define DSI_LANE_SWAP_CTRL			0x00AC
+#define DSI_DLN0_PHY_ERR			0x00B0
+#define DSI_TIMEOUT_STATUS			0x00BC
+#define DSI_CLKOUT_TIMING_CTRL			0x00C0
+#define DSI_EOT_PACKET				0x00C4
+#define DSI_EOT_PACKET_CTRL			0x00C8
+#define DSI_ERR_INT_MASK0			0x0108
+#define DSI_INT_CTRL				0x010c
+#define DSI_SOFT_RESET				0x0114
+#define DSI_CLK_CTRL				0x0118
+#define DSI_CLK_STATUS				0x011C
+#define DSI_PHY_SW_RESET			0x0128
+#define DSI_COMMAND_MODE_MDP_IDLE_CTRL		0x0190
+#define DSI_VERSION				0x01F0
+
+#define DSI_DSIPHY_PLL_CTRL_0			0x0200
+#define DSI_DSIPHY_PLL_CTRL_1			0x0204
+#define DSI_DSIPHY_PLL_CTRL_2			0x0208
+#define DSI_DSIPHY_PLL_CTRL_3			0x020C
+#define DSI_DSIPHY_PLL_CTRL_4			0x0210
+#define DSI_DSIPHY_PLL_CTRL_5			0x0214
+#define DSI_DSIPHY_PLL_CTRL_6			0x0218
+#define DSI_DSIPHY_PLL_CTRL_7			0x021C
+#define DSI_DSIPHY_PLL_CTRL_8			0x0220
+#define DSI_DSIPHY_PLL_CTRL_9			0x0224
+#define DSI_DSIPHY_PLL_CTRL_10			0x0228
+#define DSI_DSIPHY_PLL_CTRL_11			0x022C
+#define DSI_DSIPHY_PLL_CTRL_12			0x0230
+#define DSI_DSIPHY_PLL_CTRL_13			0x0234
+#define DSI_DSIPHY_PLL_CTRL_14			0x0238
+#define DSI_DSIPHY_PLL_CTRL_15			0x023C
+#define DSI_DSIPHY_PLL_CTRL_16			0x0240
+#define DSI_DSIPHY_PLL_CTRL_17			0x0244
+#define DSI_DSIPHY_PLL_CTRL_18			0x0248
+#define DSI_DSIPHY_PLL_CTRL_19			0x024C
+#define DSI_DSIPHY_ANA_CTRL0			0x0260
+#define DSI_DSIPHY_ANA_CTRL1			0x0264
+#define DSI_DSIPHY_ANA_CTRL2			0x0268
+#define DSI_DSIPHY_ANA_CTRL3			0x026C
+#define DSI_DSIPHY_ANA_CTRL4			0x0270
+#define DSI_DSIPHY_ANA_CTRL5			0x0274
+#define DSI_DSIPHY_ANA_CTRL6			0x0278
+#define DSI_DSIPHY_ANA_CTRL7			0x027C
+#define DSI_DSIPHY_PLL_RDY			0x0280
+#define DSI_DSIPHY_PLL_ANA_STATUS0		0x0294
+#define DSI_DSIPHY_PLL_ANA_STATUS1		0x0298
+#define DSI_DSIPHY_PLL_ANA_STATUS2		0x029C
+#define DSI_DSIPHY_LN0_CFG0			0x0300
+#define DSI_DSIPHY_LN0_CFG1			0x0304
+#define DSI_DSIPHY_LN0_CFG2			0x0308
+#define DSI_DSIPHY_LN1_CFG0			0x0340
+#define DSI_DSIPHY_LN1_CFG1			0x0344
+#define DSI_DSIPHY_LN1_CFG2			0x0348
+#define DSI_DSIPHY_LN2_CFG0			0x0380
+#define DSI_DSIPHY_LN2_CFG1			0x0384
+#define DSI_DSIPHY_LN2_CFG2			0x0388
+#define DSI_DSIPHY_LN3_CFG0			0x03C0
+#define DSI_DSIPHY_LN3_CFG1			0x03C4
+#define DSI_DSIPHY_LN3_CFG2			0x03C8
+#define DSI_DSIPHY_LNCK_CFG0			0x0400
+#define DSI_DSIPHY_LNCK_CFG1			0x0404
+#define DSI_DSIPHY_LNCK_CFG2			0x0408
+#define DSI_DSIPHY_TIMING_CTRL_0		0x0440
+#define DSI_DSIPHY_TIMING_CTRL_1		0x0444
+#define DSI_DSIPHY_TIMING_CTRL_2		0x0448
+#define DSI_DSIPHY_TIMING_CTRL_3		0x044C
+#define DSI_DSIPHY_TIMING_CTRL_4		0x0450
+#define DSI_DSIPHY_TIMING_CTRL_5		0x0454
+#define DSI_DSIPHY_TIMING_CTRL_6		0x0458
+#define DSI_DSIPHY_TIMING_CTRL_7		0x045C
+#define DSI_DSIPHY_TIMING_CTRL_8		0x0460
+#define DSI_DSIPHY_TIMING_CTRL_9		0x0464
+#define DSI_DSIPHY_TIMING_CTRL_10		0x0468
+#define DSI_DSIPHY_TIMING_CTRL_11		0x046C
+#define DSI_DSIPHY_CTRL_0			0x0470
+#define DSI_DSIPHY_CTRL_1			0x0474
+#define DSI_DSIPHY_CTRL_2			0x0478
+#define DSI_DSIPHY_CTRL_3			0x047C
+#define DSI_DSIPHY_STRENGTH_CTRL_0		0x0480
+#define DSI_DSIPHY_STRENGTH_CTRL_1		0x0484
+#define DSI_DSIPHY_STRENGTH_CTRL_2		0x0488
+#define DSI_DSIPHY_LDO_CNTRL			0x04B0
+#define DSI_DSIPHY_REGULATOR_CTRL_0		0x0500
+#define DSI_DSIPHY_REGULATOR_CTRL_1		0x0504
+#define DSI_DSIPHY_REGULATOR_CTRL_2		0x0508
+#define DSI_DSIPHY_REGULATOR_CTRL_3		0x050C
+#define DSI_DSIPHY_REGULATOR_CTRL_4		0x0510
+#define DSI_DSIPHY_REGULATOR_TEST		0x0514
+#define DSI_DSIPHY_REGULATOR_CAL_PWR_CFG	0x0518
+#define DSI_DSIPHY_CAL_HW_TRIGGER		0x0528
+#define DSI_DSIPHY_CAL_SW_CFG0			0x052C
+#define DSI_DSIPHY_CAL_SW_CFG1			0x0530
+#define DSI_DSIPHY_CAL_SW_CFG2			0x0534
+#define DSI_DSIPHY_CAL_HW_CFG0			0x0538
+#define DSI_DSIPHY_CAL_HW_CFG1			0x053C
+#define DSI_DSIPHY_CAL_HW_CFG2			0x0540
+#define DSI_DSIPHY_CAL_HW_CFG3			0x0544
+#define DSI_DSIPHY_CAL_HW_CFG4			0x0548
+#define DSI_DSIPHY_REGULATOR_CAL_STATUS0	0x0550
+#define DSI_DSIPHY_BIST_CTRL0			0x048C
+#define DSI_DSIPHY_BIST_CTRL1			0x0490
+#define DSI_DSIPHY_BIST_CTRL2			0x0494
+#define DSI_DSIPHY_BIST_CTRL3			0x0498
+#define DSI_DSIPHY_BIST_CTRL4			0x049C
+#define DSI_DSIPHY_BIST_CTRL5			0x04A0
+
+#endif /* DSI_HOST_V2_H */
diff --git a/drivers/video/msm/mdss/dsi_io_v2.c b/drivers/video/msm/mdss/dsi_io_v2.c
new file mode 100644
index 0000000..0486c4c
--- /dev/null
+++ b/drivers/video/msm/mdss/dsi_io_v2.c
@@ -0,0 +1,426 @@
+/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/slab.h>
+#include <linux/regulator/consumer.h>
+
+#include <mach/clk.h>
+
+#include "dsi_v2.h"
+#include "dsi_io_v2.h"
+#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;
+	struct clk *dsi_ahb_clk;
+	int msm_dsi_clk_on;
+	int msm_dsi_ahb_clk_on;
+};
+
+static struct msm_dsi_io_private *dsi_io_private;
+
+#define DSI_VDDA_VOLTAGE 1200000
+
+void msm_dsi_ahb_ctrl(int enable)
+{
+	if (enable) {
+		if (dsi_io_private->msm_dsi_ahb_clk_on) {
+			pr_debug("ahb clks already ON\n");
+			return;
+		}
+		clk_enable(dsi_io_private->dsi_ahb_clk);
+		dsi_io_private->msm_dsi_ahb_clk_on = 1;
+	} else {
+		if (dsi_io_private->msm_dsi_ahb_clk_on == 0) {
+			pr_debug("ahb clk already OFF\n");
+			return;
+		}
+		clk_disable(dsi_io_private->dsi_ahb_clk);
+		dsi_io_private->msm_dsi_ahb_clk_on = 0;
+	}
+}
+
+int msm_dsi_io_init(struct platform_device *dev)
+{
+	int rc;
+
+	if (!dsi_io_private) {
+		dsi_io_private = kzalloc(sizeof(struct msm_dsi_io_private),
+					GFP_KERNEL);
+		if (!dsi_io_private) {
+			pr_err("fail to alloc dsi io private data structure\n");
+			return -ENOMEM;
+		}
+	}
+
+	rc = msm_dsi_clk_init(dev);
+	if (rc) {
+		pr_err("fail to initialize DSI clock\n");
+		return rc;
+	}
+
+	rc = msm_dsi_regulator_init(dev);
+	if (rc) {
+		pr_err("fail to initialize DSI regulator\n");
+		return rc;
+	}
+	return 0;
+}
+
+void msm_dsi_io_deinit(void)
+{
+	if (dsi_io_private) {
+		msm_dsi_clk_deinit();
+		msm_dsi_regulator_deinit();
+		kfree(dsi_io_private);
+		dsi_io_private = NULL;
+	}
+}
+
+int msm_dsi_clk_init(struct platform_device *dev)
+{
+	int rc = 0;
+
+	dsi_io_private->dsi_byte_clk = clk_get(&dev->dev, "byte_clk");
+	if (IS_ERR(dsi_io_private->dsi_byte_clk)) {
+		pr_err("can't find dsi byte_clk\n");
+		rc = PTR_ERR(dsi_io_private->dsi_byte_clk);
+		dsi_io_private->dsi_byte_clk = NULL;
+		return rc;
+	}
+
+	dsi_io_private->dsi_esc_clk = clk_get(&dev->dev, "esc_clk");
+	if (IS_ERR(dsi_io_private->dsi_esc_clk)) {
+		pr_err("can't find dsi esc_clk\n");
+		rc = PTR_ERR(dsi_io_private->dsi_esc_clk);
+		dsi_io_private->dsi_esc_clk = NULL;
+		return rc;
+	}
+
+	dsi_io_private->dsi_pixel_clk = clk_get(&dev->dev, "pixel_clk");
+	if (IS_ERR(dsi_io_private->dsi_pixel_clk)) {
+		pr_err("can't find dsi pixel\n");
+		rc = PTR_ERR(dsi_io_private->dsi_pixel_clk);
+		dsi_io_private->dsi_pixel_clk = NULL;
+		return rc;
+	}
+
+	dsi_io_private->dsi_ahb_clk = clk_get(&dev->dev, "iface_clk");
+	if (IS_ERR(dsi_io_private->dsi_ahb_clk)) {
+		pr_err("can't find dsi iface_clk\n");
+		rc = PTR_ERR(dsi_io_private->dsi_ahb_clk);
+		dsi_io_private->dsi_ahb_clk = NULL;
+		return rc;
+	}
+	clk_prepare(dsi_io_private->dsi_ahb_clk);
+
+	return 0;
+}
+
+void msm_dsi_clk_deinit(void)
+{
+	if (dsi_io_private->dsi_byte_clk) {
+		clk_put(dsi_io_private->dsi_byte_clk);
+		dsi_io_private->dsi_byte_clk = NULL;
+	}
+	if (dsi_io_private->dsi_esc_clk) {
+		clk_put(dsi_io_private->dsi_esc_clk);
+		dsi_io_private->dsi_esc_clk = NULL;
+	}
+	if (dsi_io_private->dsi_pixel_clk) {
+		clk_put(dsi_io_private->dsi_pixel_clk);
+		dsi_io_private->dsi_pixel_clk = NULL;
+	}
+	if (dsi_io_private->dsi_ahb_clk) {
+		clk_unprepare(dsi_io_private->dsi_ahb_clk);
+		clk_put(dsi_io_private->dsi_ahb_clk);
+		dsi_io_private->dsi_ahb_clk = NULL;
+	}
+}
+
+int msm_dsi_prepare_clocks(void)
+{
+	clk_prepare(dsi_io_private->dsi_byte_clk);
+	clk_prepare(dsi_io_private->dsi_esc_clk);
+	clk_prepare(dsi_io_private->dsi_pixel_clk);
+	return 0;
+}
+
+int msm_dsi_unprepare_clocks(void)
+{
+	clk_unprepare(dsi_io_private->dsi_esc_clk);
+	clk_unprepare(dsi_io_private->dsi_byte_clk);
+	clk_unprepare(dsi_io_private->dsi_pixel_clk);
+	return 0;
+}
+
+int msm_dsi_clk_set_rate(unsigned long esc_rate, unsigned long byte_rate,
+			unsigned long pixel_rate)
+{
+	int rc;
+
+	rc = clk_set_rate(dsi_io_private->dsi_esc_clk, esc_rate);
+	if (rc) {
+		pr_err("dsi_esc_clk - clk_set_rate failed =%d\n", rc);
+		return rc;
+	}
+
+	rc = clk_set_rate(dsi_io_private->dsi_byte_clk, byte_rate);
+	if (rc) {
+		pr_err("dsi_byte_clk - clk_set_rate faile = %dd\n", rc);
+		return rc;
+	}
+
+	rc = clk_set_rate(dsi_io_private->dsi_pixel_clk, pixel_rate);
+	if (rc) {
+		pr_err("dsi_pixel_clk - clk_set_rate failed = %d\n", rc);
+		return rc;
+	}
+	return 0;
+}
+
+int  msm_dsi_clk_enable(void)
+{
+	if (dsi_io_private->msm_dsi_clk_on) {
+		pr_debug("dsi_clks on already\n");
+		return 0;
+	}
+
+	clk_enable(dsi_io_private->dsi_esc_clk);
+	clk_enable(dsi_io_private->dsi_byte_clk);
+	clk_enable(dsi_io_private->dsi_pixel_clk);
+
+	dsi_io_private->msm_dsi_clk_on = 1;
+	return 0;
+}
+
+int msm_dsi_clk_disable(void)
+{
+	if (dsi_io_private->msm_dsi_clk_on == 0) {
+		pr_debug("mdss_dsi_clks already OFF\n");
+		return 0;
+	}
+
+	clk_disable(dsi_io_private->dsi_byte_clk);
+	clk_disable(dsi_io_private->dsi_esc_clk);
+	clk_disable(dsi_io_private->dsi_pixel_clk);
+
+	dsi_io_private->msm_dsi_clk_on = 0;
+	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 (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)
+{
+	MIPI_OUTP(ctrl_base + DSI_DSIPHY_STRENGTH_CTRL_0, pd->strength[0]);
+	MIPI_OUTP(ctrl_base + DSI_DSIPHY_STRENGTH_CTRL_2, pd->strength[1]);
+}
+
+static void msm_dsi_phy_ctrl_init(unsigned char *ctrl_base,
+				struct mdss_panel_data *pdata)
+{
+	MIPI_OUTP(ctrl_base + DSI_DSIPHY_CTRL_0, 0x5f);
+	MIPI_OUTP(ctrl_base + DSI_DSIPHY_CTRL_3, 0x10);
+}
+
+static void msm_dsi_phy_regulator_init(unsigned char *ctrl_base,
+					struct mdss_dsi_phy_ctrl *pd)
+{
+	MIPI_OUTP(ctrl_base + DSI_DSIPHY_LDO_CNTRL, 0x04);
+	MIPI_OUTP(ctrl_base + DSI_DSIPHY_REGULATOR_CTRL_0, pd->regulator[0]);
+	MIPI_OUTP(ctrl_base + DSI_DSIPHY_REGULATOR_CTRL_1, pd->regulator[1]);
+	MIPI_OUTP(ctrl_base + DSI_DSIPHY_REGULATOR_CTRL_2, pd->regulator[2]);
+	MIPI_OUTP(ctrl_base + DSI_DSIPHY_REGULATOR_CTRL_3, pd->regulator[3]);
+	MIPI_OUTP(ctrl_base + DSI_DSIPHY_REGULATOR_CTRL_4, pd->regulator[4]);
+	MIPI_OUTP(ctrl_base + DSI_DSIPHY_REGULATOR_CAL_PWR_CFG,
+			pd->regulator[5]);
+
+}
+
+static int msm_dsi_phy_calibration(unsigned char *ctrl_base)
+{
+	int i = 0, term_cnt = 5000, ret = 0, cal_busy;
+
+	MIPI_OUTP(ctrl_base + DSI_DSIPHY_CAL_SW_CFG2, 0x0);
+	MIPI_OUTP(ctrl_base + DSI_DSIPHY_CAL_HW_CFG1, 0x5a);
+	MIPI_OUTP(ctrl_base + DSI_DSIPHY_CAL_HW_CFG3, 0x10);
+	MIPI_OUTP(ctrl_base + DSI_DSIPHY_CAL_HW_CFG4, 0x01);
+	MIPI_OUTP(ctrl_base + DSI_DSIPHY_CAL_HW_CFG0, 0x01);
+	MIPI_OUTP(ctrl_base + DSI_DSIPHY_CAL_HW_TRIGGER, 0x01);
+	usleep_range(5000, 5000); /*per DSI controller spec*/
+	MIPI_OUTP(ctrl_base + DSI_DSIPHY_CAL_HW_TRIGGER, 0x00);
+
+	cal_busy = MIPI_INP(ctrl_base + DSI_DSIPHY_REGULATOR_CAL_STATUS0);
+	while (cal_busy & 0x10) {
+		i++;
+		if (i > term_cnt) {
+			ret = -EINVAL;
+			pr_err("msm_dsi_phy_calibration error\n");
+			break;
+		}
+		cal_busy = MIPI_INP(ctrl_base +
+					DSI_DSIPHY_REGULATOR_CAL_STATUS0);
+	}
+
+	return ret;
+}
+
+static void msm_dsi_phy_lane_init(unsigned char *ctrl_base,
+			struct mdss_dsi_phy_ctrl *pd)
+{
+	int ln, index;
+
+	/*CFG0, CFG1, CFG2, TEST_DATAPATH, TEST_STR0, TEST_STR1*/
+	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]);
+	}
+	wmb();
+}
+
+static void msm_dsi_phy_timing_init(unsigned char *ctrl_base,
+			struct mdss_dsi_phy_ctrl *pd)
+{
+	int i, off = DSI_DSIPHY_TIMING_CTRL_0;
+	for (i = 0; i < 12; i++) {
+		MIPI_OUTP(ctrl_base + off, pd->timing[i]);
+		off += 4;
+	}
+	wmb();
+}
+
+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, 0);
+	wmb();
+}
+
+int msm_dsi_phy_init(unsigned char *ctrl_base,
+			struct mdss_panel_data *pdata)
+{
+	struct mdss_dsi_phy_ctrl *pd;
+
+	pd = pdata->panel_info.mipi.dsi_phy_db;
+
+	msm_dsi_phy_strength_init(ctrl_base, pd);
+
+	msm_dsi_phy_ctrl_init(ctrl_base, pdata);
+
+	msm_dsi_phy_regulator_init(ctrl_base, pd);
+
+	msm_dsi_phy_calibration(ctrl_base);
+
+	msm_dsi_phy_lane_init(ctrl_base, pd);
+
+	msm_dsi_phy_timing_init(ctrl_base, pd);
+
+	msm_dsi_phy_bist_init(ctrl_base, pd);
+
+	return 0;
+}
+
+void msm_dsi_phy_sw_reset(unsigned char *ctrl_base)
+{
+	/* start phy sw reset */
+	MIPI_OUTP(ctrl_base + DSI_PHY_SW_RESET, 0x0001);
+	udelay(1000); /*per DSI controller spec*/
+	wmb();
+	/* end phy sw reset */
+	MIPI_OUTP(ctrl_base + DSI_PHY_SW_RESET, 0x0000);
+	udelay(100); /*per DSI controller spec*/
+	wmb();
+}
+
+void msm_dsi_phy_enable(unsigned char *ctrl_base, int on)
+{
+	if (on) {
+		MIPI_OUTP(ctrl_base + DSI_DSIPHY_PLL_CTRL_5, 0x050);
+	} else {
+		MIPI_OUTP(ctrl_base + DSI_DSIPHY_PLL_CTRL_5, 0x05f);
+		MIPI_OUTP(ctrl_base + DSI_DSIPHY_REGULATOR_CTRL_0, 0x02);
+		MIPI_OUTP(ctrl_base + DSI_DSIPHY_CTRL_0, 0x00);
+		MIPI_OUTP(ctrl_base + DSI_DSIPHY_CTRL_1, 0x7f);
+		MIPI_OUTP(ctrl_base + DSI_CLK_CTRL, 0);
+	}
+}
diff --git a/drivers/video/msm/mdss/dsi_io_v2.h b/drivers/video/msm/mdss/dsi_io_v2.h
new file mode 100644
index 0000000..25ecd7f
--- /dev/null
+++ b/drivers/video/msm/mdss/dsi_io_v2.h
@@ -0,0 +1,52 @@
+/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+#ifndef DSI_IO_V2_H
+#define DSI_IO_V2_H
+
+#include "mdss_panel.h"
+
+void msm_dsi_ahb_ctrl(int enable);
+
+int msm_dsi_io_init(struct platform_device *dev);
+
+void msm_dsi_io_deinit(void);
+
+int msm_dsi_clk_init(struct platform_device *dev);
+
+void msm_dsi_clk_deinit(void);
+
+int msm_dsi_prepare_clocks(void);
+
+int msm_dsi_unprepare_clocks(void);
+
+int msm_dsi_clk_set_rate(unsigned long esc_rate, unsigned long byte_rate,
+			unsigned long pixel_rate);
+
+int msm_dsi_clk_enable(void);
+
+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);
+
+void msm_dsi_phy_sw_reset(unsigned char *ctrl_base);
+
+#endif /* DSI_IO_V2_H */
diff --git a/drivers/video/msm/mdss/dsi_panel_v2.c b/drivers/video/msm/mdss/dsi_panel_v2.c
new file mode 100644
index 0000000..6686de3
--- /dev/null
+++ b/drivers/video/msm/mdss/dsi_panel_v2.c
@@ -0,0 +1,753 @@
+/* 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/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;
+	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;
+};
+
+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 (panel_private->vddio_vreg)
+		devm_regulator_put(panel_private->vddio_vreg);
+
+	if (panel_private->vdda_vreg)
+		devm_regulator_put(panel_private->vddio_vreg);
+
+	kfree(panel_private);
+	panel_private = NULL;
+}
+
+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) {
+		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_set_value(panel_private->disp_en_gpio, 1);
+	} else {
+		gpio_set_value(panel_private->rst_gpio, 0);
+		if (gpio_is_valid(panel_private->disp_en_gpio))
+			gpio_set_value(panel_private->disp_en_gpio, 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;
+
+		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);
+
+	if (mipi->mode == DSI_VIDEO_MODE) {
+		dsi_cmds_tx_v2(pdata, &panel_private->dsi_panel_tx_buf,
+				panel_private->on_cmds_list->buf,
+				panel_private->on_cmds_list->size);
+	} else {
+		pr_err("%s:%d, CMD MODE NOT SUPPORTED", __func__, __LINE__);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+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__);
+
+	if (mipi->mode == DSI_VIDEO_MODE) {
+		dsi_cmds_tx_v2(pdata, &panel_private->dsi_panel_tx_buf,
+				panel_private->off_cmds_list->buf,
+				panel_private->off_cmds_list->size);
+	} else {
+		pr_debug("%s:%d, CMD mode not supported", __func__, __LINE__);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+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);
+	return 0;
+}
+
+static int dsi_panel_parse_regulator(struct platform_device *pdev)
+{
+	panel_private->vddio_vreg = devm_regulator_get(&pdev->dev, "vddio");
+	panel_private->vdda_vreg = devm_regulator_get(&pdev->dev, "vdda");
+	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;
+	u32 res[6], tmp;
+	int i, len, rc;
+	const char *data;
+
+	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-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);
+
+	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;
+	char *on_cmds = NULL, *off_cmds = NULL;
+	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__);
+		goto parse_init_cmds_error;
+	}
+
+	on_cmds = kzalloc(sizeof(char) * len, GFP_KERNEL);
+	if (!on_cmds)
+		goto parse_init_cmds_error;
+
+	memcpy(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 = 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__);
+		goto parse_init_cmds_error;
+	}
+
+	panel_data->dsi_panel_on_cmds =
+		kzalloc(sizeof(struct dsi_panel_cmds_list), GFP_KERNEL);
+	if (!panel_data->dsi_panel_on_cmds)
+		goto parse_init_cmds_error;
+
+	(panel_data->dsi_panel_on_cmds)->buf =
+		kzalloc((num_of_on_cmds * sizeof(struct dsi_cmd_desc)),
+			GFP_KERNEL);
+	if (!(panel_data->dsi_panel_on_cmds)->buf)
+		goto parse_init_cmds_error;
+
+	data_offset = 0;
+	for (i = 0; i < num_of_on_cmds; i++) {
+		panel_data->dsi_panel_on_cmds->buf[i].dtype =
+						on_cmds[data_offset++];
+		panel_data->dsi_panel_on_cmds->buf[i].last =
+						on_cmds[data_offset++];
+		panel_data->dsi_panel_on_cmds->buf[i].vc =
+						on_cmds[data_offset++];
+		panel_data->dsi_panel_on_cmds->buf[i].ack =
+						on_cmds[data_offset++];
+		panel_data->dsi_panel_on_cmds->buf[i].wait =
+						on_cmds[data_offset++];
+		panel_data->dsi_panel_on_cmds->buf[i].dlen =
+						on_cmds[data_offset++];
+		panel_data->dsi_panel_on_cmds->buf[i].payload =
+						&on_cmds[data_offset];
+		data_offset += (panel_data->dsi_panel_on_cmds->buf[i].dlen);
+	}
+
+	if (data_offset != len) {
+		pr_err("%s:%d, Incorrect ON command entries",
+						__func__, __LINE__);
+		goto parse_init_cmds_error;
+	}
+
+	(panel_data->dsi_panel_on_cmds)->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_data->dsi_panel_on_cmds)->ctrl_state = DSI_LP_MODE;
+	} else if (!strncmp(on_cmds_state, "DSI_HS_MODE", 11)) {
+		(panel_data->dsi_panel_on_cmds)->ctrl_state = DSI_HS_MODE;
+	} else {
+		pr_debug("%s: ON cmds state not specified. Set Default\n",
+							__func__);
+		(panel_data->dsi_panel_on_cmds)->ctrl_state = DSI_LP_MODE;
+	}
+
+	panel_private->on_cmds_list = panel_data->dsi_panel_on_cmds;
+	data = of_get_property(np, "qcom,panel-off-cmds", &len);
+	if (!data) {
+		pr_err("%s:%d, Unable to read OFF cmds", __func__, __LINE__);
+		goto parse_init_cmds_error;
+	}
+
+	off_cmds = kzalloc(sizeof(char) * len, GFP_KERNEL);
+	if (!off_cmds)
+		goto parse_init_cmds_error;
+
+	memcpy(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 = 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__);
+		goto parse_init_cmds_error;
+	}
+
+	panel_data->dsi_panel_off_cmds =
+		kzalloc(sizeof(struct dsi_panel_cmds_list), GFP_KERNEL);
+	if (!panel_data->dsi_panel_off_cmds)
+		goto parse_init_cmds_error;
+
+	(panel_data->dsi_panel_off_cmds)->buf = kzalloc(num_of_off_cmds
+					* sizeof(struct dsi_cmd_desc),
+						GFP_KERNEL);
+	if (!(panel_data->dsi_panel_off_cmds)->buf)
+		goto parse_init_cmds_error;
+
+	data_offset = 0;
+	for (i = 0; i < num_of_off_cmds; i++) {
+		panel_data->dsi_panel_off_cmds->buf[i].dtype =
+						off_cmds[data_offset++];
+		panel_data->dsi_panel_off_cmds->buf[i].last =
+						off_cmds[data_offset++];
+		panel_data->dsi_panel_off_cmds->buf[i].vc =
+						off_cmds[data_offset++];
+		panel_data->dsi_panel_off_cmds->buf[i].ack =
+						off_cmds[data_offset++];
+		panel_data->dsi_panel_off_cmds->buf[i].wait =
+						off_cmds[data_offset++];
+		panel_data->dsi_panel_off_cmds->buf[i].dlen =
+						off_cmds[data_offset++];
+		panel_data->dsi_panel_off_cmds->buf[i].payload =
+						&off_cmds[data_offset];
+		data_offset += (panel_data->dsi_panel_off_cmds->buf[i].dlen);
+	}
+
+	if (data_offset != len) {
+		pr_err("%s:%d, Incorrect OFF command entries",
+						__func__, __LINE__);
+		goto parse_init_cmds_error;
+	}
+
+	(panel_data->dsi_panel_off_cmds)->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_data->dsi_panel_off_cmds)->ctrl_state =
+						DSI_LP_MODE;
+	} else if (!strncmp(off_cmds_state, "DSI_HS_MODE", 11)) {
+		(panel_data->dsi_panel_off_cmds)->ctrl_state = DSI_HS_MODE;
+	} else {
+		pr_debug("%s: ON cmds state not specified. Set Default\n",
+							__func__);
+		(panel_data->dsi_panel_off_cmds)->ctrl_state = DSI_LP_MODE;
+	}
+
+	panel_private->off_cmds_list = panel_data->dsi_panel_on_cmds;
+	kfree(on_cmds);
+	kfree(off_cmds);
+
+	return 0;
+parse_init_cmds_error:
+	if (panel_data->dsi_panel_on_cmds) {
+		kfree((panel_data->dsi_panel_on_cmds)->buf);
+		kfree(panel_data->dsi_panel_on_cmds);
+		panel_data->dsi_panel_on_cmds = NULL;
+	}
+	if (panel_data->dsi_panel_off_cmds) {
+		kfree((panel_data->dsi_panel_off_cmds)->buf);
+		kfree(panel_data->dsi_panel_off_cmds);
+		panel_data->dsi_panel_off_cmds = NULL;
+	}
+
+	kfree(on_cmds);
+	kfree(off_cmds);
+	return -EINVAL;
+}
+
+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;
+	}
+
+	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;
+
+	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);
+
+	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_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.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
new file mode 100644
index 0000000..5e46bf5
--- /dev/null
+++ b/drivers/video/msm/mdss/dsi_v2.c
@@ -0,0 +1,789 @@
+/* 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/delay.h>
+#include <linux/io.h>
+#include <linux/dma-mapping.h>
+#include <linux/slab.h>
+#include <linux/iopoll.h>
+#include <linux/of_device.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 int dsi_off(struct mdss_panel_data *pdata)
+{
+	int rc = 0;
+	if (!panel_common_data || !pdata)
+		return -ENODEV;
+
+	if (dsi_intf.off)
+		rc = dsi_intf.off(pdata);
+
+	if (rc) {
+		pr_err("mdss_dsi_off DSI failed %d\n", rc);
+		return rc;
+	}
+
+	pr_debug("dsi_off reset\n");
+	if (panel_common_data->off)
+		panel_common_data->off(pdata);
+
+	return rc;
+}
+
+static int dsi_on(struct mdss_panel_data *pdata)
+{
+	int rc = 0;
+
+	pr_debug("dsi_on\n");
+
+	if (!panel_common_data || !pdata)
+		return -ENODEV;
+
+	if (panel_common_data->reset)
+		panel_common_data->reset(1);
+
+	pr_debug("dsi_on DSI controller ont\n");
+	if (dsi_intf.on)
+		rc = dsi_intf.on(pdata);
+
+	if (rc) {
+		pr_err("mdss_dsi_on DSI failed %d\n", rc);
+		return rc;
+	}
+
+	pr_debug("dsi_on DSI panel ont\n");
+	if (panel_common_data->on)
+		rc = panel_common_data->on(pdata);
+
+	if (rc) {
+		pr_err("mdss_dsi_on panel failed %d\n", rc);
+		return rc;
+	}
+	return rc;
+}
+
+static int dsi_event_handler(struct mdss_panel_data *pdata,
+				int event, void *arg)
+{
+	int rc = 0;
+
+	if (!pdata || !panel_common_data) {
+		pr_err("%s: Invalid input data\n", __func__);
+		return -ENODEV;
+	}
+
+	switch (event) {
+	case MDSS_EVENT_PANEL_ON:
+		rc = dsi_on(pdata);
+		break;
+	case MDSS_EVENT_PANEL_OFF:
+		rc = dsi_off(pdata);
+		break;
+	default:
+		pr_debug("%s: unhandled event=%d\n", __func__, event);
+		break;
+	}
+	return rc;
+}
+
+static struct platform_device *get_dsi_platform_device(
+			struct platform_device *dev)
+{
+	struct device_node *dsi_ctrl_np;
+	struct platform_device *ctrl_pdev;
+
+	dsi_ctrl_np = of_parse_phandle(dev->dev.of_node,
+					"qcom,dsi-ctrl-phandle", 0);
+
+	if (!dsi_ctrl_np)
+		return NULL;
+
+	ctrl_pdev = of_find_device_by_node(dsi_ctrl_np);
+	if (!ctrl_pdev)
+		return NULL;
+
+	return ctrl_pdev;
+}
+
+int dsi_panel_device_register_v2(struct platform_device *dev,
+				struct dsi_panel_common_pdata *panel_data,
+				char backlight_ctrl)
+{
+	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;
+
+	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));
+
+	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));
+
+	mipi  = &panel_data->panel_info.mipi;
+
+	panel_data->panel_info.type =
+		((mipi->mode == DSI_VIDEO_MODE)
+			? MIPI_VIDEO_PANEL : MIPI_CMD_PANEL);
+
+	if (mipi->data_lane3)
+		lanes += 1;
+	if (mipi->data_lane2)
+		lanes += 1;
+	if (mipi->data_lane1)
+		lanes += 1;
+	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))
+		bpp = 3;
+	else if ((mipi->dst_format == DSI_CMD_DST_FORMAT_RGB565)
+		|| (mipi->dst_format == DSI_VIDEO_DST_FORMAT_RGB565))
+		bpp = 2;
+	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 (lanes > 0) {
+			panel_data->panel_info.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 =
+				(h_period * v_period
+					 * (mipi->frame_rate) * bpp * 8);
+		}
+	}
+
+	ctrl_pdev = get_dsi_platform_device(dev);
+	if (!ctrl_pdev)
+		return -EPROBE_DEFER;
+
+	dsi_panel_data.event_handler = dsi_event_handler;
+
+	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);
+	if (rc) {
+		dev_err(&dev->dev, "unable to register MIPI DSI panel\n");
+		return rc;
+	}
+
+	pr_debug("%s: Panal data initialized\n", __func__);
+	return 0;
+}
+
+void dsi_register_interface(struct dsi_interface *intf)
+{
+	dsi_intf = *intf;
+}
+
+int dsi_cmds_tx_v2(struct mdss_panel_data *pdata,
+			struct dsi_buf *tp, struct dsi_cmd_desc *cmds,
+			int cnt)
+{
+	int rc = 0;
+
+	if (!dsi_intf.tx)
+		return -EINVAL;
+
+	rc = dsi_intf.tx(pdata, tp, cmds, cnt);
+	return rc;
+}
+
+int dsi_cmds_rx_v2(struct mdss_panel_data *pdata,
+			struct dsi_buf *tp, struct dsi_buf *rp,
+			struct dsi_cmd_desc *cmds, int rlen)
+{
+	int rc = 0;
+
+	if (pdata == NULL) {
+		pr_err("%s: Invalid input data\n", __func__);
+		return -EINVAL;
+	}
+
+	if (!dsi_intf.rx)
+		return -EINVAL;
+
+	rc = dsi_intf.rx(pdata, tp, rp, cmds, rlen);
+	return rc;
+}
+
+static char *dsi_buf_reserve(struct dsi_buf *dp, int len)
+{
+	dp->data += len;
+	return dp->data;
+}
+
+
+static char *dsi_buf_push(struct dsi_buf *dp, int len)
+{
+	dp->data -= len;
+	dp->len += len;
+	return dp->data;
+}
+
+static char *dsi_buf_reserve_hdr(struct dsi_buf *dp, int hlen)
+{
+	dp->hdr = (u32 *)dp->data;
+	return dsi_buf_reserve(dp, hlen);
+}
+
+char *dsi_buf_init(struct dsi_buf *dp)
+{
+	int off;
+
+	dp->data = dp->start;
+	off = (int)dp->data;
+	/* 8 byte align */
+	off &= 0x07;
+	if (off)
+		off = 8 - off;
+	dp->data += off;
+	dp->len = 0;
+	return dp->data;
+}
+
+int dsi_buf_alloc(struct dsi_buf *dp, int size)
+{
+	dp->start = kmalloc(size, GFP_KERNEL);
+	if (dp->start == NULL) {
+		pr_err("%s:%u\n", __func__, __LINE__);
+		return -ENOMEM;
+	}
+
+	dp->end = dp->start + size;
+	dp->size = size;
+
+	if ((int)dp->start & 0x07) {
+		pr_err("%s: buf NOT 8 bytes aligned\n", __func__);
+		return -EINVAL;
+	}
+
+	dp->data = dp->start;
+	dp->len = 0;
+	return 0;
+}
+
+/*
+ * mipi dsi generic long write
+ */
+static int dsi_generic_lwrite(struct dsi_buf *dp, struct dsi_cmd_desc *cm)
+{
+	char *bp;
+	u32 *hp;
+	int i, len;
+
+	bp = dsi_buf_reserve_hdr(dp, DSI_HOST_HDR_SIZE);
+
+	/* fill up payload */
+	if (cm->payload) {
+		len = cm->dlen;
+		len += 3;
+		len &= ~0x03; /* multipled by 4 */
+		for (i = 0; i < cm->dlen; i++)
+			*bp++ = cm->payload[i];
+
+		/* append 0xff to the end */
+		for (; i < len; i++)
+			*bp++ = 0xff;
+
+		dp->len += len;
+	}
+
+	/* fill up header */
+	hp = dp->hdr;
+	*hp = 0;
+	*hp = DSI_HDR_WC(cm->dlen);
+	*hp |= DSI_HDR_VC(cm->vc);
+	*hp |= DSI_HDR_LONG_PKT;
+	*hp |= DSI_HDR_DTYPE(DTYPE_GEN_LWRITE);
+	if (cm->last)
+		*hp |= DSI_HDR_LAST;
+
+	dsi_buf_push(dp, DSI_HOST_HDR_SIZE);
+
+	return dp->len;
+}
+
+/*
+ * mipi dsi generic short write with 0, 1 2 parameters
+ */
+static int dsi_generic_swrite(struct dsi_buf *dp, struct dsi_cmd_desc *cm)
+{
+	u32 *hp;
+	int len;
+
+	if (cm->dlen && cm->payload == 0) {
+		pr_err("%s: NO payload error\n", __func__);
+		return 0;
+	}
+
+	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_LAST;
+
+	len = (cm->dlen > 2) ? 2 : cm->dlen;
+
+	if (len == 1) {
+		*hp |= DSI_HDR_DTYPE(DTYPE_GEN_WRITE1);
+		*hp |= DSI_HDR_DATA1(cm->payload[0]);
+		*hp |= DSI_HDR_DATA2(0);
+	} else if (len == 2) {
+		*hp |= DSI_HDR_DTYPE(DTYPE_GEN_WRITE2);
+		*hp |= DSI_HDR_DATA1(cm->payload[0]);
+		*hp |= DSI_HDR_DATA2(cm->payload[1]);
+	} else {
+		*hp |= DSI_HDR_DTYPE(DTYPE_GEN_WRITE);
+		*hp |= DSI_HDR_DATA1(0);
+		*hp |= DSI_HDR_DATA2(0);
+	}
+
+	dsi_buf_push(dp, DSI_HOST_HDR_SIZE);
+
+	return dp->len;
+}
+
+/*
+ * mipi dsi gerneric read with 0, 1 2 parameters
+ */
+static int dsi_generic_read(struct dsi_buf *dp, struct dsi_cmd_desc *cm)
+{
+	u32 *hp;
+	int len;
+
+	if (cm->dlen && cm->payload == 0) {
+		pr_err("%s: NO payload error\n", __func__);
+		return 0;
+	}
+
+	dsi_buf_reserve_hdr(dp, DSI_HOST_HDR_SIZE);
+	hp = dp->hdr;
+	*hp = 0;
+	*hp |= DSI_HDR_VC(cm->vc);
+	*hp |= DSI_HDR_BTA;
+	if (cm->last)
+		*hp |= DSI_HDR_LAST;
+
+	len = (cm->dlen > 2) ? 2 : cm->dlen;
+
+	if (len == 1) {
+		*hp |= DSI_HDR_DTYPE(DTYPE_GEN_READ1);
+		*hp |= DSI_HDR_DATA1(cm->payload[0]);
+		*hp |= DSI_HDR_DATA2(0);
+	} else if (len == 2) {
+		*hp |= DSI_HDR_DTYPE(DTYPE_GEN_READ2);
+		*hp |= DSI_HDR_DATA1(cm->payload[0]);
+		*hp |= DSI_HDR_DATA2(cm->payload[1]);
+	} else {
+		*hp |= DSI_HDR_DTYPE(DTYPE_GEN_READ);
+		*hp |= DSI_HDR_DATA1(0);
+		*hp |= DSI_HDR_DATA2(0);
+	}
+
+	dsi_buf_push(dp, DSI_HOST_HDR_SIZE);
+	return dp->len;
+}
+
+/*
+ * mipi dsi dcs long write
+ */
+static int dsi_dcs_lwrite(struct dsi_buf *dp, struct dsi_cmd_desc *cm)
+{
+	char *bp;
+	u32 *hp;
+	int i, len;
+
+	bp = dsi_buf_reserve_hdr(dp, DSI_HOST_HDR_SIZE);
+
+	/*
+	 * fill up payload
+	 * dcs command byte (first byte) followed by payload
+	 */
+	if (cm->payload) {
+		len = cm->dlen;
+		len += 3;
+		len &= ~0x03; /* multipled by 4 */
+		for (i = 0; i < cm->dlen; i++)
+			*bp++ = cm->payload[i];
+
+		/* append 0xff to the end */
+		for (; i < len; i++)
+			*bp++ = 0xff;
+
+		dp->len += len;
+	}
+
+	/* fill up header */
+	hp = dp->hdr;
+	*hp = 0;
+	*hp = DSI_HDR_WC(cm->dlen);
+	*hp |= DSI_HDR_VC(cm->vc);
+	*hp |= DSI_HDR_LONG_PKT;
+	*hp |= DSI_HDR_DTYPE(DTYPE_DCS_LWRITE);
+	if (cm->last)
+		*hp |= DSI_HDR_LAST;
+
+	dsi_buf_push(dp, DSI_HOST_HDR_SIZE);
+
+	return dp->len;
+}
+
+/*
+ * mipi dsi dcs short write with 0 parameters
+ */
+static int dsi_dcs_swrite(struct dsi_buf *dp, struct dsi_cmd_desc *cm)
+{
+	u32 *hp;
+	int len;
+
+	if (cm->payload == 0) {
+		pr_err("%s: NO payload error\n", __func__);
+		return -EINVAL;
+	}
+
+	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_BTA;
+	if (cm->last)
+		*hp |= DSI_HDR_LAST;
+
+	len = (cm->dlen > 1) ? 1 : cm->dlen;
+
+	*hp |= DSI_HDR_DTYPE(DTYPE_DCS_WRITE);
+	*hp |= DSI_HDR_DATA1(cm->payload[0]); /* dcs command byte */
+	*hp |= DSI_HDR_DATA2(0);
+
+	dsi_buf_push(dp, DSI_HOST_HDR_SIZE);
+	return dp->len;
+}
+
+/*
+ * mipi dsi dcs short write with 1 parameters
+ */
+static int dsi_dcs_swrite1(struct dsi_buf *dp, struct dsi_cmd_desc *cm)
+{
+	u32 *hp;
+
+	if (cm->dlen < 2 || cm->payload == 0) {
+		pr_err("%s: NO payload error\n", __func__);
+		return -EINVAL;
+	}
+
+	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_BTA;
+	if (cm->last)
+		*hp |= DSI_HDR_LAST;
+
+	*hp |= DSI_HDR_DTYPE(DTYPE_DCS_WRITE1);
+	*hp |= DSI_HDR_DATA1(cm->payload[0]); /* dcs comamnd byte */
+	*hp |= DSI_HDR_DATA2(cm->payload[1]); /* parameter */
+
+	dsi_buf_push(dp, DSI_HOST_HDR_SIZE);
+
+	return dp->len;
+}
+
+/*
+ * mipi dsi dcs read with 0 parameters
+ */
+static int dsi_dcs_read(struct dsi_buf *dp, struct dsi_cmd_desc *cm)
+{
+	u32 *hp;
+
+	if (cm->payload == 0) {
+		pr_err("%s: NO payload error\n", __func__);
+		return -EINVAL;
+	}
+
+	dsi_buf_reserve_hdr(dp, DSI_HOST_HDR_SIZE);
+	hp = dp->hdr;
+	*hp = 0;
+	*hp |= DSI_HDR_VC(cm->vc);
+	*hp |= DSI_HDR_BTA;
+	*hp |= DSI_HDR_DTYPE(DTYPE_DCS_READ);
+	if (cm->last)
+		*hp |= DSI_HDR_LAST;
+
+	*hp |= DSI_HDR_DATA1(cm->payload[0]); /* dcs command byte */
+	*hp |= DSI_HDR_DATA2(0);
+
+	dsi_buf_push(dp, DSI_HOST_HDR_SIZE);
+
+	return dp->len; /* 4 bytes */
+}
+
+static int dsi_cm_on(struct dsi_buf *dp, struct dsi_cmd_desc *cm)
+{
+	u32 *hp;
+
+	dsi_buf_reserve_hdr(dp, DSI_HOST_HDR_SIZE);
+	hp = dp->hdr;
+	*hp = 0;
+	*hp |= DSI_HDR_VC(cm->vc);
+	*hp |= DSI_HDR_DTYPE(DTYPE_CM_ON);
+	if (cm->last)
+		*hp |= DSI_HDR_LAST;
+
+	dsi_buf_push(dp, DSI_HOST_HDR_SIZE);
+
+	return dp->len; /* 4 bytes */
+}
+
+static int dsi_cm_off(struct dsi_buf *dp, struct dsi_cmd_desc *cm)
+{
+	u32 *hp;
+
+	dsi_buf_reserve_hdr(dp, DSI_HOST_HDR_SIZE);
+	hp = dp->hdr;
+	*hp = 0;
+	*hp |= DSI_HDR_VC(cm->vc);
+	*hp |= DSI_HDR_DTYPE(DTYPE_CM_OFF);
+	if (cm->last)
+		*hp |= DSI_HDR_LAST;
+
+	dsi_buf_push(dp, DSI_HOST_HDR_SIZE);
+
+	return dp->len; /* 4 bytes */
+}
+
+static int dsi_peripheral_on(struct dsi_buf *dp, struct dsi_cmd_desc *cm)
+{
+	u32 *hp;
+
+	dsi_buf_reserve_hdr(dp, DSI_HOST_HDR_SIZE);
+	hp = dp->hdr;
+	*hp = 0;
+	*hp |= DSI_HDR_VC(cm->vc);
+	*hp |= DSI_HDR_DTYPE(DTYPE_PERIPHERAL_ON);
+	if (cm->last)
+		*hp |= DSI_HDR_LAST;
+
+	dsi_buf_push(dp, DSI_HOST_HDR_SIZE);
+
+	return dp->len; /* 4 bytes */
+}
+
+static int dsi_peripheral_off(struct dsi_buf *dp, struct dsi_cmd_desc *cm)
+{
+	u32 *hp;
+
+	dsi_buf_reserve_hdr(dp, DSI_HOST_HDR_SIZE);
+	hp = dp->hdr;
+	*hp = 0;
+	*hp |= DSI_HDR_VC(cm->vc);
+	*hp |= DSI_HDR_DTYPE(DTYPE_PERIPHERAL_OFF);
+	if (cm->last)
+		*hp |= DSI_HDR_LAST;
+
+	dsi_buf_push(dp, DSI_HOST_HDR_SIZE);
+
+	return dp->len; /* 4 bytes */
+}
+
+static int dsi_set_max_pktsize(struct dsi_buf *dp, struct dsi_cmd_desc *cm)
+{
+	u32 *hp;
+
+	if (cm->payload == 0) {
+		pr_err("%s: NO payload error\n", __func__);
+		return 0;
+	}
+
+	dsi_buf_reserve_hdr(dp, DSI_HOST_HDR_SIZE);
+	hp = dp->hdr;
+	*hp = 0;
+	*hp |= DSI_HDR_VC(cm->vc);
+	*hp |= DSI_HDR_DTYPE(DTYPE_MAX_PKTSIZE);
+	if (cm->last)
+		*hp |= DSI_HDR_LAST;
+
+	*hp |= DSI_HDR_DATA1(cm->payload[0]);
+	*hp |= DSI_HDR_DATA2(cm->payload[1]);
+
+	dsi_buf_push(dp, DSI_HOST_HDR_SIZE);
+
+	return dp->len; /* 4 bytes */
+}
+
+static int dsi_null_pkt(struct dsi_buf *dp, struct dsi_cmd_desc *cm)
+{
+	u32 *hp;
+
+	dsi_buf_reserve_hdr(dp, DSI_HOST_HDR_SIZE);
+	hp = dp->hdr;
+	*hp = 0;
+	*hp = DSI_HDR_WC(cm->dlen);
+	*hp |= DSI_HDR_LONG_PKT;
+	*hp |= DSI_HDR_VC(cm->vc);
+	*hp |= DSI_HDR_DTYPE(DTYPE_NULL_PKT);
+	if (cm->last)
+		*hp |= DSI_HDR_LAST;
+
+	dsi_buf_push(dp, DSI_HOST_HDR_SIZE);
+
+	return dp->len; /* 4 bytes */
+}
+
+static int dsi_blank_pkt(struct dsi_buf *dp, struct dsi_cmd_desc *cm)
+{
+	u32 *hp;
+
+	dsi_buf_reserve_hdr(dp, DSI_HOST_HDR_SIZE);
+	hp = dp->hdr;
+	*hp = 0;
+	*hp = DSI_HDR_WC(cm->dlen);
+	*hp |= DSI_HDR_LONG_PKT;
+	*hp |= DSI_HDR_VC(cm->vc);
+	*hp |= DSI_HDR_DTYPE(DTYPE_BLANK_PKT);
+	if (cm->last)
+		*hp |= DSI_HDR_LAST;
+
+	dsi_buf_push(dp, DSI_HOST_HDR_SIZE);
+
+	return dp->len; /* 4 bytes */
+}
+
+/*
+ * prepare cmd buffer to be txed
+ */
+int dsi_cmd_dma_add(struct dsi_buf *dp, struct dsi_cmd_desc *cm)
+{
+	int len = 0;
+
+	switch (cm->dtype) {
+	case DTYPE_GEN_WRITE:
+	case DTYPE_GEN_WRITE1:
+	case DTYPE_GEN_WRITE2:
+		len = dsi_generic_swrite(dp, cm);
+		break;
+	case DTYPE_GEN_LWRITE:
+		len = dsi_generic_lwrite(dp, cm);
+		break;
+	case DTYPE_GEN_READ:
+	case DTYPE_GEN_READ1:
+	case DTYPE_GEN_READ2:
+		len = dsi_generic_read(dp, cm);
+		break;
+	case DTYPE_DCS_LWRITE:
+		len = dsi_dcs_lwrite(dp, cm);
+		break;
+	case DTYPE_DCS_WRITE:
+		len = dsi_dcs_swrite(dp, cm);
+		break;
+	case DTYPE_DCS_WRITE1:
+		len = dsi_dcs_swrite1(dp, cm);
+		break;
+	case DTYPE_DCS_READ:
+		len = dsi_dcs_read(dp, cm);
+		break;
+	case DTYPE_MAX_PKTSIZE:
+		len = dsi_set_max_pktsize(dp, cm);
+		break;
+	case DTYPE_NULL_PKT:
+		len = dsi_null_pkt(dp, cm);
+		break;
+	case DTYPE_BLANK_PKT:
+		len = dsi_blank_pkt(dp, cm);
+		break;
+	case DTYPE_CM_ON:
+		len = dsi_cm_on(dp, cm);
+		break;
+	case DTYPE_CM_OFF:
+		len = dsi_cm_off(dp, cm);
+		break;
+	case DTYPE_PERIPHERAL_ON:
+		len = dsi_peripheral_on(dp, cm);
+		break;
+	case DTYPE_PERIPHERAL_OFF:
+		len = dsi_peripheral_off(dp, cm);
+		break;
+	default:
+		pr_debug("%s: dtype=%x NOT supported\n",
+					__func__, cm->dtype);
+		break;
+
+	}
+
+	return len;
+}
+
+/*
+ * mdss_dsi_short_read1_resp: 1 parameter
+ */
+int dsi_short_read1_resp(struct dsi_buf *rp)
+{
+	/* strip out dcs type */
+	rp->data++;
+	rp->len = 1;
+	return rp->len;
+}
+
+/*
+ * mdss_dsi_short_read2_resp: 2 parameter
+ */
+int dsi_short_read2_resp(struct dsi_buf *rp)
+{
+	/* strip out dcs type */
+	rp->data++;
+	rp->len = 2;
+	return rp->len;
+}
+
+int dsi_long_read_resp(struct dsi_buf *rp)
+{
+	short len;
+
+	len = rp->data[2];
+	len <<= 8;
+	len |= rp->data[1];
+	/* strip out dcs header */
+	rp->data += 4;
+	rp->len -= 4;
+	/* strip out 2 bytes of checksum */
+	rp->len -= 2;
+	return len;
+}
diff --git a/drivers/video/msm/mdss/dsi_v2.h b/drivers/video/msm/mdss/dsi_v2.h
new file mode 100644
index 0000000..fa868ab
--- /dev/null
+++ b/drivers/video/msm/mdss/dsi_v2.h
@@ -0,0 +1,237 @@
+/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#ifndef MDSS_DSI_H
+#define MDSS_DSI_H
+
+#include <linux/list.h>
+#include <mach/scm-io.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;
+	char 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)(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);
+	void (*op_mode_config)(int mode, struct mdss_panel_data *pdata);
+	int (*tx)(struct mdss_panel_data *pdata,
+		struct dsi_buf *tp, struct dsi_cmd_desc *cmds, int cnt);
+	int (*rx)(struct mdss_panel_data *pdata,
+		 struct dsi_buf *tp, struct dsi_buf *rp,
+		struct dsi_cmd_desc *cmds, int len);
+	int index;
+	void *private;
+};
+
+int dsi_panel_device_register_v2(struct platform_device *pdev,
+				struct dsi_panel_common_pdata *panel_data,
+				char bl_ctrl);
+
+void dsi_register_interface(struct dsi_interface *intf);
+
+int dsi_cmds_rx_v2(struct mdss_panel_data *pdata,
+			struct dsi_buf *tp, struct dsi_buf *rp,
+			struct dsi_cmd_desc *cmds, int len);
+
+int dsi_cmds_tx_v2(struct mdss_panel_data *pdata,
+			struct dsi_buf *tp, struct dsi_cmd_desc *cmds,
+			int cnt);
+
+char *dsi_buf_init(struct dsi_buf *dp);
+
+int dsi_buf_alloc(struct dsi_buf *dp, int size);
+
+int dsi_cmd_dma_add(struct dsi_buf *dp, struct dsi_cmd_desc *cm);
+
+int dsi_short_read1_resp(struct dsi_buf *rp);
+
+int dsi_short_read2_resp(struct dsi_buf *rp);
+
+int dsi_long_read_resp(struct dsi_buf *rp);
+
+#endif /* MDSS_DSI_H */
diff --git a/drivers/video/msm/mdss/mdp3.c b/drivers/video/msm/mdss/mdp3.c
new file mode 100644
index 0000000..890b00b
--- /dev/null
+++ b/drivers/video/msm/mdss/mdp3.c
@@ -0,0 +1,917 @@
+/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ * Copyright (C) 2007 Google Incorporated
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#define pr_fmt(fmt)	"%s: " fmt, __func__
+
+#include <linux/clk.h>
+#include <linux/debugfs.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/iommu.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/pm_runtime.h>
+#include <linux/regulator/consumer.h>
+#include <linux/memory_alloc.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/sched.h>
+#include <linux/time.h>
+#include <linux/spinlock.h>
+#include <linux/semaphore.h>
+#include <linux/uaccess.h>
+
+#include <mach/board.h>
+#include <mach/clk.h>
+#include <mach/hardware.h>
+#include <mach/msm_bus.h>
+#include <mach/msm_bus_board.h>
+#include <mach/iommu.h>
+#include <mach/iommu_domains.h>
+#include <mach/msm_memtypes.h>
+
+#include "mdp3.h"
+#include "mdss_fb.h"
+#include "mdp3_hwio.h"
+#include "mdp3_ctrl.h"
+
+#define MDP_CORE_HW_VERSION	0x03030304
+struct mdp3_hw_resource *mdp3_res;
+
+#define MDP_BUS_VECTOR_ENTRY(ab_val, ib_val)		\
+	{						\
+		.src = MSM_BUS_MASTER_MDP_PORT0,	\
+		.dst = MSM_BUS_SLAVE_EBI_CH0,		\
+		.ab = (ab_val),				\
+		.ib = (ib_val),				\
+	}
+
+static struct msm_bus_vectors mdp_bus_vectors[] = {
+	MDP_BUS_VECTOR_ENTRY(0, 0),
+	MDP_BUS_VECTOR_ENTRY(SZ_128M, SZ_256M),
+	MDP_BUS_VECTOR_ENTRY(SZ_256M, SZ_512M),
+};
+
+static struct msm_bus_paths mdp_bus_usecases[ARRAY_SIZE(mdp_bus_vectors)];
+
+static struct msm_bus_scale_pdata mdp_bus_scale_table = {
+	.usecase = mdp_bus_usecases,
+	.num_usecases = ARRAY_SIZE(mdp_bus_usecases),
+	.name = "mdp3",
+};
+
+struct mdp3_iommu_domain_map mdp3_iommu_domains[MDP3_IOMMU_DOMAIN_MAX] = {
+	[MDP3_IOMMU_DOMAIN] = {
+		.domain_type = MDP3_IOMMU_DOMAIN,
+		.client_name = "mdp_dma",
+		.partitions = {
+			{
+				.start = SZ_128K,
+				.size = SZ_1G - SZ_128K,
+			},
+		},
+		.npartitions = 1,
+	},
+};
+
+struct mdp3_iommu_ctx_map mdp3_iommu_contexts[MDP3_IOMMU_CTX_MAX] = {
+	[MDP3_IOMMU_CTX_PPP_0] = {
+		.ctx_type = MDP3_IOMMU_CTX_PPP_0,
+		.domain = &mdp3_iommu_domains[MDP3_IOMMU_DOMAIN],
+		.ctx_name = "mdpe_0",
+		.attached = 0,
+	},
+	[MDP3_IOMMU_CTX_PPP_1] = {
+		.ctx_type = MDP3_IOMMU_CTX_PPP_1,
+		.domain = &mdp3_iommu_domains[MDP3_IOMMU_DOMAIN],
+		.ctx_name = "mdpe_1",
+		.attached = 0,
+	},
+
+	[MDP3_IOMMU_CTX_DMA_0] = {
+		.ctx_type = MDP3_IOMMU_CTX_DMA_0,
+		.domain = &mdp3_iommu_domains[MDP3_IOMMU_DOMAIN],
+		.ctx_name = "mdps_0",
+		.attached = 0,
+	},
+
+	[MDP3_IOMMU_CTX_DMA_1] = {
+		.ctx_type = MDP3_IOMMU_CTX_DMA_1,
+		.domain = &mdp3_iommu_domains[MDP3_IOMMU_DOMAIN],
+		.ctx_name = "mdps_1",
+		.attached = 0,
+	},
+};
+
+static irqreturn_t mdp3_irq_handler(int irq, void *ptr)
+{
+	int i = 0;
+	struct mdp3_hw_resource *mdata = (struct mdp3_hw_resource *)ptr;
+	u32 mdp_interrupt = MDP3_REG_READ(MDP3_REG_INTR_STATUS);
+
+	MDP3_REG_WRITE(MDP3_REG_INTR_CLEAR, mdp_interrupt);
+	pr_debug("mdp3_irq_handler irq=%d\n", mdp_interrupt);
+
+	spin_lock(&mdata->irq_lock);
+	mdp_interrupt &= mdata->irqMask;
+
+	while (mdp_interrupt && i < MDP3_MAX_INTR) {
+		if ((mdp_interrupt & 0x1) && mdata->callbacks[i].cb)
+			mdata->callbacks[i].cb(i, mdata->callbacks[i].data);
+		mdp_interrupt = mdp_interrupt >> 1;
+		i++;
+	}
+	spin_unlock(&mdata->irq_lock);
+
+	return IRQ_HANDLED;
+}
+
+void mdp3_irq_enable(int type)
+{
+	unsigned long flag;
+	int irqEnabled = 0;
+
+	pr_debug("mdp3_irq_enable type=%d\n", type);
+	spin_lock_irqsave(&mdp3_res->irq_lock, flag);
+	if (mdp3_res->irqMask & BIT(type)) {
+		pr_debug("interrupt %d already enabled\n", type);
+		spin_unlock_irqrestore(&mdp3_res->irq_lock, flag);
+		return;
+	}
+	irqEnabled = mdp3_res->irqMask;
+	mdp3_res->irqMask |= BIT(type);
+	MDP3_REG_WRITE(MDP3_REG_INTR_ENABLE, mdp3_res->irqMask);
+	if (!irqEnabled)
+		enable_irq(mdp3_res->irq);
+	spin_unlock_irqrestore(&mdp3_res->irq_lock, flag);
+}
+
+void mdp3_irq_disable(int type)
+{
+	unsigned long flag;
+
+	spin_lock_irqsave(&mdp3_res->irq_lock, flag);
+	if (mdp3_res->irqMask & BIT(type)) {
+		mdp3_res->irqMask &= ~BIT(type);
+		MDP3_REG_WRITE(MDP3_REG_INTR_ENABLE, mdp3_res->irqMask);
+		if (!mdp3_res->irqMask)
+			disable_irq(mdp3_res->irq);
+	} else {
+		pr_debug("interrupt %d not enabled\n", type);
+	}
+	spin_unlock_irqrestore(&mdp3_res->irq_lock, flag);
+}
+
+void mdp3_irq_disable_nosync(int type)
+{
+	if (mdp3_res->irqMask & BIT(type)) {
+		mdp3_res->irqMask &= ~BIT(type);
+		MDP3_REG_WRITE(MDP3_REG_INTR_ENABLE, mdp3_res->irqMask);
+		if (!mdp3_res->irqMask)
+			disable_irq_nosync(mdp3_res->irq);
+	} else {
+		pr_debug("interrupt %d not enabled\n", type);
+	}
+}
+
+int mdp3_set_intr_callback(u32 type, struct mdp3_intr_cb *cb)
+{
+	unsigned long flag;
+
+	pr_debug("interrupt %d callback n", type);
+	spin_lock_irqsave(&mdp3_res->irq_lock, flag);
+	if (cb)
+		mdp3_res->callbacks[type] = *cb;
+	else
+		mdp3_res->callbacks[type].cb = NULL;
+
+	spin_unlock_irqrestore(&mdp3_res->irq_lock, flag);
+	return 0;
+}
+
+static int mdp3_bus_scale_register(void)
+{
+	if (!mdp3_res->bus_handle) {
+		struct msm_bus_scale_pdata *bus_pdata = &mdp_bus_scale_table;
+		int i;
+
+		for (i = 0; i < bus_pdata->num_usecases; i++) {
+			mdp_bus_usecases[i].num_paths = 1;
+			mdp_bus_usecases[i].vectors = &mdp_bus_vectors[i];
+		}
+
+		mdp3_res->bus_handle = msm_bus_scale_register_client(bus_pdata);
+		if (!mdp3_res->bus_handle) {
+			pr_err("not able to get bus scale\n");
+			return -ENOMEM;
+		}
+		pr_debug("register bus_hdl=%x\n", mdp3_res->bus_handle);
+	}
+	return 0;
+}
+
+static void mdp3_bus_scale_unregister(void)
+{
+	pr_debug("unregister bus_handle=%x\n", mdp3_res->bus_handle);
+
+	if (mdp3_res->bus_handle)
+		msm_bus_scale_unregister_client(mdp3_res->bus_handle);
+}
+
+int mdp3_bus_scale_set_quota(int client, u64 ab_quota, u64 ib_quota)
+{
+	static int current_bus_idx;
+	int bus_idx;
+	int rc;
+
+	if (mdp3_res->bus_handle < 1) {
+		pr_err("invalid bus handle %d\n", mdp3_res->bus_handle);
+		return -EINVAL;
+	}
+
+	if ((ab_quota | ib_quota) == 0) {
+		bus_idx = 0;
+	} else {
+		int num_cases = mdp_bus_scale_table.num_usecases;
+		struct msm_bus_vectors *vect = NULL;
+
+		bus_idx = (current_bus_idx % (num_cases - 1)) + 1;
+
+		/* aligning to avoid performing updates for small changes */
+		ab_quota = ALIGN(ab_quota, SZ_64M);
+		ib_quota = ALIGN(ib_quota, SZ_64M);
+
+		vect = mdp_bus_scale_table.usecase[current_bus_idx].vectors;
+		if ((ab_quota == vect->ab) && (ib_quota == vect->ib)) {
+			pr_debug("skip bus scaling, no change in vectors\n");
+			return 0;
+		}
+
+		vect = mdp_bus_scale_table.usecase[bus_idx].vectors;
+		vect->ab = ab_quota;
+		vect->ib = ib_quota;
+
+		pr_debug("bus scale idx=%d ab=%llu ib=%llu\n", bus_idx,
+				vect->ab, vect->ib);
+	}
+	current_bus_idx = bus_idx;
+	rc = msm_bus_scale_client_update_request(mdp3_res->bus_handle, bus_idx);
+	return rc;
+}
+
+static int mdp3_clk_update(u32 clk_idx, u32 enable)
+{
+	int ret = -EINVAL;
+	struct clk *clk;
+	int count = 0;
+
+	if (clk_idx >= MDP3_MAX_CLK || !mdp3_res->clocks[clk_idx])
+		return -ENODEV;
+
+	clk = mdp3_res->clocks[clk_idx];
+
+	if (enable)
+		mdp3_res->clock_ref_count[clk_idx]++;
+	else
+		mdp3_res->clock_ref_count[clk_idx]--;
+
+	count = mdp3_res->clock_ref_count[clk_idx];
+	if (count == 1) {
+		pr_debug("clk=%d en=%d\n", clk_idx, enable);
+		ret = clk_prepare_enable(clk);
+	} else if (count == 0) {
+		pr_debug("clk=%d disable\n", clk_idx);
+		clk_disable_unprepare(clk);
+		ret = 0;
+	} else if (count < 0) {
+		pr_err("clk=%d count=%d\n", clk_idx, count);
+		ret = -EINVAL;
+	}
+	return ret;
+}
+
+int mdp3_vsync_clk_enable(int enable)
+{
+	int ret = 0;
+
+	pr_debug("vsync clk enable=%d\n", enable);
+	mutex_lock(&mdp3_res->res_mutex);
+	mdp3_clk_update(MDP3_CLK_VSYNC, enable);
+	mutex_unlock(&mdp3_res->res_mutex);
+	return ret;
+}
+
+int mdp3_clk_set_rate(int clk_type, unsigned long clk_rate)
+{
+	int ret = 0;
+	unsigned long rounded_rate;
+	struct clk *clk = mdp3_res->clocks[clk_type];
+
+	if (clk) {
+		mutex_lock(&mdp3_res->res_mutex);
+		rounded_rate = clk_round_rate(clk, clk_rate);
+		if (IS_ERR_VALUE(rounded_rate)) {
+			pr_err("unable to round rate err=%ld\n", rounded_rate);
+			mutex_unlock(&mdp3_res->res_mutex);
+			return -EINVAL;
+		}
+		if (rounded_rate != clk_get_rate(clk)) {
+			ret = clk_set_rate(clk, rounded_rate);
+			if (ret)
+				pr_err("clk_set_rate failed ret=%d\n", ret);
+			else
+				pr_debug("mdp clk rate=%lu\n", rounded_rate);
+		}
+		mutex_unlock(&mdp3_res->res_mutex);
+	} else {
+		pr_err("mdp src clk not setup properly\n");
+		ret = -EINVAL;
+	}
+	return ret;
+}
+
+unsigned long mdp3_get_clk_rate(u32 clk_idx)
+{
+	unsigned long clk_rate = 0;
+	struct clk *clk;
+
+	if (clk_idx >= MDP3_MAX_CLK)
+		return -ENODEV;
+
+	clk = mdp3_res->clocks[clk_idx];
+
+	if (clk) {
+		mutex_lock(&mdp3_res->res_mutex);
+		clk_rate = clk_get_rate(clk);
+		mutex_unlock(&mdp3_res->res_mutex);
+	}
+	return clk_rate;
+}
+
+static int mdp3_clk_register(char *clk_name, int clk_idx)
+{
+	struct clk *tmp;
+
+	if (clk_idx >= MDP3_MAX_CLK) {
+		pr_err("invalid clk index %d\n", clk_idx);
+		return -EINVAL;
+	}
+
+	tmp = devm_clk_get(&mdp3_res->pdev->dev, clk_name);
+	if (IS_ERR(tmp)) {
+		pr_err("unable to get clk: %s\n", clk_name);
+		return PTR_ERR(tmp);
+	}
+
+	mdp3_res->clocks[clk_idx] = tmp;
+
+	return 0;
+}
+
+static int mdp3_clk_setup(void)
+{
+	int rc;
+
+	rc = mdp3_clk_register("iface_clk", MDP3_CLK_AHB);
+	if (rc)
+		return rc;
+
+	rc = mdp3_clk_register("core_clk", MDP3_CLK_CORE);
+	if (rc)
+		return rc;
+
+	rc = mdp3_clk_register("vsync_clk", MDP3_CLK_VSYNC);
+	if (rc)
+		return rc;
+
+	rc = mdp3_clk_register("lcdc_clk", MDP3_CLK_LCDC);
+	if (rc)
+		return rc;
+
+	return rc;
+}
+
+static void mdp3_clk_remove(void)
+{
+	clk_put(mdp3_res->clocks[MDP3_CLK_AHB]);
+	clk_put(mdp3_res->clocks[MDP3_CLK_CORE]);
+	clk_put(mdp3_res->clocks[MDP3_CLK_VSYNC]);
+	clk_put(mdp3_res->clocks[MDP3_CLK_LCDC]);
+}
+
+int mdp3_clk_enable(int enable)
+{
+	int rc;
+
+	pr_debug("MDP CLKS %s\n", (enable ? "Enable" : "Disable"));
+
+	mutex_lock(&mdp3_res->res_mutex);
+	rc = mdp3_clk_update(MDP3_CLK_AHB, enable);
+	rc |= mdp3_clk_update(MDP3_CLK_CORE, enable);
+	rc |= mdp3_clk_update(MDP3_CLK_VSYNC, enable);
+	mutex_unlock(&mdp3_res->res_mutex);
+	return rc;
+}
+
+static int mdp3_irq_setup(void)
+{
+	int ret;
+
+	ret = devm_request_irq(&mdp3_res->pdev->dev,
+				mdp3_res->irq,
+				mdp3_irq_handler,
+				IRQF_DISABLED, "MDP", mdp3_res);
+	if (ret) {
+		pr_err("mdp request_irq() failed!\n");
+		return ret;
+	}
+	disable_irq(mdp3_res->irq);
+	return 0;
+}
+
+static int mdp3_iommu_fault_handler(struct iommu_domain *domain,
+		struct device *dev, unsigned long iova, int flags, void *token)
+{
+	pr_err("MDP IOMMU page fault: iova 0x%lx\n", iova);
+	return 0;
+}
+
+int mdp3_iommu_attach(int context)
+{
+	struct mdp3_iommu_ctx_map *context_map;
+	struct mdp3_iommu_domain_map *domain_map;
+
+	if (context >= MDP3_IOMMU_CTX_MAX)
+		return -EINVAL;
+
+	context_map = mdp3_res->iommu_contexts + context;
+	if (context_map->attached) {
+		pr_warn("mdp iommu already attached\n");
+		return 0;
+	}
+
+	domain_map = context_map->domain;
+
+	iommu_attach_device(domain_map->domain, context_map->ctx);
+
+	context_map->attached = true;
+	return 0;
+}
+
+int mdp3_iommu_dettach(int context)
+{
+	struct mdp3_iommu_ctx_map *context_map;
+	struct mdp3_iommu_domain_map *domain_map;
+
+	if (context >= MDP3_IOMMU_CTX_MAX)
+		return -EINVAL;
+
+	context_map = mdp3_res->iommu_contexts + context;
+	if (!context_map->attached) {
+		pr_warn("mdp iommu not attached\n");
+		return 0;
+	}
+
+	domain_map = context_map->domain;
+	iommu_detach_device(domain_map->domain, context_map->ctx);
+	context_map->attached = false;
+
+	return 0;
+}
+
+int mdp3_iommu_domain_init(void)
+{
+	struct msm_iova_layout layout;
+	int i;
+
+	if (mdp3_res->domains) {
+		pr_warn("iommu domain already initialized\n");
+		return 0;
+	}
+
+	for (i = 0; i < MDP3_IOMMU_DOMAIN_MAX; i++) {
+		int domain_idx;
+		layout.client_name = mdp3_iommu_domains[i].client_name;
+		layout.partitions = mdp3_iommu_domains[i].partitions;
+		layout.npartitions = mdp3_iommu_domains[i].npartitions;
+		layout.is_secure = false;
+
+		domain_idx = msm_register_domain(&layout);
+		if (IS_ERR_VALUE(domain_idx))
+			return -EINVAL;
+
+		mdp3_iommu_domains[i].domain_idx = domain_idx;
+		mdp3_iommu_domains[i].domain = msm_get_iommu_domain(domain_idx);
+		if (!mdp3_iommu_domains[i].domain) {
+			pr_err("unable to get iommu domain(%d)\n",
+				domain_idx);
+			return -EINVAL;
+		}
+		iommu_set_fault_handler(mdp3_iommu_domains[i].domain,
+					mdp3_iommu_fault_handler,
+					NULL);
+	}
+
+	mdp3_res->domains = mdp3_iommu_domains;
+
+	return 0;
+}
+
+int mdp3_iommu_context_init(void)
+{
+	int i;
+
+	if (mdp3_res->iommu_contexts) {
+		pr_warn("iommu context already initialized\n");
+		return 0;
+	}
+
+	for (i = 0; i < MDP3_IOMMU_CTX_MAX; i++) {
+		mdp3_iommu_contexts[i].ctx =
+			msm_iommu_get_ctx(mdp3_iommu_contexts[i].ctx_name);
+
+		if (!mdp3_iommu_contexts[i].ctx) {
+			pr_warn("unable to get iommu ctx(%s)\n",
+				mdp3_iommu_contexts[i].ctx_name);
+			return -EINVAL;
+		}
+	}
+
+	mdp3_res->iommu_contexts = mdp3_iommu_contexts;
+
+	return 0;
+}
+
+int mdp3_iommu_init(void)
+{
+	int ret;
+
+	ret = mdp3_iommu_domain_init();
+	if (ret) {
+		pr_err("mdp3 iommu domain init fails\n");
+		return ret;
+	}
+
+	ret = mdp3_iommu_context_init();
+	if (ret) {
+		pr_err("mdp3 iommu context init fails\n");
+		return ret;
+	}
+	return ret;
+}
+
+static int mdp3_check_version(void)
+{
+	int rc;
+
+	rc = mdp3_clk_update(MDP3_CLK_AHB, 1);
+	if (rc)
+		return rc;
+
+	mdp3_res->mdp_rev = MDP3_REG_READ(MDP3_REG_HW_VERSION);
+
+	rc = mdp3_clk_update(MDP3_CLK_AHB, 0);
+	if (rc)
+		pr_err("fail to turn off the MDP3_CLK_AHB clk\n");
+
+	if (mdp3_res->mdp_rev != MDP_CORE_HW_VERSION) {
+		pr_err("mdp_hw_revision=%x mismatch\n", mdp3_res->mdp_rev);
+		rc = -ENODEV;
+	}
+	return rc;
+}
+
+static int mdp3_hw_init(void)
+{
+	int i;
+
+	for (i = MDP3_DMA_P; i < MDP3_DMA_MAX; i++) {
+		mdp3_res->dma[i].dma_sel = i;
+		mdp3_res->dma[i].capability = MDP3_DMA_CAP_ALL;
+		mdp3_res->dma[i].in_use = 0;
+		mdp3_res->dma[i].available = 1;
+	}
+	mdp3_res->dma[MDP3_DMA_S].capability = MDP3_DMA_CAP_DITHER;
+	mdp3_res->dma[MDP3_DMA_E].available = 0;
+
+	for (i = MDP3_DMA_OUTPUT_SEL_AHB; i < MDP3_DMA_OUTPUT_SEL_MAX; i++) {
+		mdp3_res->intf[i].cfg.type = i;
+		mdp3_res->intf[i].active = 0;
+		mdp3_res->intf[i].in_use = 0;
+		mdp3_res->intf[i].available = 1;
+	}
+	mdp3_res->intf[MDP3_DMA_OUTPUT_SEL_AHB].available = 0;
+	mdp3_res->intf[MDP3_DMA_OUTPUT_SEL_LCDC].available = 0;
+
+	return 0;
+}
+
+static int mdp3_res_init(void)
+{
+	int rc = 0;
+
+	rc = mdp3_irq_setup();
+	if (rc)
+		return rc;
+
+	rc = mdp3_clk_setup();
+	if (rc)
+		return rc;
+
+	mdp3_res->ion_client = msm_ion_client_create(-1, mdp3_res->pdev->name);
+	if (IS_ERR_OR_NULL(mdp3_res->ion_client)) {
+		pr_err("msm_ion_client_create() return error (%p)\n",
+				mdp3_res->ion_client);
+		mdp3_res->ion_client = NULL;
+		return -EINVAL;
+	}
+
+	rc = mdp3_iommu_init();
+	if (rc)
+		return rc;
+
+	rc = mdp3_iommu_attach(MDP3_IOMMU_CTX_DMA_0);
+	if (rc) {
+		pr_err("fail to attach DMA-P context 0\n");
+		return rc;
+	}
+	rc = mdp3_bus_scale_register();
+	if (rc) {
+		pr_err("unable to register bus scaling\n");
+		return rc;
+	}
+
+	rc = mdp3_hw_init();
+
+	return rc;
+}
+
+static int mdp3_parse_dt(struct platform_device *pdev)
+{
+	struct resource *res;
+
+	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "mdp_phys");
+	if (!res) {
+		pr_err("unable to get MDP base address\n");
+		return -EINVAL;
+	}
+
+	mdp3_res->mdp_reg_size = resource_size(res);
+	mdp3_res->mdp_base = devm_ioremap(&pdev->dev, res->start,
+					mdp3_res->mdp_reg_size);
+	if (unlikely(!mdp3_res->mdp_base)) {
+		pr_err("unable to map MDP base\n");
+		return -ENOMEM;
+	}
+
+	pr_debug("MDP HW Base phy_Address=0x%x virt=0x%x\n",
+		(int) res->start,
+		(int) mdp3_res->mdp_base);
+
+	res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+	if (!res) {
+		pr_err("unable to get MDSS irq\n");
+		return -EINVAL;
+	}
+	mdp3_res->irq = res->start;
+
+	return 0;
+}
+
+static int mdp3_init(struct msm_fb_data_type *mfd)
+{
+	return mdp3_ctrl_init(mfd);
+}
+
+u32 mdp3_fb_stride(u32 fb_index, u32 xres, int bpp)
+{
+	/*
+	 * The adreno GPU hardware requires that the pitch be aligned to
+	 * 32 pixels for color buffers, so for the cases where the GPU
+	 * is writing directly to fb0, the framebuffer pitch
+	 * also needs to be 32 pixel aligned
+	 */
+
+	if (fb_index == 0)
+		return ALIGN(xres, 32) * bpp;
+	else
+		return xres * bpp;
+}
+
+/*
+ * physical contiguous memory should be allocated in mdss_fb, and SMMU
+ * virtual address mapping can be done in the MDP h/w specific code.   It
+ * should have a reference count, if none is current mapped, the SMMU context
+ * can bedetached, thus allowing power saving in SMMU.
+ */
+static int mdp3_fbmem_alloc(struct msm_fb_data_type *mfd)
+{
+	int dom;
+	void *virt = NULL;
+	unsigned long phys = 0;
+	size_t size;
+	u32 yres = mfd->fbi->var.yres_virtual;
+
+	size = PAGE_ALIGN(mfd->fbi->fix.line_length * yres);
+
+	if (mfd->index == 0) {
+		virt = allocate_contiguous_memory(size, MEMTYPE_EBI1, SZ_1M, 0);
+		if (!virt) {
+			pr_err("unable to alloc fbmem size=%u\n", size);
+			return -ENOMEM;
+		}
+		phys = memory_pool_node_paddr(virt);
+		dom = (mdp3_res->domains + MDP3_IOMMU_DOMAIN)->domain_idx;
+		msm_iommu_map_contig_buffer(phys, dom, 0, size, SZ_4K, 0,
+					&mfd->iova);
+
+		pr_debug("allocating %u bytes at %p (%lx phys) for fb %d\n",
+			size, virt, phys, mfd->index);
+	} else {
+		size = 0;
+	}
+
+	mfd->fbi->screen_base = virt;
+	mfd->fbi->fix.smem_start = phys;
+	mfd->fbi->fix.smem_len = size;
+	return 0;
+}
+
+struct mdp3_dma *mdp3_get_dma_pipe(int capability)
+{
+	int i;
+
+	for (i = MDP3_DMA_P; i < MDP3_DMA_MAX; i++) {
+		if (!mdp3_res->dma[i].in_use && mdp3_res->dma[i].available &&
+			mdp3_res->dma[i].capability & capability) {
+			mdp3_res->dma[i].in_use = true;
+			return &mdp3_res->dma[i];
+		}
+	}
+	return NULL;
+}
+
+struct mdp3_intf *mdp3_get_display_intf(int type)
+{
+	int i;
+
+	for (i = MDP3_DMA_OUTPUT_SEL_AHB; i < MDP3_DMA_OUTPUT_SEL_MAX; i++) {
+		if (!mdp3_res->intf[i].in_use && mdp3_res->intf[i].available &&
+			mdp3_res->intf[i].cfg.type == type) {
+			mdp3_res->intf[i].in_use = true;
+			return &mdp3_res->intf[i];
+		}
+	}
+	return NULL;
+}
+
+static int mdp3_probe(struct platform_device *pdev)
+{
+	int rc;
+	static struct msm_mdp_interface mdp3_interface = {
+	.init_fnc = mdp3_init,
+	.fb_mem_alloc_fnc = mdp3_fbmem_alloc,
+	.fb_stride = mdp3_fb_stride,
+	};
+
+	if (!pdev->dev.of_node) {
+		pr_err("MDP driver only supports device tree probe\n");
+		return -ENOTSUPP;
+	}
+
+	if (mdp3_res) {
+		pr_err("MDP already initialized\n");
+		return -EINVAL;
+	}
+
+	mdp3_res = devm_kzalloc(&pdev->dev, sizeof(struct mdp3_hw_resource),
+				GFP_KERNEL);
+	if (mdp3_res == NULL)
+		return -ENOMEM;
+
+	pdev->id = 0;
+	mdp3_res->pdev = pdev;
+	mutex_init(&mdp3_res->res_mutex);
+	spin_lock_init(&mdp3_res->irq_lock);
+	platform_set_drvdata(pdev, mdp3_res);
+
+	rc = mdp3_parse_dt(pdev);
+	if (rc)
+		goto probe_done;
+
+	rc = mdp3_res_init();
+	if (rc) {
+		pr_err("unable to initialize mdp3 resources\n");
+		goto probe_done;
+	}
+
+	rc = mdp3_check_version();
+	if (rc) {
+		pr_err("mdp3 check version failed\n");
+		goto probe_done;
+	}
+
+	rc = mdss_fb_register_mdp_instance(&mdp3_interface);
+	if (rc)
+		pr_err("unable to register mdp instance\n");
+
+probe_done:
+	if (IS_ERR_VALUE(rc)) {
+		devm_kfree(&pdev->dev, mdp3_res);
+		mdp3_res = NULL;
+	}
+
+	return rc;
+}
+
+static  int mdp3_suspend_sub(struct mdp3_hw_resource *mdata)
+{
+	return 0;
+}
+
+static  int mdp3_resume_sub(struct mdp3_hw_resource *mdata)
+{
+	return 0;
+}
+
+static int mdp3_suspend(struct platform_device *pdev, pm_message_t state)
+{
+	struct mdp3_hw_resource *mdata = platform_get_drvdata(pdev);
+
+	if (!mdata)
+		return -ENODEV;
+
+	pr_debug("display suspend\n");
+
+	return mdp3_suspend_sub(mdata);
+}
+
+static int mdp3_resume(struct platform_device *pdev)
+{
+	struct mdp3_hw_resource *mdata = platform_get_drvdata(pdev);
+
+	if (!mdata)
+		return -ENODEV;
+
+	pr_debug("display resume\n");
+
+	return mdp3_resume_sub(mdata);
+}
+
+static int mdp3_remove(struct platform_device *pdev)
+{
+	struct mdp3_hw_resource *mdata = platform_get_drvdata(pdev);
+
+	if (!mdata)
+		return -ENODEV;
+	pm_runtime_disable(&pdev->dev);
+	mdp3_bus_scale_unregister();
+	mdp3_clk_remove();
+	return 0;
+}
+
+static const struct of_device_id mdp3_dt_match[] = {
+	{ .compatible = "qcom,mdss_mdp3",},
+	{}
+};
+MODULE_DEVICE_TABLE(of, mdp3_dt_match);
+EXPORT_COMPAT("qcom,mdss_mdp3");
+
+static struct platform_driver mdp3_driver = {
+	.probe = mdp3_probe,
+	.remove = mdp3_remove,
+	.suspend = mdp3_suspend,
+	.resume = mdp3_resume,
+	.shutdown = NULL,
+	.driver = {
+		.name = "mdp3",
+		.of_match_table = mdp3_dt_match,
+	},
+};
+
+static int __init mdp3_driver_init(void)
+{
+	int ret;
+
+	ret = platform_driver_register(&mdp3_driver);
+	if (ret) {
+		pr_err("register mdp3 driver failed!\n");
+		return ret;
+	}
+
+	return 0;
+}
+
+module_init(mdp3_driver_init);
diff --git a/drivers/video/msm/mdss/mdp3.h b/drivers/video/msm/mdss/mdp3.h
new file mode 100644
index 0000000..c853664
--- /dev/null
+++ b/drivers/video/msm/mdss/mdp3.h
@@ -0,0 +1,123 @@
+/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ * Copyright (C) 2007 Google Incorporated
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+#ifndef MDP3_H
+#define MDP3_H
+
+#include <linux/types.h>
+#include <linux/mutex.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+#include <linux/earlysuspend.h>
+
+#include <mach/iommu_domains.h>
+
+#include "mdp3_dma.h"
+
+enum  {
+	MDP3_CLK_AHB,
+	MDP3_CLK_CORE,
+	MDP3_CLK_VSYNC,
+	MDP3_CLK_LCDC,
+	MDP3_MAX_CLK
+};
+
+enum {
+	MDP3_IOMMU_DOMAIN,
+	MDP3_IOMMU_DOMAIN_MAX
+};
+
+enum {
+	MDP3_IOMMU_CTX_PPP_0,
+	MDP3_IOMMU_CTX_PPP_1,
+	MDP3_IOMMU_CTX_DMA_0,
+	MDP3_IOMMU_CTX_DMA_1,
+	MDP3_IOMMU_CTX_MAX
+};
+
+enum {
+	MDP3_BW_CLIENT_DMA_P,
+	MDP3_BW_CLIENT_DMA_S,
+	MDP3_BW_CLIENT_DMA_E,
+	MDP3_BW_CLIENT_PPP,
+};
+
+struct mdp3_iommu_domain_map {
+	u32 domain_type;
+	char *client_name;
+	struct msm_iova_partition partitions[1];
+	int npartitions;
+	int domain_idx;
+	struct iommu_domain *domain;
+};
+
+struct mdp3_iommu_ctx_map {
+	u32 ctx_type;
+	struct mdp3_iommu_domain_map *domain;
+	char *ctx_name;
+	struct device *ctx;
+	int attached;
+};
+
+#define MDP3_MAX_INTR 28
+
+struct mdp3_intr_cb {
+	void (*cb)(int type, void *);
+	void *data;
+};
+
+struct mdp3_hw_resource {
+	struct platform_device *pdev;
+	u32 mdp_rev;
+
+	struct mutex res_mutex;
+
+	struct clk *clocks[MDP3_MAX_CLK];
+	int clock_ref_count[MDP3_MAX_CLK];
+
+	char __iomem *mdp_base;
+	size_t mdp_reg_size;
+
+	u32 irq;
+	u32 bus_handle;
+
+	struct ion_client *ion_client;
+	struct mdp3_iommu_domain_map *domains;
+	struct mdp3_iommu_ctx_map *iommu_contexts;
+
+	struct mdp3_dma dma[MDP3_DMA_MAX];
+	struct mdp3_intf intf[MDP3_DMA_OUTPUT_SEL_MAX];
+
+	spinlock_t irq_lock;
+	u32 irqMask;
+	struct mdp3_intr_cb callbacks[MDP3_MAX_INTR];
+
+	struct early_suspend suspend_handler;
+};
+
+extern struct mdp3_hw_resource *mdp3_res;
+
+struct mdp3_dma *mdp3_get_dma_pipe(int capability);
+struct mdp3_intf *mdp3_get_display_intf(int type);
+void mdp3_irq_enable(int type);
+void mdp3_irq_disable(int type);
+void mdp3_irq_disable_nosync(int type);
+int mdp3_set_intr_callback(u32 type, struct mdp3_intr_cb *cb);
+int mdp3_clk_set_rate(int clk_type, unsigned long clk_rate);
+int mdp3_clk_enable(int enable);
+int mdp3_bus_scale_set_quota(int client, u64 ab_quota, u64 ib_quota);
+
+#define MDP3_REG_WRITE(addr, val) writel_relaxed(val, mdp3_res->mdp_base + addr)
+#define MDP3_REG_READ(addr) readl_relaxed(mdp3_res->mdp_base + addr)
+
+#endif /* MDP3_H */
diff --git a/drivers/video/msm/mdss/mdp3_ctrl.c b/drivers/video/msm/mdss/mdp3_ctrl.c
new file mode 100644
index 0000000..e07c0a4
--- /dev/null
+++ b/drivers/video/msm/mdss/mdp3_ctrl.c
@@ -0,0 +1,511 @@
+/* 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.
+ *
+ */
+
+#define pr_fmt(fmt)	"%s: " fmt, __func__
+
+#include <linux/dma-mapping.h>
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/major.h>
+#include <linux/module.h>
+#include <linux/uaccess.h>
+
+#include "mdp3_ctrl.h"
+#include "mdp3.h"
+
+#define MDP_VSYNC_CLK_RATE	19200000
+#define VSYNC_PERIOD 16
+
+void vsync_notify_handler(void *arg)
+{
+	struct mdp3_session_data *session = (struct mdp3_session_data *)session;
+	complete(&session->vsync_comp);
+}
+
+static int mdp3_ctrl_vsync_enable(struct msm_fb_data_type *mfd, int enable)
+{
+	struct mdp3_session_data *mdp3_session;
+	struct mdp3_vsync_notification vsync_client;
+
+	mdp3_session = (struct mdp3_session_data *)mfd->mdp.private1;
+	if (!mdp3_session || !mdp3_session->panel || !mdp3_session->dma ||
+		!mdp3_session->intf)
+		return -ENODEV;
+
+	vsync_client.handler = vsync_notify_handler;
+	vsync_client.arg = mdp3_session;
+
+	mutex_lock(&mdp3_session->lock);
+	if (!mdp3_session->status) {
+		pr_debug("fb%d is not on yet", mfd->index);
+		mutex_unlock(&mdp3_session->lock);
+		return -EINVAL;
+	}
+
+	mdp3_session->dma->vsync_enable(mdp3_session->dma, &vsync_client);
+	mutex_unlock(&mdp3_session->lock);
+	return 0;
+}
+
+static ssize_t mdp3_vsync_show_event(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct fb_info *fbi = dev_get_drvdata(dev);
+	struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)fbi->par;
+	struct mdp3_session_data *mdp3_session = NULL;
+	u64 vsync_ticks;
+	ktime_t vsync_time;
+	int rc;
+
+	if (!mfd || !mfd->mdp.private1)
+		return 0;
+
+	mdp3_session = (struct mdp3_session_data *)mfd->mdp.private1;
+
+	rc = wait_for_completion_interruptible_timeout(
+				&mdp3_session->vsync_comp,
+				msecs_to_jiffies(VSYNC_PERIOD * 5));
+	if (rc <= 0) {
+		pr_warn("vsync wait on fb%d interrupted (%d)\n",
+			mfd->index, rc);
+		return -EBUSY;
+	}
+
+	vsync_time = mdp3_session->dma->get_vsync_time(mdp3_session->dma);
+	vsync_ticks = ktime_to_ns(vsync_time);
+
+	pr_debug("fb%d vsync=%llu", mfd->index, vsync_ticks);
+	rc = snprintf(buf, PAGE_SIZE, "VSYNC=%llu", vsync_ticks);
+	return rc;
+}
+
+static DEVICE_ATTR(vsync_event, S_IRUGO, mdp3_vsync_show_event, NULL);
+
+static struct attribute *vsync_fs_attrs[] = {
+	&dev_attr_vsync_event.attr,
+	NULL,
+};
+
+static struct attribute_group vsync_fs_attr_group = {
+	.attrs = vsync_fs_attrs,
+};
+
+static int mdp3_ctrl_res_req_dma(struct msm_fb_data_type *mfd, int status)
+{
+	int rc = 0;
+	if (status) {
+		struct mdss_panel_info *panel_info = mfd->panel_info;
+		int ab = 0;
+		int ib = 0;
+		unsigned long core_clk = 0;
+		int vtotal = 0;
+		ab = panel_info->xres * panel_info->yres * 4;
+		ab *= panel_info->mipi.frame_rate;
+		ib = (ab * 3) / 2;
+		vtotal = panel_info->lcdc.v_back_porch +
+			panel_info->lcdc.v_front_porch +
+			panel_info->lcdc.v_pulse_width +
+			panel_info->yres;
+		core_clk = panel_info->xres * panel_info->yres;
+		core_clk *= panel_info->mipi.frame_rate;
+		core_clk = (core_clk / panel_info->yres) * vtotal;
+		mdp3_clk_set_rate(MDP3_CLK_CORE, core_clk);
+		mdp3_clk_set_rate(MDP3_CLK_VSYNC, MDP_VSYNC_CLK_RATE);
+
+		rc = mdp3_clk_enable(true);
+		if (rc)
+			return rc;
+
+		mdp3_bus_scale_set_quota(MDP3_BW_CLIENT_DMA_P, ab, ib);
+	} else {
+		rc = mdp3_clk_enable(false);
+		rc |= mdp3_bus_scale_set_quota(MDP3_BW_CLIENT_DMA_P, 0, 0);
+	}
+	return rc;
+}
+
+static int mdp3_ctrl_get_intf_type(struct msm_fb_data_type *mfd)
+{
+	int type;
+	switch (mfd->panel.type) {
+	case MIPI_VIDEO_PANEL:
+		type = MDP3_DMA_OUTPUT_SEL_DSI_VIDEO;
+		break;
+	case MIPI_CMD_PANEL:
+		type = MDP3_DMA_OUTPUT_SEL_DSI_CMD;
+		break;
+	case LCDC_PANEL:
+		type = MDP3_DMA_OUTPUT_SEL_LCDC;
+		break;
+	default:
+		type = MDP3_DMA_OUTPUT_SEL_MAX;
+	}
+	return type;
+}
+
+static int mdp3_ctrl_get_source_format(struct msm_fb_data_type *mfd)
+{
+	int format;
+	switch (mfd->fb_imgType) {
+	case MDP_RGB_565:
+		format = MDP3_DMA_IBUF_FORMAT_RGB565;
+		break;
+	case MDP_RGB_888:
+		format = MDP3_DMA_IBUF_FORMAT_RGB888;
+		break;
+	case MDP_ARGB_8888:
+	case MDP_RGBA_8888:
+		format = MDP3_DMA_IBUF_FORMAT_XRGB8888;
+		break;
+	default:
+		format = MDP3_DMA_IBUF_FORMAT_UNDEFINED;
+	}
+	return format;
+}
+
+static int mdp3_ctrl_get_pack_pattern(struct msm_fb_data_type *mfd)
+{
+	int packPattern = MDP3_DMA_OUTPUT_PACK_PATTERN_RGB;
+	if (mfd->fb_imgType == MDP_RGBA_8888)
+		packPattern = MDP3_DMA_OUTPUT_PACK_PATTERN_BGR;
+	return packPattern;
+}
+
+static int mdp3_ctrl_intf_init(struct msm_fb_data_type *mfd,
+				struct mdp3_intf *intf)
+{
+	int rc;
+	struct mdp3_intf_cfg cfg;
+	struct mdp3_video_intf_cfg *video = &cfg.video;
+	struct mdss_panel_info *p = mfd->panel_info;
+	int h_back_porch = p->lcdc.h_back_porch;
+	int h_front_porch = p->lcdc.h_front_porch;
+	int w = p->xres;
+	int v_back_porch = p->lcdc.v_back_porch;
+	int v_front_porch = p->lcdc.v_front_porch;
+	int h = p->yres;
+	int h_sync_skew = p->lcdc.hsync_skew;
+	int h_pulse_width = p->lcdc.h_pulse_width;
+	int v_pulse_width = p->lcdc.v_pulse_width;
+	int hsync_period = h_front_porch + h_back_porch + w + h_pulse_width;
+	int vsync_period = v_front_porch + v_back_porch + h + v_pulse_width;
+	vsync_period *= hsync_period;
+
+	cfg.type = mdp3_ctrl_get_intf_type(mfd);
+	if (cfg.type == MDP3_DMA_OUTPUT_SEL_DSI_VIDEO ||
+		cfg.type == MDP3_DMA_OUTPUT_SEL_LCDC) {
+		video->hsync_period = hsync_period;
+		video->hsync_pulse_width = h_pulse_width;
+		video->vsync_period = vsync_period;
+		video->vsync_pulse_width = v_pulse_width * hsync_period;
+		video->display_start_x = h_back_porch + h_pulse_width;
+		video->display_end_x = hsync_period - h_front_porch - 1;
+		video->display_start_y =
+			(v_back_porch + v_pulse_width) * hsync_period;
+		video->display_end_y =
+			vsync_period - v_front_porch * hsync_period - 1;
+		video->active_start_x = video->display_start_x;
+		video->active_end_x = video->display_end_x;
+		video->active_h_enable = true;
+		video->active_start_y = video->display_start_y;
+		video->active_end_y = video->display_end_y;
+		video->active_v_enable = true;
+		video->hsync_skew = h_sync_skew;
+		video->hsync_polarity = 1;
+		video->vsync_polarity = 1;
+		video->de_polarity = 1;
+	} else if (cfg.type == MDP3_DMA_OUTPUT_SEL_DSI_CMD) {
+		cfg.dsi_cmd.primary_dsi_cmd_id = 0;
+		cfg.dsi_cmd.secondary_dsi_cmd_id = 1;
+		cfg.dsi_cmd.dsi_cmd_tg_intf_sel = 0;
+	} else
+		return -EINVAL;
+	rc = mdp3_intf_init(intf, &cfg);
+	return rc;
+}
+
+static int mdp3_ctrl_dma_init(struct msm_fb_data_type *mfd,
+				struct mdp3_dma *dma)
+{
+	int rc;
+	struct mdss_panel_info *panel_info = mfd->panel_info;
+	struct fb_info *fbi = mfd->fbi;
+	struct fb_fix_screeninfo *fix;
+	struct fb_var_screeninfo *var;
+	struct mdp3_dma_output_config outputConfig;
+	struct mdp3_dma_source sourceConfig;
+
+	fix = &fbi->fix;
+	var = &fbi->var;
+
+	sourceConfig.format = mdp3_ctrl_get_source_format(mfd);
+	sourceConfig.width = panel_info->xres;
+	sourceConfig.height = panel_info->yres;
+	sourceConfig.x = 0;
+	sourceConfig.y = 0;
+	sourceConfig.stride = fix->line_length;
+	sourceConfig.buf = (void *)mfd->iova;
+
+	outputConfig.dither_en = 0;
+	outputConfig.out_sel = mdp3_ctrl_get_intf_type(mfd);
+	outputConfig.bit_mask_polarity = 0;
+	outputConfig.color_components_flip = 0;
+	outputConfig.pack_pattern = mdp3_ctrl_get_pack_pattern(mfd);
+	outputConfig.pack_align = MDP3_DMA_OUTPUT_PACK_ALIGN_LSB;
+	outputConfig.color_comp_out_bits = (MDP3_DMA_OUTPUT_COMP_BITS_8 << 4) |
+					(MDP3_DMA_OUTPUT_COMP_BITS_8 << 2)|
+					MDP3_DMA_OUTPUT_COMP_BITS_8;
+
+	rc = mdp3_dma_init(dma, &sourceConfig, &outputConfig);
+	return rc;
+}
+
+static int mdp3_ctrl_on(struct msm_fb_data_type *mfd)
+{
+	int rc = 0;
+	struct mdp3_session_data *mdp3_session;
+	struct mdss_panel_data *panel;
+
+	pr_debug("mdp3_ctrl_on\n");
+	mdp3_session = (struct mdp3_session_data *)mfd->mdp.private1;
+	if (!mdp3_session || !mdp3_session->panel || !mdp3_session->dma ||
+		!mdp3_session->intf) {
+		pr_err("mdp3_ctrl_on no device");
+		return -ENODEV;
+	}
+	mutex_lock(&mdp3_session->lock);
+	if (mdp3_session->status) {
+		pr_info("fb%d is on already", mfd->index);
+		goto on_error;
+	}
+
+	rc = mdp3_ctrl_res_req_dma(mfd, 1);
+	if (rc) {
+		pr_err("resource request for dma on failed\n");
+		goto on_error;
+	}
+
+	rc = mdp3_ctrl_dma_init(mfd, mdp3_session->dma);
+	if (rc) {
+		pr_err("dma init failed\n");
+		goto on_error;
+	}
+
+	rc = mdp3_ctrl_intf_init(mfd, mdp3_session->intf);
+	if (rc) {
+		pr_err("display interface init failed\n");
+		goto on_error;
+	}
+
+	panel = mdp3_session->panel;
+
+	if (panel->event_handler)
+		rc = panel->event_handler(panel, MDSS_EVENT_PANEL_ON, NULL);
+
+	if (rc) {
+		pr_err("fail to turn on the panel\n");
+		goto on_error;
+	}
+
+	rc = mdp3_session->dma->start(mdp3_session->dma, mdp3_session->intf);
+	if (rc) {
+		pr_err("fail to start the MDP display interface\n");
+		goto on_error;
+	}
+
+on_error:
+	if (!rc)
+		mdp3_session->status = 1;
+
+	mutex_unlock(&mdp3_session->lock);
+	return rc;
+}
+
+static int mdp3_ctrl_off(struct msm_fb_data_type *mfd)
+{
+	int rc = 0;
+	struct mdp3_session_data *mdp3_session;
+	struct mdss_panel_data *panel;
+
+	pr_debug("mdp3_ctrl_off\n");
+	mdp3_session = (struct mdp3_session_data *)mfd->mdp.private1;
+	if (!mdp3_session || !mdp3_session->panel || !mdp3_session->dma ||
+		!mdp3_session->intf) {
+		pr_err("mdp3_ctrl_on no device");
+		return -ENODEV;
+	}
+
+	mutex_lock(&mdp3_session->lock);
+
+	if (!mdp3_session->status) {
+		pr_info("fb%d is off already", mfd->index);
+		goto off_error;
+	}
+
+	panel = mdp3_session->panel;
+	if (panel->event_handler)
+		rc = panel->event_handler(panel, MDSS_EVENT_PANEL_OFF, NULL);
+
+	if (rc)
+		pr_err("fail to turn off the panel\n");
+
+	rc = mdp3_session->dma->stop(mdp3_session->dma, mdp3_session->intf);
+
+	if (rc)
+		pr_err("fail to stop the MDP3 dma\n");
+
+	rc = mdp3_ctrl_res_req_dma(mfd, 0);
+	if (rc)
+		pr_err("resource release  for dma on failed\n");
+
+off_error:
+	mdp3_session->status = 0;
+
+	mutex_unlock(&mdp3_session->lock);
+	return 0;
+}
+
+static void mdp3_ctrl_pan_display(struct msm_fb_data_type *mfd)
+{
+	struct fb_info *fbi;
+	struct mdp3_session_data *mdp3_session;
+	u32 offset;
+	int bpp;
+
+	pr_debug("mdp3_ctrl_pan_display\n");
+	if (!mfd || !mfd->mdp.private1)
+		return;
+
+	mdp3_session = (struct mdp3_session_data *)mfd->mdp.private1;
+	if (!mdp3_session || !mdp3_session->dma)
+		return;
+
+	if (!mdp3_session->status) {
+		pr_err("mdp3_ctrl_pan_display, display off!\n");
+		return;
+	}
+
+	mutex_lock(&mdp3_session->lock);
+	fbi = mfd->fbi;
+
+	bpp = fbi->var.bits_per_pixel / 8;
+	offset = fbi->var.xoffset * bpp +
+		 fbi->var.yoffset * fbi->fix.line_length;
+
+	if (offset > fbi->fix.smem_len) {
+		pr_err("invalid fb offset=%u total length=%u\n",
+			offset, fbi->fix.smem_len);
+		goto pan_error;
+	}
+
+	mdp3_session->dma->update(mdp3_session->dma,
+				(void *)mfd->iova + offset);
+pan_error:
+	mutex_unlock(&mdp3_session->lock);
+}
+
+static int mdp3_ctrl_ioctl_handler(struct msm_fb_data_type *mfd,
+					u32 cmd, void __user *argp)
+{
+	int rc = -EINVAL;
+	struct mdp3_session_data *mdp3_session;
+	int val;
+
+	pr_debug("mdp3_ctrl_ioctl_handler\n");
+
+	mdp3_session = (struct mdp3_session_data *)mfd->mdp.private1;
+	if (!mdp3_session)
+		return -ENODEV;
+
+	if (!mdp3_session->status) {
+		pr_err("mdp3_ctrl_ioctl_handler, display off!\n");
+		return -EINVAL;
+	}
+
+	switch (cmd) {
+	case MSMFB_VSYNC_CTRL:
+	case MSMFB_OVERLAY_VSYNC_CTRL:
+		if (!copy_from_user(&val, argp, sizeof(val))) {
+			rc = mdp3_ctrl_vsync_enable(mfd, val);
+			if (!val)
+				init_completion(&mdp3_session->vsync_comp);
+		} else {
+			pr_err("MSMFB_OVERLAY_VSYNC_CTRL failed\n");
+			rc = -EFAULT;
+		}
+		break;
+	default:
+		break;
+	}
+
+	return rc;
+}
+
+int mdp3_ctrl_init(struct msm_fb_data_type *mfd)
+{
+	struct device *dev = mfd->fbi->dev;
+	struct msm_mdp_interface *mdp3_interface = &mfd->mdp;
+	struct mdp3_session_data *mdp3_session = NULL;
+	u32 intf_type = MDP3_DMA_OUTPUT_SEL_DSI_VIDEO;
+	int rc;
+
+	pr_debug("mdp3_ctrl_init\n");
+	mdp3_interface->on_fnc = mdp3_ctrl_on;
+	mdp3_interface->off_fnc = mdp3_ctrl_off;
+	mdp3_interface->do_histogram = NULL;
+	mdp3_interface->cursor_update = NULL;
+	mdp3_interface->dma_fnc = mdp3_ctrl_pan_display;
+	mdp3_interface->ioctl_handler = mdp3_ctrl_ioctl_handler;
+	mdp3_interface->kickoff_fnc = NULL;
+
+	mdp3_session = kmalloc(sizeof(struct mdp3_session_data), GFP_KERNEL);
+	if (!mdp3_session) {
+		pr_err("fail to allocate mdp3 private data structure");
+		return -ENOMEM;
+	}
+	memset(mdp3_session, 0, sizeof(struct mdp3_session_data));
+	mutex_init(&mdp3_session->lock);
+	init_completion(&mdp3_session->vsync_comp);
+	mdp3_session->dma = mdp3_get_dma_pipe(MDP3_DMA_CAP_ALL);
+	if (!mdp3_session->dma) {
+		rc = -ENODEV;
+		goto init_done;
+	}
+
+	intf_type = mdp3_ctrl_get_intf_type(mfd);
+	mdp3_session->intf = mdp3_get_display_intf(intf_type);
+	if (!mdp3_session->intf) {
+		rc = -ENODEV;
+		goto init_done;
+	}
+
+	mdp3_session->panel = dev_get_platdata(&mfd->pdev->dev);
+	mdp3_session->status = 0;
+
+	mfd->mdp.private1 = mdp3_session;
+
+	rc = sysfs_create_group(&dev->kobj, &vsync_fs_attr_group);
+	if (rc) {
+		pr_err("vsync sysfs group creation failed, ret=%d\n", rc);
+		goto init_done;
+	}
+
+	kobject_uevent(&dev->kobj, KOBJ_ADD);
+	pr_debug("vsync kobject_uevent(KOBJ_ADD)\n");
+
+init_done:
+	if (IS_ERR_VALUE(rc))
+		kfree(mdp3_session);
+
+	return rc;
+}
diff --git a/drivers/video/msm/mdss/mdp3_ctrl.h b/drivers/video/msm/mdss/mdp3_ctrl.h
new file mode 100644
index 0000000..d42ece7
--- /dev/null
+++ b/drivers/video/msm/mdss/mdp3_ctrl.h
@@ -0,0 +1,37 @@
+/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#ifndef MDP3_CTRL_H
+#define MDP3_CTRL_H
+
+#include <linux/types.h>
+#include <linux/mutex.h>
+#include <linux/completion.h>
+
+#include "mdp3_dma.h"
+#include "mdss_fb.h"
+#include "mdss_panel.h"
+
+struct mdp3_session_data {
+	struct mutex lock;
+	int status;
+	struct mdp3_dma *dma;
+	struct mdss_panel_data *panel;
+	struct mdp3_intf *intf;
+	struct msm_fb_data_type *mfd;
+	struct completion vsync_comp;
+};
+
+int mdp3_ctrl_init(struct msm_fb_data_type *mfd);
+
+#endif /* MDP3_CTRL_H */
diff --git a/drivers/video/msm/mdss/mdp3_dma.c b/drivers/video/msm/mdss/mdp3_dma.c
new file mode 100644
index 0000000..69e3d7e
--- /dev/null
+++ b/drivers/video/msm/mdss/mdp3_dma.c
@@ -0,0 +1,914 @@
+/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+#include <linux/bitops.h>
+#include <linux/iopoll.h>
+
+#include "mdp3.h"
+#include "mdp3_dma.h"
+#include "mdp3_hwio.h"
+
+#define DMA_STOP_POLL_SLEEP_US 1000
+#define DMA_STOP_POLL_TIMEOUT_US 16000
+
+static ktime_t mdp3_get_vsync_time(struct mdp3_dma *dma)
+{
+	unsigned long flag;
+	ktime_t time;
+
+	spin_lock_irqsave(&dma->dma_lock, flag);
+	time = dma->vsync_time;
+	spin_unlock_irqrestore(&dma->dma_lock, flag);
+	return time;
+}
+
+static void mdp3_vsync_intr_handler(int type, void *arg)
+{
+	struct mdp3_dma *dma = (struct mdp3_dma *)arg;
+	struct mdp3_vsync_notification vsync_client;
+
+	pr_debug("mdp3_vsync_intr_handler\n");
+	spin_lock(&dma->dma_lock);
+	vsync_client = dma->vsync_client;
+	if (!vsync_client.handler)
+		dma->cb_type &= ~MDP3_DMA_CALLBACK_TYPE_VSYNC;
+	dma->vsync_time = ktime_get();
+	complete(&dma->vsync_comp);
+	if (vsync_client.handler)
+		vsync_client.handler(vsync_client.arg);
+	spin_unlock(&dma->dma_lock);
+
+	if (!vsync_client.handler)
+		mdp3_irq_disable_nosync(type);
+}
+
+static void mdp3_dma_done_intr_handler(int type, void *arg)
+{
+	struct mdp3_dma *dma = (struct mdp3_dma *)arg;
+
+	pr_debug("mdp3_dma_done_intr_handler\n");
+	spin_lock(&dma->dma_lock);
+	dma->busy = false;
+	dma->cb_type &= ~MDP3_DMA_CALLBACK_TYPE_DMA_DONE;
+	spin_unlock(&dma->dma_lock);
+	complete(&dma->dma_comp);
+	mdp3_irq_disable_nosync(type);
+}
+
+void mdp3_dma_callback_enable(struct mdp3_dma *dma, int type)
+{
+	int irq_bit;
+	unsigned long flag;
+
+	pr_debug("mdp3_dma_callback_enable type=%d\n", type);
+
+	spin_lock_irqsave(&dma->dma_lock, flag);
+	if (dma->cb_type & type) {
+		spin_unlock_irqrestore(&dma->dma_lock, flag);
+		return;
+	} else {
+		dma->cb_type |= type;
+		spin_unlock_irqrestore(&dma->dma_lock, flag);
+	}
+
+	if (dma->output_config.out_sel == MDP3_DMA_OUTPUT_SEL_DSI_VIDEO ||
+		dma->output_config.out_sel == MDP3_DMA_OUTPUT_SEL_LCDC) {
+		if (type & MDP3_DMA_CALLBACK_TYPE_VSYNC)
+			mdp3_irq_enable(MDP3_INTR_LCDC_START_OF_FRAME);
+	} else if (dma->output_config.out_sel == MDP3_DMA_OUTPUT_SEL_DSI_CMD) {
+		if (type & MDP3_DMA_CALLBACK_TYPE_VSYNC) {
+			irq_bit = MDP3_INTR_SYNC_PRIMARY_LINE;
+			irq_bit += dma->dma_sel;
+			mdp3_irq_enable(irq_bit);
+		}
+
+		if (type & MDP3_DMA_CALLBACK_TYPE_DMA_DONE) {
+			irq_bit = MDP3_INTR_DMA_P_DONE;
+			if (dma->dma_sel == MDP3_DMA_S)
+				irq_bit = MDP3_INTR_DMA_S_DONE;
+			mdp3_irq_enable(irq_bit);
+		}
+	} else {
+		pr_err("mdp3_dma_callback_enable not supported interface\n");
+	}
+}
+
+void mdp3_dma_callback_disable(struct mdp3_dma *dma, int type)
+{
+	int irq_bit;
+	unsigned long flag;
+
+	pr_debug("mdp3_dma_callback_disable type=%d\n", type);
+
+	spin_lock_irqsave(&dma->dma_lock, flag);
+	if ((dma->cb_type & type) == 0) {
+		spin_unlock_irqrestore(&dma->dma_lock, flag);
+		return;
+	} else {
+		dma->cb_type &= ~type;
+		spin_unlock_irqrestore(&dma->dma_lock, flag);
+	}
+
+	if (dma->output_config.out_sel == MDP3_DMA_OUTPUT_SEL_DSI_VIDEO ||
+		dma->output_config.out_sel == MDP3_DMA_OUTPUT_SEL_LCDC) {
+		if (type & MDP3_DMA_CALLBACK_TYPE_VSYNC)
+			mdp3_irq_disable(MDP3_INTR_LCDC_START_OF_FRAME);
+	} else if (dma->output_config.out_sel == MDP3_DMA_OUTPUT_SEL_DSI_CMD) {
+		if (type & MDP3_DMA_CALLBACK_TYPE_VSYNC) {
+			irq_bit = MDP3_INTR_SYNC_PRIMARY_LINE;
+			irq_bit += dma->dma_sel;
+			mdp3_irq_disable(irq_bit);
+		}
+
+		if (type & MDP3_DMA_CALLBACK_TYPE_DMA_DONE) {
+			irq_bit = MDP3_INTR_DMA_P_DONE;
+			if (dma->dma_sel == MDP3_DMA_S)
+				irq_bit = MDP3_INTR_DMA_S_DONE;
+			mdp3_irq_disable(irq_bit);
+		}
+	}
+}
+
+static int mdp3_dma_callback_setup(struct mdp3_dma *dma)
+{
+	int rc;
+	struct mdp3_intr_cb vsync_cb = {
+		.cb = mdp3_vsync_intr_handler,
+		.data = dma,
+	};
+
+	struct mdp3_intr_cb dma_cb = {
+		.cb = mdp3_dma_done_intr_handler,
+		.data = dma,
+	};
+
+	if (dma->output_config.out_sel == MDP3_DMA_OUTPUT_SEL_DSI_VIDEO ||
+		dma->output_config.out_sel == MDP3_DMA_OUTPUT_SEL_LCDC)
+		rc = mdp3_set_intr_callback(MDP3_INTR_LCDC_START_OF_FRAME,
+					&vsync_cb);
+	else if (dma->output_config.out_sel == MDP3_DMA_OUTPUT_SEL_DSI_CMD) {
+		int irq_bit = MDP3_INTR_SYNC_PRIMARY_LINE;
+		irq_bit += dma->dma_sel;
+		rc = mdp3_set_intr_callback(irq_bit, &vsync_cb);
+		irq_bit = MDP3_INTR_DMA_P_DONE;
+		if (dma->dma_sel == MDP3_DMA_S)
+			irq_bit = MDP3_INTR_DMA_S_DONE;
+		rc |= mdp3_set_intr_callback(irq_bit, &dma_cb);
+	} else {
+		pr_err("mdp3_dma_callback_setup not suppported interface\n");
+		rc = -ENODEV;
+	}
+	return rc;
+}
+
+static void mdp3_dma_vsync_enable(struct mdp3_dma *dma,
+				struct mdp3_vsync_notification *vsync_client)
+{
+	unsigned long flag;
+	int updated = 0;
+	int cb_type = MDP3_DMA_CALLBACK_TYPE_VSYNC;
+
+	pr_debug("mdp3_dma_vsync_enable\n");
+
+	spin_lock_irqsave(&dma->dma_lock, flag);
+	if (vsync_client) {
+		if (dma->vsync_client.handler != vsync_client->handler) {
+			dma->vsync_client = *vsync_client;
+			updated = 1;
+		}
+	} else {
+		if (!dma->vsync_client.handler) {
+			dma->vsync_client.handler = NULL;
+			dma->vsync_client.arg = NULL;
+			updated = 1;
+		}
+	}
+	spin_unlock_irqrestore(&dma->dma_lock, flag);
+
+	if (updated) {
+		if (vsync_client && vsync_client->handler)
+			mdp3_dma_callback_enable(dma, cb_type);
+		else
+			mdp3_dma_callback_disable(dma, cb_type);
+	}
+}
+
+static int mdp3_dmap_config(struct mdp3_dma *dma,
+			struct mdp3_dma_source *source_config,
+			struct mdp3_dma_output_config *output_config)
+{
+	u32 dma_p_cfg_reg, dma_p_size, dma_p_out_xy;
+
+	dma_p_cfg_reg = source_config->format << 25;
+	if (output_config->dither_en)
+		dma_p_cfg_reg |= BIT(24);
+	dma_p_cfg_reg |= output_config->out_sel << 19;
+	dma_p_cfg_reg |= output_config->bit_mask_polarity << 18;
+	dma_p_cfg_reg |= output_config->color_components_flip << 14;
+	dma_p_cfg_reg |= output_config->pack_pattern << 8;
+	dma_p_cfg_reg |= output_config->pack_align << 7;
+	dma_p_cfg_reg |= output_config->color_comp_out_bits;
+
+	dma_p_size = source_config->width | (source_config->height << 16);
+	dma_p_out_xy = source_config->x | (source_config->y << 16);
+
+	MDP3_REG_WRITE(MDP3_REG_DMA_P_CONFIG, dma_p_cfg_reg);
+	MDP3_REG_WRITE(MDP3_REG_DMA_P_SIZE, dma_p_size);
+	MDP3_REG_WRITE(MDP3_REG_DMA_P_IBUF_ADDR, (u32)source_config->buf);
+	MDP3_REG_WRITE(MDP3_REG_DMA_P_IBUF_Y_STRIDE, source_config->stride);
+	MDP3_REG_WRITE(MDP3_REG_DMA_P_OUT_XY, dma_p_out_xy);
+
+	/*
+	 * NOTE: MDP_DMA_P_FETCH_CFG: max_burst_size need to use value 4, not
+	 * the default 16 for MDP hang issue workaround
+	 */
+	MDP3_REG_WRITE(MDP3_REG_DMA_P_FETCH_CFG, 0x10);
+	MDP3_REG_WRITE(MDP3_REG_PRIMARY_RD_PTR_IRQ, 0x10);
+
+	dma->source_config = *source_config;
+	dma->output_config = *output_config;
+
+	mdp3_dma_callback_setup(dma);
+	return 0;
+}
+
+static int mdp3_dmas_config(struct mdp3_dma *dma,
+			struct mdp3_dma_source *source_config,
+			struct mdp3_dma_output_config *output_config)
+{
+	u32 dma_s_cfg_reg, dma_s_size, dma_s_out_xy;
+
+	dma_s_cfg_reg = source_config->format << 25;
+	if (output_config->dither_en)
+		dma_s_cfg_reg |= BIT(24);
+	dma_s_cfg_reg |= output_config->out_sel << 19;
+	dma_s_cfg_reg |= output_config->bit_mask_polarity << 18;
+	dma_s_cfg_reg |= output_config->color_components_flip << 14;
+	dma_s_cfg_reg |= output_config->pack_pattern << 8;
+	dma_s_cfg_reg |= output_config->pack_align << 7;
+	dma_s_cfg_reg |= output_config->color_comp_out_bits;
+
+	dma_s_size = source_config->width | (source_config->height << 16);
+	dma_s_out_xy = source_config->x | (source_config->y << 16);
+
+	MDP3_REG_WRITE(MDP3_REG_DMA_S_CONFIG, dma_s_cfg_reg);
+	MDP3_REG_WRITE(MDP3_REG_DMA_S_SIZE, dma_s_size);
+	MDP3_REG_WRITE(MDP3_REG_DMA_S_IBUF_ADDR, (u32)source_config->buf);
+	MDP3_REG_WRITE(MDP3_REG_DMA_S_IBUF_Y_STRIDE, source_config->stride);
+	MDP3_REG_WRITE(MDP3_REG_DMA_S_OUT_XY, dma_s_out_xy);
+
+	MDP3_REG_WRITE(MDP3_REG_SECONDARY_RD_PTR_IRQ, 0x10);
+
+	dma->source_config = *source_config;
+	dma->output_config = *output_config;
+
+	mdp3_dma_callback_setup(dma);
+	return 0;
+}
+
+static int mdp3_dmap_cursor_config(struct mdp3_dma *dma,
+				struct mdp3_dma_cursor *cursor)
+{
+	u32 cursor_size, cursor_pos, blend_param, trans_mask;
+
+	cursor_size = cursor->width | (cursor->height << 16);
+	cursor_pos = cursor->x | (cursor->y << 16);
+	trans_mask = 0;
+	if (cursor->blend_config.mode == MDP3_DMA_CURSOR_BLEND_CONSTANT_ALPHA) {
+		blend_param = cursor->blend_config.constant_alpha << 24;
+	} else if (cursor->blend_config.mode ==
+			MDP3_DMA_CURSOR_BLEND_COLOR_KEYING) {
+		blend_param = cursor->blend_config.transparent_color;
+		trans_mask = cursor->blend_config.transparency_mask;
+	} else {
+		blend_param = 0;
+	}
+
+	MDP3_REG_WRITE(MDP3_REG_DMA_P_CURSOR_FORMAT, cursor->format);
+	MDP3_REG_WRITE(MDP3_REG_DMA_P_CURSOR_SIZE, cursor_size);
+	MDP3_REG_WRITE(MDP3_REG_DMA_P_CURSOR_BUF_ADDR, (u32)cursor->buf);
+	MDP3_REG_WRITE(MDP3_REG_DMA_P_CURSOR_POS, cursor_pos);
+	MDP3_REG_WRITE(MDP3_REG_DMA_P_CURSOR_BLEND_CONFIG,
+			cursor->blend_config.mode);
+	MDP3_REG_WRITE(MDP3_REG_DMA_P_CURSOR_BLEND_PARAM, blend_param);
+	MDP3_REG_WRITE(MDP3_REG_DMA_P_CURSOR_BLEND_TRANS_MASK, trans_mask);
+	dma->cursor = *cursor;
+	return 0;
+}
+
+static int mdp3_dmap_ccs_config(struct mdp3_dma *dma,
+			struct mdp3_dma_color_correct_config *config,
+			struct mdp3_dma_ccs *ccs,
+			struct mdp3_dma_lut *lut)
+{
+	int i;
+	u32 addr, cc_config, color;
+
+	cc_config = config->lut_enable;
+	if (config->ccs_enable)
+		cc_config |= BIT(3);
+	cc_config |= config->lut_position << 4;
+	cc_config |= config->ccs_sel << 5;
+	cc_config |= config->pre_bias_sel << 6;
+	cc_config |= config->post_bias_sel << 7;
+	cc_config |= config->pre_limit_sel << 8;
+	cc_config |= config->post_limit_sel << 9;
+	cc_config |= config->lut_sel << 10;
+
+	MDP3_REG_WRITE(MDP3_REG_DMA_P_COLOR_CORRECT_CONFIG, cc_config);
+
+	if (config->ccs_enable && ccs) {
+		if (ccs->mv1) {
+			addr = MDP3_REG_DMA_P_CSC_MV1;
+			for (i = 0; i < 9; i++) {
+				MDP3_REG_WRITE(addr, ccs->mv1[i]);
+				addr += 4;
+			}
+		}
+
+		if (ccs->mv2) {
+			addr = MDP3_REG_DMA_P_CSC_MV2;
+			for (i = 0; i < 9; i++) {
+				MDP3_REG_WRITE(addr, ccs->mv2[i]);
+				addr += 4;
+			}
+		}
+
+		if (ccs->pre_bv1) {
+			addr = MDP3_REG_DMA_P_CSC_PRE_BV1;
+			for (i = 0; i < 3; i++) {
+				MDP3_REG_WRITE(addr, ccs->pre_bv1[i]);
+				addr += 4;
+			}
+		}
+
+		if (ccs->pre_bv2) {
+			addr = MDP3_REG_DMA_P_CSC_PRE_BV2;
+			for (i = 0; i < 3; i++) {
+				MDP3_REG_WRITE(addr, ccs->pre_bv2[i]);
+				addr += 4;
+			}
+		}
+
+		if (ccs->post_bv1) {
+			addr = MDP3_REG_DMA_P_CSC_POST_BV1;
+			for (i = 0; i < 3; i++) {
+				MDP3_REG_WRITE(addr, ccs->post_bv1[i]);
+				addr += 4;
+			}
+		}
+
+		if (ccs->post_bv2) {
+			addr = MDP3_REG_DMA_P_CSC_POST_BV2;
+			for (i = 0; i < 3; i++) {
+				MDP3_REG_WRITE(addr, ccs->post_bv2[i]);
+				addr += 4;
+			}
+		}
+
+		if (ccs->pre_lv1) {
+			addr = MDP3_REG_DMA_P_CSC_PRE_LV1;
+			for (i = 0; i < 6; i++) {
+				MDP3_REG_WRITE(addr, ccs->pre_lv1[i]);
+				addr += 4;
+			}
+		}
+
+		if (ccs->pre_lv2) {
+			addr = MDP3_REG_DMA_P_CSC_PRE_LV2;
+			for (i = 0; i < 6; i++) {
+				MDP3_REG_WRITE(addr, ccs->pre_lv2[i]);
+				addr += 4;
+			}
+		}
+
+		if (ccs->post_lv1) {
+			addr = MDP3_REG_DMA_P_CSC_POST_LV1;
+			for (i = 0; i < 6; i++) {
+				MDP3_REG_WRITE(addr, ccs->post_lv1[i]);
+				addr += 4;
+			}
+		}
+
+		if (ccs->post_lv2) {
+			addr = MDP3_REG_DMA_P_CSC_POST_LV2;
+			for (i = 0; i < 6; i++) {
+				MDP3_REG_WRITE(addr, ccs->post_lv2[i]);
+				addr += 4;
+			}
+		}
+	}
+
+	if (config->lut_enable && lut) {
+		if (lut->color0_lut1 && lut->color1_lut1 && lut->color2_lut1) {
+			addr = MDP3_REG_DMA_P_CSC_LUT1;
+			for (i = 0; i < 256; i++) {
+				color = lut->color0_lut1[i];
+				color |= lut->color1_lut1[i] << 8;
+				color |= lut->color2_lut1[i] << 16;
+				MDP3_REG_WRITE(addr, color);
+				addr += 4;
+			}
+		}
+
+		if (lut->color0_lut2 && lut->color1_lut2 && lut->color2_lut2) {
+			addr = MDP3_REG_DMA_P_CSC_LUT2;
+			for (i = 0; i < 256; i++) {
+				color = lut->color0_lut2[i];
+				color |= lut->color1_lut2[i] << 8;
+				color |= lut->color2_lut2[i] << 16;
+				MDP3_REG_WRITE(addr, color);
+				addr += 4;
+			}
+		}
+	}
+
+	dma->ccs_config = *config;
+	return 0;
+}
+
+static int mdp3_dmap_histo_config(struct mdp3_dma *dma,
+			struct mdp3_dma_histogram_config *histo_config)
+{
+	u32 hist_bit_mask, hist_control;
+
+	if (histo_config->bit_mask_polarity)
+		hist_bit_mask = BIT(31);
+	hist_bit_mask |= histo_config->bit_mask;
+
+	if (histo_config->auto_clear_en)
+		hist_control = BIT(0);
+	MDP3_REG_WRITE(MDP3_REG_DMA_P_HIST_FRAME_CNT,
+			histo_config->frame_count);
+	MDP3_REG_WRITE(MDP3_REG_DMA_P_HIST_BIT_MASK, hist_bit_mask);
+	MDP3_REG_WRITE(MDP3_REG_DMA_P_HIST_CONTROL, hist_control);
+	return 0;
+}
+
+static int mdp3_dmap_update(struct mdp3_dma *dma, void *buf)
+{
+	int wait_for_dma_done = 0;
+	unsigned long flag;
+	int cb_type = MDP3_DMA_CALLBACK_TYPE_VSYNC;
+
+	pr_debug("mdp3_dmap_update\n");
+
+	if (dma->output_config.out_sel == MDP3_DMA_OUTPUT_SEL_DSI_CMD) {
+		cb_type |= MDP3_DMA_CALLBACK_TYPE_DMA_DONE;
+		spin_lock_irqsave(&dma->dma_lock, flag);
+		if (dma->busy)
+			wait_for_dma_done = 1;
+		spin_unlock_irqrestore(&dma->dma_lock, flag);
+
+		if (wait_for_dma_done)
+			wait_for_completion_killable(&dma->dma_comp);
+	}
+
+	spin_lock_irqsave(&dma->dma_lock, flag);
+	MDP3_REG_WRITE(MDP3_REG_DMA_P_IBUF_ADDR, (u32)buf);
+	dma->source_config.buf = buf;
+	if (dma->output_config.out_sel == MDP3_DMA_OUTPUT_SEL_DSI_CMD) {
+		MDP3_REG_WRITE(MDP3_REG_DMA_P_START, 1);
+		dma->busy = true;
+	}
+	wmb();
+	init_completion(&dma->vsync_comp);
+	spin_unlock_irqrestore(&dma->dma_lock, flag);
+
+	mdp3_dma_callback_enable(dma, cb_type);
+	pr_debug("mdp3_dmap_update wait for vsync_comp in\n");
+	wait_for_completion_killable(&dma->vsync_comp);
+	pr_debug("mdp3_dmap_update wait for vsync_comp out\n");
+	return 0;
+}
+
+static int mdp3_dmas_update(struct mdp3_dma *dma, void *buf)
+{
+	int wait_for_dma_done = 0;
+	unsigned long flag;
+	int cb_type = MDP3_DMA_CALLBACK_TYPE_VSYNC;
+
+	if (dma->output_config.out_sel == MDP3_DMA_OUTPUT_SEL_DSI_CMD) {
+		cb_type |= MDP3_DMA_CALLBACK_TYPE_DMA_DONE;
+		spin_lock_irqsave(&dma->dma_lock, flag);
+		if (dma->busy)
+			wait_for_dma_done = 1;
+		spin_unlock_irqrestore(&dma->dma_lock, flag);
+
+		if (wait_for_dma_done)
+			wait_for_completion_killable(&dma->dma_comp);
+	}
+
+	spin_lock_irqsave(&dma->dma_lock, flag);
+	MDP3_REG_WRITE(MDP3_REG_DMA_S_IBUF_ADDR, (u32)buf);
+	dma->source_config.buf = buf;
+	if (dma->output_config.out_sel == MDP3_DMA_OUTPUT_SEL_DSI_CMD) {
+		MDP3_REG_WRITE(MDP3_REG_DMA_S_START, 1);
+		dma->busy = true;
+	}
+	wmb();
+	init_completion(&dma->vsync_comp);
+	spin_unlock_irqrestore(&dma->dma_lock, flag);
+
+	mdp3_dma_callback_enable(dma, cb_type);
+	wait_for_completion_killable(&dma->vsync_comp);
+	return 0;
+}
+
+static int mdp3_dmap_cursor_update(struct mdp3_dma *dma, int x, int y)
+{
+	u32 cursor_pos;
+
+	cursor_pos = x | (y << 16);
+	MDP3_REG_WRITE(MDP3_REG_DMA_P_CURSOR_POS, cursor_pos);
+	dma->cursor.x = x;
+	dma->cursor.y = y;
+	return 0;
+}
+
+static int mdp3_dmap_histo_get(struct mdp3_dma *dma,
+			struct mdp3_dma_histogram_data *data)
+{
+	int i;
+	u32 addr, extra;
+
+	addr = MDP3_REG_DMA_P_HIST_R_DATA;
+	for (i = 0; i < 32; i++) {
+		data->r_data[i] = MDP3_REG_READ(addr);
+		addr += 4;
+	}
+
+	addr = MDP3_REG_DMA_P_HIST_G_DATA;
+	for (i = 0; i < 32; i++) {
+		data->g_data[i] = MDP3_REG_READ(addr);
+		addr += 4;
+	}
+
+	addr = MDP3_REG_DMA_P_HIST_B_DATA;
+	for (i = 0; i < 32; i++) {
+		data->b_data[i] = MDP3_REG_READ(addr);
+		addr += 4;
+	}
+
+	extra = MDP3_REG_READ(MDP3_REG_DMA_P_HIST_EXTRA_INFO_0);
+	data->r_min_value = (extra & 0x1F0000) >> 16;
+	data->r_max_value = (extra & 0x1F000000) >> 24;
+	extra = MDP3_REG_READ(MDP3_REG_DMA_P_HIST_EXTRA_INFO_1);
+	data->g_min_value = extra & 0x1F;
+	data->g_max_value = (extra & 0x1F00) >> 8;
+	data->b_min_value = (extra & 0x1F0000) >> 16;
+	data->b_max_value = (extra & 0x1F000000) >> 24;
+	return 0;
+}
+
+static int mdp3_dmap_histo_op(struct mdp3_dma *dma, u32 op)
+{
+	switch (op) {
+	case MDP3_DMA_HISTO_OP_START:
+		MDP3_REG_WRITE(MDP3_REG_DMA_P_HIST_START, 1);
+		break;
+	case MDP3_DMA_HISTO_OP_STOP:
+		MDP3_REG_WRITE(MDP3_REG_DMA_P_HIST_STOP_REQ, 1);
+		break;
+	case MDP3_DMA_HISTO_OP_CANCEL:
+		MDP3_REG_WRITE(MDP3_REG_DMA_P_HIST_CANCEL_REQ, 1);
+		break;
+	case MDP3_DMA_HISTO_OP_RESET:
+		MDP3_REG_WRITE(MDP3_REG_DMA_P_HIST_RESET_SEQ_START, 1);
+		break;
+	default:
+		return -EINVAL;
+	}
+	return 0;
+}
+
+static int mdp3_dmap_histo_intr_status(struct mdp3_dma *dma, int *status)
+{
+	*status = MDP3_REG_READ(MDP3_REG_DMA_P_HIST_INTR_STATUS);
+	return 0;
+}
+
+static int mdp3_dmap_histo_intr_enable(struct mdp3_dma *dma, u32 mask)
+{
+	MDP3_REG_WRITE(MDP3_REG_DMA_P_HIST_INTR_ENABLE, mask);
+	return 0;
+}
+
+static int mdp3_dmap_histo_intr_clear(struct mdp3_dma *dma, u32 mask)
+{
+	MDP3_REG_WRITE(MDP3_REG_DMA_P_HIST_INTR_CLEAR, mask);
+	return 0;
+}
+
+static int mdp3_dma_start(struct mdp3_dma *dma, struct mdp3_intf *intf)
+{
+	unsigned long flag;
+	int cb_type = MDP3_DMA_CALLBACK_TYPE_VSYNC;
+	u32 dma_start_offset = MDP3_REG_DMA_P_START;
+
+	if (dma->dma_sel == MDP3_DMA_P)
+		dma_start_offset = MDP3_REG_DMA_P_START;
+	else if (dma->dma_sel == MDP3_DMA_S)
+		dma_start_offset = MDP3_REG_DMA_S_START;
+	else
+		return -EINVAL;
+
+	spin_lock_irqsave(&dma->dma_lock, flag);
+	if (dma->output_config.out_sel == MDP3_DMA_OUTPUT_SEL_DSI_CMD) {
+		cb_type |= MDP3_DMA_CALLBACK_TYPE_DMA_DONE;
+		MDP3_REG_WRITE(dma_start_offset, 1);
+		dma->busy = true;
+	}
+
+	intf->start(intf);
+	wmb();
+	init_completion(&dma->vsync_comp);
+	spin_unlock_irqrestore(&dma->dma_lock, flag);
+
+	mdp3_dma_callback_enable(dma, cb_type);
+	pr_debug("mdp3_dma_start wait for vsync_comp in\n");
+	wait_for_completion_killable(&dma->vsync_comp);
+	pr_debug("mdp3_dma_start wait for vsync_comp out\n");
+	return 0;
+}
+
+static int mdp3_dma_stop(struct mdp3_dma *dma, struct mdp3_intf *intf)
+{
+	int ret = 0;
+	u32 status, display_status_bit;
+
+	if (dma->dma_sel == MDP3_DMA_P)
+		display_status_bit = BIT(6);
+	else if (dma->dma_sel == MDP3_DMA_S)
+		display_status_bit = BIT(7);
+	else
+		return -EINVAL;
+
+	if (dma->output_config.out_sel == MDP3_DMA_OUTPUT_SEL_DSI_VIDEO)
+		display_status_bit |= BIT(11);
+
+	intf->stop(intf);
+	ret = readl_poll_timeout((mdp3_res->mdp_base + MDP3_REG_DISPLAY_STATUS),
+				status,
+				((status & display_status_bit) == 0),
+				DMA_STOP_POLL_SLEEP_US,
+				DMA_STOP_POLL_TIMEOUT_US);
+
+	mdp3_dma_callback_disable(dma, MDP3_DMA_CALLBACK_TYPE_VSYNC |
+					MDP3_DMA_CALLBACK_TYPE_DMA_DONE);
+
+	dma->busy = false;
+	return ret;
+}
+
+int mdp3_dma_init(struct mdp3_dma *dma,
+		struct mdp3_dma_source *source_config,
+		struct mdp3_dma_output_config *output_config)
+{
+	int ret = 0;
+
+	pr_debug("mdp3_dma_init\n");
+	switch (dma->dma_sel) {
+	case MDP3_DMA_P:
+		dma->busy = 0;
+
+		ret = mdp3_dmap_config(dma, source_config, output_config);
+		if (ret < 0)
+			return ret;
+
+		dma->config_cursor = mdp3_dmap_cursor_config;
+		dma->config_ccs = mdp3_dmap_ccs_config;
+		dma->config_histo = mdp3_dmap_histo_config;
+		dma->update = mdp3_dmap_update;
+		dma->update_cursor = mdp3_dmap_cursor_update;
+		dma->get_histo = mdp3_dmap_histo_get;
+		dma->histo_op = mdp3_dmap_histo_op;
+		dma->histo_intr_status = mdp3_dmap_histo_intr_status;
+		dma->histo_intr_enable = mdp3_dmap_histo_intr_enable;
+		dma->histo_intr_clear = mdp3_dmap_histo_intr_clear;
+		dma->vsync_enable = mdp3_dma_vsync_enable;
+		dma->get_vsync_time = mdp3_get_vsync_time;
+		dma->start = mdp3_dma_start;
+		dma->stop = mdp3_dma_stop;
+		break;
+	case MDP3_DMA_S:
+		dma->busy = 0;
+		ret = mdp3_dmas_config(dma, source_config, output_config);
+		if (ret < 0)
+			return ret;
+
+		dma->config_cursor = NULL;
+		dma->config_ccs = NULL;
+		dma->config_histo = NULL;
+		dma->update = mdp3_dmas_update;
+		dma->update_cursor = NULL;
+		dma->get_histo = NULL;
+		dma->histo_op = NULL;
+		dma->histo_intr_status = NULL;
+		dma->histo_intr_enable = NULL;
+		dma->histo_intr_clear = NULL;
+		dma->vsync_enable = mdp3_dma_vsync_enable;
+		dma->get_vsync_time = mdp3_get_vsync_time;
+		dma->start = mdp3_dma_start;
+		dma->stop = mdp3_dma_stop;
+		break;
+	case MDP3_DMA_E:
+	default:
+		ret = -ENODEV;
+		break;
+	}
+
+	spin_lock_init(&dma->dma_lock);
+	init_completion(&dma->vsync_comp);
+	init_completion(&dma->dma_comp);
+	dma->cb_type = 0;
+	dma->vsync_client.handler = NULL;
+	dma->vsync_client.arg = NULL;
+
+	memset(&dma->cursor, 0, sizeof(dma->cursor));
+	memset(&dma->ccs_config, 0, sizeof(dma->ccs_config));
+	memset(&dma->histogram_config, 0, sizeof(dma->histogram_config));
+
+	return ret;
+}
+
+int lcdc_config(struct mdp3_intf *intf, struct mdp3_intf_cfg *cfg)
+{
+	u32 temp;
+	struct mdp3_video_intf_cfg *v = &cfg->video;
+	temp = v->hsync_pulse_width | (v->hsync_period << 16);
+	MDP3_REG_WRITE(MDP3_REG_LCDC_HSYNC_CTL, temp);
+	MDP3_REG_WRITE(MDP3_REG_LCDC_VSYNC_PERIOD, v->vsync_period);
+	MDP3_REG_WRITE(MDP3_REG_LCDC_VSYNC_PULSE_WIDTH, v->vsync_pulse_width);
+	temp = v->display_start_x | (v->display_end_x << 16);
+	MDP3_REG_WRITE(MDP3_REG_LCDC_DISPLAY_HCTL, temp);
+	MDP3_REG_WRITE(MDP3_REG_LCDC_DISPLAY_V_START, v->display_start_y);
+	MDP3_REG_WRITE(MDP3_REG_LCDC_DISPLAY_V_END, v->display_end_y);
+	temp = v->active_start_x | (v->active_end_x);
+	if (v->active_h_enable)
+		temp |= BIT(31);
+	MDP3_REG_WRITE(MDP3_REG_LCDC_ACTIVE_HCTL, temp);
+	MDP3_REG_WRITE(MDP3_REG_LCDC_ACTIVE_V_START, v->active_start_y);
+	MDP3_REG_WRITE(MDP3_REG_LCDC_ACTIVE_V_END, v->active_end_y);
+	MDP3_REG_WRITE(MDP3_REG_LCDC_HSYNC_SKEW, v->hsync_skew);
+	temp = 0;
+	if (!v->hsync_polarity)
+		temp = BIT(0);
+	if (!v->vsync_polarity)
+		temp = BIT(1);
+	if (!v->de_polarity)
+		temp = BIT(2);
+	MDP3_REG_WRITE(MDP3_REG_LCDC_CTL_POLARITY, temp);
+
+	return 0;
+}
+
+int lcdc_start(struct mdp3_intf *intf)
+{
+	MDP3_REG_WRITE(MDP3_REG_LCDC_EN, BIT(0));
+	wmb();
+	intf->active = true;
+	return 0;
+}
+
+int lcdc_stop(struct mdp3_intf *intf)
+{
+	MDP3_REG_WRITE(MDP3_REG_LCDC_EN, 0);
+	wmb();
+	intf->active = false;
+	return 0;
+}
+
+int dsi_video_config(struct mdp3_intf *intf, struct mdp3_intf_cfg *cfg)
+{
+	u32 temp;
+	struct mdp3_video_intf_cfg *v = &cfg->video;
+
+	pr_debug("dsi_video_config\n");
+
+	temp = v->hsync_pulse_width | (v->hsync_period << 16);
+	MDP3_REG_WRITE(MDP3_REG_DSI_VIDEO_HSYNC_CTL, temp);
+	MDP3_REG_WRITE(MDP3_REG_DSI_VIDEO_VSYNC_PERIOD, v->vsync_period);
+	MDP3_REG_WRITE(MDP3_REG_DSI_VIDEO_VSYNC_PULSE_WIDTH,
+			v->vsync_pulse_width);
+	temp = v->display_start_x | (v->display_end_x << 16);
+	MDP3_REG_WRITE(MDP3_REG_DSI_VIDEO_DISPLAY_HCTL, temp);
+	MDP3_REG_WRITE(MDP3_REG_DSI_VIDEO_DISPLAY_V_START, v->display_start_y);
+	MDP3_REG_WRITE(MDP3_REG_DSI_VIDEO_DISPLAY_V_END, v->display_end_y);
+	temp = v->active_start_x | (v->active_end_x << 16);
+	if (v->active_h_enable)
+		temp |= BIT(31);
+	MDP3_REG_WRITE(MDP3_REG_DSI_VIDEO_ACTIVE_HCTL, temp);
+
+	temp = v->active_start_y;
+	if (v->active_v_enable)
+		temp |= BIT(31);
+	MDP3_REG_WRITE(MDP3_REG_DSI_VIDEO_ACTIVE_V_START, temp);
+	MDP3_REG_WRITE(MDP3_REG_DSI_VIDEO_ACTIVE_V_END, v->active_end_y);
+	MDP3_REG_WRITE(MDP3_REG_DSI_VIDEO_HSYNC_SKEW, v->hsync_skew);
+	temp = 0;
+	if (!v->hsync_polarity)
+		temp |= BIT(0);
+	if (!v->vsync_polarity)
+		temp |= BIT(1);
+	if (!v->de_polarity)
+		temp |= BIT(2);
+	MDP3_REG_WRITE(MDP3_REG_DSI_VIDEO_CTL_POLARITY, temp);
+
+	return 0;
+}
+
+int dsi_video_start(struct mdp3_intf *intf)
+{
+	pr_debug("dsi_video_start\n");
+	MDP3_REG_WRITE(MDP3_REG_DSI_VIDEO_EN, BIT(0));
+	wmb();
+	intf->active = true;
+	return 0;
+}
+
+int dsi_video_stop(struct mdp3_intf *intf)
+{
+	pr_debug("dsi_video_stop\n");
+	MDP3_REG_WRITE(MDP3_REG_DSI_VIDEO_EN, 0);
+	wmb();
+	intf->active = false;
+	return 0;
+}
+
+int dsi_cmd_config(struct mdp3_intf *intf, struct mdp3_intf_cfg *cfg)
+{
+	u32 id_map = 0;
+	u32 trigger_en = 0;
+
+	if (cfg->dsi_cmd.primary_dsi_cmd_id)
+		id_map = BIT(0);
+	if (cfg->dsi_cmd.secondary_dsi_cmd_id)
+		id_map = BIT(4);
+
+	if (cfg->dsi_cmd.dsi_cmd_tg_intf_sel)
+		trigger_en = BIT(4);
+
+	MDP3_REG_WRITE(MDP3_REG_DSI_CMD_MODE_ID_MAP, id_map);
+	MDP3_REG_WRITE(MDP3_REG_DSI_CMD_MODE_TRIGGER_EN, trigger_en);
+
+	return 0;
+}
+
+int dsi_cmd_start(struct mdp3_intf *intf)
+{
+	intf->active = true;
+	return 0;
+}
+
+int dsi_cmd_stop(struct mdp3_intf *intf)
+{
+	intf->active = false;
+	return 0;
+}
+
+int mdp3_intf_init(struct mdp3_intf *intf, struct mdp3_intf_cfg *cfg)
+{
+	int ret = 0;
+	switch (cfg->type) {
+	case MDP3_DMA_OUTPUT_SEL_LCDC:
+		intf->config = lcdc_config;
+		intf->start = lcdc_start;
+		intf->stop = lcdc_stop;
+		break;
+	case MDP3_DMA_OUTPUT_SEL_DSI_VIDEO:
+		intf->config = dsi_video_config;
+		intf->start = dsi_video_start;
+		intf->stop = dsi_video_stop;
+		break;
+	case MDP3_DMA_OUTPUT_SEL_DSI_CMD:
+		intf->config = dsi_cmd_config;
+		intf->start = dsi_cmd_start;
+		intf->stop = dsi_cmd_stop;
+		break;
+
+	default:
+		return -EINVAL;
+	}
+
+	intf->active = false;
+	if (intf->config)
+		ret = intf->config(intf, cfg);
+
+	if (ret) {
+		pr_err("MDP interface initialization failed\n");
+		return ret;
+	}
+
+	intf->cfg = *cfg;
+	return 0;
+}
diff --git a/drivers/video/msm/mdss/mdp3_dma.h b/drivers/video/msm/mdss/mdp3_dma.h
new file mode 100644
index 0000000..2fb8427
--- /dev/null
+++ b/drivers/video/msm/mdss/mdp3_dma.h
@@ -0,0 +1,336 @@
+/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#ifndef MDP3_DMA_H
+#define MDP3_DMA_H
+
+#include <linux/sched.h>
+
+enum {
+	MDP3_DMA_P,
+	MDP3_DMA_S,
+	MDP3_DMA_E,
+	MDP3_DMA_MAX
+};
+
+enum {
+	MDP3_DMA_CAP_CURSOR = 0x1,
+	MDP3_DMA_CAP_COLOR_CORRECTION = 0x2,
+	MDP3_DMA_CAP_HISTOGRAM = 0x4,
+	MDP3_DMA_CAP_GAMMA_CORRECTION = 0x8,
+	MDP3_DMA_CAP_DITHER = 0x10,
+	MDP3_DMA_CAP_ALL = 0x1F
+};
+
+enum {
+	MDP3_DMA_OUTPUT_SEL_AHB,
+	MDP3_DMA_OUTPUT_SEL_DSI_CMD,
+	MDP3_DMA_OUTPUT_SEL_LCDC,
+	MDP3_DMA_OUTPUT_SEL_DSI_VIDEO,
+	MDP3_DMA_OUTPUT_SEL_MAX
+};
+
+enum {
+	MDP3_DMA_IBUF_FORMAT_RGB888,
+	MDP3_DMA_IBUF_FORMAT_RGB565,
+	MDP3_DMA_IBUF_FORMAT_XRGB8888,
+	MDP3_DMA_IBUF_FORMAT_UNDEFINED
+};
+
+enum {
+	MDP3_DMA_OUTPUT_PACK_PATTERN_RGB = 0x21,
+	MDP3_DMA_OUTPUT_PACK_PATTERN_RBG = 0x24,
+	MDP3_DMA_OUTPUT_PACK_PATTERN_BGR = 0x12,
+	MDP3_DMA_OUTPUT_PACK_PATTERN_BRG = 0x18,
+	MDP3_DMA_OUTPUT_PACK_PATTERN_GBR = 0x06,
+	MDP3_DMA_OUTPUT_PACK_PATTERN_GRB = 0x09,
+};
+
+enum {
+	MDP3_DMA_OUTPUT_PACK_ALIGN_LSB,
+	MDP3_DMA_OUTPUT_PACK_ALIGN_MSB
+};
+
+enum {
+	MDP3_DMA_OUTPUT_COMP_BITS_4, /*4 bits per color component*/
+	MDP3_DMA_OUTPUT_COMP_BITS_5,
+	MDP3_DMA_OUTPUT_COMP_BITS_6,
+	MDP3_DMA_OUTPUT_COMP_BITS_8,
+};
+
+enum {
+	MDP3_DMA_CURSOR_FORMAT_ARGB888,
+};
+
+enum {
+	MDP3_DMA_COLOR_CORRECT_SET_1,
+	MDP3_DMA_COLOR_CORRECT_SET_2
+};
+
+enum {
+	MDP3_DMA_LUT_POSITION_PRE,
+	MDP3_DMA_LUT_POSITION_POST
+};
+
+enum {
+	MDP3_DMA_LUT_DISABLE = 0x0,
+	MDP3_DMA_LUT_ENABLE_C0 = 0x01,
+	MDP3_DMA_LUT_ENABLE_C1 = 0x02,
+	MDP3_DMA_LUT_ENABLE_C2 = 0x04,
+	MDP3_DMA_LUT_ENABLE_ALL = 0x07,
+};
+
+enum {
+	MDP3_DMA_HISTOGRAM_BIT_MASK_NONE = 0X0,
+	MDP3_DMA_HISTOGRAM_BIT_MASK_ONE_MSB = 0x1,
+	MDP3_DMA_HISTOGRAM_BIT_MASK_TWO_MSB = 0x2,
+	MDP3_DMA_HISTOGRAM_BIT_MASK_THREE_MSB = 0x3
+};
+
+enum {
+	MDP3_DMA_COLOR_FLIP_NONE,
+	MDP3_DMA_COLOR_FLIP_COMP1 = 0x1,
+	MDP3_DMA_COLOR_FLIP_COMP2 = 0x2,
+	MDP3_DMA_COLOR_FLIP_COMP3 = 0x4,
+};
+
+enum {
+	MDP3_DMA_CURSOR_BLEND_NONE = 0x0,
+	MDP3_DMA_CURSOR_BLEND_PER_PIXEL_ALPHA =  0x3,
+	MDP3_DMA_CURSOR_BLEND_CONSTANT_ALPHA = 0x5,
+	MDP3_DMA_CURSOR_BLEND_COLOR_KEYING = 0x9
+};
+
+enum {
+	MDP3_DMA_HISTO_OP_START,
+	MDP3_DMA_HISTO_OP_STOP,
+	MDP3_DMA_HISTO_OP_CANCEL,
+	MDP3_DMA_HISTO_OP_RESET
+};
+
+enum {
+	MDP3_DMA_CALLBACK_TYPE_VSYNC = 0x01,
+	MDP3_DMA_CALLBACK_TYPE_DMA_DONE = 0x02,
+};
+
+struct mdp3_dma_source {
+	u32 format;
+	int width;
+	int height;
+	int x;
+	int y;
+	void *buf;
+	int stride;
+};
+
+struct mdp3_dma_output_config {
+	int dither_en;
+	u32 out_sel;
+	u32 bit_mask_polarity;
+	u32 color_components_flip;
+	u32 pack_pattern;
+	u32 pack_align;
+	u32 color_comp_out_bits;
+};
+
+struct mdp3_dma_cursor_blend_config {
+	u32 mode;
+	u32 transparent_color; /*color keying*/
+	u32 transparency_mask;
+	u32 constant_alpha;
+};
+
+struct mdp3_dma_cursor {
+	int enable; /* enable cursor or not*/
+	u32 format;
+	int width;
+	int height;
+	int x;
+	int y;
+	void *buf;
+	struct mdp3_dma_cursor_blend_config blend_config;
+};
+
+struct mdp3_dma_ccs {
+	u32 *mv1; /*set1 matrix vector, 3x3 */
+	u32 *mv2;
+	u32 *pre_bv1; /*pre-bias vector for set1, 1x3*/
+	u32 *pre_bv2;
+	u32 *post_bv1; /*post-bias vecotr for set1,  */
+	u32 *post_bv2;
+	u32 *pre_lv1; /*pre-limit vector for set 1, 1x6*/
+	u32 *pre_lv2;
+	u32 *post_lv1;
+	u32 *post_lv2;
+};
+
+struct mdp3_dma_lut {
+	uint8_t *color0_lut1;
+	uint8_t *color1_lut1;
+	uint8_t *color2_lut1;
+	uint8_t *color0_lut2;
+	uint8_t *color1_lut2;
+	uint8_t *color2_lut2;
+};
+
+struct mdp3_dma_color_correct_config {
+	int ccs_enable;
+	int lut_enable;
+	u32 lut_sel;
+	u32 post_limit_sel;
+	u32 pre_limit_sel;
+	u32 post_bias_sel;
+	u32 pre_bias_sel;
+	u32 ccs_sel;
+	u32 lut_position;
+};
+
+struct mdp3_dma_histogram_config {
+	int frame_count;
+	u32 bit_mask_polarity;
+	u32 bit_mask;
+	int auto_clear_en;
+};
+
+struct mdp3_dma_histogram_data {
+	uint8_t r_max_value;
+	uint8_t r_min_value;
+	uint8_t b_max_value;
+	uint8_t b_min_value;
+	uint8_t g_max_value;
+	uint8_t g_min_value;
+	uint8_t r_data[32];
+	uint8_t g_data[32];
+	uint8_t b_data[32];
+};
+
+struct mdp3_vsync_notification {
+	void (*handler)(void *arg);
+	void *arg;
+};
+
+struct mdp3_intf;
+
+struct mdp3_dma {
+	u32 dma_sel;
+	u32 capability;
+	int in_use;
+	int available;
+	int busy;
+
+	spinlock_t dma_lock;
+	struct completion vsync_comp;
+	struct completion dma_comp;
+	ktime_t vsync_time;
+	struct mdp3_vsync_notification vsync_client;
+	u32 cb_type;
+
+	struct mdp3_dma_output_config output_config;
+	struct mdp3_dma_source source_config;
+
+	struct mdp3_dma_cursor cursor;
+	struct mdp3_dma_color_correct_config ccs_config;
+	struct mdp3_dma_histogram_config histogram_config;
+
+	int (*start)(struct mdp3_dma *dma, struct mdp3_intf *intf);
+
+	int (*stop)(struct mdp3_dma *dma, struct mdp3_intf *intf);
+
+	int (*config_cursor)(struct mdp3_dma *dma,
+				struct mdp3_dma_cursor *cursor);
+
+	int (*config_ccs)(struct mdp3_dma *dma,
+			struct mdp3_dma_color_correct_config *config,
+			struct mdp3_dma_ccs *ccs,
+			struct mdp3_dma_lut *lut);
+
+	int (*update)(struct mdp3_dma *dma, void *buf);
+
+	int (*update_cursor)(struct mdp3_dma *dma, int x, int y);
+
+	int (*get_histo)(struct mdp3_dma *dma,
+				struct mdp3_dma_histogram_data *data);
+
+	int (*config_histo)(struct mdp3_dma *dma,
+				struct mdp3_dma_histogram_config *histo_config);
+
+	int (*histo_op)(struct mdp3_dma *dma,
+				u32 op);
+
+	int (*histo_intr_status)(struct mdp3_dma *dma, int *status);
+
+	int (*histo_intr_enable)(struct mdp3_dma *dma, u32 mask);
+
+	int (*histo_intr_clear)(struct mdp3_dma *dma, u32 mask);
+
+	void (*vsync_enable)(struct mdp3_dma *dma,
+			struct mdp3_vsync_notification *vsync_client);
+
+	ktime_t (*get_vsync_time)(struct mdp3_dma *dma);
+
+};
+
+struct mdp3_video_intf_cfg {
+	int hsync_period;
+	int hsync_pulse_width;
+	int vsync_period;
+	int vsync_pulse_width;
+	int display_start_x;
+	int display_end_x;
+	int display_start_y;
+	int display_end_y;
+	int active_start_x;
+	int active_end_x;
+	int active_h_enable;
+	int active_start_y;
+	int active_end_y;
+	int active_v_enable;
+	int hsync_skew;
+	int hsync_polarity;
+	int vsync_polarity;
+	int de_polarity;
+};
+
+struct mdp3_dsi_cmd_intf_cfg {
+	int primary_dsi_cmd_id;
+	int secondary_dsi_cmd_id;
+	int dsi_cmd_tg_intf_sel;
+};
+
+struct mdp3_intf_cfg {
+	u32 type;
+	struct mdp3_video_intf_cfg video;
+	struct mdp3_dsi_cmd_intf_cfg dsi_cmd;
+};
+
+struct mdp3_intf {
+	struct mdp3_intf_cfg cfg;
+	int active;
+	int available;
+	int in_use;
+	int (*config)(struct mdp3_intf *intf, struct mdp3_intf_cfg *cfg);
+	int (*start)(struct mdp3_intf *intf);
+	int (*stop)(struct mdp3_intf *intf);
+};
+
+int mdp3_dma_init(struct mdp3_dma *dma,
+		struct mdp3_dma_source *source_config,
+		struct mdp3_dma_output_config *output_config);
+
+int mdp3_intf_init(struct mdp3_intf *intf, struct mdp3_intf_cfg *cfg);
+
+void mdp3_dma_callback_enable(struct mdp3_dma *dma, int type);
+
+void mdp3_dma_callback_disable(struct mdp3_dma *dma, int type);
+
+#endif /* MDP3_DMA_H */
diff --git a/drivers/video/msm/mdss/mdp3_hwio.h b/drivers/video/msm/mdss/mdp3_hwio.h
new file mode 100644
index 0000000..2763f46
--- /dev/null
+++ b/drivers/video/msm/mdss/mdp3_hwio.h
@@ -0,0 +1,216 @@
+/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#ifndef MDP3_HWIO_H
+#define MDP3_HWIO_H
+
+#include <linux/bitops.h>
+
+/*synchronization*/
+#define MDP3_REG_SYNC_CONFIG_0				0x0300
+#define MDP3_REG_SYNC_CONFIG_1				0x0304
+#define MDP3_REG_SYNC_CONFIG_2				0x0308
+#define MDP3_REG_SYNC_STATUS_0				0x030c
+#define MDP3_REG_SYNC_STATUS_1				0x0310
+#define MDP3_REG_SYNC_STATUS_2				0x0314
+#define MDP3_REG_PRIMARY_VSYNC_OUT_CTRL			0x0318
+#define MDP3_REG_SECONDARY_VSYNC_OUT_CTRL		0x031c
+#define MDP3_REG_EXTERNAL_VSYNC_OUT_CTRL		0x0320
+#define MDP3_REG_VSYNC_SEL				0x0324
+
+/*interrupt*/
+#define MDP3_REG_INTR_ENABLE				0x0020
+#define MDP3_REG_INTR_STATUS				0x0024
+#define MDP3_REG_INTR_CLEAR				0x0028
+
+#define MDP3_REG_PRIMARY_RD_PTR_IRQ			0x021C
+#define MDP3_REG_SECONDARY_RD_PTR_IRQ			0x0220
+
+/*operation control*/
+#define MDP3_REG_DMA_P_START				0x0044
+#define MDP3_REG_DMA_S_START				0x0048
+#define MDP3_REG_DMA_E_START				0x004c
+
+#define MDP3_REG_DISPLAY_STATUS				0x0038
+
+#define MDP3_REG_HW_VERSION				0x0070
+#define MDP3_REG_SW_RESET				0x0074
+
+/*EBI*/
+#define MDP3_REG_EBI2_LCD0				0x003c
+#define MDP3_REG_EBI2_LCD0_YSTRIDE			0x0050
+
+/*DMA_P*/
+#define MDP3_REG_DMA_P_CONFIG				0x90000
+#define MDP3_REG_DMA_P_SIZE				0x90004
+#define MDP3_REG_DMA_P_IBUF_ADDR			0x90008
+#define MDP3_REG_DMA_P_IBUF_Y_STRIDE			0x9000C
+#define MDP3_REG_DMA_P_PROFILE_EN			0x90020
+#define MDP3_REG_DMA_P_OUT_XY				0x90010
+#define MDP3_REG_DMA_P_CURSOR_FORMAT			0x90040
+#define MDP3_REG_DMA_P_CURSOR_SIZE			0x90044
+#define MDP3_REG_DMA_P_CURSOR_BUF_ADDR			0x90048
+#define MDP3_REG_DMA_P_CURSOR_POS			0x9004c
+#define MDP3_REG_DMA_P_CURSOR_BLEND_CONFIG		0x90060
+#define MDP3_REG_DMA_P_CURSOR_BLEND_PARAM		0x90064
+#define MDP3_REG_DMA_P_CURSOR_BLEND_TRANS_MASK		0x90068
+#define MDP3_REG_DMA_P_COLOR_CORRECT_CONFIG		0x90070
+#define MDP3_REG_DMA_P_CSC_BYPASS			0X93004
+#define MDP3_REG_DMA_P_CSC_MV1				0x93400
+#define MDP3_REG_DMA_P_CSC_MV2				0x93440
+#define MDP3_REG_DMA_P_CSC_PRE_BV1			0x93500
+#define MDP3_REG_DMA_P_CSC_PRE_BV2			0x93540
+#define MDP3_REG_DMA_P_CSC_POST_BV1			0x93580
+#define MDP3_REG_DMA_P_CSC_POST_BV2			0x935c0
+#define MDP3_REG_DMA_P_CSC_PRE_LV1			0x93600
+#define MDP3_REG_DMA_P_CSC_PRE_LV2			0x93640
+#define MDP3_REG_DMA_P_CSC_POST_LV1			0x93680
+#define MDP3_REG_DMA_P_CSC_POST_LV2			0x936c0
+#define MDP3_REG_DMA_P_CSC_LUT1				0x93800
+#define MDP3_REG_DMA_P_CSC_LUT2				0x93c00
+#define MDP3_REG_DMA_P_HIST_START			0x94000
+#define MDP3_REG_DMA_P_HIST_FRAME_CNT			0x94004
+#define MDP3_REG_DMA_P_HIST_BIT_MASK			0x94008
+#define MDP3_REG_DMA_P_HIST_RESET_SEQ_START		0x9400c
+#define MDP3_REG_DMA_P_HIST_CONTROL			0x94010
+#define MDP3_REG_DMA_P_HIST_INTR_STATUS			0x94014
+#define MDP3_REG_DMA_P_HIST_INTR_CLEAR			0x94018
+#define MDP3_REG_DMA_P_HIST_INTR_ENABLE			0x9401c
+#define MDP3_REG_DMA_P_HIST_STOP_REQ			0x94020
+#define MDP3_REG_DMA_P_HIST_CANCEL_REQ			0x94024
+#define MDP3_REG_DMA_P_HIST_EXTRA_INFO_0		0x94028
+#define MDP3_REG_DMA_P_HIST_EXTRA_INFO_1		0x9402c
+#define MDP3_REG_DMA_P_HIST_R_DATA			0x94100
+#define MDP3_REG_DMA_P_HIST_G_DATA			0x94200
+#define MDP3_REG_DMA_P_HIST_B_DATA			0x94300
+#define MDP3_REG_DMA_P_FETCH_CFG			0x90074
+#define MDP3_REG_DMA_P_DCVS_CTRL			0x90080
+#define MDP3_REG_DMA_P_DCVS_STATUS			0x90084
+
+/*DMA_S*/
+#define MDP3_REG_DMA_S_CONFIG				0x90000
+#define MDP3_REG_DMA_S_SIZE				0x90004
+#define MDP3_REG_DMA_S_IBUF_ADDR			0x90008
+#define MDP3_REG_DMA_S_IBUF_Y_STRIDE			0x9000C
+#define MDP3_REG_DMA_S_OUT_XY				0x90010
+
+/*interface*/
+#define MDP3_REG_LCDC_EN				0xE0000
+#define MDP3_REG_LCDC_HSYNC_CTL				0xE0004
+#define MDP3_REG_LCDC_VSYNC_PERIOD			0xE0008
+#define MDP3_REG_LCDC_VSYNC_PULSE_WIDTH			0xE000C
+#define MDP3_REG_LCDC_DISPLAY_HCTL			0xE0010
+#define MDP3_REG_LCDC_DISPLAY_V_START			0xE0014
+#define MDP3_REG_LCDC_DISPLAY_V_END			0xE0018
+#define MDP3_REG_LCDC_ACTIVE_HCTL			0xE001C
+#define MDP3_REG_LCDC_ACTIVE_V_START			0xE0020
+#define MDP3_REG_LCDC_ACTIVE_V_END			0xE0024
+#define MDP3_REG_LCDC_BORDER_COLOR			0xE0028
+#define MDP3_REG_LCDC_UNDERFLOW_CTL			0xE002C
+#define MDP3_REG_LCDC_HSYNC_SKEW			0xE0030
+#define MDP3_REG_LCDC_TEST_CTL				0xE0034
+#define MDP3_REG_LCDC_CTL_POLARITY			0xE0038
+#define MDP3_REG_LCDC_TEST_COL_VAR1			0xE003C
+#define MDP3_REG_LCDC_TEST_COL_VAR2			0xE0040
+#define MDP3_REG_LCDC_UFLOW_HIDING_CTL			0xE0044
+#define MDP3_REG_LCDC_LOST_PIXEL_CNT_VALUE		0xE0048
+
+#define MDP3_REG_DSI_VIDEO_EN				0xF0000
+#define MDP3_REG_DSI_VIDEO_HSYNC_CTL			0xF0004
+#define MDP3_REG_DSI_VIDEO_VSYNC_PERIOD			0xF0008
+#define MDP3_REG_DSI_VIDEO_VSYNC_PULSE_WIDTH		0xF000C
+#define MDP3_REG_DSI_VIDEO_DISPLAY_HCTL			0xF0010
+#define MDP3_REG_DSI_VIDEO_DISPLAY_V_START		0xF0014
+#define MDP3_REG_DSI_VIDEO_DISPLAY_V_END		0xF0018
+#define MDP3_REG_DSI_VIDEO_ACTIVE_HCTL			0xF001C
+#define MDP3_REG_DSI_VIDEO_ACTIVE_V_START		0xF0020
+#define MDP3_REG_DSI_VIDEO_ACTIVE_V_END			0xF0024
+#define MDP3_REG_DSI_VIDEO_BORDER_COLOR			0xF0028
+#define MDP3_REG_DSI_VIDEO_UNDERFLOW_CTL		0xF002C
+#define MDP3_REG_DSI_VIDEO_HSYNC_SKEW			0xF0030
+#define MDP3_REG_DSI_VIDEO_TEST_CTL			0xF0034
+#define MDP3_REG_DSI_VIDEO_CTL_POLARITY			0xF0038
+#define MDP3_REG_DSI_VIDEO_TEST_COL_VAR1		0xF003C
+#define MDP3_REG_DSI_VIDEO_TEST_COL_VAR2		0xF0040
+#define MDP3_REG_DSI_VIDEO_UFLOW_HIDING_CTL		0xF0044
+#define MDP3_REG_DSI_VIDEO_LOST_PIXEL_CNT_VALUE		0xF0048
+
+#define MDP3_REG_DSI_CMD_MODE_ID_MAP			0xF1000
+#define MDP3_REG_DSI_CMD_MODE_TRIGGER_EN		0xF1004
+
+/*interrupt mask*/
+
+#define MDP3_INTR_DP0_ROI_DONE_BIT			BIT(0)
+#define MDP3_INTR_DP1_ROI_DONE_BIT			BIT(1)
+#define MDP3_INTR_DMA_S_DONE_BIT			BIT(2)
+#define MDP3_INTR_DMA_E_DONE_BIT			BIT(3)
+#define MDP3_INTR_DP0_TERMINAL_FRAME_DONE_BIT		BIT(4)
+#define MDP3_INTR_DP1_TERMINAL_FRAME_DONE_BIT		BIT(5)
+#define MDP3_INTR_DMA_TV_DONE_BIT			BIT(6)
+#define MDP3_INTR_TV_ENCODER_UNDER_RUN_BIT		BIT(7)
+#define MDP3_INTR_SYNC_PRIMARY_LINE_BIT			BIT(8)
+#define MDP3_INTR_SYNC_SECONDARY_LINE_BIT		BIT(9)
+#define MDP3_INTR_SYNC_EXTERNAL_LINE_BIT		BIT(10)
+#define MDP3_INTR_DP0_FETCH_DONE_BIT			BIT(11)
+#define MDP3_INTR_DP1_FETCH_DONE_BIT			BIT(12)
+#define MDP3_INTR_TV_OUT_FRAME_START_BIT		BIT(13)
+#define MDP3_INTR_DMA_P_DONE_BIT			BIT(14)
+#define MDP3_INTR_LCDC_START_OF_FRAME_BIT		BIT(15)
+#define MDP3_INTR_LCDC_UNDERFLOW_BIT			BIT(16)
+#define MDP3_INTR_DMA_P_LINE_BIT			BIT(17)
+#define MDP3_INTR_DMA_S_LINE_BIT			BIT(18)
+#define MDP3_INTR_DMA_E_LINE_BIT			BIT(19)
+#define MDP3_INTR_DMA_P_HISTO_BIT			BIT(20)
+#define MDP3_INTR_DTV_OUT_DONE_BIT			BIT(21)
+#define MDP3_INTR_DTV_OUT_START_OF_FRAME_BIT		BIT(22)
+#define MDP3_INTR_DTV_OUT_UNDERFLOW_BIT			BIT(23)
+#define MDP3_INTR_DTV_OUT_LINE_BIT			BIT(24)
+#define MDP3_INTR_DMA_P_AUTO_FREFRESH_START_BIT		BIT(25)
+#define MDP3_INTR_DMA_S_AUTO_FREFRESH_START_BIT		BIT(26)
+#define MDP3_INTR_QPIC_EOF_ENABLE_BIT			BIT(27)
+
+enum {
+	MDP3_INTR_DP0_ROI_DONE,
+	MDP3_INTR_DP1_ROI_DONE,
+	MDP3_INTR_DMA_S_DONE,
+	MDP3_INTR_DMA_E_DONE,
+	MDP3_INTR_DP0_TERMINAL_FRAME_DONE,
+	MDP3_INTR_DP1_TERMINAL_FRAME_DONE,
+	MDP3_INTR_DMA_TV_DONE,
+	MDP3_INTR_TV_ENCODER_UNDER_RUN,
+	MDP3_INTR_SYNC_PRIMARY_LINE,
+	MDP3_INTR_SYNC_SECONDARY_LINE,
+	MDP3_INTR_SYNC_EXTERNAL_LINE,
+	MDP3_INTR_DP0_FETCH_DONE,
+	MDP3_INTR_DP1_FETCH_DONE,
+	MDP3_INTR_TV_OUT_FRAME_START,
+	MDP3_INTR_DMA_P_DONE,
+	MDP3_INTR_LCDC_START_OF_FRAME,
+	MDP3_INTR_LCDC_UNDERFLOW,
+	MDP3_INTR_DMA_P_LINE,
+	MDP3_INTR_DMA_S_LINE,
+	MDP3_INTR_DMA_E_LINE,
+	MDP3_INTR_DMA_P_HISTO,
+	MDP3_INTR_DTV_OUT_DONE,
+	MDP3_INTR_DTV_OUT_START_OF_FRAME,
+	MDP3_INTR_DTV_OUT_UNDERFLOW,
+	MDP3_INTR_DTV_OUT_LINE,
+	MDP3_INTR_DMA_P_AUTO_FREFRESH_START,
+	MDP3_INTR_DMA_S_AUTO_FREFRESH_START,
+	MDP3_INTR_QPIC_EOF_ENABLE,
+};
+
+#define MDP3_DMA_P_HIST_INTR_RESET_DONE_BIT		BIT(0)
+#define MDP3_DMA_P_HIST_INTR_HIST_DONE_BIT		BIT(1)
+
+#endif /* MDP3_HWIO_H */
diff --git a/drivers/video/msm/mdss/mdss_debug.c b/drivers/video/msm/mdss/mdss_debug.c
index 7dc4f49..0b2a7c0 100644
--- a/drivers/video/msm/mdss/mdss_debug.c
+++ b/drivers/video/msm/mdss/mdss_debug.c
@@ -24,7 +24,7 @@
 #include "mdss_mdp.h"
 #include "mdss_debug.h"
 
-#define DEFAULT_BASE_REG_CNT 128
+#define DEFAULT_BASE_REG_CNT 0x100
 #define GROUP_BYTES 4
 #define ROW_BYTES 16
 
@@ -67,7 +67,8 @@
 		    const char __user *user_buf, size_t count, loff_t *ppos)
 {
 	struct mdss_debug_base *dbg = file->private_data;
-	u32 off, cnt;
+	u32 off = 0;
+	u32 cnt = DEFAULT_BASE_REG_CNT;
 	char buf[24];
 
 	if (!dbg)
@@ -81,14 +82,11 @@
 
 	buf[count] = 0;	/* end of string */
 
-	sscanf(buf, "%5x %d", &off, &cnt);
+	sscanf(buf, "%5x %x", &off, &cnt);
 
 	if (off > dbg->max_offset)
 		return -EINVAL;
 
-	if (cnt <= 0)
-		cnt = DEFAULT_BASE_REG_CNT;
-
 	if (cnt > (dbg->max_offset - off))
 		cnt = dbg->max_offset - off;
 
@@ -113,7 +111,7 @@
 	if (*ppos)
 		return 0;	/* the end */
 
-	len = snprintf(buf, sizeof(buf), "0x%08x %d\n", dbg->off, dbg->off);
+	len = snprintf(buf, sizeof(buf), "0x%08x %x\n", dbg->off, dbg->cnt);
 	if (len < 0)
 		return 0;
 
diff --git a/drivers/video/msm/mdss/mdss_dsi.c b/drivers/video/msm/mdss/mdss_dsi.c
index faf3e6f..8bf8c95 100644
--- a/drivers/video/msm/mdss/mdss_dsi.c
+++ b/drivers/video/msm/mdss/mdss_dsi.c
@@ -477,7 +477,7 @@
 	struct mdss_panel_info *pinfo;
 	struct mipi_panel_info *mipi;
 	u32 hbp, hfp, vbp, vfp, hspw, vspw, width, height;
-	u32 ystride, bpp, data;
+	u32 ystride, bpp, data, dst_bpp;
 	u32 dummy_xres, dummy_yres;
 	struct mdss_dsi_ctrl_pdata *ctrl_pdata = NULL;
 
@@ -516,13 +516,22 @@
 	clk_rate = pdata->panel_info.clk_rate;
 	clk_rate = min(clk_rate, pdata->panel_info.clk_max);
 
-	hbp = pdata->panel_info.lcdc.h_back_porch;
-	hfp = pdata->panel_info.lcdc.h_front_porch;
-	vbp = pdata->panel_info.lcdc.v_back_porch;
-	vfp = pdata->panel_info.lcdc.v_front_porch;
-	hspw = pdata->panel_info.lcdc.h_pulse_width;
+	dst_bpp = pdata->panel_info.fbc.enabled ?
+		(pdata->panel_info.fbc.target_bpp) : (pinfo->bpp);
+
+	hbp = mult_frac(pdata->panel_info.lcdc.h_back_porch, dst_bpp,
+			pdata->panel_info.bpp);
+	hfp = mult_frac(pdata->panel_info.lcdc.h_front_porch, dst_bpp,
+			pdata->panel_info.bpp);
+	vbp = mult_frac(pdata->panel_info.lcdc.v_back_porch, dst_bpp,
+			pdata->panel_info.bpp);
+	vfp = mult_frac(pdata->panel_info.lcdc.v_front_porch, dst_bpp,
+			pdata->panel_info.bpp);
+	hspw = mult_frac(pdata->panel_info.lcdc.h_pulse_width, dst_bpp,
+			pdata->panel_info.bpp);
 	vspw = pdata->panel_info.lcdc.v_pulse_width;
-	width = pdata->panel_info.xres;
+	width = mult_frac(pdata->panel_info.xres, dst_bpp,
+			pdata->panel_info.bpp);
 	height = pdata->panel_info.yres;
 
 	mipi  = &pdata->panel_info.mipi;
diff --git a/drivers/video/msm/mdss/mdss_dsi_panel.c b/drivers/video/msm/mdss/mdss_dsi_panel.c
index d24ed16..c56cd41 100644
--- a/drivers/video/msm/mdss/mdss_dsi_panel.c
+++ b/drivers/video/msm/mdss/mdss_dsi_panel.c
@@ -227,6 +227,7 @@
 {
 	struct device_node *np = pdev->dev.of_node;
 	u32 res[6], tmp;
+	u32 fbc_res[7];
 	int rc, i, len;
 	int cmd_plen, data_offset;
 	const char *data;
@@ -234,6 +235,7 @@
 	static const char *on_cmds_state, *off_cmds_state;
 	char *on_cmds = NULL, *off_cmds = NULL;
 	int num_of_on_cmds = 0, num_of_off_cmds = 0;
+	bool fbc_enabled = false;
 
 	rc = of_property_read_u32_array(np, "qcom,mdss-pan-res", res, 2);
 	if (rc) {
@@ -480,6 +482,53 @@
 
 	panel_data->panel_info.mipi.dsi_phy_db = &phy_params;
 
+	fbc_enabled = of_property_read_bool(np,
+			"qcom,fbc-enabled");
+	if (fbc_enabled) {
+		pr_debug("%s:%d FBC panel enabled.\n", __func__, __LINE__);
+		panel_data->panel_info.fbc.enabled = 1;
+
+		rc = of_property_read_u32_array(np,
+				"qcom,fbc-mode", fbc_res, 7);
+		panel_data->panel_info.fbc.target_bpp =
+			(!rc ?	fbc_res[0] : panel_data->panel_info.bpp);
+		panel_data->panel_info.fbc.comp_mode = (!rc ? fbc_res[1] : 0);
+		panel_data->panel_info.fbc.qerr_enable =
+			(!rc ? fbc_res[2] : 0);
+		panel_data->panel_info.fbc.cd_bias = (!rc ? fbc_res[3] : 0);
+		panel_data->panel_info.fbc.pat_enable = (!rc ? fbc_res[4] : 0);
+		panel_data->panel_info.fbc.vlc_enable = (!rc ? fbc_res[5] : 0);
+		panel_data->panel_info.fbc.bflc_enable =
+			(!rc ? fbc_res[6] : 0);
+
+		rc = of_property_read_u32_array(np,
+				"qcom,fbc-budget-ctl", fbc_res, 3);
+		panel_data->panel_info.fbc.line_x_budget =
+			(!rc ? fbc_res[0] : 0);
+		panel_data->panel_info.fbc.block_x_budget =
+			(!rc ? fbc_res[1] : 0);
+		panel_data->panel_info.fbc.block_budget =
+			(!rc ? fbc_res[2] : 0);
+
+		rc = of_property_read_u32_array(np,
+				"qcom,fbc-lossy-mode", fbc_res, 4);
+		panel_data->panel_info.fbc.lossless_mode_thd =
+			(!rc ? fbc_res[0] : 0);
+		panel_data->panel_info.fbc.lossy_mode_thd =
+			(!rc ? fbc_res[1] : 0);
+		panel_data->panel_info.fbc.lossy_rgb_thd =
+			(!rc ? fbc_res[2] : 0);
+		panel_data->panel_info.fbc.lossy_mode_idx =
+			(!rc ? fbc_res[3] : 0);
+
+	} else {
+		pr_debug("%s:%d Panel does not support FBC.\n",
+				__func__, __LINE__);
+		panel_data->panel_info.fbc.enabled = 0;
+		panel_data->panel_info.fbc.target_bpp =
+			panel_data->panel_info.bpp;
+	}
+
 	data = of_get_property(np, "qcom,panel-on-cmds", &len);
 	if (!data) {
 		pr_err("%s:%d, Unable to read ON cmds", __func__, __LINE__);
diff --git a/drivers/video/msm/mdss/mdss_fb.c b/drivers/video/msm/mdss/mdss_fb.c
index ed730b3..a5903cf 100644
--- a/drivers/video/msm/mdss/mdss_fb.c
+++ b/drivers/video/msm/mdss/mdss_fb.c
@@ -1729,4 +1729,4 @@
 	return 0;
 }
 
-device_initcall_sync(mdss_fb_init);
+module_init(mdss_fb_init);
diff --git a/drivers/video/msm/mdss/mdss_hdmi_edid.c b/drivers/video/msm/mdss/mdss_hdmi_edid.c
index 08be337..e87f028 100644
--- a/drivers/video/msm/mdss/mdss_hdmi_edid.c
+++ b/drivers/video/msm/mdss/mdss_hdmi_edid.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2010-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -244,14 +244,14 @@
 				continue;
 			if (ret > 0)
 				ret += snprintf(buf+ret, PAGE_SIZE-ret, ",%d",
-					*video_mode++ + 1);
+					*video_mode++);
 			else
 				ret += snprintf(buf+ret, PAGE_SIZE-ret, "%d",
-					*video_mode++ + 1);
+					*video_mode++);
 		}
 	} else {
 		ret += snprintf(buf+ret, PAGE_SIZE-ret, "%d",
-			edid_ctrl->video_resolution+1);
+			edid_ctrl->video_resolution);
 	}
 
 	DEV_DBG("%s: '%s'\n", __func__, buf);
@@ -324,16 +324,16 @@
 				buff_3d);
 			if (ret > 0)
 				ret += snprintf(buf+ret, PAGE_SIZE-ret,
-					",%d=%s", *video_mode++ + 1,
+					",%d=%s", *video_mode++,
 					buff_3d);
 			else
 				ret += snprintf(buf+ret, PAGE_SIZE-ret,
-					"%d=%s", *video_mode++ + 1,
+					"%d=%s", *video_mode++,
 					buff_3d);
 		}
 	} else {
 		ret += snprintf(buf+ret, PAGE_SIZE-ret, "%d",
-			edid_ctrl->video_resolution+1);
+			edid_ctrl->video_resolution);
 	}
 
 	DEV_DBG("%s: '%s'\n", __func__, buf);
@@ -817,25 +817,25 @@
 	hdmi_get_video_3d_fmt_2string(video_3d_format, string);
 
 	DEV_DBG("%s: EDID[3D]: format: %d [%s], %s %s\n", __func__,
-		video_format, hdmi_get_video_fmt_2string(video_format),
+		video_format, msm_hdmi_mode_2string(video_format),
 		string, added ? "added" : "NOT added");
 } /* hdmi_edid_add_sink_3d_format */
 
 static void hdmi_edid_add_sink_video_format(
 	struct hdmi_edid_sink_data *sink_data, u32 video_format)
 {
-	const struct hdmi_disp_mode_timing_type *timing =
+	const struct msm_hdmi_mode_timing_info *timing =
 		hdmi_get_supported_mode(video_format);
 	u32 supported = timing != NULL;
 
 	if (video_format >= HDMI_VFRMT_MAX) {
 		DEV_ERR("%s: video format: %s is not supported\n", __func__,
-			hdmi_get_video_fmt_2string(video_format));
+			msm_hdmi_mode_2string(video_format));
 		return;
 	}
 
 	DEV_DBG("%s: EDID: format: %d [%s], %s\n", __func__,
-		video_format, hdmi_get_video_fmt_2string(video_format),
+		video_format, msm_hdmi_mode_2string(video_format),
 		supported ? "Supported" : "Not-Supported");
 
 	if (supported) {
@@ -1050,7 +1050,7 @@
 			 * while the Video identification code is 1 based in the
 			 * CEA_861D spec
 			 */
-			video_format = (*svd & 0x7F) - 1;
+			video_format = (*svd & 0x7F);
 			hdmi_edid_add_sink_video_format(sink_data,
 				video_format);
 			/* Make a note of the preferred video format */
@@ -1096,7 +1096,7 @@
 
 			DEV_DBG("[%s:%d] Block-0 Adding vid fmt = [%s]\n",
 				__func__, __LINE__,
-				hdmi_get_video_fmt_2string(video_format));
+				msm_hdmi_mode_2string(video_format));
 
 			hdmi_edid_add_sink_video_format(sink_data,
 				video_format);
@@ -1125,7 +1125,7 @@
 
 			DEV_DBG("[%s:%d] Block-0 Adding vid fmt = [%s]\n",
 				__func__, __LINE__,
-				hdmi_get_video_fmt_2string(video_format));
+				msm_hdmi_mode_2string(video_format));
 
 			hdmi_edid_add_sink_video_format(sink_data,
 				video_format);
@@ -1158,7 +1158,7 @@
 
 			DEV_DBG("[%s:%d] Block-1 Adding vid fmt = [%s]\n",
 				__func__, __LINE__,
-				hdmi_get_video_fmt_2string(video_format));
+				msm_hdmi_mode_2string(video_format));
 
 			hdmi_edid_add_sink_video_format(sink_data,
 				video_format);
diff --git a/drivers/video/msm/mdss/mdss_hdmi_tx.c b/drivers/video/msm/mdss/mdss_hdmi_tx.c
index 6a96369..66936e5 100644
--- a/drivers/video/msm/mdss/mdss_hdmi_tx.c
+++ b/drivers/video/msm/mdss/mdss_hdmi_tx.c
@@ -207,7 +207,7 @@
 {
 	int new_vic = -1;
 	u32 h_total, v_total;
-	struct hdmi_disp_mode_timing_type timing;
+	struct msm_hdmi_mode_timing_info timing;
 
 	if (!hdmi_ctrl || !pinfo) {
 		DEV_ERR("%s: invalid input\n", __func__);
@@ -215,13 +215,13 @@
 	}
 
 	if (pinfo->vic) {
-		if (hdmi_get_supported_mode(pinfo->vic - 1)) {
-			new_vic = pinfo->vic - 1;
+		if (hdmi_get_supported_mode(pinfo->vic)) {
+			new_vic = pinfo->vic;
 			DEV_DBG("%s: %s is supported\n", __func__,
-				hdmi_get_video_fmt_2string(new_vic));
+				msm_hdmi_mode_2string(new_vic));
 		} else {
-			DEV_ERR("%s: invalid or not supported vic\n",
-				__func__);
+			DEV_ERR("%s: invalid or not supported vic %d\n",
+				__func__, pinfo->vic);
 			return -EPERM;
 		}
 	} else {
@@ -397,13 +397,133 @@
 	return ret;
 } /* hdmi_tx_sysfs_wta_hpd */
 
+static ssize_t hdmi_tx_sysfs_wta_vendor_name(struct device *dev,
+	struct device_attribute *attr, const char *buf, size_t count)
+{
+	ssize_t ret;
+	u8 *s = (u8 *) buf;
+	u8 *d = NULL;
+	struct hdmi_tx_ctrl *hdmi_ctrl =
+		hdmi_tx_get_drvdata_from_sysfs_dev(dev);
+
+	if (!hdmi_ctrl) {
+		DEV_ERR("%s: invalid input\n", __func__);
+		return -EINVAL;
+	}
+
+	d = hdmi_ctrl->spd_vendor_name;
+	ret = strnlen(buf, PAGE_SIZE);
+	ret = (ret > 8) ? 8 : ret;
+
+	memset(hdmi_ctrl->spd_vendor_name, 0, 8);
+	while (*s) {
+		if (*s & 0x60 && *s ^ 0x7f) {
+			*d = *s;
+		} else {
+			/* stop copying if control character found */
+			break;
+		}
+
+		if (++s > (u8 *) (buf + ret))
+			break;
+
+		d++;
+	}
+
+	DEV_DBG("%s: '%s'\n", __func__, hdmi_ctrl->spd_vendor_name);
+
+	return ret;
+} /* hdmi_tx_sysfs_wta_vendor_name */
+
+static ssize_t hdmi_tx_sysfs_rda_vendor_name(struct device *dev,
+	struct device_attribute *attr, char *buf)
+{
+	ssize_t ret;
+	struct hdmi_tx_ctrl *hdmi_ctrl =
+		hdmi_tx_get_drvdata_from_sysfs_dev(dev);
+
+	if (!hdmi_ctrl) {
+		DEV_ERR("%s: invalid input\n", __func__);
+		return -EINVAL;
+	}
+
+	ret = snprintf(buf, PAGE_SIZE, "%s\n", hdmi_ctrl->spd_vendor_name);
+	DEV_DBG("%s: '%s'\n", __func__, hdmi_ctrl->spd_vendor_name);
+
+	return ret;
+} /* hdmi_tx_sysfs_rda_vendor_name */
+
+static ssize_t hdmi_tx_sysfs_wta_product_description(struct device *dev,
+	struct device_attribute *attr, const char *buf, size_t count)
+{
+	ssize_t ret;
+	u8 *s = (u8 *) buf;
+	u8 *d = NULL;
+	struct hdmi_tx_ctrl *hdmi_ctrl =
+		hdmi_tx_get_drvdata_from_sysfs_dev(dev);
+
+	if (!hdmi_ctrl) {
+		DEV_ERR("%s: invalid input\n", __func__);
+		return -EINVAL;
+	}
+
+	d = hdmi_ctrl->spd_product_description;
+	ret = strnlen(buf, PAGE_SIZE);
+	ret = (ret > 16) ? 16 : ret;
+
+	memset(hdmi_ctrl->spd_product_description, 0, 16);
+	while (*s) {
+		if (*s & 0x60 && *s ^ 0x7f) {
+			*d = *s;
+		} else {
+			/* stop copying if control character found */
+			break;
+		}
+
+		if (++s > (u8 *) (buf + ret))
+			break;
+
+		d++;
+	}
+
+	DEV_DBG("%s: '%s'\n", __func__, hdmi_ctrl->spd_product_description);
+
+	return ret;
+} /* hdmi_tx_sysfs_wta_product_description */
+
+static ssize_t hdmi_tx_sysfs_rda_product_description(struct device *dev,
+	struct device_attribute *attr, char *buf)
+{
+	ssize_t ret;
+	struct hdmi_tx_ctrl *hdmi_ctrl =
+		hdmi_tx_get_drvdata_from_sysfs_dev(dev);
+
+	if (!hdmi_ctrl) {
+		DEV_ERR("%s: invalid input\n", __func__);
+		return -EINVAL;
+	}
+
+	ret = snprintf(buf, PAGE_SIZE, "%s\n",
+		hdmi_ctrl->spd_product_description);
+	DEV_DBG("%s: '%s'\n", __func__, hdmi_ctrl->spd_product_description);
+
+	return ret;
+} /* hdmi_tx_sysfs_rda_product_description */
+
 static DEVICE_ATTR(connected, S_IRUGO, hdmi_tx_sysfs_rda_connected, NULL);
 static DEVICE_ATTR(hpd, S_IRUGO | S_IWUSR, hdmi_tx_sysfs_rda_hpd,
 	hdmi_tx_sysfs_wta_hpd);
+static DEVICE_ATTR(vendor_name, S_IRUGO | S_IWUSR,
+	hdmi_tx_sysfs_rda_vendor_name, hdmi_tx_sysfs_wta_vendor_name);
+static DEVICE_ATTR(product_description, S_IRUGO | S_IWUSR,
+	hdmi_tx_sysfs_rda_product_description,
+	hdmi_tx_sysfs_wta_product_description);
 
 static struct attribute *hdmi_tx_fs_attrs[] = {
 	&dev_attr_connected.attr,
 	&dev_attr_hpd.attr,
+	&dev_attr_vendor_name.attr,
+	&dev_attr_product_description.attr,
 	NULL,
 };
 static struct attribute_group hdmi_tx_fs_attrs_group = {
@@ -580,7 +700,7 @@
 static int hdmi_tx_init_panel_info(uint32_t resolution,
 	struct mdss_panel_info *pinfo)
 {
-	const struct hdmi_disp_mode_timing_type *timing =
+	const struct msm_hdmi_mode_timing_info *timing =
 		hdmi_get_supported_mode(resolution);
 
 	if (!timing || !pinfo) {
@@ -612,42 +732,12 @@
 	return 0;
 } /* hdmi_tx_init_panel_info */
 
-/* Table indicating the video format supported by the HDMI TX Core */
-/* Valid pclk rates (Mhz): 25.2, 27, 27.03, 74.25, 148.5, 268.5, 297 */
-static void hdmi_tx_setup_video_mode_lut(void)
-{
-	hdmi_init_supported_video_timings();
-
-	hdmi_set_supported_mode(HDMI_VFRMT_640x480p60_4_3);
-	hdmi_set_supported_mode(HDMI_VFRMT_720x480p60_4_3);
-	hdmi_set_supported_mode(HDMI_VFRMT_720x480p60_16_9);
-	hdmi_set_supported_mode(HDMI_VFRMT_720x576p50_4_3);
-	hdmi_set_supported_mode(HDMI_VFRMT_720x576p50_16_9);
-	hdmi_set_supported_mode(HDMI_VFRMT_1440x480i60_4_3);
-	hdmi_set_supported_mode(HDMI_VFRMT_1440x480i60_16_9);
-	hdmi_set_supported_mode(HDMI_VFRMT_1440x576i50_4_3);
-	hdmi_set_supported_mode(HDMI_VFRMT_1440x576i50_16_9);
-	hdmi_set_supported_mode(HDMI_VFRMT_1280x720p50_16_9);
-	hdmi_set_supported_mode(HDMI_VFRMT_1280x720p60_16_9);
-	hdmi_set_supported_mode(HDMI_VFRMT_1920x1080p24_16_9);
-	hdmi_set_supported_mode(HDMI_VFRMT_1920x1080p25_16_9);
-	hdmi_set_supported_mode(HDMI_VFRMT_1920x1080p30_16_9);
-	hdmi_set_supported_mode(HDMI_VFRMT_1920x1080p50_16_9);
-	hdmi_set_supported_mode(HDMI_VFRMT_1920x1080i60_16_9);
-	hdmi_set_supported_mode(HDMI_VFRMT_1920x1080p60_16_9);
-	hdmi_set_supported_mode(HDMI_VFRMT_2560x1600p60_16_9);
-	hdmi_set_supported_mode(HDMI_VFRMT_3840x2160p30_16_9);
-	hdmi_set_supported_mode(HDMI_VFRMT_3840x2160p25_16_9);
-	hdmi_set_supported_mode(HDMI_VFRMT_3840x2160p24_16_9);
-	hdmi_set_supported_mode(HDMI_VFRMT_4096x2160p24_16_9);
-} /* hdmi_tx_setup_video_mode_lut */
-
 /* Table tuned to indicate video formats supported by the MHL Tx */
 /* Valid pclk rates (Mhz): 25.2, 27, 27.03, 74.25 */
 static void hdmi_tx_setup_mhl_video_mode_lut(struct hdmi_tx_ctrl *hdmi_ctrl)
 {
 	u32 i;
-	struct hdmi_disp_mode_timing_type *temp_timing;
+	struct msm_hdmi_mode_timing_info *temp_timing;
 
 	if (!hdmi_ctrl->mhl_max_pclk) {
 		DEV_WARN("%s: mhl max pclk not set!\n", __func__);
@@ -657,7 +747,7 @@
 		__func__, hdmi_ctrl->mhl_max_pclk);
 	for (i = 0; i < HDMI_VFRMT_MAX; i++) {
 		temp_timing =
-		(struct hdmi_disp_mode_timing_type *)hdmi_get_supported_mode(i);
+		(struct msm_hdmi_mode_timing_info *)hdmi_get_supported_mode(i);
 		if (!temp_timing)
 			continue;
 		/* formats that exceed max mhl line clk bw */
@@ -765,7 +855,7 @@
 	struct mdss_panel_info *pinfo)
 {
 	int new_vic = -1;
-	const struct hdmi_disp_mode_timing_type *timing = NULL;
+	const struct msm_hdmi_mode_timing_info *timing = NULL;
 
 	if (!hdmi_ctrl || !pinfo) {
 		DEV_ERR("%s: invalid input\n", __func__);
@@ -779,8 +869,8 @@
 	}
 
 	DEV_DBG("%s: switching from %s => %s", __func__,
-		hdmi_get_video_fmt_2string(hdmi_ctrl->video_resolution),
-		hdmi_get_video_fmt_2string(new_vic));
+		msm_hdmi_mode_2string(hdmi_ctrl->video_resolution),
+		msm_hdmi_mode_2string(new_vic));
 
 	hdmi_ctrl->video_resolution = (u32)new_vic;
 
@@ -808,7 +898,7 @@
 	u32 end_v     = 0;
 	struct dss_io_data *io = NULL;
 
-	const struct hdmi_disp_mode_timing_type *timing =
+	const struct msm_hdmi_mode_timing_info *timing =
 		hdmi_get_supported_mode(video_format);
 	if (timing == NULL) {
 		DEV_ERR("%s: video format not supported: %d\n", __func__,
@@ -1521,7 +1611,7 @@
 	acr_pck_ctrl_reg = DSS_REG_R(io, HDMI_ACR_PKT_CTRL);
 
 	if (enabled) {
-		const struct hdmi_disp_mode_timing_type *timing =
+		const struct msm_hdmi_mode_timing_info *timing =
 			hdmi_get_supported_mode(hdmi_ctrl->video_resolution);
 		const struct hdmi_tx_audio_acr_arry *audio_acr =
 			&hdmi_tx_audio_acr_lut[0];
@@ -2152,7 +2242,7 @@
 
 	hdmi_ctrl->hdcp_feature_on = hdcp_feature_on;
 
-	DEV_INFO("power: ON (%s)\n", hdmi_get_video_fmt_2string(
+	DEV_INFO("power: ON (%s)\n", msm_hdmi_mode_2string(
 		hdmi_ctrl->video_resolution));
 
 	rc = hdmi_tx_core_on(hdmi_ctrl);
@@ -2381,7 +2471,7 @@
 	/* irq enable/disable will be handled in hpd on/off */
 	hdmi_tx_hw.ptr = (void *)hdmi_ctrl;
 
-	hdmi_tx_setup_video_mode_lut();
+	hdmi_setup_video_mode_lut();
 	mutex_init(&hdmi_ctrl->mutex);
 	hdmi_ctrl->workq = create_workqueue("hdmi_tx_workq");
 	if (!hdmi_ctrl->workq) {
diff --git a/drivers/video/msm/mdss/mdss_hdmi_util.c b/drivers/video/msm/mdss/mdss_hdmi_util.c
index 07c2336..0c8b0f8 100644
--- a/drivers/video/msm/mdss/mdss_hdmi_util.c
+++ b/drivers/video/msm/mdss/mdss_hdmi_util.c
@@ -15,38 +15,22 @@
 #include <mach/board.h>
 #include "mdss_hdmi_util.h"
 
-static struct hdmi_disp_mode_timing_type
+static struct msm_hdmi_mode_timing_info
 	hdmi_supported_video_mode_lut[HDMI_VFRMT_MAX];
 
-#define HDMI_SETUP_LUT(MODE) do {					\
-	struct hdmi_disp_mode_timing_type mode = HDMI_SETTINGS_##MODE;	\
-	hdmi_supported_video_mode_lut[mode.video_format] = mode;	\
-	} while (0)
-
-void hdmi_init_supported_video_timings(void)
-{
-	int i;
-
-	for (i = 0; i < HDMI_VFRMT_MAX; i++) {
-		struct hdmi_disp_mode_timing_type mode = VFRMT_NOT_SUPPORTED(i);
-
-		hdmi_supported_video_mode_lut[i] = mode;
-	}
-} /* hdmi_init_supported_video_timings */
-
 void hdmi_del_supported_mode(u32 mode)
 {
-	struct hdmi_disp_mode_timing_type *ret = NULL;
+	struct msm_hdmi_mode_timing_info *ret = NULL;
 	DEV_DBG("%s: removing %s\n", __func__,
-		 hdmi_get_video_fmt_2string(mode));
+		 msm_hdmi_mode_2string(mode));
 	ret = &hdmi_supported_video_mode_lut[mode];
 	if (ret != NULL && ret->supported)
 		ret->supported = false;
 }
 
-const struct hdmi_disp_mode_timing_type *hdmi_get_supported_mode(u32 mode)
+const struct msm_hdmi_mode_timing_info *hdmi_get_supported_mode(u32 mode)
 {
-	const struct hdmi_disp_mode_timing_type *ret = NULL;
+	const struct msm_hdmi_mode_timing_info *ret = NULL;
 
 	if (mode >= HDMI_VFRMT_MAX)
 		return NULL;
@@ -59,7 +43,7 @@
 	return ret;
 } /* hdmi_get_supported_mode */
 
-int hdmi_get_video_id_code(struct hdmi_disp_mode_timing_type *timing_in)
+int hdmi_get_video_id_code(struct msm_hdmi_mode_timing_info *timing_in)
 {
 	int i, vic = -1;
 
@@ -70,7 +54,7 @@
 
 	/* active_low_h, active_low_v and interlaced are not checked against */
 	for (i = 0; i < HDMI_VFRMT_MAX; i++) {
-		struct hdmi_disp_mode_timing_type *supported_timing =
+		struct msm_hdmi_mode_timing_info *supported_timing =
 			&hdmi_supported_video_mode_lut[i];
 
 		if (!supported_timing->supported)
@@ -105,155 +89,29 @@
 
 exit:
 	DEV_DBG("%s: vic = %d timing = %s\n", __func__, vic,
-		hdmi_get_video_fmt_2string((u32)vic));
+		msm_hdmi_mode_2string((u32)vic));
 
 	return vic;
 } /* hdmi_get_video_id_code */
 
-void hdmi_set_supported_mode(u32 mode)
+/* Table indicating the video format supported by the HDMI TX Core */
+/* Valid pclk rates (Mhz): 25.2, 27, 27.03, 74.25, 148.5, 268.5, 297 */
+void hdmi_setup_video_mode_lut(void)
 {
-	switch (mode) {
-	case HDMI_VFRMT_640x480p60_4_3:
-		HDMI_SETUP_LUT(640x480p60_4_3);
-		break;
-	case HDMI_VFRMT_720x480p60_4_3:
-		HDMI_SETUP_LUT(720x480p60_4_3);
-		break;
-	case HDMI_VFRMT_720x480p60_16_9:
-		HDMI_SETUP_LUT(720x480p60_16_9);
-		break;
-	case HDMI_VFRMT_720x576p50_4_3:
-		HDMI_SETUP_LUT(720x576p50_4_3);
-		break;
-	case HDMI_VFRMT_720x576p50_16_9:
-		HDMI_SETUP_LUT(720x576p50_16_9);
-		break;
-	case HDMI_VFRMT_1440x480i60_4_3:
-		HDMI_SETUP_LUT(1440x480i60_4_3);
-		break;
-	case HDMI_VFRMT_1440x480i60_16_9:
-		HDMI_SETUP_LUT(1440x480i60_16_9);
-		break;
-	case HDMI_VFRMT_1440x576i50_4_3:
-		HDMI_SETUP_LUT(1440x576i50_4_3);
-		break;
-	case HDMI_VFRMT_1440x576i50_16_9:
-		HDMI_SETUP_LUT(1440x576i50_16_9);
-		break;
-	case HDMI_VFRMT_1280x720p50_16_9:
-		HDMI_SETUP_LUT(1280x720p50_16_9);
-		break;
-	case HDMI_VFRMT_1280x720p60_16_9:
-		HDMI_SETUP_LUT(1280x720p60_16_9);
-		break;
-	case HDMI_VFRMT_1920x1080p24_16_9:
-		HDMI_SETUP_LUT(1920x1080p24_16_9);
-		break;
-	case HDMI_VFRMT_1920x1080p25_16_9:
-		HDMI_SETUP_LUT(1920x1080p25_16_9);
-		break;
-	case HDMI_VFRMT_1920x1080p30_16_9:
-		HDMI_SETUP_LUT(1920x1080p30_16_9);
-		break;
-	case HDMI_VFRMT_1920x1080p50_16_9:
-		HDMI_SETUP_LUT(1920x1080p50_16_9);
-		break;
-	case HDMI_VFRMT_1920x1080i60_16_9:
-		HDMI_SETUP_LUT(1920x1080i60_16_9);
-		break;
-	case HDMI_VFRMT_1920x1080p60_16_9:
-		HDMI_SETUP_LUT(1920x1080p60_16_9);
-		break;
-	case HDMI_VFRMT_2560x1600p60_16_9:
-		HDMI_SETUP_LUT(2560x1600p60_16_9);
-		break;
-	case HDMI_VFRMT_3840x2160p30_16_9:
-		HDMI_SETUP_LUT(3840x2160p30_16_9);
-		break;
-	case HDMI_VFRMT_3840x2160p25_16_9:
-		HDMI_SETUP_LUT(3840x2160p25_16_9);
-		break;
-	case HDMI_VFRMT_3840x2160p24_16_9:
-		HDMI_SETUP_LUT(3840x2160p24_16_9);
-		break;
-	case HDMI_VFRMT_4096x2160p24_16_9:
-		HDMI_SETUP_LUT(4096x2160p24_16_9);
-		break;
-	default:
-		DEV_ERR("%s: unsupported mode=%d\n", __func__, mode);
-	}
-} /* hdmi_set_supported_mode */
+	MSM_HDMI_MODES_INIT_TIMINGS(hdmi_supported_video_mode_lut);
 
-const char *hdmi_get_video_fmt_2string(u32 format)
-{
-	switch (format) {
-	case HDMI_VFRMT_640x480p60_4_3:    return " 640x 480 p60  4/3";
-	case HDMI_VFRMT_720x480p60_4_3:    return " 720x 480 p60  4/3";
-	case HDMI_VFRMT_720x480p60_16_9:   return " 720x 480 p60 16/9";
-	case HDMI_VFRMT_1280x720p60_16_9:  return "1280x 720 p60 16/9";
-	case HDMI_VFRMT_1920x1080i60_16_9: return "1920x1080 i60 16/9";
-	case HDMI_VFRMT_1440x480i60_4_3:   return "1440x 480 i60  4/3";
-	case HDMI_VFRMT_1440x480i60_16_9:  return "1440x 480 i60 16/9";
-	case HDMI_VFRMT_1440x240p60_4_3:   return "1440x 240 p60  4/3";
-	case HDMI_VFRMT_1440x240p60_16_9:  return "1440x 240 p60 16/9";
-	case HDMI_VFRMT_2880x480i60_4_3:   return "2880x 480 i60  4/3";
-	case HDMI_VFRMT_2880x480i60_16_9:  return "2880x 480 i60 16/9";
-	case HDMI_VFRMT_2880x240p60_4_3:   return "2880x 240 p60  4/3";
-	case HDMI_VFRMT_2880x240p60_16_9:  return "2880x 240 p60 16/9";
-	case HDMI_VFRMT_1440x480p60_4_3:   return "1440x 480 p60  4/3";
-	case HDMI_VFRMT_1440x480p60_16_9:  return "1440x 480 p60 16/9";
-	case HDMI_VFRMT_1920x1080p60_16_9: return "1920x1080 p60 16/9";
-	case HDMI_VFRMT_720x576p50_4_3:    return " 720x 576 p50  4/3";
-	case HDMI_VFRMT_720x576p50_16_9:   return " 720x 576 p50 16/9";
-	case HDMI_VFRMT_1280x720p50_16_9:  return "1280x 720 p50 16/9";
-	case HDMI_VFRMT_1920x1080i50_16_9: return "1920x1080 i50 16/9";
-	case HDMI_VFRMT_1440x576i50_4_3:   return "1440x 576 i50  4/3";
-	case HDMI_VFRMT_1440x576i50_16_9:  return "1440x 576 i50 16/9";
-	case HDMI_VFRMT_1440x288p50_4_3:   return "1440x 288 p50  4/3";
-	case HDMI_VFRMT_1440x288p50_16_9:  return "1440x 288 p50 16/9";
-	case HDMI_VFRMT_2880x576i50_4_3:   return "2880x 576 i50  4/3";
-	case HDMI_VFRMT_2880x576i50_16_9:  return "2880x 576 i50 16/9";
-	case HDMI_VFRMT_2880x288p50_4_3:   return "2880x 288 p50  4/3";
-	case HDMI_VFRMT_2880x288p50_16_9:  return "2880x 288 p50 16/9";
-	case HDMI_VFRMT_1440x576p50_4_3:   return "1440x 576 p50  4/3";
-	case HDMI_VFRMT_1440x576p50_16_9:  return "1440x 576 p50 16/9";
-	case HDMI_VFRMT_1920x1080p50_16_9: return "1920x1080 p50 16/9";
-	case HDMI_VFRMT_1920x1080p24_16_9: return "1920x1080 p24 16/9";
-	case HDMI_VFRMT_1920x1080p25_16_9: return "1920x1080 p25 16/9";
-	case HDMI_VFRMT_1920x1080p30_16_9: return "1920x1080 p30 16/9";
-	case HDMI_VFRMT_2880x480p60_4_3:   return "2880x 480 p60  4/3";
-	case HDMI_VFRMT_2880x480p60_16_9:  return "2880x 480 p60 16/9";
-	case HDMI_VFRMT_2880x576p50_4_3:   return "2880x 576 p50  4/3";
-	case HDMI_VFRMT_2880x576p50_16_9:  return "2880x 576 p50 16/9";
-	case HDMI_VFRMT_1920x1250i50_16_9: return "1920x1250 i50 16/9";
-	case HDMI_VFRMT_1920x1080i100_16_9:return "1920x1080 i100 16/9";
-	case HDMI_VFRMT_1280x720p100_16_9: return "1280x 720 p100 16/9";
-	case HDMI_VFRMT_720x576p100_4_3:   return " 720x 576 p100  4/3";
-	case HDMI_VFRMT_720x576p100_16_9:  return " 720x 576 p100 16/9";
-	case HDMI_VFRMT_1440x576i100_4_3:  return "1440x 576 i100  4/3";
-	case HDMI_VFRMT_1440x576i100_16_9: return "1440x 576 i100 16/9";
-	case HDMI_VFRMT_1920x1080i120_16_9:return "1920x1080 i120 16/9";
-	case HDMI_VFRMT_1280x720p120_16_9: return "1280x 720 p120 16/9";
-	case HDMI_VFRMT_720x480p120_4_3:   return " 720x 480 p120  4/3";
-	case HDMI_VFRMT_720x480p120_16_9:  return " 720x 480 p120 16/9";
-	case HDMI_VFRMT_1440x480i120_4_3:  return "1440x 480 i120  4/3";
-	case HDMI_VFRMT_1440x480i120_16_9: return "1440x 480 i120 16/9";
-	case HDMI_VFRMT_720x576p200_4_3:   return " 720x 576 p200  4/3";
-	case HDMI_VFRMT_720x576p200_16_9:  return " 720x 576 p200 16/9";
-	case HDMI_VFRMT_1440x576i200_4_3:  return "1440x 576 i200  4/3";
-	case HDMI_VFRMT_1440x576i200_16_9: return "1440x 576 i200 16/9";
-	case HDMI_VFRMT_720x480p240_4_3:   return " 720x 480 p240  4/3";
-	case HDMI_VFRMT_720x480p240_16_9:  return " 720x 480 p240 16/9";
-	case HDMI_VFRMT_1440x480i240_4_3:  return "1440x 480 i240  4/3";
-	case HDMI_VFRMT_1440x480i240_16_9: return "1440x 480 i240 16/9";
-	case HDMI_VFRMT_2560x1600p60_16_9: return "2560x1600 p60 16/9";
-	case HDMI_VFRMT_3840x2160p30_16_9: return "3840x2160 p30 16/9";
-	case HDMI_VFRMT_3840x2160p25_16_9: return "3840x2160 p25 16/9";
-	case HDMI_VFRMT_3840x2160p24_16_9: return "3840x2160 p24 16/9";
-	case HDMI_VFRMT_4096x2160p24_16_9: return "4096x2160 p24 16/9";
-	default:                           return "???";
-	}
-} /* hdmi_get_video_fmt_2string */
+	/* Add all supported CEA modes to the lut */
+	MSM_HDMI_MODES_SET_SUPP_TIMINGS(
+		hdmi_supported_video_mode_lut, MSM_HDMI_MODES_CEA);
+
+	/* Add all supported extended hdmi modes to the lut */
+	MSM_HDMI_MODES_SET_SUPP_TIMINGS(
+		hdmi_supported_video_mode_lut, MSM_HDMI_MODES_XTND);
+
+	/* Add any other specific DVI timings (DVI modes, etc.) */
+	MSM_HDMI_MODES_SET_TIMING(hdmi_supported_video_mode_lut,
+		HDMI_VFRMT_2560x1600p60_16_9);
+} /* hdmi_setup_video_mode_lut */
 
 const char *hdmi_get_single_video_3d_fmt_2string(u32 format)
 {
diff --git a/drivers/video/msm/mdss/mdss_hdmi_util.h b/drivers/video/msm/mdss/mdss_hdmi_util.h
index 914aac1..cf42346 100644
--- a/drivers/video/msm/mdss/mdss_hdmi_util.h
+++ b/drivers/video/msm/mdss/mdss_hdmi_util.h
@@ -13,6 +13,7 @@
 #ifndef __HDMI_UTIL_H__
 #define __HDMI_UTIL_H__
 #include "mdss_io_util.h"
+#include "video/msm_hdmi_modes.h"
 
 /* HDMI_TX Registers */
 #define HDMI_CTRL                        (0x00000000)
@@ -218,166 +219,6 @@
 #define HDCP_KSV_LSB                     (0x000060D8)
 #define HDCP_KSV_MSB                     (0x000060DC)
 
-/* all video formats defined by EIA CEA-861-E */
-#define HDMI_VFRMT_640x480p60_4_3	0
-#define HDMI_VFRMT_720x480p60_4_3	1
-#define HDMI_VFRMT_720x480p60_16_9	2
-#define HDMI_VFRMT_1280x720p60_16_9	3
-#define HDMI_VFRMT_1920x1080i60_16_9	4
-#define HDMI_VFRMT_720x480i60_4_3	5
-#define HDMI_VFRMT_1440x480i60_4_3	HDMI_VFRMT_720x480i60_4_3
-#define HDMI_VFRMT_720x480i60_16_9	6
-#define HDMI_VFRMT_1440x480i60_16_9	HDMI_VFRMT_720x480i60_16_9
-#define HDMI_VFRMT_720x240p60_4_3	7
-#define HDMI_VFRMT_1440x240p60_4_3	HDMI_VFRMT_720x240p60_4_3
-#define HDMI_VFRMT_720x240p60_16_9	8
-#define HDMI_VFRMT_1440x240p60_16_9	HDMI_VFRMT_720x240p60_16_9
-#define HDMI_VFRMT_2880x480i60_4_3	9
-#define HDMI_VFRMT_2880x480i60_16_9	10
-#define HDMI_VFRMT_2880x240p60_4_3	11
-#define HDMI_VFRMT_2880x240p60_16_9	12
-#define HDMI_VFRMT_1440x480p60_4_3	13
-#define HDMI_VFRMT_1440x480p60_16_9	14
-#define HDMI_VFRMT_1920x1080p60_16_9	15
-#define HDMI_VFRMT_720x576p50_4_3	16
-#define HDMI_VFRMT_720x576p50_16_9	17
-#define HDMI_VFRMT_1280x720p50_16_9	18
-#define HDMI_VFRMT_1920x1080i50_16_9	19
-#define HDMI_VFRMT_720x576i50_4_3	20
-#define HDMI_VFRMT_1440x576i50_4_3	HDMI_VFRMT_720x576i50_4_3
-#define HDMI_VFRMT_720x576i50_16_9	21
-#define HDMI_VFRMT_1440x576i50_16_9	HDMI_VFRMT_720x576i50_16_9
-#define HDMI_VFRMT_720x288p50_4_3	22
-#define HDMI_VFRMT_1440x288p50_4_3	HDMI_VFRMT_720x288p50_4_3
-#define HDMI_VFRMT_720x288p50_16_9	23
-#define HDMI_VFRMT_1440x288p50_16_9	HDMI_VFRMT_720x288p50_16_9
-#define HDMI_VFRMT_2880x576i50_4_3	24
-#define HDMI_VFRMT_2880x576i50_16_9	25
-#define HDMI_VFRMT_2880x288p50_4_3	26
-#define HDMI_VFRMT_2880x288p50_16_9	27
-#define HDMI_VFRMT_1440x576p50_4_3	28
-#define HDMI_VFRMT_1440x576p50_16_9	29
-#define HDMI_VFRMT_1920x1080p50_16_9	30
-#define HDMI_VFRMT_1920x1080p24_16_9	31
-#define HDMI_VFRMT_1920x1080p25_16_9	32
-#define HDMI_VFRMT_1920x1080p30_16_9	33
-#define HDMI_VFRMT_2880x480p60_4_3	34
-#define HDMI_VFRMT_2880x480p60_16_9	35
-#define HDMI_VFRMT_2880x576p50_4_3	36
-#define HDMI_VFRMT_2880x576p50_16_9	37
-#define HDMI_VFRMT_1920x1250i50_16_9	38
-#define HDMI_VFRMT_1920x1080i100_16_9	39
-#define HDMI_VFRMT_1280x720p100_16_9	40
-#define HDMI_VFRMT_720x576p100_4_3	41
-#define HDMI_VFRMT_720x576p100_16_9	42
-#define HDMI_VFRMT_720x576i100_4_3	43
-#define HDMI_VFRMT_1440x576i100_4_3	HDMI_VFRMT_720x576i100_4_3
-#define HDMI_VFRMT_720x576i100_16_9	44
-#define HDMI_VFRMT_1440x576i100_16_9	HDMI_VFRMT_720x576i100_16_9
-#define HDMI_VFRMT_1920x1080i120_16_9	45
-#define HDMI_VFRMT_1280x720p120_16_9	46
-#define HDMI_VFRMT_720x480p120_4_3	47
-#define HDMI_VFRMT_720x480p120_16_9	48
-#define HDMI_VFRMT_720x480i120_4_3	49
-#define HDMI_VFRMT_1440x480i120_4_3	HDMI_VFRMT_720x480i120_4_3
-#define HDMI_VFRMT_720x480i120_16_9	50
-#define HDMI_VFRMT_1440x480i120_16_9	HDMI_VFRMT_720x480i120_16_9
-#define HDMI_VFRMT_720x576p200_4_3	51
-#define HDMI_VFRMT_720x576p200_16_9	52
-#define HDMI_VFRMT_720x576i200_4_3	53
-#define HDMI_VFRMT_1440x576i200_4_3	HDMI_VFRMT_720x576i200_4_3
-#define HDMI_VFRMT_720x576i200_16_9	54
-#define HDMI_VFRMT_1440x576i200_16_9	HDMI_VFRMT_720x576i200_16_9
-#define HDMI_VFRMT_720x480p240_4_3	55
-#define HDMI_VFRMT_720x480p240_16_9	56
-#define HDMI_VFRMT_720x480i240_4_3	57
-#define HDMI_VFRMT_1440x480i240_4_3	HDMI_VFRMT_720x480i240_4_3
-#define HDMI_VFRMT_720x480i240_16_9	58
-#define HDMI_VFRMT_1440x480i240_16_9	HDMI_VFRMT_720x480i240_16_9
-/* Video Identification Codes from 65-127 are reserved for the future */
-#define HDMI_VFRMT_END			127
-/* extended video formats */
-#define HDMI_VFRMT_3840x2160p30_16_9	(HDMI_VFRMT_END + 1)
-#define HDMI_VFRMT_3840x2160p25_16_9	(HDMI_VFRMT_END + 2)
-#define HDMI_VFRMT_3840x2160p24_16_9	(HDMI_VFRMT_END + 3)
-#define HDMI_VFRMT_4096x2160p24_16_9	(HDMI_VFRMT_END + 4)
-#define HDMI_EVFRMT_END			HDMI_VFRMT_4096x2160p24_16_9
-/* DVI only resolutions */
-#define HDMI_VFRMT_2560x1600p60_16_9	(HDMI_EVFRMT_END + 1)
-#define DVI_VFRMT_END			HDMI_VFRMT_2560x1600p60_16_9
-#define HDMI_VFRMT_MAX			(DVI_VFRMT_END + 1)
-#define HDMI_VFRMT_FORCE_32BIT		0x7FFFFFFF
-
-#define VFRMT_NOT_SUPPORTED(VFRMT) \
-	{VFRMT, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, false}
-
-#define HDMI_SETTINGS_640x480p60_4_3					\
-	{HDMI_VFRMT_640x480p60_4_3,      640,  16,  96,  48,  true,	\
-	 480, 10, 2, 33, true, 25200, 60000, false, true}
-#define HDMI_SETTINGS_720x480p60_4_3					\
-	{HDMI_VFRMT_720x480p60_4_3,      720,  16,  62,  60,  true,	\
-	 480, 9, 6, 30,  true, 27030, 60000, false, true}
-#define HDMI_SETTINGS_720x480p60_16_9					\
-	{HDMI_VFRMT_720x480p60_16_9,     720,  16,  62,  60,  true,	\
-	 480, 9, 6, 30,  true, 27030, 60000, false, true}
-#define HDMI_SETTINGS_1280x720p60_16_9					\
-	{HDMI_VFRMT_1280x720p60_16_9,    1280, 110, 40,  220, false,	\
-	 720, 5, 5, 20, false, 74250, 60000, false, true}
-#define HDMI_SETTINGS_1920x1080i60_16_9					\
-	{HDMI_VFRMT_1920x1080i60_16_9,   1920, 88,  44,  148, false,	\
-	 540, 2, 5, 5, false, 74250, 60000, false, true}
-#define HDMI_SETTINGS_1440x480i60_4_3					\
-	{HDMI_VFRMT_1440x480i60_4_3,     1440, 38,  124, 114, true,	\
-	 240, 4, 3, 15, true, 27000, 60000, true, true}
-#define HDMI_SETTINGS_1440x480i60_16_9					\
-	{HDMI_VFRMT_1440x480i60_16_9,    1440, 38,  124, 114, true,	\
-	 240, 4, 3, 15, true, 27000, 60000, true, true}
-#define HDMI_SETTINGS_1920x1080p60_16_9					\
-	{HDMI_VFRMT_1920x1080p60_16_9,   1920, 88,  44,  148,  false,	\
-	 1080, 4, 5, 36, false, 148500, 60000, false, true}
-#define HDMI_SETTINGS_720x576p50_4_3					\
-	{HDMI_VFRMT_720x576p50_4_3,      720,  12,  64,  68,   true,	\
-	 576,  5, 5, 39, true, 27000, 50000, false, true}
-#define HDMI_SETTINGS_720x576p50_16_9					\
-	{HDMI_VFRMT_720x576p50_16_9,     720,  12,  64,  68,   true,	\
-	 576,  5, 5, 39, true, 27000, 50000, false, true}
-#define HDMI_SETTINGS_1280x720p50_16_9					\
-	{HDMI_VFRMT_1280x720p50_16_9,    1280, 440, 40,  220,  false,	\
-	 720,  5, 5, 20, false, 74250, 50000, false, true}
-#define HDMI_SETTINGS_1440x576i50_4_3					\
-	{HDMI_VFRMT_1440x576i50_4_3,     1440, 24,  126, 138,  true,	\
-	 288,  2, 3, 19, true, 27000, 50000, true, true}
-#define HDMI_SETTINGS_1440x576i50_16_9					\
-	{HDMI_VFRMT_1440x576i50_16_9,    1440, 24,  126, 138,  true,	\
-	 288,  2, 3, 19, true, 27000, 50000, true, true}
-#define HDMI_SETTINGS_1920x1080p50_16_9					\
-	{HDMI_VFRMT_1920x1080p50_16_9,   1920,  528,  44,  148,  false,	\
-	 1080, 4, 5, 36, false, 148500, 50000, false, true}
-#define HDMI_SETTINGS_1920x1080p24_16_9					\
-	{HDMI_VFRMT_1920x1080p24_16_9,   1920,  638,  44,  148,  false,	\
-	 1080, 4, 5, 36, false, 74250, 24000, false, true}
-#define HDMI_SETTINGS_1920x1080p25_16_9					\
-	{HDMI_VFRMT_1920x1080p25_16_9,   1920,  528,  44,  148,  false,	\
-	 1080, 4, 5, 36, false, 74250, 25000, false, true}
-#define HDMI_SETTINGS_1920x1080p30_16_9					\
-	{HDMI_VFRMT_1920x1080p30_16_9,   1920,  88,   44,  148,  false,	\
-	 1080, 4, 5, 36, false, 74250, 30000, false, true}
-#define HDMI_SETTINGS_2560x1600p60_16_9					\
-	{HDMI_VFRMT_2560x1600p60_16_9,   2560,  48,   32,  80,  false,	\
-	 1600, 3, 6, 37, false, 268500, 60000, false, true}
-#define HDMI_SETTINGS_3840x2160p30_16_9					\
-	{HDMI_VFRMT_3840x2160p30_16_9, 3840, 176, 88, 296, false,	\
-	 2160, 8, 10, 72, false, 297000, 30000, false, true}
-#define HDMI_SETTINGS_3840x2160p25_16_9					\
-	{HDMI_VFRMT_3840x2160p25_16_9, 3840, 1056, 88, 296, false,	\
-	 2160, 8, 10, 72, false, 297000, 25000, false, true}
-#define HDMI_SETTINGS_3840x2160p24_16_9					\
-	{HDMI_VFRMT_3840x2160p24_16_9, 3840, 1276, 88, 296, false,	\
-	 2160, 8, 10, 72, false, 297000, 24000, false, true}
-#define HDMI_SETTINGS_4096x2160p24_16_9					\
-	{HDMI_VFRMT_4096x2160p24_16_9, 4096, 1020, 88, 296, false,	\
-	 2160, 8, 10, 72, false, 297000, 24000, false, true}
-
 #define TOP_AND_BOTTOM		0x10
 #define FRAME_PACKING		0x20
 #define SIDE_BY_SIDE_HALF	0x40
@@ -389,26 +230,6 @@
 	HDMI_TX_FEAT_MAX,
 };
 
-struct hdmi_disp_mode_timing_type {
-	u32	video_format;
-	u32	active_h;
-	u32	front_porch_h;
-	u32	pulse_width_h;
-	u32	back_porch_h;
-	u32	active_low_h;
-	u32	active_v;
-	u32	front_porch_v;
-	u32	pulse_width_v;
-	u32	back_porch_v;
-	u32	active_low_v;
-	/* Must divide by 1000 to get the actual frequency in MHZ */
-	u32	pixel_freq;
-	/* Must divide by 1000 to get the actual frequency in HZ */
-	u32	refresh_rate;
-	u32	interlaced;
-	u32	supported;
-};
-
 struct hdmi_tx_ddc_ctrl {
 	struct dss_io_data *io;
 	struct completion ddc_sw_done;
@@ -426,12 +247,10 @@
 };
 
 /* video timing related utility routines */
-void hdmi_init_supported_video_timings(void);
-int hdmi_get_video_id_code(struct hdmi_disp_mode_timing_type *timing_in);
-const struct hdmi_disp_mode_timing_type *hdmi_get_supported_mode(u32 mode);
-void hdmi_set_supported_mode(u32 mode);
+void hdmi_setup_video_mode_lut(void);
+int hdmi_get_video_id_code(struct msm_hdmi_mode_timing_info *timing_in);
+const struct msm_hdmi_mode_timing_info *hdmi_get_supported_mode(u32 mode);
 void hdmi_del_supported_mode(u32 mode);
-const char *hdmi_get_video_fmt_2string(u32 format);
 ssize_t hdmi_get_video_3d_fmt_2string(u32 format, char *buf);
 
 /* todo: Fix this. Right now this is defined in mdss_hdmi_tx.c */
diff --git a/drivers/video/msm/mdss/mdss_mdp.c b/drivers/video/msm/mdss/mdss_mdp.c
index e89fc7a..8be64b2 100644
--- a/drivers/video/msm/mdss/mdss_mdp.c
+++ b/drivers/video/msm/mdss/mdss_mdp.c
@@ -184,14 +184,15 @@
 static inline int mdss_irq_dispatch(u32 hw_ndx, int irq, void *ptr)
 {
 	struct mdss_hw *hw;
+	int rc = -ENODEV;
 
 	spin_lock(&mdss_lock);
 	hw = mdss_irq_handlers[hw_ndx];
-	spin_unlock(&mdss_lock);
 	if (hw)
-		return hw->irq_handler(irq, hw->ptr);
+		rc = hw->irq_handler(irq, hw->ptr);
+	spin_unlock(&mdss_lock);
 
-	return -ENODEV;
+	return rc;
 }
 
 static irqreturn_t mdss_irq_handler(int irq, void *ptr)
@@ -204,8 +205,11 @@
 
 	mdata->irq_buzy = true;
 
-	if (intr & MDSS_INTR_MDP)
+	if (intr & MDSS_INTR_MDP) {
+		spin_lock(&mdp_lock);
 		mdss_irq_dispatch(MDSS_HW_MDP, irq, ptr);
+		spin_unlock(&mdp_lock);
+	}
 
 	if (intr & MDSS_INTR_DSI0)
 		mdss_irq_dispatch(MDSS_HW_DSI0, irq, ptr);
@@ -284,6 +288,7 @@
 }
 EXPORT_SYMBOL(mdss_disable_irq);
 
+/* called from interrupt context */
 void mdss_disable_irq_nosync(struct mdss_hw *hw)
 {
 	u32 ndx_bit;
@@ -296,7 +301,6 @@
 	pr_debug("Disable HW=%d irq ena=%d mask=%x\n", hw->hw_ndx,
 			mdss_res->irq_ena, mdss_res->irq_mask);
 
-	spin_lock(&mdss_lock);
 	if (!(mdss_res->irq_mask & ndx_bit)) {
 		pr_warn("MDSS HW ndx=%d is NOT set, mask=%x, hist mask=%x\n",
 			hw->hw_ndx, mdss_res->mdp_irq_mask,
@@ -309,7 +313,6 @@
 			disable_irq_nosync(mdss_res->irq);
 		}
 	}
-	spin_unlock(&mdss_lock);
 }
 EXPORT_SYMBOL(mdss_disable_irq_nosync);
 
@@ -390,6 +393,21 @@
 	return 1 << (intr_type + intf_num);
 }
 
+/* function assumes that mdp is clocked to access hw registers */
+void mdss_mdp_irq_clear(struct mdss_data_type *mdata,
+		u32 intr_type, u32 intf_num)
+{
+	unsigned long irq_flags;
+	u32 irq;
+
+	irq = mdss_mdp_irq_mask(intr_type, intf_num);
+
+	pr_debug("clearing mdp irq mask=%x\n", irq);
+	spin_lock_irqsave(&mdp_lock, irq_flags);
+	writel_relaxed(irq, mdata->mdp_base + MDSS_MDP_REG_INTR_CLEAR);
+	spin_unlock_irqrestore(&mdp_lock, irq_flags);
+}
+
 int mdss_mdp_irq_enable(u32 intr_type, u32 intf_num)
 {
 	u32 irq;
@@ -482,13 +500,13 @@
 	spin_unlock_irqrestore(&mdp_lock, irq_flags);
 }
 
+/* called from interrupt context */
 void mdss_mdp_irq_disable_nosync(u32 intr_type, u32 intf_num)
 {
 	u32 irq;
 
 	irq = mdss_mdp_irq_mask(intr_type, intf_num);
 
-	spin_lock(&mdp_lock);
 	if (!(mdss_res->mdp_irq_mask & irq)) {
 		pr_warn("MDSS MDP IRQ-%x is NOT set, mask=%x\n",
 				irq, mdss_res->mdp_irq_mask);
@@ -500,7 +518,6 @@
 			(mdss_res->mdp_hist_irq_mask == 0))
 			mdss_disable_irq_nosync(&mdss_mdp_hw);
 	}
-	spin_unlock(&mdp_lock);
 }
 
 static inline struct clk *mdss_mdp_get_clk(u32 clk_idx)
@@ -593,6 +610,9 @@
 	}
 	mdata->clk_ena = enable;
 
+	if (enable)
+		pm_runtime_get_sync(&mdata->pdev->dev);
+
 	pr_debug("MDP CLKS %s\n", (enable ? "Enable" : "Disable"));
 	mb();
 
@@ -604,6 +624,9 @@
 	if (mdata->vsync_ena)
 		mdss_mdp_clk_update(MDSS_CLK_MDP_VSYNC, enable);
 
+	if (!enable)
+		pm_runtime_put(&mdata->pdev->dev);
+
 	mutex_unlock(&mdp_clk_lock);
 }
 
@@ -895,13 +918,15 @@
 
 void mdss_mdp_footswitch_ctrl_splash(int on)
 {
-	if (mdss_res != NULL) {
+	struct mdss_data_type *mdata = mdss_mdp_get_mdata();
+	if (mdata != NULL) {
 		if (on) {
 			pr_debug("Enable MDP FS for splash.\n");
-			regulator_enable(mdss_res->fs);
+			regulator_enable(mdata->fs);
+			mdss_hw_init(mdata);
 		} else {
 			pr_debug("Disable MDP FS for splash.\n");
-			regulator_disable(mdss_res->fs);
+			regulator_disable(mdata->fs);
 		}
 	} else {
 		pr_warn("mdss mdata not initialized\n");
diff --git a/drivers/video/msm/mdss/mdss_mdp.h b/drivers/video/msm/mdss/mdss_mdp.h
index df5e5d3..07b083a 100644
--- a/drivers/video/msm/mdss/mdss_mdp.h
+++ b/drivers/video/msm/mdss/mdss_mdp.h
@@ -330,6 +330,8 @@
 irqreturn_t mdss_mdp_isr(int irq, void *ptr);
 int mdss_iommu_attach(struct mdss_data_type *mdata);
 int mdss_mdp_copy_splash_screen(struct mdss_panel_data *pdata);
+void mdss_mdp_irq_clear(struct mdss_data_type *mdata,
+		u32 intr_type, u32 intf_num);
 int mdss_mdp_irq_enable(u32 intr_type, u32 intf_num);
 void mdss_mdp_irq_disable(u32 intr_type, u32 intf_num);
 int mdss_mdp_hist_irq_enable(u32 irq);
diff --git a/drivers/video/msm/mdss/mdss_mdp_ctl.c b/drivers/video/msm/mdss/mdss_mdp_ctl.c
index 97998d8c..1ced200 100644
--- a/drivers/video/msm/mdss/mdss_mdp_ctl.c
+++ b/drivers/video/msm/mdss/mdss_mdp_ctl.c
@@ -465,6 +465,54 @@
 	return NULL;
 }
 
+static int mdss_mdp_ctl_fbc_enable(int enable,
+		struct mdss_mdp_mixer *mixer, struct mdss_panel_info *pdata)
+{
+	struct fbc_panel_info *fbc;
+	u32 mode = 0, budget_ctl = 0, lossy_mode = 0;
+
+	if (!pdata) {
+		pr_err("Invalid pdata\n");
+		return -EINVAL;
+	}
+
+	fbc = &pdata->fbc;
+
+	if (!fbc || !fbc->enabled) {
+		pr_err("Invalid FBC structure\n");
+		return -EINVAL;
+	}
+
+	if (mixer->num == MDSS_MDP_INTF_LAYERMIXER0)
+		pr_debug("Mixer supports FBC.\n");
+	else {
+		pr_debug("Mixer doesn't support FBC.\n");
+		return -EINVAL;
+	}
+
+	if (enable) {
+		mode = ((pdata->xres) << 16) | ((fbc->comp_mode) << 8) |
+			((fbc->qerr_enable) << 7) | ((fbc->cd_bias) << 4) |
+			((fbc->pat_enable) << 3) | ((fbc->vlc_enable) << 2) |
+			((fbc->bflc_enable) << 1) | enable;
+
+		budget_ctl = ((fbc->line_x_budget) << 12) |
+			((fbc->block_x_budget) << 8) | fbc->block_budget;
+
+		lossy_mode = ((fbc->lossless_mode_thd) << 16) |
+			((fbc->lossy_mode_thd) << 8) |
+			((fbc->lossy_rgb_thd) << 3) | fbc->lossy_mode_idx;
+	}
+
+	mdss_mdp_pingpong_write(mixer, MDSS_MDP_REG_PP_FBC_MODE, mode);
+	mdss_mdp_pingpong_write(mixer, MDSS_MDP_REG_PP_FBC_BUDGET_CTL,
+			budget_ctl);
+	mdss_mdp_pingpong_write(mixer, MDSS_MDP_REG_PP_FBC_LOSSY_MODE,
+			lossy_mode);
+
+	return 0;
+}
+
 int mdss_mdp_ctl_setup(struct mdss_mdp_ctl *ctl)
 {
 	struct mdss_mdp_ctl *split_ctl;
@@ -811,6 +859,7 @@
 	struct mdss_mdp_mixer *mixer;
 	u32 outsize, temp;
 	int ret = 0;
+	int i, nmixers;
 
 	if (ctl->start_fnc)
 		ret = ctl->start_fnc(ctl);
@@ -825,6 +874,10 @@
 
 	pr_debug("ctl_num=%d\n", ctl->num);
 
+	nmixers = MDSS_MDP_INTF_MAX_LAYERMIXER + MDSS_MDP_WB_MAX_LAYERMIXER;
+	for (i = 0; i < nmixers; i++)
+		mdss_mdp_ctl_write(ctl, MDSS_MDP_REG_CTL_LAYER(i), 0);
+
 	mixer = ctl->mixer_left;
 	mdss_mdp_pp_resume(mixer->num);
 	mixer->params_changed++;
@@ -836,6 +889,11 @@
 	outsize = (mixer->height << 16) | mixer->width;
 	mdp_mixer_write(mixer, MDSS_MDP_REG_LM_OUT_SIZE, outsize);
 
+	if (ctl->panel_data->panel_info.fbc.enabled) {
+		ret = mdss_mdp_ctl_fbc_enable(1, ctl->mixer_left,
+				&ctl->panel_data->panel_info);
+	}
+
 	return ret;
 }
 
@@ -845,7 +903,7 @@
 	int ret = 0;
 
 	if (ctl->power_on) {
-		pr_debug("%s:%d already on!\n", __func__, __LINE__);
+		pr_debug("%d: panel already on!\n", __LINE__);
 		return 0;
 	}
 
@@ -931,14 +989,6 @@
 		ctl->power_on = false;
 		ctl->play_cnt = 0;
 		ctl->clk_rate = 0;
-		if (ctl->mixer_left) {
-			mdss_mdp_ctl_write(ctl, MDSS_MDP_REG_CTL_LAYER(
-					ctl->mixer_left->num), 0);
-		}
-		if (ctl->mixer_right) {
-			mdss_mdp_ctl_write(ctl, MDSS_MDP_REG_CTL_LAYER(
-					ctl->mixer_right->num), 0);
-		}
 		mdss_mdp_ctl_perf_commit(ctl->mdata, MDSS_MDP_PERF_UPDATE_ALL);
 	}
 
diff --git a/drivers/video/msm/mdss/mdss_mdp_hwio.h b/drivers/video/msm/mdss/mdss_mdp_hwio.h
index bf78c61..d50f47e 100644
--- a/drivers/video/msm/mdss/mdss_mdp_hwio.h
+++ b/drivers/video/msm/mdss/mdss_mdp_hwio.h
@@ -445,6 +445,10 @@
 #define MDSS_MDP_REG_PP_LINE_COUNT			0x02C
 #define MDSS_MDP_REG_PP_AUTOREFRESH_CONFIG		0x030
 
+#define MDSS_MDP_REG_PP_FBC_MODE			0x034
+#define MDSS_MDP_REG_PP_FBC_BUDGET_CTL			0x038
+#define MDSS_MDP_REG_PP_FBC_LOSSY_MODE			0x03C
+
 #define MDSS_MDP_REG_SMP_ALLOC_W0			0x00180
 #define MDSS_MDP_REG_SMP_ALLOC_R0			0x00230
 
diff --git a/drivers/video/msm/mdss/mdss_mdp_intf_video.c b/drivers/video/msm/mdss/mdss_mdp_intf_video.c
index e7f70b6..0426784 100644
--- a/drivers/video/msm/mdss/mdss_mdp_intf_video.c
+++ b/drivers/video/msm/mdss/mdss_mdp_intf_video.c
@@ -182,6 +182,9 @@
 
 	if (atomic_inc_return(&ctx->vsync_ref) == 1)
 		mdss_mdp_irq_enable(MDSS_MDP_IRQ_INTF_VSYNC, ctl->intf_num);
+	else
+		mdss_mdp_irq_clear(ctl->mdata, MDSS_MDP_IRQ_INTF_VSYNC,
+				ctl->intf_num);
 }
 
 static inline void video_vsync_irq_disable(struct mdss_mdp_ctl *ctl)
@@ -197,6 +200,7 @@
 {
 	struct mdss_mdp_video_ctx *ctx;
 	unsigned long flags;
+	int need_update;
 
 	ctx = (struct mdss_mdp_video_ctx *) ctl->priv_data;
 	if (!ctx) {
@@ -205,14 +209,18 @@
 	}
 
 	spin_lock_irqsave(&ctx->vsync_lock, flags);
-	if (!ctx->vsync_handler && vsync_handler)
-		video_vsync_irq_enable(ctl);
-	else if (ctx->vsync_handler && !vsync_handler)
-		video_vsync_irq_disable(ctl);
-
+	need_update = (!ctx->vsync_handler && vsync_handler) ||
+			(ctx->vsync_handler && !vsync_handler);
 	ctx->vsync_handler = vsync_handler;
 	spin_unlock_irqrestore(&ctx->vsync_lock, flags);
 
+	if (need_update) {
+		if (vsync_handler)
+			video_vsync_irq_enable(ctl);
+		else
+			video_vsync_irq_disable(ctl);
+	}
+
 	return 0;
 }
 
@@ -335,8 +343,8 @@
 
 	if (!ctx->wait_pending) {
 		ctx->wait_pending++;
-		INIT_COMPLETION(ctx->vsync_comp);
 		video_vsync_irq_enable(ctl);
+		INIT_COMPLETION(ctx->vsync_comp);
 	} else {
 		WARN(1, "commit without wait! ctl=%d", ctl->num);
 	}
@@ -373,6 +381,7 @@
 	struct mdss_mdp_video_ctx *ctx;
 	struct mdss_mdp_mixer *mixer;
 	struct intf_timing_params itp = {0};
+	u32 dst_bpp;
 	int i;
 
 	mdata = ctl->mdata;
@@ -411,19 +420,27 @@
 	mdss_mdp_set_intr_callback(MDSS_MDP_IRQ_INTF_UNDER_RUN, ctl->intf_num,
 				   mdss_mdp_video_underrun_intr_done, ctl);
 
-	itp.width = pinfo->xres + pinfo->lcdc.xres_pad;
+	dst_bpp = pinfo->fbc.enabled ? (pinfo->fbc.target_bpp) : (pinfo->bpp);
+
+	itp.width = mult_frac((pinfo->xres + pinfo->lcdc.xres_pad),
+				dst_bpp, pinfo->bpp);
 	itp.height = pinfo->yres + pinfo->lcdc.yres_pad;
 	itp.border_clr = pinfo->lcdc.border_clr;
 	itp.underflow_clr = pinfo->lcdc.underflow_clr;
 	itp.hsync_skew = pinfo->lcdc.hsync_skew;
 
-	itp.xres =  pinfo->xres;
+	itp.xres =  mult_frac(pinfo->xres, dst_bpp, pinfo->bpp);
 	itp.yres = pinfo->yres;
-	itp.h_back_porch =  pinfo->lcdc.h_back_porch;
-	itp.h_front_porch =  pinfo->lcdc.h_front_porch;
-	itp.v_back_porch =  pinfo->lcdc.v_back_porch;
-	itp.v_front_porch = pinfo->lcdc.v_front_porch;
-	itp.hsync_pulse_width = pinfo->lcdc.h_pulse_width;
+	itp.h_back_porch =  mult_frac(pinfo->lcdc.h_back_porch, dst_bpp,
+			pinfo->bpp);
+	itp.h_front_porch = mult_frac(pinfo->lcdc.h_front_porch, dst_bpp,
+			pinfo->bpp);
+	itp.v_back_porch =  mult_frac(pinfo->lcdc.v_back_porch, dst_bpp,
+			pinfo->bpp);
+	itp.v_front_porch = mult_frac(pinfo->lcdc.v_front_porch, dst_bpp,
+			pinfo->bpp);
+	itp.hsync_pulse_width = mult_frac(pinfo->lcdc.h_pulse_width, dst_bpp,
+			pinfo->bpp);
 	itp.vsync_pulse_width = pinfo->lcdc.v_pulse_width;
 
 	if (mdss_mdp_video_timegen_setup(ctx, &itp)) {
diff --git a/drivers/video/msm/mdss/mdss_mdp_pp.c b/drivers/video/msm/mdss/mdss_mdp_pp.c
index 75fb7d6..2c0d5e0 100644
--- a/drivers/video/msm/mdss/mdss_mdp_pp.c
+++ b/drivers/video/msm/mdss/mdss_mdp_pp.c
@@ -524,7 +524,7 @@
 	struct mdss_data_type *mdata;
 
 	mdata = mdss_mdp_get_mdata();
-	if (mdata->mdp_rev >= MDSS_MDP_HW_REV_102)
+	if (mdata->mdp_rev >= MDSS_MDP_HW_REV_102 && pipe->src_fmt->is_yuv)
 		filter_mode = MDSS_MDP_SCALE_FILTER_CA;
 	else
 		filter_mode = MDSS_MDP_SCALE_FILTER_BIL;
diff --git a/drivers/video/msm/mdss/mdss_panel.h b/drivers/video/msm/mdss/mdss_panel.h
index 23f7445..d230100 100644
--- a/drivers/video/msm/mdss/mdss_panel.h
+++ b/drivers/video/msm/mdss/mdss_panel.h
@@ -157,6 +157,26 @@
 	char channel_swap;
 };
 
+struct fbc_panel_info {
+	u32 enabled;
+	u32 target_bpp;
+	u32 comp_mode;
+	u32 qerr_enable;
+	u32 cd_bias;
+	u32 pat_enable;
+	u32 vlc_enable;
+	u32 bflc_enable;
+
+	u32 line_x_budget;
+	u32 block_x_budget;
+	u32 block_budget;
+
+	u32 lossless_mode_thd;
+	u32 lossy_mode_thd;
+	u32 lossy_rgb_thd;
+	u32 lossy_mode_idx;
+};
+
 struct mdss_panel_info {
 	u32 xres;
 	u32 yres;
@@ -184,6 +204,7 @@
 	u32 panel_power_on;
 
 	struct lcd_panel_info lcdc;
+	struct fbc_panel_info fbc;
 	struct mipi_panel_info mipi;
 	struct lvds_panel_info lvds;
 };
diff --git a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl.h b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl.h
index 69120e8..b6dc085 100644
--- a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl.h
+++ b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl.h
@@ -14,7 +14,6 @@
 #ifndef _VCD_DDL_H_
 #define _VCD_DDL_H_
 
-#include <mach/msm_subsystem_map.h>
 #include "vcd_ddl_api.h"
 #include "vcd_ddl_core.h"
 #include "vcd_ddl_utils.h"
diff --git a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_utils.c b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_utils.c
index 61099b0..54b256d 100644
--- a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_utils.c
+++ b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_utils.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2010-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -12,7 +12,7 @@
  */
 #include <linux/memory_alloc.h>
 #include <linux/delay.h>
-#include <mach/msm_subsystem_map.h>
+#include <mach/iommu_domains.h>
 #include <mach/subsystem_restart.h>
 #include "vcd_ddl_utils.h"
 #include "vcd_ddl.h"
@@ -25,8 +25,6 @@
 };
 static struct time_data proc_time[MAX_TIME_DATA];
 #define DDL_MSG_TIME(x...) printk(KERN_DEBUG x)
-static unsigned int vidc_mmu_subsystem[] =	{
-		MSM_SUBSYSTEM_VIDEO, MSM_SUBSYSTEM_VIDEO_FWARE};
 
 #ifdef DDL_BUF_LOG
 static void ddl_print_buffer(struct ddl_context *ddl_context,
@@ -39,13 +37,10 @@
 void *ddl_pmem_alloc(struct ddl_buf_addr *addr, size_t sz, u32 alignment)
 {
 	u32 alloc_size, offset = 0 ;
-	u32 index = 0;
 	struct ddl_context *ddl_context;
-	struct msm_mapped_buffer *mapped_buffer = NULL;
 	unsigned long iova = 0;
 	unsigned long buffer_size = 0;
 	unsigned long *kernel_vaddr = NULL;
-	unsigned long flags = 0;
 	int ret = 0;
 	ion_phys_addr_t phyaddr = 0;
 	size_t len = 0;
@@ -128,51 +123,10 @@
 		addr->align_virtual_addr = addr->virtual_base_addr + offset;
 		addr->buffer_size = alloc_size;
 	} else {
-		addr->alloced_phys_addr = (phys_addr_t)
-		allocate_contiguous_memory_nomap(alloc_size,
-			res_trk_get_mem_type(), SZ_4K);
-		if (!addr->alloced_phys_addr) {
-			DDL_MSG_ERROR("%s() : acm alloc failed (%d)\n",
-					 __func__, alloc_size);
-			goto bail_out;
-		}
-		flags = MSM_SUBSYSTEM_MAP_IOVA | MSM_SUBSYSTEM_MAP_KADDR;
-		if (alignment == DDL_KILO_BYTE(128))
-				index = 1;
-		else if (alignment > SZ_4K)
-			flags |= MSM_SUBSYSTEM_ALIGN_IOVA_8K;
-
-		addr->mapped_buffer =
-		msm_subsystem_map_buffer((unsigned long)addr->alloced_phys_addr,
-			alloc_size, flags, &vidc_mmu_subsystem[index],
-			sizeof(vidc_mmu_subsystem[index])/sizeof(unsigned int));
-		if (IS_ERR(addr->mapped_buffer)) {
-			pr_err(" %s() buffer map failed", __func__);
-			goto free_acm_alloc;
-		}
-		mapped_buffer = addr->mapped_buffer;
-		if (!mapped_buffer->vaddr || !mapped_buffer->iova[0]) {
-			pr_err("%s() map buffers failed\n", __func__);
-			goto free_map_buffers;
-		}
-		addr->physical_base_addr = (u8 *)mapped_buffer->iova[0];
-		addr->virtual_base_addr = mapped_buffer->vaddr;
-		addr->align_physical_addr = (u8 *) DDL_ALIGN((u32)
-			addr->physical_base_addr, alignment);
-		offset = (u32)(addr->align_physical_addr -
-				addr->physical_base_addr);
-		addr->align_virtual_addr = addr->virtual_base_addr + offset;
-		addr->buffer_size = sz;
+		pr_err("ION must be enabled.");
+		goto bail_out;
 	}
 	return addr->virtual_base_addr;
-free_map_buffers:
-	msm_subsystem_unmap_buffer(addr->mapped_buffer);
-	addr->mapped_buffer = NULL;
-free_acm_alloc:
-		free_contiguous_memory_by_paddr(
-			(unsigned long)addr->alloced_phys_addr);
-		addr->alloced_phys_addr = (phys_addr_t)NULL;
-		return NULL;
 unmap_ion_alloc:
 	ion_unmap_kernel(ddl_context->video_ion_client,
 		addr->alloc_handle);
@@ -207,12 +161,6 @@
 			ion_free(ddl_context->video_ion_client,
 				addr->alloc_handle);
 			}
-	} else {
-		if (addr->mapped_buffer)
-			msm_subsystem_unmap_buffer(addr->mapped_buffer);
-		if (addr->alloced_phys_addr)
-			free_contiguous_memory_by_paddr(
-				(unsigned long)addr->alloced_phys_addr);
 	}
 	memset(addr, 0, sizeof(struct ddl_buf_addr));
 }
diff --git a/drivers/video/msm/vidc/1080p/resource_tracker/vcd_res_tracker.c b/drivers/video/msm/vidc/1080p/resource_tracker/vcd_res_tracker.c
index c15218d..5c15d9a 100644
--- a/drivers/video/msm/vidc/1080p/resource_tracker/vcd_res_tracker.c
+++ b/drivers/video/msm/vidc/1080p/resource_tracker/vcd_res_tracker.c
@@ -18,6 +18,7 @@
 #include <linux/pm_runtime.h>
 #include <mach/clk.h>
 #include <mach/msm_memtypes.h>
+#include <mach/iommu_domains.h>
 #include <linux/interrupt.h>
 #include <linux/memory_alloc.h>
 #include <asm/sizes.h>
@@ -30,8 +31,6 @@
 static unsigned int vidc_clk_table[5] = {
 	48000000, 133330000, 200000000, 228570000, 266670000,
 };
-static unsigned int restrk_mmu_subsystem[] =	{
-		MSM_SUBSYSTEM_VIDEO, MSM_SUBSYSTEM_VIDEO_FWARE};
 static struct res_trk_context resource_context;
 
 #define VIDC_FW	"vidc_1080p.fw"
@@ -56,10 +55,8 @@
 static void *res_trk_pmem_map
 	(struct ddl_buf_addr *addr, size_t sz, u32 alignment)
 {
-	u32 offset = 0, flags = 0;
-	u32 index = 0;
+	u32 offset = 0;
 	struct ddl_context *ddl_context;
-	struct msm_mapped_buffer *mapped_buffer = NULL;
 	int ret = 0;
 	unsigned long iova = 0;
 	unsigned long buffer_size  = 0;
@@ -100,53 +97,11 @@
 		addr->align_virtual_addr = addr->virtual_base_addr + offset;
 		addr->buffer_size = buffer_size;
 	} else {
-		if (!res_trk_check_for_sec_session()) {
-			if (!addr->alloced_phys_addr) {
-				pr_err(" %s() alloced addres NULL", __func__);
-				goto bail_out;
-			}
-			flags = MSM_SUBSYSTEM_MAP_IOVA |
-				MSM_SUBSYSTEM_MAP_KADDR;
-			if (alignment == DDL_KILO_BYTE(128))
-					index = 1;
-			else if (alignment > SZ_4K)
-				flags |= MSM_SUBSYSTEM_ALIGN_IOVA_8K;
-			addr->mapped_buffer =
-			msm_subsystem_map_buffer(
-			(unsigned long)addr->alloced_phys_addr,
-			sz, flags, &restrk_mmu_subsystem[index],
-			sizeof(restrk_mmu_subsystem[index])/
-				sizeof(unsigned int));
-			if (IS_ERR(addr->mapped_buffer)) {
-				pr_err(" %s() buffer map failed", __func__);
-				goto bail_out;
-			}
-			mapped_buffer = addr->mapped_buffer;
-			if (!mapped_buffer->vaddr || !mapped_buffer->iova[0]) {
-				pr_err("%s() map buffers failed\n", __func__);
-				goto bail_out;
-			}
-			addr->physical_base_addr =
-				 (u8 *)mapped_buffer->iova[0];
-			addr->virtual_base_addr =
-					mapped_buffer->vaddr;
-		} else {
-			addr->physical_base_addr =
-				(u8 *) addr->alloced_phys_addr;
-			addr->virtual_base_addr =
-				(u8 *)addr->alloced_phys_addr;
-		}
-		addr->align_physical_addr = (u8 *) DDL_ALIGN((u32)
-		addr->physical_base_addr, alignment);
-		offset = (u32)(addr->align_physical_addr -
-				addr->physical_base_addr);
-		addr->align_virtual_addr = addr->virtual_base_addr + offset;
-		addr->buffer_size = sz;
+		pr_err("ION must be enabled.");
+		goto bail_out;
 	}
 	return addr->virtual_base_addr;
 bail_out:
-	if (IS_ERR(addr->mapped_buffer))
-		msm_subsystem_unmap_buffer(addr->mapped_buffer);
 	return NULL;
 ion_unmap_bail_out:
 	if (!IS_ERR_OR_NULL(addr->alloc_handle)) {
@@ -171,12 +126,6 @@
 			 addr->alloc_handle);
 			addr->alloc_handle = NULL;
 		}
-	} else {
-		if (addr->mapped_buffer)
-			msm_subsystem_unmap_buffer(addr->mapped_buffer);
-		if (addr->alloced_phys_addr)
-			free_contiguous_memory_by_paddr(
-			(unsigned long)addr->alloced_phys_addr);
 	}
 	memset(addr, 0 , sizeof(struct ddl_buf_addr));
 }
@@ -263,8 +212,7 @@
 			addr->virtual_base_addr = NULL;
 			addr->physical_base_addr = NULL;
 		}
-	} else if (addr->mapped_buffer)
-		msm_subsystem_unmap_buffer(addr->mapped_buffer);
+	}
 	addr->mapped_buffer = NULL;
 }
 
diff --git a/drivers/video/msm/vidc/720p/ddl/vcd_ddl.h b/drivers/video/msm/vidc/720p/ddl/vcd_ddl.h
index 7a79a40..383a91b 100644
--- a/drivers/video/msm/vidc/720p/ddl/vcd_ddl.h
+++ b/drivers/video/msm/vidc/720p/ddl/vcd_ddl.h
@@ -12,7 +12,6 @@
  */
 #ifndef _VCD_DDL_H_
 #define _VCD_DDL_H_
-#include <mach/msm_subsystem_map.h>
 #include "vcd_ddl_api.h"
 #include "vcd_ddl_utils.h"
 #include "vcd_ddl_firmware.h"
diff --git a/drivers/video/msm/vidc/720p/ddl/vcd_ddl_utils.c b/drivers/video/msm/vidc/720p/ddl/vcd_ddl_utils.c
index 672c049..edc8112 100644
--- a/drivers/video/msm/vidc/720p/ddl/vcd_ddl_utils.c
+++ b/drivers/video/msm/vidc/720p/ddl/vcd_ddl_utils.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2010-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -87,11 +87,9 @@
 void ddl_pmem_alloc(struct ddl_buf_addr *buff_addr, size_t sz, u32 align)
 {
 	u32 guard_bytes, align_mask;
-	u32 physical_addr;
 	u32 align_offset;
-	u32 alloc_size, flags = 0;
+	u32 alloc_size;
 	struct ddl_context *ddl_context;
-	struct msm_mapped_buffer *mapped_buffer = NULL;
 	unsigned long *kernel_vaddr = NULL;
 	ion_phys_addr_t phyaddr = 0;
 	size_t len = 0;
@@ -155,36 +153,8 @@
 			(u32)buff_addr->virtual_base_addr,
 			alloc_size, align, len);
 	} else {
-		physical_addr = (u32)
-			allocate_contiguous_memory_nomap(alloc_size,
-						ddl_context->memtype, SZ_4K);
-		if (!physical_addr) {
-			ERR("\n%s(): DDL pmem allocate failed\n",
-			       __func__);
-			goto bailout;
-		}
-		buff_addr->physical_base_addr = (u32 *) physical_addr;
-		flags = MSM_SUBSYSTEM_MAP_KADDR;
-		buff_addr->mapped_buffer =
-		msm_subsystem_map_buffer((unsigned long)physical_addr,
-		alloc_size, flags, NULL, 0);
-		if (IS_ERR(buff_addr->mapped_buffer)) {
-			ERR("\n%s() buffer map failed\n", __func__);
-			goto free_pmem_buffer;
-		}
-		mapped_buffer = buff_addr->mapped_buffer;
-		if (!mapped_buffer->vaddr) {
-			ERR("\n%s() mapped virtual address is NULL\n",
-				__func__);
-			goto unmap_pmem_buffer;
-		}
-		buff_addr->virtual_base_addr = mapped_buffer->vaddr;
-		DBG("ddl_pmem_alloc: mem_type(0x%x), phys(0x%x),"\
-			" virt(0x%x), sz(%u), align(%u)",
-			(u32)buff_addr->mem_type,
-			(u32)buff_addr->physical_base_addr,
-			(u32)buff_addr->virtual_base_addr,
-			alloc_size, SZ_4K);
+		pr_err("ION must be enabled.");
+		goto bailout;
 	}
 
 	memset(buff_addr->virtual_base_addr, 0 , sz + guard_bytes);
@@ -205,16 +175,6 @@
 		(u32)buff_addr->align_virtual_addr);
 	return;
 
-unmap_pmem_buffer:
-	if (buff_addr->mapped_buffer)
-		msm_subsystem_unmap_buffer(buff_addr->mapped_buffer);
-free_pmem_buffer:
-	if (buff_addr->physical_base_addr)
-		free_contiguous_memory_by_paddr((unsigned long)
-			buff_addr->physical_base_addr);
-	memset(buff_addr, 0, sizeof(struct ddl_buf_addr));
-	return;
-
 unmap_ion_buffer:
 	if (ddl_context->video_ion_client) {
 		if (buff_addr->alloc_handle)
@@ -253,13 +213,6 @@
 			ion_free(ddl_context->video_ion_client,
 				buff_addr->alloc_handle);
 		}
-	} else {
-		if (buff_addr->mapped_buffer)
-			msm_subsystem_unmap_buffer(
-				buff_addr->mapped_buffer);
-		if (buff_addr->physical_base_addr)
-			free_contiguous_memory_by_paddr((unsigned long)
-				buff_addr->physical_base_addr);
 	}
 	memset(buff_addr, 0, sizeof(struct ddl_buf_addr));
 }
diff --git a/drivers/video/msm/vidc/common/dec/vdec.c b/drivers/video/msm/vidc/common/dec/vdec.c
index 1c69d8f..ec27b00 100644
--- a/drivers/video/msm/vidc/common/dec/vdec.c
+++ b/drivers/video/msm/vidc/common/dec/vdec.c
@@ -28,10 +28,10 @@
 
 #include <linux/clk.h>
 #include <linux/timer.h>
-#include <mach/msm_subsystem_map.h>
 #include <media/msm/vidc_type.h>
 #include <media/msm/vcd_api.h>
 #include <media/msm/vidc_init.h>
+#include <mach/iommu_domains.h>
 #include "vcd_res_tracker_api.h"
 #include "vdec_internal.h"
 
@@ -1241,13 +1241,6 @@
 
 	if (!client_ctx)
 		return false;
-	if (client_ctx->vcd_meta_buffer.client_data)
-		msm_subsystem_unmap_buffer((struct msm_mapped_buffer *)
-		client_ctx->vcd_meta_buffer.client_data);
-
-	if (client_ctx->vcd_meta_buffer.client_data_iommu)
-		msm_subsystem_unmap_buffer((struct msm_mapped_buffer *)
-		client_ctx->vcd_meta_buffer.client_data_iommu);
 
 	vcd_property_hdr.prop_id = VCD_I_FREE_EXT_METABUFFER;
 	vcd_property_hdr.sz = sizeof(struct vcd_property_buffer_size);
@@ -1300,9 +1293,6 @@
 
 	if (!client_ctx)
 		return false;
-	if (client_ctx->vcd_h264_mv_buffer.client_data)
-		msm_subsystem_unmap_buffer((struct msm_mapped_buffer *)
-		client_ctx->vcd_h264_mv_buffer.client_data);
 
 	vcd_property_hdr.prop_id = VCD_I_FREE_H264_MV_BUFFER;
 	vcd_property_hdr.sz = sizeof(struct vcd_property_buffer_size);
diff --git a/drivers/video/msm/vidc/common/enc/venc_internal.c b/drivers/video/msm/vidc/common/enc/venc_internal.c
index 3dae4be1..06b690d 100644
--- a/drivers/video/msm/vidc/common/enc/venc_internal.c
+++ b/drivers/video/msm/vidc/common/enc/venc_internal.c
@@ -27,10 +27,10 @@
 #include <linux/workqueue.h>
 
 #include <linux/clk.h>
-#include <mach/msm_subsystem_map.h>
 #include <media/msm/vidc_type.h>
 #include <media/msm/vcd_api.h>
 #include <media/msm/vidc_init.h>
+#include <mach/iommu_domains.h>
 #include "vcd_res_tracker_api.h"
 #include "venc_internal.h"
 
@@ -1948,9 +1948,6 @@
 			venc_recon->pbuffer);
 		return false;
 	}
-	if (control->client_data)
-		msm_subsystem_unmap_buffer((struct msm_mapped_buffer *)
-		control->client_data);
 
 	vcd_property_hdr.prop_id = VCD_I_FREE_RECON_BUFFERS;
 	vcd_property_hdr.sz = sizeof(struct vcd_property_buffer_size);
diff --git a/drivers/video/msm/vidc/common/init/vidc_init.c b/drivers/video/msm/vidc/common/init/vidc_init.c
index 72a1d5f..cf01622 100644
--- a/drivers/video/msm/vidc/common/init/vidc_init.c
+++ b/drivers/video/msm/vidc/common/init/vidc_init.c
@@ -30,7 +30,7 @@
 #include <linux/debugfs.h>
 #include <mach/clk.h>
 #include <linux/pm_runtime.h>
-#include <mach/msm_subsystem_map.h>
+#include <mach/iommu_domains.h>
 #include <media/msm/vcd_api.h>
 #include <media/msm/vidc_init.h>
 #include "vidc_init_internal.h"
@@ -420,12 +420,6 @@
 	if (!client_ctx->user_ion_client)
 		goto bail_out_cleanup;
 	for (i = 0; i < *num_of_buffers; ++i) {
-		if (buf_addr_table[i].client_data) {
-			msm_subsystem_unmap_buffer(
-			(struct msm_mapped_buffer *)
-			buf_addr_table[i].client_data);
-			buf_addr_table[i].client_data = NULL;
-		}
 		if (!IS_ERR_OR_NULL(buf_addr_table[i].buff_ion_handle)) {
 			if (!IS_ERR_OR_NULL(client_ctx->user_ion_client)) {
 				ion_unmap_kernel(client_ctx->user_ion_client,
@@ -448,11 +442,6 @@
 			}
 		}
 	}
-	if (client_ctx->vcd_h264_mv_buffer.client_data) {
-		msm_subsystem_unmap_buffer((struct msm_mapped_buffer *)
-		client_ctx->vcd_h264_mv_buffer.client_data);
-		client_ctx->vcd_h264_mv_buffer.client_data = NULL;
-	}
 	if (!IS_ERR_OR_NULL(client_ctx->h264_mv_ion_handle)) {
 		if (!IS_ERR_OR_NULL(client_ctx->user_ion_client)) {
 			ion_unmap_kernel(client_ctx->user_ion_client,
@@ -608,7 +597,7 @@
 	} else {
 		if (!vcd_get_ion_status()) {
 			pr_err("PMEM not available\n");
-			return false;
+			goto bail_out_add;
 		} else {
 			buff_ion_handle = ion_import_dma_buf(
 				client_ctx->user_ion_client, pmem_fd);
@@ -808,11 +797,6 @@
 			__func__, client_ctx, user_vaddr);
 		goto bail_out_del;
 	}
-	if (buf_addr_table[i].client_data) {
-		msm_subsystem_unmap_buffer(
-		(struct msm_mapped_buffer *)buf_addr_table[i].client_data);
-		buf_addr_table[i].client_data = NULL;
-	}
 	*kernel_vaddr = buf_addr_table[i].kernel_vaddr;
 	if (buf_addr_table[i].buff_ion_handle) {
 		ion_unmap_kernel(client_ctx->user_ion_client,
diff --git a/drivers/video/msm/vidc/common/vcd/vcd_sub.c b/drivers/video/msm/vidc/common/vcd/vcd_sub.c
index 09cd91d..f7424ed 100644
--- a/drivers/video/msm/vidc/common/vcd/vcd_sub.c
+++ b/drivers/video/msm/vidc/common/vcd/vcd_sub.c
@@ -11,9 +11,9 @@
  *
  */
 #include <linux/memory_alloc.h>
-#include <mach/msm_subsystem_map.h>
 #include <asm/div64.h>
 #include <media/msm/vidc_type.h>
+#include <mach/iommu_domains.h>
 #include "vcd.h"
 #include "vdec_internal.h"
 
@@ -24,19 +24,17 @@
 
 struct vcd_msm_map_buffer {
 	phys_addr_t phy_addr;
-	struct msm_mapped_buffer *mapped_buffer;
+	void *vaddr;
 	struct ion_handle *alloc_handle;
 	u32 in_use;
 };
 static struct vcd_msm_map_buffer msm_mapped_buffer_table[MAP_TABLE_SZ];
-static unsigned int vidc_mmu_subsystem[] = {MSM_SUBSYSTEM_VIDEO};
 
 static int vcd_pmem_alloc(size_t sz, u8 **kernel_vaddr, u8 **phy_addr,
 			 struct vcd_clnt_ctxt *cctxt)
 {
-	u32 memtype, i = 0, flags = 0;
+	u32 memtype, i = 0;
 	struct vcd_msm_map_buffer *map_buffer = NULL;
-	struct msm_mapped_buffer *mapped_buffer = NULL;
 	unsigned long iova = 0;
 	unsigned long buffer_size = 0;
 	int ret = 0;
@@ -64,31 +62,8 @@
 	res_trk_set_mem_type(DDL_MM_MEM);
 	memtype = res_trk_get_mem_type();
 	if (!cctxt->vcd_enable_ion) {
-		map_buffer->phy_addr = (phys_addr_t)
-		allocate_contiguous_memory_nomap(sz, memtype, SZ_4K);
-		if (!map_buffer->phy_addr) {
-			pr_err("%s() acm alloc failed", __func__);
-			goto free_map_table;
-		}
-		flags = MSM_SUBSYSTEM_MAP_IOVA | MSM_SUBSYSTEM_MAP_KADDR;
-		map_buffer->mapped_buffer =
-		msm_subsystem_map_buffer((unsigned long)map_buffer->phy_addr,
-		sz, flags, vidc_mmu_subsystem,
-		sizeof(vidc_mmu_subsystem)/sizeof(unsigned int));
-		if (IS_ERR(map_buffer->mapped_buffer)) {
-			pr_err(" %s() buffer map failed", __func__);
-			goto free_acm_alloc;
-		}
-		mapped_buffer = map_buffer->mapped_buffer;
-		if (!mapped_buffer->vaddr || !mapped_buffer->iova[0]) {
-			pr_err("%s() map buffers failed", __func__);
-			goto free_map_buffers;
-		}
-		*phy_addr = (u8 *) mapped_buffer->iova[0];
-		*kernel_vaddr = (u8 *) mapped_buffer->vaddr;
-		VCD_MSG_LOW("vcd_pmem_alloc: phys(0x%x), virt(0x%x), "\
-			"sz(%u), flags(0x%x)", (u32)*phy_addr,
-			(u32)*kernel_vaddr, sz, (u32)flags);
+		pr_err("ION must be enabled\n");
+		goto free_map_table;
 	} else {
 		map_buffer->alloc_handle = ion_alloc(
 			    cctxt->vcd_ion_client, sz, SZ_4K,
@@ -106,6 +81,7 @@
 		*kernel_vaddr = (u8 *) ion_map_kernel(
 				cctxt->vcd_ion_client,
 				map_buffer->alloc_handle);
+		map_buffer->vaddr = *kernel_vaddr;
 		if (!(*kernel_vaddr)) {
 			pr_err("%s() ION map failed", __func__);
 			goto ion_free_bailout;
@@ -143,8 +119,6 @@
 			goto free_map_table;
 		}
 		*phy_addr = (u8 *)map_buffer->phy_addr;
-		mapped_buffer = NULL;
-		map_buffer->mapped_buffer = NULL;
 		VCD_MSG_LOW("vcd_ion_alloc: phys(0x%x), virt(0x%x), "\
 			"sz(%u), ionflags(0x%x)", (u32)*phy_addr,
 			(u32)*kernel_vaddr, sz, (u32)ionflag);
@@ -152,15 +126,6 @@
 
 	return 0;
 
-free_map_buffers:
-	if (map_buffer->mapped_buffer)
-		msm_subsystem_unmap_buffer(map_buffer->mapped_buffer);
-free_acm_alloc:
-	if (!cctxt->vcd_enable_ion) {
-		free_contiguous_memory_by_paddr(
-		(unsigned long)map_buffer->phy_addr);
-	}
-	return -ENOMEM;
 ion_map_bailout:
 	ion_unmap_kernel(cctxt->vcd_ion_client, map_buffer->alloc_handle);
 ion_free_bailout:
@@ -183,8 +148,7 @@
 	}
 	for (i = 0; i  < MAP_TABLE_SZ; i++) {
 		if (msm_mapped_buffer_table[i].in_use &&
-			(msm_mapped_buffer_table[i]
-			.mapped_buffer->vaddr == kernel_vaddr)) {
+			(msm_mapped_buffer_table[i].vaddr == kernel_vaddr)) {
 			map_buffer = &msm_mapped_buffer_table[i];
 			map_buffer->in_use = 0;
 			break;
@@ -194,8 +158,6 @@
 		pr_err("%s() Entry not found", __func__);
 		goto bailout;
 	}
-	if (map_buffer->mapped_buffer)
-		msm_subsystem_unmap_buffer(map_buffer->mapped_buffer);
 	if (cctxt->vcd_enable_ion) {
 		VCD_MSG_LOW("vcd_ion_free: phys(0x%x), virt(0x%x)",
 			(u32)phy_addr, (u32)kernel_vaddr);
diff --git a/fs/jbd2/transaction.c b/fs/jbd2/transaction.c
index ddcd354..de8b4cb 100644
--- a/fs/jbd2/transaction.c
+++ b/fs/jbd2/transaction.c
@@ -209,7 +209,8 @@
 		if (!new_transaction)
 			goto alloc_transaction;
 		write_lock(&journal->j_state_lock);
-		if (!journal->j_running_transaction) {
+		if (!journal->j_running_transaction &&
+		    !journal->j_barrier_count) {
 			jbd2_get_transaction(journal, new_transaction);
 			new_transaction = NULL;
 		}
diff --git a/include/linux/input/synaptics_dsx.h b/include/linux/input/synaptics_dsx.h
index 56616d7..f90f59e 100644
--- a/include/linux/input/synaptics_dsx.h
+++ b/include/linux/input/synaptics_dsx.h
@@ -55,6 +55,7 @@
 	unsigned reset_gpio;
 	unsigned panel_x;
 	unsigned panel_y;
+	const char *fw_image_name;
 	int (*gpio_config)(unsigned gpio, bool configure);
 	struct synaptics_rmi4_capacitance_button_map *capacitance_button_map;
 };
diff --git a/include/linux/ion.h b/include/linux/ion.h
index 7c54004..67b5e6c 100644
--- a/include/linux/ion.h
+++ b/include/linux/ion.h
@@ -33,14 +33,12 @@
  * @ION_HEAP_TYPE_CP:	 memory allocated from a prereserved
  *				carveout heap, allocations are physically
  *				contiguous. Used for content protection.
- * @ION_HEAP_TYPE_DMA:          memory allocated via DMA API
  * @ION_HEAP_END:		helper for iterating over heaps
  */
 enum ion_heap_type {
 	ION_HEAP_TYPE_SYSTEM,
 	ION_HEAP_TYPE_SYSTEM_CONTIG,
 	ION_HEAP_TYPE_CARVEOUT,
-	ION_HEAP_TYPE_DMA,
 	ION_HEAP_TYPE_CUSTOM, /* must be last so device specific heaps always
 				 are at the end of this enum */
 	ION_NUM_HEAPS,
@@ -49,7 +47,6 @@
 #define ION_HEAP_SYSTEM_MASK		(1 << ION_HEAP_TYPE_SYSTEM)
 #define ION_HEAP_SYSTEM_CONTIG_MASK	(1 << ION_HEAP_TYPE_SYSTEM_CONTIG)
 #define ION_HEAP_CARVEOUT_MASK		(1 << ION_HEAP_TYPE_CARVEOUT)
-#define ION_HEAP_TYPE_DMA_MASK         (1 << ION_HEAP_TYPE_DMA)
 
 /**
  * heap flags - the lower 16 bits are used by core ion, the upper 16
diff --git a/include/linux/mfd/pm8xxx/ccadc.h b/include/linux/mfd/pm8xxx/ccadc.h
index 955e286..a29486f 100644
--- a/include/linux/mfd/pm8xxx/ccadc.h
+++ b/include/linux/mfd/pm8xxx/ccadc.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2010-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -26,11 +26,15 @@
  * @ccadc_cdata:	core data for the ccadc driver containing channel info
  * @r_sense_uohm:		sense resistor value in (micro Ohms)
  * @calib_delay_ms:	how often should the adc calculate gain and offset
+ * @periodic_wakeup:	a flag to indicate that this system wakeups periodically
+ *			for calibration/other housekeeping activities. The ccadc
+ *			does a quick calibration while resuming
  */
 struct pm8xxx_ccadc_platform_data {
 	struct pm8xxx_ccadc_core_data	ccadc_cdata;
 	int				r_sense_uohm;
 	unsigned int			calib_delay_ms;
+	bool				periodic_wakeup;
 };
 
 #define CCADC_READING_RESOLUTION_N	542535
diff --git a/include/linux/mfd/wcd9xxx/pdata.h b/include/linux/mfd/wcd9xxx/pdata.h
index 392c0ae..813cac3 100644
--- a/include/linux/mfd/wcd9xxx/pdata.h
+++ b/include/linux/mfd/wcd9xxx/pdata.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011-2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2011-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -69,6 +69,21 @@
 #define TABLA_DCYCLE_3839 0xE
 #define TABLA_DCYCLE_4095 0xF
 
+#define TAIKO_MCLK_CLK_12P288MHZ 12288000
+#define TAIKO_MCLK_CLK_9P6HZ 9600000
+
+/* Only valid for 9.6 MHz mclk */
+#define TAIKO_DMIC_SAMPLE_RATE_2P4MHZ 2400000
+#define TAIKO_DMIC_SAMPLE_RATE_3P2MHZ 3200000
+#define TAIKO_DMIC_SAMPLE_RATE_4P8MHZ 4800000
+
+/* Only valid for 12.288 MHz mclk */
+#define TAIKO_DMIC_SAMPLE_RATE_3P072MHZ 3072000
+#define TAIKO_DMIC_SAMPLE_RATE_4P096MHZ 4096000
+#define TAIKO_DMIC_SAMPLE_RATE_6P144MHZ 6144000
+
+#define TAIKO_DMIC_SAMPLE_RATE_UNDEFINED 0
+
 struct wcd9xxx_amic {
 	/*legacy mode, txfe_enable and txfe_buff take 7 input
 	 * each bit represent the channel / TXFE number
@@ -155,6 +170,7 @@
 	struct wcd9xxx_ocp_setting ocp;
 	struct wcd9xxx_regulator regulator[MAX_REGULATOR];
 	u32 mclk_rate;
+	u32 dmic_sample_rate;
 };
 
 #endif
diff --git a/include/linux/mfd/wcd9xxx/wcd9310_registers.h b/include/linux/mfd/wcd9xxx/wcd9310_registers.h
index 46336e2..cec0ce2 100644
--- a/include/linux/mfd/wcd9xxx/wcd9310_registers.h
+++ b/include/linux/mfd/wcd9xxx/wcd9310_registers.h
@@ -1,14 +1,3 @@
-/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- */
 #ifndef TABLA_CODEC_DIGITAL_H
 
 #define TABLA_CODEC_DIGITAL_H
diff --git a/include/linux/mmc/sdhci.h b/include/linux/mmc/sdhci.h
index a5f36b5..407a005 100644
--- a/include/linux/mmc/sdhci.h
+++ b/include/linux/mmc/sdhci.h
@@ -116,6 +116,12 @@
  * required frequency.
  */
 #define SDHCI_QUIRK2_ALWAYS_USE_BASE_CLOCK		(1<<4)
+/*
+ * Dont use the max_discard_to in sdhci driver so that the maximum discard
+ * unit gets picked by the mmc queue. Otherwise, it takes a long time for
+ * secure discard kind of operations to complete.
+ */
+#define SDHCI_QUIRK2_USE_MAX_DISCARD_SIZE		(1<<5)
 
 	int irq;		/* Device IRQ */
 	void __iomem *ioaddr;	/* Mapped address */
diff --git a/include/linux/msm_audio_ion.h b/include/linux/msm_audio_ion.h
new file mode 100644
index 0000000..83e5dff
--- /dev/null
+++ b/include/linux/msm_audio_ion.h
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _LINUX_MSM_AUDIO_ION_H
+#define _LINUX_MSM_AUDIO_ION_H
+
+#include <linux/msm_ion.h>
+
+
+int msm_audio_ion_alloc(const char *name, struct ion_client **client,
+			struct ion_handle **handle, size_t bufsz,
+			ion_phys_addr_t *paddr, size_t *pa_len, void **vaddr);
+
+int msm_audio_ion_import(const char *name, struct ion_client **client,
+			struct ion_handle **handle, int fd,
+			unsigned long *ionflag, size_t bufsz,
+			ion_phys_addr_t *paddr, size_t *pa_len, void **vaddr);
+int msm_audio_ion_free(struct ion_client *client, struct ion_handle *handle);
+
+
+bool msm_audio_ion_is_smmu_available(void);
+
+#ifdef CONFIG_SND_SOC_QDSP6V2
+struct ion_client *msm_audio_ion_client_create(unsigned int heap_mask,
+					const char *name);
+void msm_audio_ion_client_destroy(struct ion_client *client);
+int msm_audio_ion_import_legacy(const char *name, struct ion_client *client,
+			struct ion_handle **handle, int fd,
+			unsigned long *ionflag, size_t bufsz,
+			ion_phys_addr_t *paddr, size_t *pa_len, void **vaddr);
+int msm_audio_ion_free_legacy(struct ion_client *client,
+			struct ion_handle *handle);
+#else
+static struct ion_client *msm_audio_ion_client_create(unsigned int heap_mask,
+					const char *name)
+{ return NULL; }
+static void msm_audio_ion_client_destroy(struct ion_client *client)
+{}
+static int msm_audio_ion_import_legacy(const char *name,
+			struct ion_client *client,
+			struct ion_handle **handle, int fd,
+			unsigned long *ionflag, size_t bufsz,
+			ion_phys_addr_t *paddr, size_t *pa_len, void **vaddr)
+{ return 0; }
+static int msm_audio_ion_free_legacy(struct ion_client *client,
+			struct ion_handle *handle)
+{ return 0; }
+
+#endif /* CONFIG_MSM_QDSP6V2_CODECS */
+#endif /* _LINUX_MSM_AUDIO_ION_H */
+
diff --git a/include/linux/msm_ion.h b/include/linux/msm_ion.h
index 95c4e6a..37c935d 100644
--- a/include/linux/msm_ion.h
+++ b/include/linux/msm_ion.h
@@ -1,18 +1,3 @@
-/*
- *
- * Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- */
-
 #ifndef _LINUX_MSM_ION_H
 #define _LINUX_MSM_ION_H
 
@@ -21,6 +6,7 @@
 enum msm_ion_heap_types {
 	ION_HEAP_TYPE_MSM_START = ION_HEAP_TYPE_CUSTOM + 1,
 	ION_HEAP_TYPE_IOMMU = ION_HEAP_TYPE_MSM_START,
+	ION_HEAP_TYPE_DMA,
 	ION_HEAP_TYPE_CP,
 	ION_HEAP_TYPE_SECURE_DMA,
 };
@@ -71,18 +57,25 @@
 };
 
 #define ION_HEAP_CP_MASK		(1 << ION_HEAP_TYPE_CP)
+#define ION_HEAP_TYPE_DMA_MASK         (1 << ION_HEAP_TYPE_DMA)
 
 /**
  * Flag to use when allocating to indicate that a heap is secure.
  */
-#define ION_SECURE (1 << ION_HEAP_ID_RESERVED)
+#define ION_FLAG_SECURE (1 << ION_HEAP_ID_RESERVED)
 
 /**
  * Flag for clients to force contiguous memort allocation
  *
  * Use of this flag is carefully monitored!
  */
-#define ION_FORCE_CONTIGUOUS (1 << 30)
+#define ION_FLAG_FORCE_CONTIGUOUS (1 << 30)
+
+/**
+* Deprecated! Please use the corresponding ION_FLAG_*
+*/
+#define ION_SECURE ION_FLAG_SECURE
+#define ION_FORCE_CONTIGUOUS ION_FLAG_FORCE_CONTIGUOUS
 
 /**
  * Macro should be used with ion_heap_ids defined above.
diff --git a/include/linux/msm_kgsl.h b/include/linux/msm_kgsl.h
index 307be2b..2ad040e 100644
--- a/include/linux/msm_kgsl.h
+++ b/include/linux/msm_kgsl.h
@@ -21,7 +21,15 @@
 #define KGSL_CONTEXT_PER_CONTEXT_TS	0x00000040
 #define KGSL_CONTEXT_USER_GENERATED_TS	0x00000080
 #define KGSL_CONTEXT_NO_FAULT_TOLERANCE 0x00000200
+/* bits [12:15] are reserved for future use */
+#define KGSL_CONTEXT_TYPE_MASK          0x01F00000
+#define KGSL_CONTEXT_TYPE_SHIFT         20
 
+#define KGSL_CONTEXT_TYPE_ANY		0
+#define KGSL_CONTEXT_TYPE_GL		1
+#define KGSL_CONTEXT_TYPE_CL		2
+#define KGSL_CONTEXT_TYPE_C2D		3
+#define KGSL_CONTEXT_TYPE_RS		4
 
 #define KGSL_CONTEXT_INVALID 0xffffffff
 
diff --git a/include/linux/msm_tsens.h b/include/linux/msm_tsens.h
index 5837094..e40f301 100644
--- a/include/linux/msm_tsens.h
+++ b/include/linux/msm_tsens.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011-2012, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2011-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -41,5 +41,5 @@
 
 int32_t tsens_get_temp(struct tsens_device *dev, unsigned long *temp);
 int msm_tsens_early_init(struct tsens_platform_data *pdata);
-
+int tsens_get_max_sensor_num(uint32_t *tsens_num_sensors);
 #endif /*MSM_TSENS_H */
diff --git a/include/linux/nl80211.h b/include/linux/nl80211.h
index 84e099d..f551e75 100644
--- a/include/linux/nl80211.h
+++ b/include/linux/nl80211.h
@@ -170,6 +170,9 @@
  *	%NL80211_ATTR_CIPHER_GROUP, %NL80211_ATTR_WPA_VERSIONS,
  *	%NL80211_ATTR_AKM_SUITES, %NL80211_ATTR_PRIVACY,
  *	%NL80211_ATTR_AUTH_TYPE and %NL80211_ATTR_INACTIVITY_TIMEOUT.
+ *	%NL80211_ATTR_ACL_POLICY and %NL80211_ATTR_MAC_ADDRS.
+ *	The channel to use can be set on the interface or be given using the
+ *	%NL80211_ATTR_WIPHY_FREQ and the attributes determining channel width.
  * @NL80211_CMD_NEW_BEACON: old alias for %NL80211_CMD_START_AP
  * @NL80211_CMD_STOP_AP: Stop AP operation on the given interface
  * @NL80211_CMD_DEL_BEACON: old alias for %NL80211_CMD_STOP_AP
@@ -554,6 +557,57 @@
  * @NL80211_CMD_SET_NOACK_MAP: sets a bitmap for the individual TIDs whether
  *      No Acknowledgement Policy should be applied.
  *
+ * @NL80211_CMD_CH_SWITCH_NOTIFY: An AP or GO may decide to switch channels
+ *	independently of the userspace SME, send this event indicating
+ *	%NL80211_ATTR_IFINDEX is now on %NL80211_ATTR_WIPHY_FREQ and the
+ *	attributes determining channel width.
+ *
+ * @NL80211_CMD_START_P2P_DEVICE: Start the given P2P Device, identified by
+ *	its %NL80211_ATTR_WDEV identifier. It must have been created with
+ *	%NL80211_CMD_NEW_INTERFACE previously. After it has been started, the
+ *	P2P Device can be used for P2P operations, e.g. remain-on-channel and
+ *	public action frame TX.
+ * @NL80211_CMD_STOP_P2P_DEVICE: Stop the given P2P Device, identified by
+ *	its %NL80211_ATTR_WDEV identifier.
+ *
+ * @NL80211_CMD_CONN_FAILED: connection request to an AP failed; used to
+ *	notify userspace that AP has rejected the connection request from a
+ *	station, due to particular reason. %NL80211_ATTR_CONN_FAILED_REASON
+ *	is used for this.
+ *
+ * @NL80211_CMD_SET_MCAST_RATE: Change the rate used to send multicast frames
+ *	for IBSS or MESH vif.
+ *
+ * @NL80211_CMD_SET_MAC_ACL: sets ACL for MAC address based access control.
+ *	This is to be used with the drivers advertising the support of MAC
+ *	address based access control. List of MAC addresses is passed in
+ *	%NL80211_ATTR_MAC_ADDRS and ACL policy is passed in
+ *	%NL80211_ATTR_ACL_POLICY. Driver will enable ACL with this list, if it
+ *	is not already done. The new list will replace any existing list. Driver
+ *	will clear its ACL when the list of MAC addresses passed is empty. This
+ *	command is used in AP/P2P GO mode. Driver has to make sure to clear its
+ *	ACL list during %NL80211_CMD_STOP_AP.
+ *
+ * @NL80211_CMD_RADAR_DETECT: Start a Channel availability check (CAC). Once
+ *	a radar is detected or the channel availability scan (CAC) has finished
+ *	or was aborted, or a radar was detected, usermode will be notified with
+ *	this event. This command is also used to notify userspace about radars
+ *	while operating on this channel.
+ *	%NL80211_ATTR_RADAR_EVENT is used to inform about the type of the
+ *	event.
+ *
+ * @NL80211_CMD_GET_PROTOCOL_FEATURES: Get global nl80211 protocol features,
+ *	i.e. features for the nl80211 protocol rather than device features.
+ *	Returns the features in the %NL80211_ATTR_PROTOCOL_FEATURES bitmap.
+ *
+ * @NL80211_CMD_UPDATE_FT_IES: Pass down the most up-to-date Fast Transition
+ *	Information Element to the WLAN driver
+ *
+ * @NL80211_CMD_FT_EVENT: Send a Fast transition event from the WLAN driver
+ *	to the supplicant. This will carry the target AP's MAC address along
+ *	with the relevant Information Elements. This event is used to report
+ *	received FT IEs (MDIE, FTIE, RSN IE, TIE, RICIE).
+ *
  * @NL80211_CMD_MAX: highest used command number
  * @__NL80211_CMD_AFTER_LAST: internal use
  */
@@ -695,6 +749,25 @@
 
 	NL80211_CMD_SET_NOACK_MAP,
 
+
+	NL80211_CMD_CH_SWITCH_NOTIFY,
+
+	NL80211_CMD_START_P2P_DEVICE,
+	NL80211_CMD_STOP_P2P_DEVICE,
+
+	NL80211_CMD_CONN_FAILED,
+
+	NL80211_CMD_SET_MCAST_RATE,
+
+	NL80211_CMD_SET_MAC_ACL,
+
+	NL80211_CMD_RADAR_DETECT,
+
+	NL80211_CMD_GET_PROTOCOL_FEATURES,
+
+	NL80211_CMD_UPDATE_FT_IES,
+	NL80211_CMD_FT_EVENT,
+
 	/* add new commands above here */
 
 	/* used to define NL80211_CMD_MAX below */
@@ -1275,6 +1348,18 @@
  *	advertised to the driver, e.g., to enable TDLS off channel operations
  *	and PU-APSD.
  *
+ * @NL80211_ATTR_PROTOCOL_FEATURES: global nl80211 feature flags, see
+ *	&enum nl80211_protocol_features, the attribute is a u32.
+ *
+ * @NL80211_ATTR_SPLIT_WIPHY_DUMP: flag attribute, userspace supports
+ *	receiving the data for a single wiphy split across multiple
+ *	messages, given with wiphy dump message
+ *
+ * @NL80211_ATTR_MDID: Mobility Domain Identifier
+ *
+ * @NL80211_ATTR_IE_RIC: Resource Information Container Information
+ *	Element
+ *
  * @NL80211_ATTR_MAX: highest attribute number currently defined
  * @__NL80211_ATTR_AFTER_LAST: internal use
  */
@@ -1561,6 +1646,15 @@
 	NL80211_ATTR_STA_CAPABILITY,
 	NL80211_ATTR_STA_EXT_CAPABILITY,
 
+	NL80211_ATTR_PROTOCOL_FEATURES,
+	NL80211_ATTR_SPLIT_WIPHY_DUMP,
+
+	NL80211_ATTR_DISABLE_VHT,
+	NL80211_ATTR_VHT_CAPABILITY_MASK,
+
+	NL80211_ATTR_MDID,
+	NL80211_ATTR_IE_RIC,
+
 	/* add attributes here, update the policy in nl80211.c */
 
 	__NL80211_ATTR_AFTER_LAST,
diff --git a/include/linux/qseecom.h b/include/linux/qseecom.h
index b0f089b..c399b81 100644
--- a/include/linux/qseecom.h
+++ b/include/linux/qseecom.h
@@ -6,7 +6,7 @@
 
 #define MAX_ION_FD  4
 #define MAX_APP_NAME_SIZE  32
-
+#define QSEECOM_HASH_SIZE  32
 /*
  * struct qseecom_register_listener_req -
  *      for register listener ioctl request
@@ -117,6 +117,27 @@
 	int app_id; /* out */
 };
 
+struct qseecom_send_svc_cmd_req {
+	uint32_t cmd_id;
+	void *cmd_req_buf; /* in */
+	unsigned int cmd_req_len; /* in */
+	void *resp_buf; /* in/out */
+	unsigned int resp_len; /* in/out */
+};
+
+enum qseecom_key_management_usage_type {
+	QSEOS_KM_USAGE_DISK_ENCRYPTION = 0x01,
+};
+
+struct qseecom_create_key_req {
+	unsigned char hash32[QSEECOM_HASH_SIZE];
+	enum qseecom_key_management_usage_type usage;
+};
+
+struct qseecom_wipe_key_req {
+	enum qseecom_key_management_usage_type usage;
+};
+
 #define QSEECOM_IOC_MAGIC    0x97
 
 
@@ -165,5 +186,14 @@
 #define QSEECOM_IOCTL_APP_LOADED_QUERY_REQ \
 	_IOWR(QSEECOM_IOC_MAGIC, 15, struct qseecom_qseos_app_load_query)
 
+#define QSEECOM_IOCTL_SEND_CMD_SERVICE_REQ \
+	_IOWR(QSEECOM_IOC_MAGIC, 16, struct qseecom_send_svc_cmd_req)
+
+#define QSEECOM_IOCTL_CREATE_KEY_REQ \
+	_IOWR(QSEECOM_IOC_MAGIC, 17, struct qseecom_create_key_req)
+
+#define QSEECOM_IOCTL_WIPE_KEY_REQ \
+	_IOWR(QSEECOM_IOC_MAGIC, 18, struct qseecom_wipe_key_req)
+
 
 #endif /* __QSEECOM_H_ */
diff --git a/include/linux/regulator/cpr-regulator.h b/include/linux/regulator/cpr-regulator.h
index 538ad15..b6fc091 100644
--- a/include/linux/regulator/cpr-regulator.h
+++ b/include/linux/regulator/cpr-regulator.h
@@ -54,6 +54,21 @@
 	NUM_APC_PVS,
 };
 
+/**
+ * enum vdd_mx_vmin_method - Method to determine vmin for vdd-mx
+ * %VDD_MX_VMIN_APC:			Equal to APC voltage
+ * %VDD_MX_VMIN_APC_CORNER_CEILING:	Equal to PVS corner ceiling voltage
+ * %VDD_MX_VMIN_APC_SLOW_CORNER_CEILING:
+ *					Equal to slow speed corner ceiling
+ * %VDD_MX_VMIN_MX_VMAX:		Equal to specified vdd-mx-vmax voltage
+ */
+enum vdd_mx_vmin_method {
+	VDD_MX_VMIN_APC,
+	VDD_MX_VMIN_APC_CORNER_CEILING,
+	VDD_MX_VMIN_APC_SLOW_CORNER_CEILING,
+	VDD_MX_VMIN_MX_VMAX,
+};
+
 #ifdef CONFIG_MSM_CPR_REGULATOR
 
 int __init cpr_regulator_init(void);
diff --git a/include/linux/usb/msm_hsusb.h b/include/linux/usb/msm_hsusb.h
index 79fe16b..c8a20da 100644
--- a/include/linux/usb/msm_hsusb.h
+++ b/include/linux/usb/msm_hsusb.h
@@ -279,6 +279,7 @@
  * @pclk: clock struct of iface_clk.
  * @phy_reset_clk: clock struct of phy_clk.
  * @core_clk: clock struct of core_bus_clk.
+ * @core_clk_rate: core clk max frequency
  * @regs: ioremapped register base address.
  * @inputs: OTG state machine inputs(Id, SessValid etc).
  * @sm_work: OTG state machine work.
@@ -313,6 +314,7 @@
 	struct clk *pclk;
 	struct clk *phy_reset_clk;
 	struct clk *core_clk;
+	long core_clk_rate;
 	void __iomem *regs;
 #define ID		0
 #define B_SESS_VLD	1
@@ -400,6 +402,7 @@
 	unsigned strobe;
 	unsigned data;
 	bool ignore_cal_pad_config;
+	bool phy_sof_workaround;
 	int strobe_pad_offset;
 	int data_pad_offset;
 
diff --git a/include/media/msm/vcd_api.h b/include/media/msm/vcd_api.h
index 944446f..09e1a53 100644
--- a/include/media/msm/vcd_api.h
+++ b/include/media/msm/vcd_api.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2010-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -12,6 +12,7 @@
  */
 #ifndef _VCD_API_H_
 #define _VCD_API_H_
+#include <linux/types.h>
 #include "vcd_property.h"
 #include "vcd_status.h"
 
diff --git a/include/media/msm/vcd_property.h b/include/media/msm/vcd_property.h
index 5fcb049..ce6c479 100644
--- a/include/media/msm/vcd_property.h
+++ b/include/media/msm/vcd_property.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2010-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -13,6 +13,8 @@
 #ifndef _VCD_DRIVER_PROPERTY_H_
 #define _VCD_DRIVER_PROPERTY_H_
 
+#include <linux/types.h>
+
 #define VCD_START_BASE       0x0
 #define VCD_I_LIVE           (VCD_START_BASE + 0x1)
 #define VCD_I_CODEC          (VCD_START_BASE + 0x2)
diff --git a/include/media/msm_cam_sensor.h b/include/media/msm_cam_sensor.h
index 4e1fb31..bce6af3 100644
--- a/include/media/msm_cam_sensor.h
+++ b/include/media/msm_cam_sensor.h
@@ -44,9 +44,12 @@
 #define MOVE_NEAR 0
 #define MOVE_FAR  1
 
+#define MAX_EEPROM_NAME 32
+
 enum msm_camera_i2c_reg_addr_type {
 	MSM_CAMERA_I2C_BYTE_ADDR = 1,
 	MSM_CAMERA_I2C_WORD_ADDR,
+	MSM_CAMERA_I2C_3B_ADDR,
 };
 
 enum msm_camera_i2c_data_type {
@@ -283,6 +286,37 @@
 	} cfg;
 };
 
+enum eeprom_cfg_type_t {
+	CFG_EEPROM_GET_INFO,
+	CFG_EEPROM_GET_DATA,
+	CFG_EEPROM_READ_DATA,
+	CFG_EEPROM_WRITE_DATA,
+};
+struct eeprom_get_t {
+	uint16_t num_bytes;
+};
+
+struct eeprom_read_t {
+	uint8_t *dbuffer;
+	uint16_t num_bytes;
+};
+
+struct eeprom_write_t {
+	uint8_t *dbuffer;
+	uint16_t num_bytes;
+};
+
+struct msm_eeprom_cfg_data {
+	enum eeprom_cfg_type_t cfgtype;
+	uint8_t is_supported;
+	union {
+		char eeprom_name[MAX_SENSOR_NAME];
+		struct eeprom_get_t get_data;
+		struct eeprom_read_t read_data;
+		struct eeprom_write_t write_data;
+	} cfg;
+};
+
 enum msm_sensor_cfg_type_t {
 	CFG_SET_SLAVE_INFO,
 	CFG_WRITE_I2C_ARRAY,
@@ -456,6 +490,9 @@
 #define VIDIOC_MSM_FLASH_LED_DATA_CFG \
 	_IOWR('V', BASE_VIDIOC_PRIVATE + 7, struct msm_camera_led_cfg_t)
 
+#define VIDIOC_MSM_EEPROM_CFG \
+	_IOWR('V', BASE_VIDIOC_PRIVATE + 8, struct msm_eeprom_cfg_data)
+
 #define MSM_V4L2_PIX_FMT_META v4l2_fourcc('M', 'E', 'T', 'A') /* META */
 
 #endif /* __LINUX_MSM_CAM_SENSOR_H */
diff --git a/include/media/msm_camera.h b/include/media/msm_camera.h
index 9c310a9..afd5a42 100644
--- a/include/media/msm_camera.h
+++ b/include/media/msm_camera.h
@@ -1550,6 +1550,7 @@
 enum msm_camera_i2c_reg_addr_type {
 	MSM_CAMERA_I2C_BYTE_ADDR = 1,
 	MSM_CAMERA_I2C_WORD_ADDR,
+	MSM_CAMERA_I2C_3B_ADDR,
 };
 
 struct msm_camera_i2c_reg_array {
diff --git a/include/media/msm_gestures.h b/include/media/msm_gestures.h
index a6efd4f..9388d99 100644
--- a/include/media/msm_gestures.h
+++ b/include/media/msm_gestures.h
@@ -1,15 +1,3 @@
-/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- */
 #ifndef __LINUX_MSM_GESTURES_H
 #define __LINUX_MSM_GESTURES_H
 
diff --git a/include/media/msm_isp.h b/include/media/msm_isp.h
index 77455ca..99f418c 100644
--- a/include/media/msm_isp.h
+++ b/include/media/msm_isp.h
@@ -1,15 +1,3 @@
-/* Copyright (c) 2011-2012, The Linux Foundation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- */
 #ifndef __MSM_ISP_H__
 #define __MSM_ISP_H__
 
diff --git a/include/media/msmb_isp.h b/include/media/msmb_isp.h
index 7f70a01..6fb1a65 100644
--- a/include/media/msmb_isp.h
+++ b/include/media/msmb_isp.h
@@ -109,6 +109,7 @@
 		struct msm_vfe_rdi_cfg rdi_cfg;
 	} d;
 	enum msm_vfe_input_src input_src;
+	uint32_t input_pix_clk;
 };
 
 struct msm_vfe_axi_plane_cfg {
diff --git a/include/media/msmb_ispif.h b/include/media/msmb_ispif.h
index f0f015e..c9eb12a 100644
--- a/include/media/msmb_ispif.h
+++ b/include/media/msmb_ispif.h
@@ -20,6 +20,8 @@
 	RDI2,
 	INTF_MAX
 };
+#define MAX_PARAM_ENTRIES (INTF_MAX * 2)
+
 #define PIX0_MASK (1 << PIX0)
 #define PIX1_MASK (1 << PIX1)
 #define RDI0_MASK (1 << RDI0)
@@ -76,7 +78,7 @@
 
 struct msm_ispif_param_data {
 	uint32_t num;
-	struct msm_ispif_params_entry entries[INTF_MAX];
+	struct msm_ispif_params_entry entries[MAX_PARAM_ENTRIES];
 };
 
 struct msm_isp_info {
diff --git a/include/media/msmb_pproc.h b/include/media/msmb_pproc.h
index 9000774..c185096 100644
--- a/include/media/msmb_pproc.h
+++ b/include/media/msmb_pproc.h
@@ -106,6 +106,7 @@
 	struct ion_handle *dest_ion_handle;
 	struct timeval in_time, out_time;
 	void *cookie;
+	int32_t *status;
 
 	struct msm_cpp_buffer_info_t input_buffer_info;
 	struct msm_cpp_buffer_info_t output_buffer_info;
@@ -145,7 +146,7 @@
 struct msm_camera_v4l2_ioctl_t {
 	uint32_t id;
 	uint32_t len;
-	uint32_t trans_code;
+	int32_t trans_code;
 	void __user *ioctl_ptr;
 };
 
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index bfa0eca..dc29eb9 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -1361,6 +1361,21 @@
 };
 
 /**
+ * struct cfg80211_update_ft_ies_params - FT IE Information
+ *
+ * This structure provides information needed to update the fast transition IE
+ *
+ * @md: The Mobility Domain ID, 2 Octet value
+ * @ie: Fast Transition IEs
+ * @ie_len: Length of ft_ie in octets
+ */
+struct cfg80211_update_ft_ies_params {
+	u16 md;
+	const u8 *ie;
+	size_t ie_len;
+};
+
+/**
  * struct cfg80211_ops - backend description for wireless configuration
  *
  * This struct is registered by fullmac card drivers and/or wireless stacks
@@ -1740,6 +1755,8 @@
 				  u16 noack_map);
 
 	struct ieee80211_channel *(*get_channel)(struct wiphy *wiphy);
+	int	(*update_ft_ies)(struct wiphy *wiphy, struct net_device *dev,
+				 struct cfg80211_update_ft_ies_params *ftie);
 };
 
 /*
@@ -3410,6 +3427,31 @@
  */
 u16 cfg80211_calculate_bitrate(struct rate_info *rate);
 
+/**
+ * struct cfg80211_ft_event - FT Information Elements
+ * @ies: FT IEs
+ * @ies_len: length of the FT IE in bytes
+ * @target_ap: target AP's MAC address
+ * @ric_ies: RIC IE
+ * @ric_ies_len: length of the RIC IE in bytes
+ */
+struct cfg80211_ft_event_params {
+	const u8 *ies;
+	size_t ies_len;
+	const u8 *target_ap;
+	const u8 *ric_ies;
+	size_t ric_ies_len;
+};
+
+/**
+ * cfg80211_ft_event - notify userspace about FT IE and RIC IE
+ * @netdev: network device
+ * @ft_event: IE information
+ */
+void cfg80211_ft_event(struct net_device *netdev,
+		       struct cfg80211_ft_event_params *ft_event);
+
+
 /* Logging, debugging and troubleshooting/diagnostic helpers. */
 
 /* wiphy_printk helpers, similar to dev_printk */
diff --git a/include/sound/apr_audio-v2.h b/include/sound/apr_audio-v2.h
index 04e683f..fa4dedc 100644
--- a/include/sound/apr_audio-v2.h
+++ b/include/sound/apr_audio-v2.h
@@ -335,6 +335,7 @@
 /*  Payload an #ADM_CMD_GET_PP_PARAMS_V5 command.
 */
 struct adm_cmd_get_pp_params_v5 {
+	struct apr_hdr hdr;
 	u32                  data_payload_addr_lsw;
 	/* LSW of parameter data payload address.*/
 
@@ -2593,6 +2594,14 @@
 
 } __packed;
 
+/* @brief Dolby Digital Plus end point configuration structure
+ */
+struct asm_dec_ddp_endp_param_v2 {
+	struct apr_hdr hdr;
+	struct asm_stream_cmd_set_encdec_param  encdec;
+	int endp_param_value;
+} __packed;
+
 /* @brief Multichannel PCM encoder configuration structure used
  * in the #ASM_STREAM_CMD_OPEN_READ_V2 command.
  */
@@ -6913,4 +6922,7 @@
 	struct afe_port_cmd_set_param_v2 param;
 } __packed;
 
+/* Dolby DAP topology */
+#define DOLBY_ADM_COPP_TOPOLOGY_ID	0x0001033B
+
 #endif /*_APR_AUDIO_V2_H_ */
diff --git a/include/sound/compress_params.h b/include/sound/compress_params.h
index b95fa3c..f5ab179 100644
--- a/include/sound/compress_params.h
+++ b/include/sound/compress_params.h
@@ -89,6 +89,8 @@
 #define SND_AUDIOCODEC_PASS_THROUGH          ((__u32) 0x00000015)
 #define SND_AUDIOCODEC_MP2                   ((__u32) 0x00000016)
 #define SND_AUDIOCODEC_DTS_LBR_PASS_THROUGH  ((__u32) 0x00000017)
+#define SND_AUDIOCODEC_EAC3                  ((__u32) 0x00000018)
+#define SND_AUDIOCODEC_MAX  SND_AUDIOCODEC_EAC3
 /*
  * Profile and modes are listed with bit masks. This allows for a
  * more compact representation of fields that will not evolve
@@ -337,7 +339,12 @@
 	__u32 modelIdLength;
 	__u8 *modelId;
 };
-
+struct snd_dec_ddp {
+	__u32 params_length;
+	__u8 *params;
+	__u32 params_id[18];
+	__u32 params_value[18];
+};
 union snd_codec_options {
 	struct snd_enc_wma wma;
 	struct snd_enc_vorbis vorbis;
@@ -345,6 +352,7 @@
 	struct snd_enc_flac flac;
 	struct snd_enc_generic generic;
 	struct snd_dec_dts dts;
+	struct snd_dec_ddp ddp;
 };
 
 /** struct snd_codec_desc - description of codec capabilities
diff --git a/include/sound/q6adm-v2.h b/include/sound/q6adm-v2.h
index 77a805c..4bea1e1 100644
--- a/include/sound/q6adm-v2.h
+++ b/include/sound/q6adm-v2.h
@@ -32,6 +32,12 @@
 int adm_open(int port, int path, int rate, int mode, int topology,
 				bool perf_mode, uint16_t bits_per_sample);
 
+int adm_dolby_dap_get_params(int port_id, uint32_t module_id, uint32_t param_id,
+			uint32_t params_length, char *params);
+
+int adm_dolby_dap_send_params(int port_id, char *params,
+				 uint32_t params_length);
+
 int adm_multi_ch_copp_open(int port, int path, int rate, int mode,
 			int topology, bool perf_mode, uint16_t bits_per_sample);
 
diff --git a/include/sound/q6afe-v2.h b/include/sound/q6afe-v2.h
index 9c86e1d..2a740f4 100644
--- a/include/sound/q6afe-v2.h
+++ b/include/sound/q6afe-v2.h
@@ -81,6 +81,8 @@
 	IDX_AFE_PORT_ID_TERTIARY_MI2S_TX = 39,
 	IDX_AFE_PORT_ID_PRIMARY_MI2S_RX = 40,
 	IDX_AFE_PORT_ID_PRIMARY_MI2S_TX = 41,
+	IDX_AFE_PORT_ID_SECONDARY_PCM_RX = 42,
+	IDX_AFE_PORT_ID_SECONDARY_PCM_TX = 43,
 	IDX_GLOBAL_CFG,
 	AFE_MAX_PORTS
 };
diff --git a/include/sound/q6asm-v2.h b/include/sound/q6asm-v2.h
index f9d2a40..0dd14e6 100644
--- a/include/sound/q6asm-v2.h
+++ b/include/sound/q6asm-v2.h
@@ -13,7 +13,6 @@
 #define __Q6_ASM_V2_H__
 
 #include <mach/qdsp6v2/apr.h>
-#include <mach/msm_subsystem_map.h>
 #include <sound/apr_audio-v2.h>
 #include <linux/list.h>
 #include <linux/msm_ion.h>
@@ -42,6 +41,8 @@
 #define FORMAT_AMR_WB_PLUS  0x0010
 #define FORMAT_MPEG4_MULTI_AAC 0x0011
 #define FORMAT_MULTI_CHANNEL_LINEAR_PCM 0x0012
+#define FORMAT_AC3          0x0013
+#define FORMAT_EAC3         0x0014
 
 #define ENCDEC_SBCBITRATE   0x0001
 #define ENCDEC_IMMEDIATE_DECODE 0x0002
@@ -296,6 +297,10 @@
 
 int q6asm_media_format_block_amrwbplus(struct audio_client *ac,
 			struct asm_amrwbplus_cfg *cfg);
+
+int q6asm_ds1_set_endp_params(struct audio_client *ac,
+				int param_id, int param_value);
+
 /* PP specific */
 int q6asm_equalizer(struct audio_client *ac, void *eq);
 
diff --git a/include/sound/q6lsm.h b/include/sound/q6lsm.h
index 5c9d4b9..e9ca91d 100644
--- a/include/sound/q6lsm.h
+++ b/include/sound/q6lsm.h
@@ -18,7 +18,6 @@
 #include <sound/apr_audio-v2.h>
 #include <sound/lsm_params.h>
 #include <mach/qdsp6v2/apr.h>
-#include <mach/msm_subsystem_map.h>
 
 typedef void (*app_cb)(uint32_t opcode, uint32_t token,
 		       uint32_t *payload, void *priv);
diff --git a/include/video/Kbuild b/include/video/Kbuild
index ad3e622..53e13cb 100644
--- a/include/video/Kbuild
+++ b/include/video/Kbuild
@@ -1,3 +1,4 @@
 header-y += edid.h
 header-y += sisfb.h
 header-y += uvesafb.h
+header-y += msm_hdmi_modes.h
diff --git a/include/video/msm_hdmi_modes.h b/include/video/msm_hdmi_modes.h
new file mode 100644
index 0000000..a15272b
--- /dev/null
+++ b/include/video/msm_hdmi_modes.h
@@ -0,0 +1,334 @@
+#ifndef __MSM_HDMI_MODES_H__
+#define __MSM_HDMI_MODES_H__
+#include <linux/types.h>
+
+struct msm_hdmi_mode_timing_info {
+	uint32_t	video_format;
+	uint32_t	active_h;
+	uint32_t	front_porch_h;
+	uint32_t	pulse_width_h;
+	uint32_t	back_porch_h;
+	uint32_t	active_low_h;
+	uint32_t	active_v;
+	uint32_t	front_porch_v;
+	uint32_t	pulse_width_v;
+	uint32_t	back_porch_v;
+	uint32_t	active_low_v;
+	/* Must divide by 1000 to get the actual frequency in MHZ */
+	uint32_t	pixel_freq;
+	/* Must divide by 1000 to get the actual frequency in HZ */
+	uint32_t	refresh_rate;
+	uint32_t	interlaced;
+	uint32_t	supported;
+};
+
+#define MSM_HDMI_MODES_CEA		(1 << 0)
+#define MSM_HDMI_MODES_XTND		(1 << 1)
+#define MSM_HDMI_MODES_DVI		(1 << 2)
+#define MSM_HDMI_MODES_ALL		(MSM_HDMI_MODES_CEA |\
+					 MSM_HDMI_MODES_XTND |\
+					 MSM_HDMI_MODES_DVI)
+
+/* all video formats defined by CEA 861D */
+#define HDMI_VFRMT_UNKNOWN		0
+#define HDMI_VFRMT_640x480p60_4_3	1
+#define HDMI_VFRMT_720x480p60_4_3	2
+#define HDMI_VFRMT_720x480p60_16_9	3
+#define HDMI_VFRMT_1280x720p60_16_9	4
+#define HDMI_VFRMT_1920x1080i60_16_9	5
+#define HDMI_VFRMT_720x480i60_4_3	6
+#define HDMI_VFRMT_1440x480i60_4_3	HDMI_VFRMT_720x480i60_4_3
+#define HDMI_VFRMT_720x480i60_16_9	7
+#define HDMI_VFRMT_1440x480i60_16_9	HDMI_VFRMT_720x480i60_16_9
+#define HDMI_VFRMT_720x240p60_4_3	8
+#define HDMI_VFRMT_1440x240p60_4_3	HDMI_VFRMT_720x240p60_4_3
+#define HDMI_VFRMT_720x240p60_16_9	9
+#define HDMI_VFRMT_1440x240p60_16_9	HDMI_VFRMT_720x240p60_16_9
+#define HDMI_VFRMT_2880x480i60_4_3	10
+#define HDMI_VFRMT_2880x480i60_16_9	11
+#define HDMI_VFRMT_2880x240p60_4_3	12
+#define HDMI_VFRMT_2880x240p60_16_9	13
+#define HDMI_VFRMT_1440x480p60_4_3	14
+#define HDMI_VFRMT_1440x480p60_16_9	15
+#define HDMI_VFRMT_1920x1080p60_16_9	16
+#define HDMI_VFRMT_720x576p50_4_3	17
+#define HDMI_VFRMT_720x576p50_16_9	18
+#define HDMI_VFRMT_1280x720p50_16_9	19
+#define HDMI_VFRMT_1920x1080i50_16_9	20
+#define HDMI_VFRMT_720x576i50_4_3	21
+#define HDMI_VFRMT_1440x576i50_4_3	HDMI_VFRMT_720x576i50_4_3
+#define HDMI_VFRMT_720x576i50_16_9	22
+#define HDMI_VFRMT_1440x576i50_16_9	HDMI_VFRMT_720x576i50_16_9
+#define HDMI_VFRMT_720x288p50_4_3	23
+#define HDMI_VFRMT_1440x288p50_4_3	HDMI_VFRMT_720x288p50_4_3
+#define HDMI_VFRMT_720x288p50_16_9	24
+#define HDMI_VFRMT_1440x288p50_16_9	HDMI_VFRMT_720x288p50_16_9
+#define HDMI_VFRMT_2880x576i50_4_3	25
+#define HDMI_VFRMT_2880x576i50_16_9	26
+#define HDMI_VFRMT_2880x288p50_4_3	27
+#define HDMI_VFRMT_2880x288p50_16_9	28
+#define HDMI_VFRMT_1440x576p50_4_3	29
+#define HDMI_VFRMT_1440x576p50_16_9	30
+#define HDMI_VFRMT_1920x1080p50_16_9	31
+#define HDMI_VFRMT_1920x1080p24_16_9	32
+#define HDMI_VFRMT_1920x1080p25_16_9	33
+#define HDMI_VFRMT_1920x1080p30_16_9	34
+#define HDMI_VFRMT_2880x480p60_4_3	35
+#define HDMI_VFRMT_2880x480p60_16_9	36
+#define HDMI_VFRMT_2880x576p50_4_3	37
+#define HDMI_VFRMT_2880x576p50_16_9	38
+#define HDMI_VFRMT_1920x1250i50_16_9	39
+#define HDMI_VFRMT_1920x1080i100_16_9	40
+#define HDMI_VFRMT_1280x720p100_16_9	41
+#define HDMI_VFRMT_720x576p100_4_3	42
+#define HDMI_VFRMT_720x576p100_16_9	43
+#define HDMI_VFRMT_720x576i100_4_3	44
+#define HDMI_VFRMT_1440x576i100_4_3	HDMI_VFRMT_720x576i100_4_3
+#define HDMI_VFRMT_720x576i100_16_9	45
+#define HDMI_VFRMT_1440x576i100_16_9	HDMI_VFRMT_720x576i100_16_9
+#define HDMI_VFRMT_1920x1080i120_16_9	46
+#define HDMI_VFRMT_1280x720p120_16_9	47
+#define HDMI_VFRMT_720x480p120_4_3	48
+#define HDMI_VFRMT_720x480p120_16_9	49
+#define HDMI_VFRMT_720x480i120_4_3	50
+#define HDMI_VFRMT_1440x480i120_4_3	HDMI_VFRMT_720x480i120_4_3
+#define HDMI_VFRMT_720x480i120_16_9	51
+#define HDMI_VFRMT_1440x480i120_16_9	HDMI_VFRMT_720x480i120_16_9
+#define HDMI_VFRMT_720x576p200_4_3	52
+#define HDMI_VFRMT_720x576p200_16_9	53
+#define HDMI_VFRMT_720x576i200_4_3	54
+#define HDMI_VFRMT_1440x576i200_4_3	HDMI_VFRMT_720x576i200_4_3
+#define HDMI_VFRMT_720x576i200_16_9	55
+#define HDMI_VFRMT_1440x576i200_16_9	HDMI_VFRMT_720x576i200_16_9
+#define HDMI_VFRMT_720x480p240_4_3	56
+#define HDMI_VFRMT_720x480p240_16_9	57
+#define HDMI_VFRMT_720x480i240_4_3	58
+#define HDMI_VFRMT_1440x480i240_4_3	HDMI_VFRMT_720x480i240_4_3
+#define HDMI_VFRMT_720x480i240_16_9	59
+#define HDMI_VFRMT_1440x480i240_16_9	HDMI_VFRMT_720x480i240_16_9
+#define HDMI_VFRMT_1280x720p24_16_9	60
+#define HDMI_VFRMT_1280x720p25_16_9	61
+#define HDMI_VFRMT_1280x720p30_16_9	62
+#define HDMI_VFRMT_1920x1080p120_16_9	63
+#define HDMI_VFRMT_1920x1080p100_16_9	64
+/* Video Identification Codes from 65-127 are reserved for the future */
+#define HDMI_VFRMT_END			127
+
+/* extended video formats */
+#define HDMI_VFRMT_3840x2160p30_16_9	(HDMI_VFRMT_END + 1)
+#define HDMI_VFRMT_3840x2160p25_16_9	(HDMI_VFRMT_END + 2)
+#define HDMI_VFRMT_3840x2160p24_16_9	(HDMI_VFRMT_END + 3)
+#define HDMI_VFRMT_4096x2160p24_16_9	(HDMI_VFRMT_END + 4)
+#define HDMI_EVFRMT_END			HDMI_VFRMT_4096x2160p24_16_9
+
+/* VESA DMT TIMINGS */
+#define HDMI_VFRMT_2560x1600p60_16_9	(HDMI_EVFRMT_END + 1)
+#define HDMI_VFRMT_1280x1024p60_5_4	(HDMI_EVFRMT_END + 2)
+#define VESA_DMT_VFRMT_END		HDMI_VFRMT_1280x1024p60_5_4
+#define HDMI_VFRMT_MAX			(VESA_DMT_VFRMT_END + 1)
+#define HDMI_VFRMT_FORCE_32BIT		0x7FFFFFFF
+
+/* Timing information for supported modes */
+#define VFRMT_NOT_SUPPORTED(VFRMT) \
+	{VFRMT, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, false}
+
+#define HDMI_VFRMT_640x480p60_4_3_TIMING				\
+	{HDMI_VFRMT_640x480p60_4_3, 640, 16, 96, 48, true,		\
+	 480, 10, 2, 33, true, 25200, 60000, false, true}
+#define HDMI_VFRMT_720x480p60_4_3_TIMING				\
+	{HDMI_VFRMT_720x480p60_4_3, 720, 16, 62, 60, true,		\
+	 480, 9, 6, 30, true, 27030, 60000, false, true}
+#define HDMI_VFRMT_720x480p60_16_9_TIMING				\
+	{HDMI_VFRMT_720x480p60_16_9, 720, 16, 62, 60, true,		\
+	 480, 9, 6, 30, true, 27030, 60000, false, true}
+#define HDMI_VFRMT_1280x720p60_16_9_TIMING				\
+	{HDMI_VFRMT_1280x720p60_16_9, 1280, 110, 40, 220, false,	\
+	 720, 5, 5, 20, false, 74250, 60000, false, true}
+#define HDMI_VFRMT_1920x1080i60_16_9_TIMING				\
+	{HDMI_VFRMT_1920x1080i60_16_9, 1920, 88, 44, 148, false,	\
+	 540, 2, 5, 5, false, 74250, 60000, false, true}
+#define HDMI_VFRMT_1440x480i60_4_3_TIMING				\
+	{HDMI_VFRMT_1440x480i60_4_3, 1440, 38, 124, 114, true,		\
+	 240, 4, 3, 15, true, 27000, 60000, true, true}
+#define HDMI_VFRMT_1440x480i60_16_9_TIMING				\
+	{HDMI_VFRMT_1440x480i60_16_9, 1440, 38, 124, 114, true,		\
+	 240, 4, 3, 15, true, 27000, 60000, true, true}
+#define HDMI_VFRMT_1920x1080p60_16_9_TIMING				\
+	{HDMI_VFRMT_1920x1080p60_16_9, 1920, 88, 44, 148, false,	\
+	 1080, 4, 5, 36, false, 148500, 60000, false, true}
+#define HDMI_VFRMT_720x576p50_4_3_TIMING				\
+	{HDMI_VFRMT_720x576p50_4_3, 720, 12, 64, 68, true,		\
+	 576,  5, 5, 39, true, 27000, 50000, false, true}
+#define HDMI_VFRMT_720x576p50_16_9_TIMING				\
+	{HDMI_VFRMT_720x576p50_16_9, 720, 12, 64, 68, true,		\
+	 576,  5, 5, 39, true, 27000, 50000, false, true}
+#define HDMI_VFRMT_1280x720p50_16_9_TIMING				\
+	{HDMI_VFRMT_1280x720p50_16_9, 1280, 440, 40, 220, false,	\
+	 720,  5, 5, 20, false, 74250, 50000, false, true}
+#define HDMI_VFRMT_1440x576i50_4_3_TIMING				\
+	{HDMI_VFRMT_1440x576i50_4_3, 1440, 24, 126, 138, true,		\
+	 288,  2, 3, 19, true, 27000, 50000, true, true}
+#define HDMI_VFRMT_1440x576i50_16_9_TIMING				\
+	{HDMI_VFRMT_1440x576i50_16_9, 1440, 24, 126, 138, true,		\
+	 288,  2, 3, 19, true, 27000, 50000, true, true}
+#define HDMI_VFRMT_1920x1080p50_16_9_TIMING				\
+	{HDMI_VFRMT_1920x1080p50_16_9, 1920, 528, 44, 148, false,	\
+	 1080, 4, 5, 36, false, 148500, 50000, false, true}
+#define HDMI_VFRMT_1920x1080p24_16_9_TIMING				\
+	{HDMI_VFRMT_1920x1080p24_16_9, 1920, 638, 44, 148, false,	\
+	 1080, 4, 5, 36, false, 74250, 24000, false, true}
+#define HDMI_VFRMT_1920x1080p25_16_9_TIMING				\
+	{HDMI_VFRMT_1920x1080p25_16_9, 1920, 528, 44, 148, false,	\
+	 1080, 4, 5, 36, false, 74250, 25000, false, true}
+#define HDMI_VFRMT_1920x1080p30_16_9_TIMING				\
+	{HDMI_VFRMT_1920x1080p30_16_9, 1920, 88, 44, 148, false,	\
+	 1080, 4, 5, 36, false, 74250, 30000, false, true}
+#define HDMI_VFRMT_1280x1024p60_5_4_TIMING				\
+	{HDMI_VFRMT_1280x1024p60_5_4, 1280, 48, 112, 248, false,	\
+	1024, 1, 3, 38, false, 108000, 60000, false, true}
+#define HDMI_VFRMT_2560x1600p60_16_9_TIMING				\
+	{HDMI_VFRMT_2560x1600p60_16_9, 2560, 48, 32, 80, false,		\
+	 1600, 3, 6, 37, false, 268500, 60000, false, true}
+#define HDMI_VFRMT_3840x2160p30_16_9_TIMING				\
+	{HDMI_VFRMT_3840x2160p30_16_9, 3840, 176, 88, 296, false,	\
+	 2160, 8, 10, 72, false, 297000, 30000, false, true}
+#define HDMI_VFRMT_3840x2160p25_16_9_TIMING				\
+	{HDMI_VFRMT_3840x2160p25_16_9, 3840, 1056, 88, 296, false,	\
+	 2160, 8, 10, 72, false, 297000, 25000, false, true}
+#define HDMI_VFRMT_3840x2160p24_16_9_TIMING				\
+	{HDMI_VFRMT_3840x2160p24_16_9, 3840, 1276, 88, 296, false,	\
+	 2160, 8, 10, 72, false, 297000, 24000, false, true}
+#define HDMI_VFRMT_4096x2160p24_16_9_TIMING				\
+	{HDMI_VFRMT_4096x2160p24_16_9, 4096, 1020, 88, 296, false,	\
+	 2160, 8, 10, 72, false, 297000, 24000, false, true}
+
+#define MSM_HDMI_MODES_SET_TIMING(LUT, MODE) do {		\
+	struct msm_hdmi_mode_timing_info mode = MODE##_TIMING;	\
+	LUT[MODE] = mode;\
+	} while (0)
+
+static inline void MSM_HDMI_MODES_INIT_TIMINGS(
+	struct msm_hdmi_mode_timing_info *lut)
+{
+	int i;
+
+	for (i = 0; i < HDMI_VFRMT_MAX; i++) {
+		struct msm_hdmi_mode_timing_info mode = VFRMT_NOT_SUPPORTED(i);
+		lut[i] = mode;
+	}
+}
+
+static inline void MSM_HDMI_MODES_SET_SUPP_TIMINGS(
+	struct msm_hdmi_mode_timing_info *lut, int type)
+{
+	if (type & MSM_HDMI_MODES_CEA) {
+		MSM_HDMI_MODES_SET_TIMING(lut, HDMI_VFRMT_640x480p60_4_3);
+		MSM_HDMI_MODES_SET_TIMING(lut, HDMI_VFRMT_720x480p60_4_3);
+		MSM_HDMI_MODES_SET_TIMING(lut, HDMI_VFRMT_720x480p60_16_9);
+		MSM_HDMI_MODES_SET_TIMING(lut, HDMI_VFRMT_1280x720p60_16_9);
+		MSM_HDMI_MODES_SET_TIMING(lut, HDMI_VFRMT_1920x1080i60_16_9);
+		MSM_HDMI_MODES_SET_TIMING(lut, HDMI_VFRMT_1440x480i60_4_3);
+		MSM_HDMI_MODES_SET_TIMING(lut, HDMI_VFRMT_1440x480i60_16_9);
+		MSM_HDMI_MODES_SET_TIMING(lut, HDMI_VFRMT_1920x1080p60_16_9);
+		MSM_HDMI_MODES_SET_TIMING(lut, HDMI_VFRMT_720x576p50_4_3);
+		MSM_HDMI_MODES_SET_TIMING(lut, HDMI_VFRMT_720x576p50_16_9);
+		MSM_HDMI_MODES_SET_TIMING(lut, HDMI_VFRMT_1280x720p50_16_9);
+		MSM_HDMI_MODES_SET_TIMING(lut, HDMI_VFRMT_1440x576i50_4_3);
+		MSM_HDMI_MODES_SET_TIMING(lut, HDMI_VFRMT_1440x576i50_16_9);
+		MSM_HDMI_MODES_SET_TIMING(lut, HDMI_VFRMT_1920x1080p50_16_9);
+		MSM_HDMI_MODES_SET_TIMING(lut, HDMI_VFRMT_1920x1080p24_16_9);
+		MSM_HDMI_MODES_SET_TIMING(lut, HDMI_VFRMT_1920x1080p25_16_9);
+		MSM_HDMI_MODES_SET_TIMING(lut, HDMI_VFRMT_1920x1080p30_16_9);
+	}
+
+	if (type & MSM_HDMI_MODES_XTND) {
+		MSM_HDMI_MODES_SET_TIMING(lut, HDMI_VFRMT_3840x2160p30_16_9);
+		MSM_HDMI_MODES_SET_TIMING(lut, HDMI_VFRMT_3840x2160p25_16_9);
+		MSM_HDMI_MODES_SET_TIMING(lut, HDMI_VFRMT_3840x2160p24_16_9);
+		MSM_HDMI_MODES_SET_TIMING(lut, HDMI_VFRMT_4096x2160p24_16_9);
+	}
+
+	if (type & MSM_HDMI_MODES_DVI) {
+		MSM_HDMI_MODES_SET_TIMING(lut, HDMI_VFRMT_1280x1024p60_5_4);
+		MSM_HDMI_MODES_SET_TIMING(lut, HDMI_VFRMT_2560x1600p60_16_9);
+	}
+}
+
+static inline const char *msm_hdmi_mode_2string(uint32_t mode)
+{
+	switch (mode) {
+	case HDMI_VFRMT_UNKNOWN:		return "Unknown";
+	case HDMI_VFRMT_640x480p60_4_3:		return "640x480 p60 4/3";
+	case HDMI_VFRMT_720x480p60_4_3:		return "720x480 p60 4/3";
+	case HDMI_VFRMT_720x480p60_16_9:	return "720x480 p60 16/9";
+	case HDMI_VFRMT_1280x720p60_16_9:	return "1280x 720 p60 16/9";
+	case HDMI_VFRMT_1920x1080i60_16_9:	return "1920x1080 i60 16/9";
+	case HDMI_VFRMT_1440x480i60_4_3:	return "1440x480 i60 4/3";
+	case HDMI_VFRMT_1440x480i60_16_9:	return "1440x480 i60 16/9";
+	case HDMI_VFRMT_1440x240p60_4_3:	return "1440x240 p60 4/3";
+	case HDMI_VFRMT_1440x240p60_16_9:	return "1440x240 p60 16/9";
+	case HDMI_VFRMT_2880x480i60_4_3:	return "2880x480 i60 4/3";
+	case HDMI_VFRMT_2880x480i60_16_9:	return "2880x480 i60 16/9";
+	case HDMI_VFRMT_2880x240p60_4_3:	return "2880x240 p60 4/3";
+	case HDMI_VFRMT_2880x240p60_16_9:	return "2880x240 p60 16/9";
+	case HDMI_VFRMT_1440x480p60_4_3:	return "1440x480 p60 4/3";
+	case HDMI_VFRMT_1440x480p60_16_9:	return "1440x480 p60 16/9";
+	case HDMI_VFRMT_1920x1080p60_16_9:	return "1920x1080 p60 16/9";
+	case HDMI_VFRMT_720x576p50_4_3:		return "720x576 p50 4/3";
+	case HDMI_VFRMT_720x576p50_16_9:	return "720x576 p50 16/9";
+	case HDMI_VFRMT_1280x720p50_16_9:	return "1280x720 p50 16/9";
+	case HDMI_VFRMT_1920x1080i50_16_9:	return "1920x1080 i50 16/9";
+	case HDMI_VFRMT_1440x576i50_4_3:	return "1440x576 i50 4/3";
+	case HDMI_VFRMT_1440x576i50_16_9:	return "1440x576 i50 16/9";
+	case HDMI_VFRMT_1440x288p50_4_3:	return "1440x288 p50 4/3";
+	case HDMI_VFRMT_1440x288p50_16_9:	return "1440x288 p50 16/9";
+	case HDMI_VFRMT_2880x576i50_4_3:	return "2880x576 i50 4/3";
+	case HDMI_VFRMT_2880x576i50_16_9:	return "2880x576 i50 16/9";
+	case HDMI_VFRMT_2880x288p50_4_3:	return "2880x288 p50 4/3";
+	case HDMI_VFRMT_2880x288p50_16_9:	return "2880x288 p50 16/9";
+	case HDMI_VFRMT_1440x576p50_4_3:	return "1440x576 p50 4/3";
+	case HDMI_VFRMT_1440x576p50_16_9:	return "1440x576 p50 16/9";
+	case HDMI_VFRMT_1920x1080p50_16_9:	return "1920x1080 p50 16/9";
+	case HDMI_VFRMT_1920x1080p24_16_9:	return "1920x1080 p24 16/9";
+	case HDMI_VFRMT_1920x1080p25_16_9:	return "1920x1080 p25 16/9";
+	case HDMI_VFRMT_1920x1080p30_16_9:	return "1920x1080 p30 16/9";
+	case HDMI_VFRMT_2880x480p60_4_3:	return "2880x480 p60 4/3";
+	case HDMI_VFRMT_2880x480p60_16_9:	return "2880x480 p60 16/9";
+	case HDMI_VFRMT_2880x576p50_4_3:	return "2880x576 p50 4/3";
+	case HDMI_VFRMT_2880x576p50_16_9:	return "2880x576 p50 16/9";
+	case HDMI_VFRMT_1920x1250i50_16_9:	return "1920x1250 i50 16/9";
+	case HDMI_VFRMT_1920x1080i100_16_9:	return "1920x1080 i100 16/9";
+	case HDMI_VFRMT_1280x720p100_16_9:	return "1280x720 p100 16/9";
+	case HDMI_VFRMT_720x576p100_4_3:	return "720x576 p100 4/3";
+	case HDMI_VFRMT_720x576p100_16_9:	return "720x576 p100 16/9";
+	case HDMI_VFRMT_1440x576i100_4_3:	return "1440x576 i100 4/3";
+	case HDMI_VFRMT_1440x576i100_16_9:	return "1440x576 i100 16/9";
+	case HDMI_VFRMT_1920x1080i120_16_9:	return "1920x1080 i120 16/9";
+	case HDMI_VFRMT_1280x720p120_16_9:	return "1280x720 p120 16/9";
+	case HDMI_VFRMT_720x480p120_4_3:	return "720x480 p120 4/3";
+	case HDMI_VFRMT_720x480p120_16_9:	return "720x480 p120 16/9";
+	case HDMI_VFRMT_1440x480i120_4_3:	return "1440x480 i120 4/3";
+	case HDMI_VFRMT_1440x480i120_16_9:	return "1440x480 i120 16/9";
+	case HDMI_VFRMT_720x576p200_4_3:	return "720x576 p200 4/3";
+	case HDMI_VFRMT_720x576p200_16_9:	return "720x576 p200 16/9";
+	case HDMI_VFRMT_1440x576i200_4_3:	return "1440x576 i200 4/3";
+	case HDMI_VFRMT_1440x576i200_16_9:	return "1440x576 i200 16/9";
+	case HDMI_VFRMT_720x480p240_4_3:	return "720x480 p240 4/3";
+	case HDMI_VFRMT_720x480p240_16_9:	return "720x480 p240 16/9";
+	case HDMI_VFRMT_1440x480i240_4_3:	return "1440x480 i240 4/3";
+	case HDMI_VFRMT_1440x480i240_16_9:	return "1440x480 i240 16/9";
+	case HDMI_VFRMT_1280x720p24_16_9:	return "1280x720 p24 16/9";
+	case HDMI_VFRMT_1280x720p25_16_9:	return "1280x720 p25 16/9";
+	case HDMI_VFRMT_1280x720p30_16_9:	return "1280x720 p30 16/9";
+	case HDMI_VFRMT_1920x1080p120_16_9:	return "1920x1080 p120 16/9";
+	case HDMI_VFRMT_1920x1080p100_16_9:	return "1920x1080 p100 16/9";
+	case HDMI_VFRMT_3840x2160p30_16_9:	return "3840x2160 p30 16/9";
+	case HDMI_VFRMT_3840x2160p25_16_9:	return "3840x2160 p25 16/9";
+	case HDMI_VFRMT_3840x2160p24_16_9:	return "3840x2160 p24 16/9";
+	case HDMI_VFRMT_4096x2160p24_16_9:	return "4096x2160 p24 16/9";
+	case HDMI_VFRMT_2560x1600p60_16_9:	return "2560x1600 p60 16/9";
+	case HDMI_VFRMT_1280x1024p60_5_4:	return "1280x1042 p60 5/4";
+	default:				return "???";
+	}
+}
+#endif /* __MSM_HDMI_MODES_H__ */
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 5097036..e1fa62e 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -212,6 +212,14 @@
 	[NL80211_ATTR_VHT_CAPABILITY] = { .len = NL80211_VHT_CAPABILITY_LEN },
 	[NL80211_ATTR_STA_CAPABILITY] = { .type = NLA_U16 },
 	[NL80211_ATTR_STA_EXT_CAPABILITY] = { .type = NLA_BINARY, },
+	[NL80211_ATTR_SPLIT_WIPHY_DUMP] = { .type = NLA_FLAG, },
+	[NL80211_ATTR_DISABLE_VHT] = { .type = NLA_FLAG },
+	[NL80211_ATTR_VHT_CAPABILITY_MASK] = {
+		.len = NL80211_VHT_CAPABILITY_LEN,
+	},
+	[NL80211_ATTR_MDID] = { .type = NLA_U16 },
+	[NL80211_ATTR_IE_RIC] = { .type = NLA_BINARY,
+				  .len = IEEE80211_MAX_DATA_LEN },
 };
 
 /* policy for the key attributes */
@@ -6445,6 +6453,27 @@
 	return 0;
 }
 
+static int nl80211_update_ft_ies(struct sk_buff *skb, struct genl_info *info)
+{
+	struct cfg80211_registered_device *rdev = info->user_ptr[0];
+	struct cfg80211_update_ft_ies_params ft_params;
+	struct net_device *dev = info->user_ptr[1];
+
+	if (!rdev->ops->update_ft_ies)
+		return -EOPNOTSUPP;
+
+	if (!info->attrs[NL80211_ATTR_MDID] ||
+	    !is_valid_ie_attr(info->attrs[NL80211_ATTR_IE]))
+		return -EINVAL;
+
+	memset(&ft_params, 0, sizeof(ft_params));
+	ft_params.md = nla_get_u16(info->attrs[NL80211_ATTR_MDID]);
+	ft_params.ie = nla_data(info->attrs[NL80211_ATTR_IE]);
+	ft_params.ie_len = nla_len(info->attrs[NL80211_ATTR_IE]);
+
+	return rdev->ops->update_ft_ies(&rdev->wiphy, dev, &ft_params);
+}
+
 #define NL80211_FLAG_NEED_WIPHY		0x01
 #define NL80211_FLAG_NEED_NETDEV	0x02
 #define NL80211_FLAG_NEED_RTNL		0x04
@@ -7033,6 +7062,14 @@
 		.internal_flags = NL80211_FLAG_NEED_NETDEV |
 				  NL80211_FLAG_NEED_RTNL,
 	},
+	{
+		.cmd = NL80211_CMD_UPDATE_FT_IES,
+		.doit = nl80211_update_ft_ies,
+		.policy = nl80211_policy,
+		.flags = GENL_ADMIN_PERM,
+		.internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
+				  NL80211_FLAG_NEED_RTNL,
+	},
 
 };
 
@@ -8270,6 +8307,48 @@
 	.notifier_call = nl80211_netlink_notify,
 };
 
+void cfg80211_ft_event(struct net_device *netdev,
+		       struct cfg80211_ft_event_params *ft_event)
+{
+	struct wiphy *wiphy = netdev->ieee80211_ptr->wiphy;
+	struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
+	struct sk_buff *msg;
+	void *hdr;
+	int err;
+
+	if (!ft_event->target_ap)
+		return;
+
+	msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
+	if (!msg)
+		return;
+
+	hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_FT_EVENT);
+	if (!hdr) {
+		nlmsg_free(msg);
+		return;
+	}
+
+	nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx);
+	nla_put_u32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex);
+	nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, ft_event->target_ap);
+	if (ft_event->ies)
+		nla_put(msg, NL80211_ATTR_IE, ft_event->ies_len, ft_event->ies);
+	if (ft_event->ric_ies)
+		nla_put(msg, NL80211_ATTR_IE_RIC, ft_event->ric_ies_len,
+			ft_event->ric_ies);
+
+	err = genlmsg_end(msg, hdr);
+	if (err < 0) {
+		nlmsg_free(msg);
+		return;
+	}
+
+	genlmsg_multicast_netns(wiphy_net(&rdev->wiphy), msg, 0,
+				nl80211_mlme_mcgrp.id, GFP_KERNEL);
+}
+EXPORT_SYMBOL(cfg80211_ft_event);
+
 /* initialisation/exit functions */
 
 int nl80211_init(void)
diff --git a/sound/soc/codecs/wcd9304.c b/sound/soc/codecs/wcd9304.c
index 36d5d6b..866f524 100644
--- a/sound/soc/codecs/wcd9304.c
+++ b/sound/soc/codecs/wcd9304.c
@@ -4850,8 +4850,10 @@
 
 	if (sitar) {
 		codec = sitar->codec;
-		if (sitar->hphlocp_cnt++ < SITAR_OCP_ATTEMPT) {
+		if ((sitar->hphlocp_cnt < SITAR_OCP_ATTEMPT) &&
+		    (!sitar->hphrocp_cnt)) {
 			pr_info("%s: retry\n", __func__);
+			sitar->hphlocp_cnt++;
 			snd_soc_update_bits(codec, SITAR_A_RX_HPH_OCP_CTL, 0x10,
 					    0x00);
 			snd_soc_update_bits(codec, SITAR_A_RX_HPH_OCP_CTL, 0x10,
@@ -4859,7 +4861,6 @@
 		} else {
 			wcd9xxx_disable_irq(codec->control_data,
 					    WCD9XXX_IRQ_HPH_PA_OCPL_FAULT);
-			sitar->hphlocp_cnt = 0;
 			sitar->hph_status |= SND_JACK_OC_HPHL;
 			if (sitar->mbhc_cfg.headset_jack)
 				sitar_snd_soc_jack_report(sitar,
@@ -4883,8 +4884,10 @@
 
 	if (sitar) {
 		codec = sitar->codec;
-		if (sitar->hphrocp_cnt++ < SITAR_OCP_ATTEMPT) {
+		if ((sitar->hphrocp_cnt < SITAR_OCP_ATTEMPT) &&
+		    (!sitar->hphlocp_cnt)) {
 			pr_info("%s: retry\n", __func__);
+			sitar->hphrocp_cnt++;
 			snd_soc_update_bits(codec, SITAR_A_RX_HPH_OCP_CTL, 0x10,
 					   0x00);
 			snd_soc_update_bits(codec, SITAR_A_RX_HPH_OCP_CTL, 0x10,
@@ -4892,7 +4895,6 @@
 		} else {
 			wcd9xxx_disable_irq(codec->control_data,
 					    WCD9XXX_IRQ_HPH_PA_OCPR_FAULT);
-			sitar->hphrocp_cnt = 0;
 			sitar->hph_status |= SND_JACK_OC_HPHR;
 			if (sitar->mbhc_cfg.headset_jack)
 				sitar_snd_soc_jack_report(sitar,
diff --git a/sound/soc/codecs/wcd9320.c b/sound/soc/codecs/wcd9320.c
index 5f4490b..8f63250 100644
--- a/sound/soc/codecs/wcd9320.c
+++ b/sound/soc/codecs/wcd9320.c
@@ -204,8 +204,21 @@
 #define TAIKO_TX_PORT_NUMBER	16
 
 #define TAIKO_I2S_MASTER_MODE_MASK 0x08
-#define TAIKO_MCLK_CLK_12P288MHZ 12288000
-#define TAIKO_MCLK_CLK_9P6HZ 9600000
+
+#define TAIKO_DMIC_SAMPLE_RATE_DIV_2	0x0
+#define TAIKO_DMIC_SAMPLE_RATE_DIV_3	0x1
+#define TAIKO_DMIC_SAMPLE_RATE_DIV_4	0x2
+
+#define TAIKO_DMIC_B1_CTL_DIV_2 0x00
+#define TAIKO_DMIC_B1_CTL_DIV_3 0x22
+#define TAIKO_DMIC_B1_CTL_DIV_4 0x44
+
+#define TAIKO_DMIC_B2_CTL_DIV_2 0x00
+#define TAIKO_DMIC_B2_CTL_DIV_3 0x02
+#define TAIKO_DMIC_B2_CTL_DIV_4 0x04
+
+#define TAIKO_ANC_DMIC_X2_ON	0x1
+#define TAIKO_ANC_DMIC_X2_OFF	0x0
 
 #define TAIKO_SLIM_CLOSE_TIMEOUT 1000
 #define TAIKO_SLIM_IRQ_OVERFLOW (1 << 0)
@@ -1061,6 +1074,21 @@
 		40, digital_gain),
 	SOC_SINGLE_S8_TLV("IIR1 INP4 Volume", TAIKO_A_CDC_IIR1_GAIN_B4_CTL, -84,
 		40, digital_gain),
+	SOC_SINGLE_S8_TLV("IIR2 INP1 Volume", TAIKO_A_CDC_IIR2_GAIN_B1_CTL, -84,
+		40, digital_gain),
+	SOC_SINGLE_S8_TLV("IIR2 INP2 Volume", TAIKO_A_CDC_IIR2_GAIN_B2_CTL, -84,
+		40, digital_gain),
+	SOC_SINGLE_S8_TLV("IIR2 INP3 Volume", TAIKO_A_CDC_IIR2_GAIN_B3_CTL, -84,
+		40, digital_gain),
+	SOC_SINGLE_S8_TLV("IIR2 INP4 Volume", TAIKO_A_CDC_IIR2_GAIN_B4_CTL, -84,
+		40, digital_gain),
+	SOC_SINGLE_TLV("ADC1 Volume", TAIKO_A_TX_1_2_EN, 5, 3, 0, analog_gain),
+	SOC_SINGLE_TLV("ADC2 Volume", TAIKO_A_TX_1_2_EN, 1, 3, 0, analog_gain),
+	SOC_SINGLE_TLV("ADC3 Volume", TAIKO_A_TX_3_4_EN, 5, 3, 0, analog_gain),
+	SOC_SINGLE_TLV("ADC4 Volume", TAIKO_A_TX_3_4_EN, 1, 3, 0, analog_gain),
+	SOC_SINGLE_TLV("ADC5 Volume", TAIKO_A_TX_5_6_EN, 5, 3, 0, analog_gain),
+	SOC_SINGLE_TLV("ADC6 Volume", TAIKO_A_TX_5_6_EN, 1, 3, 0, analog_gain),
+
 
 	SOC_SINGLE_EXT("ANC Slot", SND_SOC_NOPM, 0, 100, 0, taiko_get_anc_slot,
 		taiko_put_anc_slot),
@@ -1375,7 +1403,7 @@
 	"ZERO", "EAR_HPH_L", "EAR_LINE_1",
 };
 
-static const char * const iir1_inp1_text[] = {
+static const char * const iir_inp1_text[] = {
 	"ZERO", "DEC1", "DEC2", "DEC3", "DEC4", "DEC5", "DEC6", "DEC7", "DEC8",
 	"DEC9", "DEC10", "RX1", "RX2", "RX3", "RX4", "RX5", "RX6", "RX7"
 };
@@ -1523,7 +1551,10 @@
 	SOC_ENUM_SINGLE(TAIKO_A_CDC_CONN_ANC_B2_CTL, 0, 3, anc1_fb_mux_text);
 
 static const struct soc_enum iir1_inp1_mux_enum =
-	SOC_ENUM_SINGLE(TAIKO_A_CDC_CONN_EQ1_B1_CTL, 0, 18, iir1_inp1_text);
+	SOC_ENUM_SINGLE(TAIKO_A_CDC_CONN_EQ1_B1_CTL, 0, 18, iir_inp1_text);
+
+static const struct soc_enum iir2_inp1_mux_enum =
+	SOC_ENUM_SINGLE(TAIKO_A_CDC_CONN_EQ2_B1_CTL, 0, 18, iir_inp1_text);
 
 static const struct snd_kcontrol_new rx_mix1_inp1_mux =
 	SOC_DAPM_ENUM("RX1 MIX1 INP1 Mux", rx_mix1_inp1_chain_enum);
@@ -1747,6 +1778,9 @@
 static const struct snd_kcontrol_new iir1_inp1_mux =
 	SOC_DAPM_ENUM("IIR1 INP1 Mux", iir1_inp1_mux_enum);
 
+static const struct snd_kcontrol_new iir2_inp1_mux =
+	SOC_DAPM_ENUM("IIR2 INP1 Mux", iir2_inp1_mux_enum);
+
 static const struct snd_kcontrol_new anc1_mux =
 	SOC_DAPM_ENUM("ANC1 MUX Mux", anc1_mux_enum);
 
@@ -3359,6 +3393,7 @@
 	{"RX1 MIX1 INP1", "RX6", "SLIM RX6"},
 	{"RX1 MIX1 INP1", "RX7", "SLIM RX7"},
 	{"RX1 MIX1 INP1", "IIR1", "IIR1"},
+	{"RX1 MIX1 INP1", "IIR2", "IIR2"},
 	{"RX1 MIX1 INP2", "RX1", "SLIM RX1"},
 	{"RX1 MIX1 INP2", "RX2", "SLIM RX2"},
 	{"RX1 MIX1 INP2", "RX3", "SLIM RX3"},
@@ -3367,6 +3402,7 @@
 	{"RX1 MIX1 INP2", "RX6", "SLIM RX6"},
 	{"RX1 MIX1 INP2", "RX7", "SLIM RX7"},
 	{"RX1 MIX1 INP2", "IIR1", "IIR1"},
+	{"RX1 MIX1 INP2", "IIR2", "IIR2"},
 	{"RX1 MIX1 INP3", "RX1", "SLIM RX1"},
 	{"RX1 MIX1 INP3", "RX2", "SLIM RX2"},
 	{"RX1 MIX1 INP3", "RX3", "SLIM RX3"},
@@ -3382,6 +3418,7 @@
 	{"RX2 MIX1 INP1", "RX6", "SLIM RX6"},
 	{"RX2 MIX1 INP1", "RX7", "SLIM RX7"},
 	{"RX2 MIX1 INP1", "IIR1", "IIR1"},
+	{"RX2 MIX1 INP1", "IIR2", "IIR2"},
 	{"RX2 MIX1 INP2", "RX1", "SLIM RX1"},
 	{"RX2 MIX1 INP2", "RX2", "SLIM RX2"},
 	{"RX2 MIX1 INP2", "RX3", "SLIM RX3"},
@@ -3390,6 +3427,7 @@
 	{"RX2 MIX1 INP2", "RX6", "SLIM RX6"},
 	{"RX2 MIX1 INP2", "RX7", "SLIM RX7"},
 	{"RX2 MIX1 INP2", "IIR1", "IIR1"},
+	{"RX2 MIX1 INP2", "IIR2", "IIR2"},
 	{"RX3 MIX1 INP1", "RX1", "SLIM RX1"},
 	{"RX3 MIX1 INP1", "RX2", "SLIM RX2"},
 	{"RX3 MIX1 INP1", "RX3", "SLIM RX3"},
@@ -3398,6 +3436,7 @@
 	{"RX3 MIX1 INP1", "RX6", "SLIM RX6"},
 	{"RX3 MIX1 INP1", "RX7", "SLIM RX7"},
 	{"RX3 MIX1 INP1", "IIR1", "IIR1"},
+	{"RX3 MIX1 INP1", "IIR2", "IIR2"},
 	{"RX3 MIX1 INP2", "RX1", "SLIM RX1"},
 	{"RX3 MIX1 INP2", "RX2", "SLIM RX2"},
 	{"RX3 MIX1 INP2", "RX3", "SLIM RX3"},
@@ -3406,6 +3445,7 @@
 	{"RX3 MIX1 INP2", "RX6", "SLIM RX6"},
 	{"RX3 MIX1 INP2", "RX7", "SLIM RX7"},
 	{"RX3 MIX1 INP2", "IIR1", "IIR1"},
+	{"RX3 MIX1 INP2", "IIR2", "IIR2"},
 	{"RX4 MIX1 INP1", "RX1", "SLIM RX1"},
 	{"RX4 MIX1 INP1", "RX2", "SLIM RX2"},
 	{"RX4 MIX1 INP1", "RX3", "SLIM RX3"},
@@ -3414,6 +3454,7 @@
 	{"RX4 MIX1 INP1", "RX6", "SLIM RX6"},
 	{"RX4 MIX1 INP1", "RX7", "SLIM RX7"},
 	{"RX4 MIX1 INP1", "IIR1", "IIR1"},
+	{"RX4 MIX1 INP1", "IIR2", "IIR2"},
 	{"RX4 MIX1 INP2", "RX1", "SLIM RX1"},
 	{"RX4 MIX1 INP2", "RX2", "SLIM RX2"},
 	{"RX4 MIX1 INP2", "RX3", "SLIM RX3"},
@@ -3422,6 +3463,7 @@
 	{"RX4 MIX1 INP2", "RX6", "SLIM RX6"},
 	{"RX4 MIX1 INP2", "RX7", "SLIM RX7"},
 	{"RX4 MIX1 INP2", "IIR1", "IIR1"},
+	{"RX4 MIX1 INP2", "IIR2", "IIR2"},
 	{"RX5 MIX1 INP1", "RX1", "SLIM RX1"},
 	{"RX5 MIX1 INP1", "RX2", "SLIM RX2"},
 	{"RX5 MIX1 INP1", "RX3", "SLIM RX3"},
@@ -3430,6 +3472,7 @@
 	{"RX5 MIX1 INP1", "RX6", "SLIM RX6"},
 	{"RX5 MIX1 INP1", "RX7", "SLIM RX7"},
 	{"RX5 MIX1 INP1", "IIR1", "IIR1"},
+	{"RX5 MIX1 INP1", "IIR2", "IIR2"},
 	{"RX5 MIX1 INP2", "RX1", "SLIM RX1"},
 	{"RX5 MIX1 INP2", "RX2", "SLIM RX2"},
 	{"RX5 MIX1 INP2", "RX3", "SLIM RX3"},
@@ -3438,6 +3481,7 @@
 	{"RX5 MIX1 INP2", "RX6", "SLIM RX6"},
 	{"RX5 MIX1 INP2", "RX7", "SLIM RX7"},
 	{"RX5 MIX1 INP2", "IIR1", "IIR1"},
+	{"RX5 MIX1 INP2", "IIR2", "IIR2"},
 	{"RX6 MIX1 INP1", "RX1", "SLIM RX1"},
 	{"RX6 MIX1 INP1", "RX2", "SLIM RX2"},
 	{"RX6 MIX1 INP1", "RX3", "SLIM RX3"},
@@ -3446,6 +3490,7 @@
 	{"RX6 MIX1 INP1", "RX6", "SLIM RX6"},
 	{"RX6 MIX1 INP1", "RX7", "SLIM RX7"},
 	{"RX6 MIX1 INP1", "IIR1", "IIR1"},
+	{"RX6 MIX1 INP1", "IIR2", "IIR2"},
 	{"RX6 MIX1 INP2", "RX1", "SLIM RX1"},
 	{"RX6 MIX1 INP2", "RX2", "SLIM RX2"},
 	{"RX6 MIX1 INP2", "RX3", "SLIM RX3"},
@@ -3454,6 +3499,7 @@
 	{"RX6 MIX1 INP2", "RX6", "SLIM RX6"},
 	{"RX6 MIX1 INP2", "RX7", "SLIM RX7"},
 	{"RX6 MIX1 INP2", "IIR1", "IIR1"},
+	{"RX6 MIX1 INP2", "IIR2", "IIR2"},
 	{"RX7 MIX1 INP1", "RX1", "SLIM RX1"},
 	{"RX7 MIX1 INP1", "RX2", "SLIM RX2"},
 	{"RX7 MIX1 INP1", "RX3", "SLIM RX3"},
@@ -3462,6 +3508,7 @@
 	{"RX7 MIX1 INP1", "RX6", "SLIM RX6"},
 	{"RX7 MIX1 INP1", "RX7", "SLIM RX7"},
 	{"RX7 MIX1 INP1", "IIR1", "IIR1"},
+	{"RX7 MIX1 INP1", "IIR2", "IIR2"},
 	{"RX7 MIX1 INP2", "RX1", "SLIM RX1"},
 	{"RX7 MIX1 INP2", "RX2", "SLIM RX2"},
 	{"RX7 MIX1 INP2", "RX3", "SLIM RX3"},
@@ -3476,6 +3523,13 @@
 	{"RX2 MIX2 INP2", "IIR1", "IIR1"},
 	{"RX7 MIX2 INP1", "IIR1", "IIR1"},
 	{"RX7 MIX2 INP2", "IIR1", "IIR1"},
+	{"RX7 MIX1 INP2", "IIR2", "IIR2"},
+	{"RX1 MIX2 INP1", "IIR2", "IIR2"},
+	{"RX1 MIX2 INP2", "IIR2", "IIR2"},
+	{"RX2 MIX2 INP1", "IIR2", "IIR2"},
+	{"RX2 MIX2 INP2", "IIR2", "IIR2"},
+	{"RX7 MIX2 INP1", "IIR2", "IIR2"},
+	{"RX7 MIX2 INP2", "IIR2", "IIR2"},
 
 	/* Decimator Inputs */
 	{"DEC1 MUX", "DMIC1", "DMIC1"},
@@ -3548,6 +3602,18 @@
 	{"IIR1 INP1 MUX", "DEC9", "DEC9 MUX"},
 	{"IIR1 INP1 MUX", "DEC10", "DEC10 MUX"},
 
+	{"IIR2", NULL, "IIR2 INP1 MUX"},
+	{"IIR2 INP1 MUX", "DEC1", "DEC1 MUX"},
+	{"IIR2 INP1 MUX", "DEC2", "DEC2 MUX"},
+	{"IIR2 INP1 MUX", "DEC3", "DEC3 MUX"},
+	{"IIR2 INP1 MUX", "DEC4", "DEC4 MUX"},
+	{"IIR2 INP1 MUX", "DEC5", "DEC5 MUX"},
+	{"IIR2 INP1 MUX", "DEC6", "DEC6 MUX"},
+	{"IIR2 INP1 MUX", "DEC7", "DEC7 MUX"},
+	{"IIR2 INP1 MUX", "DEC8", "DEC8 MUX"},
+	{"IIR2 INP1 MUX", "DEC9", "DEC9 MUX"},
+	{"IIR2 INP1 MUX", "DEC10", "DEC10 MUX"},
+
 	{"MIC BIAS1 Internal1", NULL, "LDO_H"},
 	{"MIC BIAS1 Internal2", NULL, "LDO_H"},
 	{"MIC BIAS1 External", NULL, "LDO_H"},
@@ -5101,6 +5167,9 @@
 	SND_SOC_DAPM_MUX("IIR1 INP1 MUX", SND_SOC_NOPM, 0, 0, &iir1_inp1_mux),
 	SND_SOC_DAPM_PGA("IIR1", TAIKO_A_CDC_CLK_SD_CTL, 0, 0, NULL, 0),
 
+	SND_SOC_DAPM_MUX("IIR2 INP1 MUX", SND_SOC_NOPM, 0, 0, &iir2_inp1_mux),
+	SND_SOC_DAPM_PGA("IIR2", TAIKO_A_CDC_CLK_SD_CTL, 1, 0, NULL, 0),
+
 	/* AUX PGA */
 	SND_SOC_DAPM_ADC_E("AUX_PGA_Left", NULL, TAIKO_A_RX_AUX_SW_CTL, 7, 0,
 		taiko_codec_enable_aux_pga, SND_SOC_DAPM_PRE_PMU |
@@ -5208,6 +5277,9 @@
 	u8 leg_mode, txfe_bypass, txfe_buff, flag;
 	u8 i = 0, j = 0;
 	u8 val_txfe = 0, value = 0;
+	u8 dmic_sample_rate_value = 0;
+	u8 dmic_b1_ctl_value = 0, dmic_b2_ctl_value = 0;
+	u8 anc_ctl_value = 0;
 
 	if (!pdata) {
 		pr_err("%s: NULL pdata\n", __func__);
@@ -5338,6 +5410,96 @@
 		 0x00 : 0x16);
 	snd_soc_update_bits(codec, TAIKO_A_MICB_4_CTL, 0x1E, value);
 
+	/* Set the DMIC sample rate */
+	if (pdata->mclk_rate == TAIKO_MCLK_CLK_9P6HZ) {
+		switch (pdata->dmic_sample_rate) {
+		case TAIKO_DMIC_SAMPLE_RATE_2P4MHZ:
+			dmic_sample_rate_value = TAIKO_DMIC_SAMPLE_RATE_DIV_4;
+			dmic_b1_ctl_value = TAIKO_DMIC_B1_CTL_DIV_4;
+			dmic_b2_ctl_value = TAIKO_DMIC_B2_CTL_DIV_4;
+			anc_ctl_value = TAIKO_ANC_DMIC_X2_OFF;
+			break;
+		case TAIKO_DMIC_SAMPLE_RATE_4P8MHZ:
+			dmic_sample_rate_value = TAIKO_DMIC_SAMPLE_RATE_DIV_2;
+			dmic_b1_ctl_value = TAIKO_DMIC_B1_CTL_DIV_2;
+			dmic_b2_ctl_value = TAIKO_DMIC_B2_CTL_DIV_2;
+			anc_ctl_value = TAIKO_ANC_DMIC_X2_ON;
+			break;
+		case TAIKO_DMIC_SAMPLE_RATE_3P2MHZ:
+		case TAIKO_DMIC_SAMPLE_RATE_UNDEFINED:
+			dmic_sample_rate_value = TAIKO_DMIC_SAMPLE_RATE_DIV_3;
+			dmic_b1_ctl_value = TAIKO_DMIC_B1_CTL_DIV_3;
+			dmic_b2_ctl_value = TAIKO_DMIC_B2_CTL_DIV_3;
+			anc_ctl_value = TAIKO_ANC_DMIC_X2_OFF;
+			break;
+		default:
+			pr_err("%s Invalid sample rate %d for mclk %d\n",
+			__func__, pdata->dmic_sample_rate, pdata->mclk_rate);
+			rc = -EINVAL;
+			goto done;
+			break;
+		}
+	} else if (pdata->mclk_rate == TAIKO_MCLK_CLK_12P288MHZ) {
+		switch (pdata->dmic_sample_rate) {
+		case TAIKO_DMIC_SAMPLE_RATE_3P072MHZ:
+			dmic_sample_rate_value = TAIKO_DMIC_SAMPLE_RATE_DIV_4;
+			dmic_b1_ctl_value = TAIKO_DMIC_B1_CTL_DIV_4;
+			dmic_b2_ctl_value = TAIKO_DMIC_B2_CTL_DIV_4;
+			anc_ctl_value = TAIKO_ANC_DMIC_X2_OFF;
+			break;
+		case TAIKO_DMIC_SAMPLE_RATE_6P144MHZ:
+			dmic_sample_rate_value = TAIKO_DMIC_SAMPLE_RATE_DIV_2;
+			dmic_b1_ctl_value = TAIKO_DMIC_B1_CTL_DIV_2;
+			dmic_b2_ctl_value = TAIKO_DMIC_B2_CTL_DIV_2;
+			anc_ctl_value = TAIKO_ANC_DMIC_X2_ON;
+			break;
+		case TAIKO_DMIC_SAMPLE_RATE_4P096MHZ:
+		case TAIKO_DMIC_SAMPLE_RATE_UNDEFINED:
+			dmic_sample_rate_value = TAIKO_DMIC_SAMPLE_RATE_DIV_3;
+			dmic_b1_ctl_value = TAIKO_DMIC_B1_CTL_DIV_3;
+			dmic_b2_ctl_value = TAIKO_DMIC_B2_CTL_DIV_3;
+			anc_ctl_value = TAIKO_ANC_DMIC_X2_OFF;
+			break;
+		default:
+			pr_err("%s Invalid sample rate %d for mclk %d\n",
+			__func__, pdata->dmic_sample_rate, pdata->mclk_rate);
+			rc = -EINVAL;
+			goto done;
+			break;
+		}
+	} else {
+		pr_err("%s MCLK is not set!\n", __func__);
+		rc = -EINVAL;
+		goto done;
+	}
+
+	snd_soc_update_bits(codec, TAIKO_A_CDC_TX1_DMIC_CTL,
+		0x7, dmic_sample_rate_value);
+	snd_soc_update_bits(codec, TAIKO_A_CDC_TX2_DMIC_CTL,
+		0x7, dmic_sample_rate_value);
+	snd_soc_update_bits(codec, TAIKO_A_CDC_TX3_DMIC_CTL,
+		0x7, dmic_sample_rate_value);
+	snd_soc_update_bits(codec, TAIKO_A_CDC_TX4_DMIC_CTL,
+		0x7, dmic_sample_rate_value);
+	snd_soc_update_bits(codec, TAIKO_A_CDC_TX5_DMIC_CTL,
+		0x7, dmic_sample_rate_value);
+	snd_soc_update_bits(codec, TAIKO_A_CDC_TX6_DMIC_CTL,
+		0x7, dmic_sample_rate_value);
+	snd_soc_update_bits(codec, TAIKO_A_CDC_TX7_DMIC_CTL,
+		0x7, dmic_sample_rate_value);
+	snd_soc_update_bits(codec, TAIKO_A_CDC_TX8_DMIC_CTL,
+		0x7, dmic_sample_rate_value);
+	snd_soc_update_bits(codec, TAIKO_A_CDC_TX9_DMIC_CTL,
+		0x7, dmic_sample_rate_value);
+	snd_soc_update_bits(codec, TAIKO_A_CDC_TX10_DMIC_CTL,
+		0x7, dmic_sample_rate_value);
+	snd_soc_update_bits(codec, TAIKO_A_CDC_CLK_DMIC_B1_CTL,
+		0xEE, dmic_b1_ctl_value);
+	snd_soc_update_bits(codec, TAIKO_A_CDC_CLK_DMIC_B2_CTL,
+		0xE, dmic_b2_ctl_value);
+	snd_soc_update_bits(codec, TAIKO_A_CDC_ANC1_B2_CTL,
+		0x1, anc_ctl_value);
+
 done:
 	return rc;
 }
@@ -5568,22 +5730,6 @@
 	{TAIKO_A_CDC_TX9_MUX_CTL, 0x8, 0x0},
 	{TAIKO_A_CDC_TX10_MUX_CTL, 0x8, 0x0},
 
-	/* config Decimator for DMIC CLK_MODE_1(3.2Mhz@9.6Mhz mclk) */
-	{TAIKO_A_CDC_TX1_DMIC_CTL, 0x7, 0x1},
-	{TAIKO_A_CDC_TX2_DMIC_CTL, 0x7, 0x1},
-	{TAIKO_A_CDC_TX3_DMIC_CTL, 0x7, 0x1},
-	{TAIKO_A_CDC_TX4_DMIC_CTL, 0x7, 0x1},
-	{TAIKO_A_CDC_TX5_DMIC_CTL, 0x7, 0x1},
-	{TAIKO_A_CDC_TX6_DMIC_CTL, 0x7, 0x1},
-	{TAIKO_A_CDC_TX7_DMIC_CTL, 0x7, 0x1},
-	{TAIKO_A_CDC_TX8_DMIC_CTL, 0x7, 0x1},
-	{TAIKO_A_CDC_TX9_DMIC_CTL, 0x7, 0x1},
-	{TAIKO_A_CDC_TX10_DMIC_CTL, 0x7, 0x1},
-
-	/* config DMIC clk to CLK_MODE_1 (3.2Mhz@9.6Mhz mclk) */
-	{TAIKO_A_CDC_CLK_DMIC_B1_CTL, 0xEE, 0x22},
-	{TAIKO_A_CDC_CLK_DMIC_B2_CTL, 0x0E, 0x02},
-
 	/* Compander zone selection */
 	{TAIKO_A_CDC_COMP0_B4_CTL, 0x3F, 0x37},
 	{TAIKO_A_CDC_COMP1_B4_CTL, 0x3F, 0x37},
diff --git a/sound/soc/msm/Kconfig b/sound/soc/msm/Kconfig
index 35a9646..66c475f 100644
--- a/sound/soc/msm/Kconfig
+++ b/sound/soc/msm/Kconfig
@@ -163,6 +163,16 @@
 	 OCMEM gets exercised for low-power
 	 audio and voice use cases.
 
+config DOLBY_DAP
+	bool "Enable Dolby DAP"
+	depends on SND_SOC_MSM8974
+	help
+	 To add support for dolby DAP post processing.
+	 This support is to configure the post processing parameters
+	 to DSP. The configuration includes sending the end point
+	 device, end point dependent post processing parameters and
+	 the various posrt processing parameters
+
 config SND_SOC_MSM8974
 	tristate "SoC Machine driver for MSM8974 boards"
 	depends on ARCH_MSM8974
@@ -173,6 +183,7 @@
 	select SND_SOC_MSM_HDMI_CODEC_RX
 	select SND_DYNAMIC_MINORS
 	select AUDIO_OCMEM
+	select DOLBY_DAP
 	help
 	 To add support for SoC audio on MSM8974.
 	 This will enable sound soc drivers which
diff --git a/sound/soc/msm/Makefile b/sound/soc/msm/Makefile
index c26eafc..ebde90b 100644
--- a/sound/soc/msm/Makefile
+++ b/sound/soc/msm/Makefile
@@ -62,12 +62,13 @@
 snd-soc-qdsp6-objs += msm-pcm-lpa.o msm-pcm-afe.o
 obj-$(CONFIG_SND_SOC_QDSP6) += snd-soc-qdsp6.o
 
+snd-soc-hostless-pcm-objs := msm-pcm-hostless.o
+obj-$(CONFIG_SND_SOC_MSM_HOSTLESS_PCM) += snd-soc-hostless-pcm.o
+
 snd-soc-msm8960-objs := msm8960.o apq8064.o msm8930.o mpq8064.o apq8064-i2s.o
 obj-$(CONFIG_SND_SOC_MSM8960) += snd-soc-msm8960.o
 
 # Generic MSM drivers
-snd-soc-hostless-pcm-objs := msm-pcm-hostless.o
-obj-$(CONFIG_SND_SOC_MSM_HOSTLESS_PCM) += snd-soc-hostless-pcm.o
 
 snd-soc-msm8660-apq-objs := msm8660-apq-wm8903.o
 obj-$(CONFIG_SND_SOC_MSM8660_APQ) += snd-soc-msm8660-apq.o
diff --git a/sound/soc/msm/apq8064-i2s.c b/sound/soc/msm/apq8064-i2s.c
index f9e0402..99defcd 100644
--- a/sound/soc/msm/apq8064-i2s.c
+++ b/sound/soc/msm/apq8064-i2s.c
@@ -2636,6 +2636,7 @@
 		pr_info("%s: Not APQ8064 in I2S mode\n", __func__);
 		return -ENODEV;
 	}
+	mutex_init(&cdc_mclk_mutex);
 	pr_debug("%s: APQ8064 is in I2S mode\n", __func__);
 	mbhc_cfg.calibration = def_tabla_mbhc_cal();
 	if (!mbhc_cfg.calibration) {
@@ -2680,7 +2681,6 @@
 		return ret;
 	}
 
-	mutex_init(&cdc_mclk_mutex);
 	atomic_set(&mi2s_rsc_ref, 0);
 	atomic_set(&auxpcm_rsc_ref, 0);
 	return ret;
diff --git a/sound/soc/msm/apq8064.c b/sound/soc/msm/apq8064.c
index cafc5c3..7960f13 100644
--- a/sound/soc/msm/apq8064.c
+++ b/sound/soc/msm/apq8064.c
@@ -2187,6 +2187,8 @@
 	if (socinfo_get_pmic_model() == PMIC_MODEL_PM8917)
 		bottom_spk_pamp_gpio = PM8921_GPIO_PM_TO_SYS(16);
 
+	mutex_init(&cdc_mclk_mutex);
+
 	mbhc_cfg.calibration = def_tabla_mbhc_cal();
 	if (!mbhc_cfg.calibration) {
 		pr_err("Calibration data allocation failed\n");
@@ -2208,7 +2210,6 @@
 		return ret;
 	}
 
-	mutex_init(&cdc_mclk_mutex);
 	atomic_set(&auxpcm_rsc_ref, 0);
 	return ret;
 
diff --git a/sound/soc/msm/msm-dai-fe.c b/sound/soc/msm/msm-dai-fe.c
index 734bd39..8db13f6 100644
--- a/sound/soc/msm/msm-dai-fe.c
+++ b/sound/soc/msm/msm-dai-fe.c
@@ -25,7 +25,7 @@
 /* Conventional and unconventional sample rate supported */
 static unsigned int supported_sample_rates[] = {
 	8000, 11025, 12000, 16000, 22050, 24000, 32000, 44100, 48000,
-	96000
+	96000, 192000
 };
 
 static struct snd_pcm_hw_constraint_list constraints_sample_rates = {
@@ -53,14 +53,14 @@
 		.playback = {
 			.stream_name = "Multimedia1 Playback",
 			.aif_name = "MM_DL1",
-			.rates = (SNDRV_PCM_RATE_8000_96000|
+			.rates = (SNDRV_PCM_RATE_8000_192000|
 					SNDRV_PCM_RATE_KNOT),
 			.formats = (SNDRV_PCM_FMTBIT_S16_LE |
 						SNDRV_PCM_FMTBIT_S24_LE),
 			.channels_min = 1,
 			.channels_max = 8,
 			.rate_min =     8000,
-			.rate_max =	96000,
+			.rate_max =	192000,
 		},
 		.capture = {
 			.stream_name = "Multimedia1 Capture",
@@ -80,14 +80,14 @@
 		.playback = {
 			.stream_name = "Multimedia2 Playback",
 			.aif_name = "MM_DL2",
-			.rates = (SNDRV_PCM_RATE_8000_96000|
+			.rates = (SNDRV_PCM_RATE_8000_192000|
 					SNDRV_PCM_RATE_KNOT),
 			.formats = (SNDRV_PCM_FMTBIT_S16_LE |
 						SNDRV_PCM_FMTBIT_S24_LE),
 			.channels_min = 1,
 			.channels_max = 8,
 			.rate_min =     8000,
-			.rate_max =	96000,
+			.rate_max =	192000,
 		},
 		.capture = {
 			.stream_name = "Multimedia2 Capture",
@@ -157,14 +157,14 @@
 		.playback = {
 			.stream_name = "MultiMedia3 Playback",
 			.aif_name = "MM_DL3",
-			.rates = (SNDRV_PCM_RATE_8000_96000 |
+			.rates = (SNDRV_PCM_RATE_8000_192000 |
 					SNDRV_PCM_RATE_KNOT),
 			.formats = (SNDRV_PCM_FMTBIT_S16_LE |
 						SNDRV_PCM_FMTBIT_S24_LE),
 			.channels_min = 1,
 			.channels_max = 6,
 			.rate_min =	8000,
-			.rate_max = 96000,
+			.rate_max = 192000,
 		},
 		.ops = &msm_fe_Multimedia_dai_ops,
 		.name = "MultiMedia3",
@@ -173,14 +173,14 @@
 		.playback = {
 			.stream_name = "MultiMedia4 Playback",
 			.aif_name = "MM_DL4",
-			.rates = (SNDRV_PCM_RATE_8000_96000 |
+			.rates = (SNDRV_PCM_RATE_8000_192000 |
 					SNDRV_PCM_RATE_KNOT),
 			.formats = (SNDRV_PCM_FMTBIT_S16_LE |
 						SNDRV_PCM_FMTBIT_S24_LE),
 			.channels_min = 1,
 			.channels_max = 8,
 			.rate_min =	8000,
-			.rate_max = 96000,
+			.rate_max = 192000,
 		},
 		.capture = {
 			.stream_name = "MultiMedia4 Capture",
@@ -200,14 +200,14 @@
 		.playback = {
 			.stream_name = "MultiMedia5 Playback",
 			.aif_name = "MM_DL5",
-			.rates = (SNDRV_PCM_RATE_8000_96000 |
+			.rates = (SNDRV_PCM_RATE_8000_192000 |
 					SNDRV_PCM_RATE_KNOT),
 			.formats = (SNDRV_PCM_FMTBIT_S16_LE |
 						SNDRV_PCM_FMTBIT_S24_LE),
 			.channels_min = 1,
 			.channels_max = 8,
 			.rate_min =	8000,
-			.rate_max = 96000,
+			.rate_max = 192000,
 		},
 		.capture = {
 			.stream_name = "MultiMedia5 Capture",
@@ -227,14 +227,14 @@
 		.playback = {
 			.stream_name = "MultiMedia6 Playback",
 			.aif_name = "MM_DL6",
-			.rates = (SNDRV_PCM_RATE_8000_96000 |
+			.rates = (SNDRV_PCM_RATE_8000_192000 |
 					SNDRV_PCM_RATE_KNOT),
 			.formats = (SNDRV_PCM_FMTBIT_S16_LE |
 						SNDRV_PCM_FMTBIT_S24_LE),
 			.channels_min = 1,
 			.channels_max = 8,
 			.rate_min =	8000,
-			.rate_max = 96000,
+			.rate_max = 192000,
 		},
 		.ops = &msm_fe_Multimedia_dai_ops,
 		.name = "MultiMedia6",
@@ -243,14 +243,14 @@
 		.playback = {
 			.stream_name = "MultiMedia7 Playback",
 			.aif_name = "MM_DL7",
-			.rates = (SNDRV_PCM_RATE_8000_96000 |
+			.rates = (SNDRV_PCM_RATE_8000_192000 |
 					SNDRV_PCM_RATE_KNOT),
 			.formats = (SNDRV_PCM_FMTBIT_S16_LE |
 						SNDRV_PCM_FMTBIT_S24_LE),
 			.channels_min = 1,
 			.channels_max = 8,
 			.rate_min =	8000,
-			.rate_max = 96000,
+			.rate_max = 192000,
 		},
 		.ops = &msm_fe_Multimedia_dai_ops,
 		.name = "MultiMedia7",
@@ -259,14 +259,14 @@
 		.playback = {
 			.stream_name = "MultiMedia8 Playback",
 			.aif_name = "MM_DL8",
-			.rates = (SNDRV_PCM_RATE_8000_96000 |
+			.rates = (SNDRV_PCM_RATE_8000_192000 |
 					SNDRV_PCM_RATE_KNOT),
 			.formats = (SNDRV_PCM_FMTBIT_S16_LE |
 						SNDRV_PCM_FMTBIT_S24_LE),
 			.channels_min = 1,
 			.channels_max = 8,
 			.rate_min =	8000,
-			.rate_max = 96000,
+			.rate_max = 192000,
 		},
 		.ops = &msm_fe_Multimedia_dai_ops,
 		.name = "MultiMedia8",
@@ -276,7 +276,7 @@
 		.playback = {
 			.stream_name = "SLIMBUS0 Hostless Playback",
 			.aif_name = "SLIM0_DL_HL",
-			.rates = SNDRV_PCM_RATE_8000_96000,
+			.rates = SNDRV_PCM_RATE_8000_192000,
 			.formats = (SNDRV_PCM_FMTBIT_S16_LE |
 						SNDRV_PCM_FMTBIT_S24_LE),
 			.channels_min = 1,
@@ -301,13 +301,13 @@
 		.playback = {
 			.stream_name = "SLIMBUS1 Hostless Playback",
 			.aif_name = "SLIM1_DL_HL",
-			.rates = SNDRV_PCM_RATE_8000_96000,
+			.rates = SNDRV_PCM_RATE_8000_192000,
 			.formats = (SNDRV_PCM_FMTBIT_S16_LE |
 						SNDRV_PCM_FMTBIT_S24_LE),
 			.channels_min = 1,
 			.channels_max = 2,
 			.rate_min =     8000,
-			.rate_max =     96000,
+			.rate_max =     192000,
 		},
 		.capture = {
 			.stream_name = "SLIMBUS1 Hostless Capture",
@@ -326,13 +326,13 @@
 		.playback = {
 			.stream_name = "SLIMBUS3 Hostless Playback",
 			.aif_name = "SLIM3_DL_HL",
-			.rates = SNDRV_PCM_RATE_8000_48000,
+			.rates = SNDRV_PCM_RATE_8000_192000,
 			.formats = (SNDRV_PCM_FMTBIT_S16_LE |
 						SNDRV_PCM_FMTBIT_S24_LE),
 			.channels_min = 1,
 			.channels_max = 2,
 			.rate_min =     8000,
-			.rate_max =     48000,
+			.rate_max =     192000,
 		},
 		.capture = {
 			.stream_name = "SLIMBUS3 Hostless Capture",
@@ -351,13 +351,13 @@
 		.playback = {
 			.stream_name = "SLIMBUS4 Hostless Playback",
 			.aif_name = "SLIM4_DL_HL",
-			.rates = SNDRV_PCM_RATE_8000_96000,
+			.rates = SNDRV_PCM_RATE_8000_192000,
 			.formats = (SNDRV_PCM_FMTBIT_S16_LE |
 						SNDRV_PCM_FMTBIT_S24_LE),
 			.channels_min = 1,
 			.channels_max = 2,
 			.rate_min =     8000,
-			.rate_max =     48000,
+			.rate_max =     192000,
 		},
 		.capture = {
 			.stream_name = "SLIMBUS4 Hostless Capture",
diff --git a/sound/soc/msm/msm-pcm-afe.c b/sound/soc/msm/msm-pcm-afe.c
index a3bcf23..35b5dcf 100644
--- a/sound/soc/msm/msm-pcm-afe.c
+++ b/sound/soc/msm/msm-pcm-afe.c
@@ -30,7 +30,6 @@
 #include <sound/q6adm.h>
 #include <asm/dma.h>
 #include <linux/memory_alloc.h>
-#include <mach/msm_subsystem_map.h>
 #include "msm-pcm-afe.h"
 #include "msm-pcm-q6.h"
 
diff --git a/sound/soc/msm/msm8930.c b/sound/soc/msm/msm8930.c
index 2bd5c88..737317c 100644
--- a/sound/soc/msm/msm8930.c
+++ b/sound/soc/msm/msm8930.c
@@ -63,6 +63,7 @@
 static int clk_users;
 
 static int msm8930_headset_gpios_configured;
+static struct mutex cdc_mclk_mutex;
 
 static struct snd_soc_jack hs_jack;
 static struct snd_soc_jack button_jack;
@@ -265,35 +266,42 @@
 		struct snd_soc_codec *codec, int enable,
 		bool dapm)
 {
+	int r = 0;
 	pr_debug("%s: enable = %d\n", __func__, enable);
+
+	mutex_lock(&cdc_mclk_mutex);
 	if (enable) {
 		clk_users++;
 		pr_debug("%s: clk_users = %d\n", __func__, clk_users);
-		if (clk_users != 1)
-			return 0;
-
-		if (codec_clk) {
-			clk_set_rate(codec_clk, SITAR_EXT_CLK_RATE);
-			clk_prepare_enable(codec_clk);
-			sitar_mclk_enable(codec, 1, dapm);
-		} else {
-			pr_err("%s: Error setting Sitar MCLK\n", __func__);
-			clk_users--;
-			return -EINVAL;
+		if (clk_users == 1) {
+			if (codec_clk) {
+				clk_set_rate(codec_clk, SITAR_EXT_CLK_RATE);
+				clk_prepare_enable(codec_clk);
+				sitar_mclk_enable(codec, 1, dapm);
+			} else {
+				pr_err("%s: Error setting Sitar MCLK\n",
+					__func__);
+				clk_users--;
+				r = -EINVAL;
+			}
 		}
 	} else {
-		pr_debug("%s: clk_users = %d\n", __func__, clk_users);
-		if (clk_users == 0)
-			return 0;
-		clk_users--;
-		if (!clk_users) {
-			pr_debug("%s: disabling MCLK. clk_users = %d\n",
+		if (clk_users > 0) {
+			clk_users--;
+			pr_debug("%s: clk_users = %d\n", __func__, clk_users);
+			if (clk_users == 0) {
+				pr_debug("%s: disabling MCLK. clk_users = %d\n",
 					 __func__, clk_users);
-			sitar_mclk_enable(codec, 0, dapm);
-			clk_disable_unprepare(codec_clk);
+				sitar_mclk_enable(codec, 0, dapm);
+				clk_disable_unprepare(codec_clk);
+			}
+		} else {
+			pr_err("%s: Error releasing Sitar MCLK\n", __func__);
+			r = -EINVAL;
 		}
 	}
-	return 0;
+	mutex_unlock(&cdc_mclk_mutex);
+	return r;
 }
 
 static int msm8930_mclk_event(struct snd_soc_dapm_widget *w,
@@ -1378,6 +1386,7 @@
 		msm8930_headset_gpios_configured = 1;
 
 	atomic_set(&auxpcm_rsc_ref, 0);
+	mutex_init(&cdc_mclk_mutex);
 	return ret;
 
 }
@@ -1392,6 +1401,7 @@
 	msm8930_free_headset_mic_gpios();
 	platform_device_unregister(msm8930_snd_device);
 	kfree(mbhc_cfg.calibration);
+	mutex_destroy(&cdc_mclk_mutex);
 }
 module_exit(msm8930_audio_exit);
 
diff --git a/sound/soc/msm/msm8960.c b/sound/soc/msm/msm8960.c
index 65b3a57..c7fbc43 100644
--- a/sound/soc/msm/msm8960.c
+++ b/sound/soc/msm/msm8960.c
@@ -1778,6 +1778,7 @@
 		return -ENODEV ;
 	}
 
+	mutex_init(&cdc_mclk_mutex);
 	mbhc_cfg.calibration = def_tabla_mbhc_cal();
 	if (!mbhc_cfg.calibration) {
 		pr_err("Calibration data allocation failed\n");
@@ -1837,7 +1838,6 @@
 								__func__);
 	}
 
-	mutex_init(&cdc_mclk_mutex);
 	atomic_set(&auxpcm_rsc_ref, 0);
 	return ret;
 
diff --git a/sound/soc/msm/msm8974.c b/sound/soc/msm/msm8974.c
index 30e9629..9ff968f 100644
--- a/sound/soc/msm/msm8974.c
+++ b/sound/soc/msm/msm8974.c
@@ -48,6 +48,7 @@
 
 #define SAMPLING_RATE_48KHZ 48000
 #define SAMPLING_RATE_96KHZ 96000
+#define SAMPLING_RATE_192KHZ 192000
 
 static int msm8974_auxpcm_rate = 8000;
 #define LO_1_SPK_AMP	0x1
@@ -137,19 +138,28 @@
 	u32 mclk_freq;
 	int us_euro_gpio;
 	struct msm_auxpcm_ctrl *pri_auxpcm_ctrl;
+	struct msm_auxpcm_ctrl *sec_auxpcm_ctrl;
 };
 
 #define GPIO_NAME_INDEX 0
 #define DT_PARSE_INDEX  1
 
-static char *msm_auxpcm_gpio_name[][2] = {
-	{"PRIM_AUXPCM_CLK",       "prim-auxpcm-gpio-clk"},
-	{"PRIM_AUXPCM_SYNC",      "prim-auxpcm-gpio-sync"},
-	{"PRIM_AUXPCM_DIN",       "prim-auxpcm-gpio-din"},
-	{"PRIM_AUXPCM_DOUT",      "prim-auxpcm-gpio-dout"},
+static char *msm_prim_auxpcm_gpio_name[][2] = {
+	{"PRIM_AUXPCM_CLK",       "qcom,prim-auxpcm-gpio-clk"},
+	{"PRIM_AUXPCM_SYNC",      "qcom,prim-auxpcm-gpio-sync"},
+	{"PRIM_AUXPCM_DIN",       "qcom,prim-auxpcm-gpio-din"},
+	{"PRIM_AUXPCM_DOUT",      "qcom,prim-auxpcm-gpio-dout"},
+};
+
+static char *msm_sec_auxpcm_gpio_name[][2] = {
+	{"SEC_AUXPCM_CLK",       "qcom,sec-auxpcm-gpio-clk"},
+	{"SEC_AUXPCM_SYNC",      "qcom,sec-auxpcm-gpio-sync"},
+	{"SEC_AUXPCM_DIN",       "qcom,sec-auxpcm-gpio-din"},
+	{"SEC_AUXPCM_DOUT",      "qcom,sec-auxpcm-gpio-dout"},
 };
 
 void *lpaif_pri_muxsel_virt_addr;
+void *lpaif_sec_muxsel_virt_addr;
 
 struct msm8974_liquid_dock_dev {
 	int dock_plug_gpio;
@@ -187,7 +197,8 @@
 static struct mutex cdc_mclk_mutex;
 static struct q_clkdiv *codec_clk;
 static int clk_users;
-static atomic_t auxpcm_rsc_ref;
+static atomic_t prim_auxpcm_rsc_ref;
+static atomic_t sec_auxpcm_rsc_ref;
 
 
 static int msm8974_liquid_ext_spk_power_amp_init(void)
@@ -577,13 +588,8 @@
 static char const *hdmi_rx_ch_text[] = {"Two", "Three", "Four", "Five",
 					"Six", "Seven", "Eight"};
 static char const *rx_bit_format_text[] = {"S16_LE", "S24_LE"};
-static char const *slim0_rx_sample_rate_text[] = {"KHZ_48", "KHZ_96"};
-
-static const struct soc_enum msm_enum[] = {
-	SOC_ENUM_SINGLE_EXT(2, spk_function),
-	SOC_ENUM_SINGLE_EXT(2, slim0_rx_ch_text),
-	SOC_ENUM_SINGLE_EXT(4, slim0_tx_ch_text),
-};
+static char const *slim0_rx_sample_rate_text[] = {"KHZ_48", "KHZ_96",
+					"KHZ_192"};
 
 static const char *const btsco_rate_text[] = {"8000", "16000"};
 static const struct soc_enum msm_btsco_enum[] = {
@@ -596,6 +602,10 @@
 	int sample_rate_val = 0;
 
 	switch (slim0_rx_sample_rate) {
+	case SAMPLING_RATE_192KHZ:
+		sample_rate_val = 2;
+		break;
+
 	case SAMPLING_RATE_96KHZ:
 		sample_rate_val = 1;
 		break;
@@ -620,6 +630,9 @@
 			ucontrol->value.integer.value[0]);
 
 	switch (ucontrol->value.integer.value[0]) {
+	case 2:
+		slim0_rx_sample_rate = SAMPLING_RATE_192KHZ;
+		break;
 	case 1:
 		slim0_rx_sample_rate = SAMPLING_RATE_96KHZ;
 		break;
@@ -891,30 +904,13 @@
 	return 0;
 }
 
-static int msm_aux_pcm_get_gpios(struct snd_pcm_substream *substream)
+static int msm_aux_pcm_get_gpios(struct msm_auxpcm_ctrl *auxpcm_ctrl)
 {
-	struct snd_soc_pcm_runtime *rtd = substream->private_data;
-	struct snd_soc_card *card = rtd->card;
-	struct msm8974_asoc_mach_data *pdata = snd_soc_card_get_drvdata(card);
-	struct msm_auxpcm_ctrl *auxpcm_ctrl = NULL;
 	struct msm_auxpcm_gpio *pin_data = NULL;
 	int ret = 0;
 	int i;
 	int j;
 
-	if (pdata == NULL) {
-		pr_err("%s: pdata is NULL\n", __func__);
-		ret = -EINVAL;
-		goto err;
-	}
-
-	auxpcm_ctrl = pdata->pri_auxpcm_ctrl;
-
-	if (auxpcm_ctrl == NULL || auxpcm_ctrl->pin_data == NULL) {
-		pr_err("%s: Ctrl pointers are NULL\n", __func__);
-		ret = -EINVAL;
-		goto err;
-	}
 	pin_data = auxpcm_ctrl->pin_data;
 	for (i = 0; i < auxpcm_ctrl->cnt; i++, pin_data++) {
 		ret = gpio_request(pin_data->gpio_no,
@@ -930,31 +926,17 @@
 			/* Release all GPIOs on failure */
 			for (j = i; j >= 0; j--)
 				gpio_free(pin_data->gpio_no);
-			goto err;
+			return ret;
 		}
 	}
-
-err:
-	return ret;
+	return 0;
 }
 
-static int msm_aux_pcm_free_gpios(struct snd_pcm_substream *substream)
+static int msm_aux_pcm_free_gpios(struct msm_auxpcm_ctrl *auxpcm_ctrl)
 {
-	struct snd_soc_pcm_runtime *rtd = substream->private_data;
-	struct snd_soc_card *card = rtd->card;
-	struct msm8974_asoc_mach_data *pdata = snd_soc_card_get_drvdata(card);
-	struct msm_auxpcm_ctrl *auxpcm_ctrl = NULL;
 	struct msm_auxpcm_gpio *pin_data = NULL;
-	int ret = 0;
 	int i;
-
-	if (pdata == NULL) {
-		pr_err("%s: pdata is NULL\n", __func__);
-		ret = -EINVAL;
-		goto err;
-	}
-
-	auxpcm_ctrl = pdata->pri_auxpcm_ctrl;
+	int ret = 0;
 
 	if (auxpcm_ctrl == NULL || auxpcm_ctrl->pin_data == NULL) {
 		pr_err("%s: Ctrl pointers are NULL\n", __func__);
@@ -973,40 +955,115 @@
 	return ret;
 }
 
-static int msm_auxpcm_startup(struct snd_pcm_substream *substream)
+static int msm_prim_auxpcm_startup(struct snd_pcm_substream *substream)
 {
+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
+	struct snd_soc_card *card = rtd->card;
+	struct msm8974_asoc_mach_data *pdata = snd_soc_card_get_drvdata(card);
+	struct msm_auxpcm_ctrl *auxpcm_ctrl = NULL;
 	int ret = 0;
 
-	pr_debug("%s(): substream = %s, auxpcm_rsc_ref counter = %d\n",
-		__func__, substream->name, atomic_read(&auxpcm_rsc_ref));
+	pr_debug("%s(): substream = %s, prim_auxpcm_rsc_ref counter = %d\n",
+		__func__, substream->name, atomic_read(&prim_auxpcm_rsc_ref));
 
-	if (atomic_inc_return(&auxpcm_rsc_ref) == 1) {
+	auxpcm_ctrl = pdata->pri_auxpcm_ctrl;
+
+	if (auxpcm_ctrl == NULL || auxpcm_ctrl->pin_data == NULL) {
+		pr_err("%s: Ctrl pointers are NULL\n", __func__);
+		ret = -EINVAL;
+		goto err;
+	}
+	if (atomic_inc_return(&prim_auxpcm_rsc_ref) == 1) {
 		if (lpaif_pri_muxsel_virt_addr != NULL)
 			iowrite32(I2S_PCM_SEL << I2S_PCM_SEL_OFFSET,
 				lpaif_pri_muxsel_virt_addr);
 		else
 			pr_err("%s lpaif_pri_muxsel_virt_addr is NULL\n",
 				 __func__);
-		ret = msm_aux_pcm_get_gpios(substream);
+		ret = msm_aux_pcm_get_gpios(auxpcm_ctrl);
 	}
 	if (ret < 0) {
 		pr_err("%s: Aux PCM GPIO request failed\n", __func__);
 		return -EINVAL;
 	}
+err:
 	return ret;
 }
 
-static void msm_auxpcm_shutdown(struct snd_pcm_substream *substream)
+static void msm_prim_auxpcm_shutdown(struct snd_pcm_substream *substream)
 {
+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
+	struct snd_soc_card *card = rtd->card;
+	struct msm8974_asoc_mach_data *pdata = snd_soc_card_get_drvdata(card);
+	struct msm_auxpcm_ctrl *auxpcm_ctrl = NULL;
 
-	pr_debug("%s(): substream = %s, auxpcm_rsc_ref counter = %d\n",
-		__func__, substream->name, atomic_read(&auxpcm_rsc_ref));
-	if (atomic_dec_return(&auxpcm_rsc_ref) == 0)
-		msm_aux_pcm_free_gpios(substream);
+	pr_debug("%s(): substream = %s, prim_auxpcm_rsc_ref counter = %d\n",
+		__func__, substream->name, atomic_read(&prim_auxpcm_rsc_ref));
+
+	auxpcm_ctrl = pdata->pri_auxpcm_ctrl;
+
+	if (atomic_dec_return(&prim_auxpcm_rsc_ref) == 0)
+		msm_aux_pcm_free_gpios(auxpcm_ctrl);
 }
-static struct snd_soc_ops msm_auxpcm_be_ops = {
-	.startup = msm_auxpcm_startup,
-	.shutdown = msm_auxpcm_shutdown,
+static struct snd_soc_ops msm_pri_auxpcm_be_ops = {
+	.startup = msm_prim_auxpcm_startup,
+	.shutdown = msm_prim_auxpcm_shutdown,
+};
+
+static int msm_sec_auxpcm_startup(struct snd_pcm_substream *substream)
+{
+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
+	struct snd_soc_card *card = rtd->card;
+	struct msm8974_asoc_mach_data *pdata = snd_soc_card_get_drvdata(card);
+	struct msm_auxpcm_ctrl *auxpcm_ctrl = NULL;
+	int ret = 0;
+
+	pr_debug("%s(): substream = %s, sec_auxpcm_rsc_ref counter = %d\n",
+		__func__, substream->name, atomic_read(&sec_auxpcm_rsc_ref));
+
+	auxpcm_ctrl = pdata->sec_auxpcm_ctrl;
+
+	if (auxpcm_ctrl == NULL || auxpcm_ctrl->pin_data == NULL) {
+		pr_err("%s: Ctrl pointers are NULL\n", __func__);
+		ret = -EINVAL;
+		goto err;
+	}
+	if (atomic_inc_return(&sec_auxpcm_rsc_ref) == 1) {
+		if (lpaif_sec_muxsel_virt_addr != NULL)
+			iowrite32(I2S_PCM_SEL << I2S_PCM_SEL_OFFSET,
+				lpaif_sec_muxsel_virt_addr);
+		else
+			pr_err("%s lpaif_sec_muxsel_virt_addr is NULL\n",
+				 __func__);
+		ret = msm_aux_pcm_get_gpios(auxpcm_ctrl);
+	}
+	if (ret < 0) {
+		pr_err("%s: Aux PCM GPIO request failed\n", __func__);
+		return -EINVAL;
+	}
+err:
+	return ret;
+}
+
+static void msm_sec_auxpcm_shutdown(struct snd_pcm_substream *substream)
+{
+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
+	struct snd_soc_card *card = rtd->card;
+	struct msm8974_asoc_mach_data *pdata = snd_soc_card_get_drvdata(card);
+	struct msm_auxpcm_ctrl *auxpcm_ctrl = NULL;
+
+	pr_debug("%s(): substream = %s, sec_auxpcm_rsc_ref counter = %d\n",
+		__func__, substream->name, atomic_read(&sec_auxpcm_rsc_ref));
+
+	auxpcm_ctrl = pdata->sec_auxpcm_ctrl;
+
+	if (atomic_dec_return(&sec_auxpcm_rsc_ref) == 0)
+		msm_aux_pcm_free_gpios(auxpcm_ctrl);
+}
+
+static struct snd_soc_ops msm_sec_auxpcm_be_ops = {
+	.startup = msm_sec_auxpcm_startup,
+	.shutdown = msm_sec_auxpcm_shutdown,
 };
 
 static int msm_slim_0_rx_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
@@ -1092,7 +1149,7 @@
 	SOC_ENUM_SINGLE_EXT(4, slim0_tx_ch_text),
 	SOC_ENUM_SINGLE_EXT(7, hdmi_rx_ch_text),
 	SOC_ENUM_SINGLE_EXT(2, rx_bit_format_text),
-	SOC_ENUM_SINGLE_EXT(2, slim0_rx_sample_rate_text),
+	SOC_ENUM_SINGLE_EXT(3, slim0_rx_sample_rate_text),
 };
 
 static const struct snd_kcontrol_new msm_snd_controls[] = {
@@ -1784,7 +1841,7 @@
 		.codec_dai_name = "snd-soc-dummy-dai",
 		.codec_name = "snd-soc-dummy",
 	},
-	/* AUX PCM Backend DAI Links */
+	/* Primary AUX PCM Backend DAI Links */
 	{
 		.name = LPASS_BE_AUXPCM_RX,
 		.stream_name = "AUX PCM Playback",
@@ -1795,7 +1852,7 @@
 		.no_pcm = 1,
 		.be_id = MSM_BACKEND_DAI_AUXPCM_RX,
 		.be_hw_params_fixup = msm_auxpcm_be_params_fixup,
-		.ops = &msm_auxpcm_be_ops,
+		.ops = &msm_pri_auxpcm_be_ops,
 		.ignore_pmdown_time = 1,
 		.ignore_suspend = 1,
 		/* this dainlink has playback support */
@@ -1810,9 +1867,39 @@
 		.no_pcm = 1,
 		.be_id = MSM_BACKEND_DAI_AUXPCM_TX,
 		.be_hw_params_fixup = msm_auxpcm_be_params_fixup,
-		.ops = &msm_auxpcm_be_ops,
+		.ops = &msm_pri_auxpcm_be_ops,
 		.ignore_suspend = 1,
 	},
+	/* Secondary AUX PCM Backend DAI Links */
+	{
+		.name = LPASS_BE_SEC_AUXPCM_RX,
+		.stream_name = "Sec AUX PCM Playback",
+		.cpu_dai_name = "msm-dai-q6.4108",
+		.platform_name = "msm-pcm-routing",
+		.codec_name = "msm-stub-codec.1",
+		.codec_dai_name = "msm-stub-rx",
+		.no_pcm = 1,
+		.be_id = MSM_BACKEND_DAI_SEC_AUXPCM_RX,
+		.be_hw_params_fixup = msm_auxpcm_be_params_fixup,
+		.ops = &msm_sec_auxpcm_be_ops,
+		.ignore_pmdown_time = 1,
+		.ignore_suspend = 1,
+		/* this dainlink has playback support */
+	},
+	{
+		.name = LPASS_BE_SEC_AUXPCM_TX,
+		.stream_name = "Sec AUX PCM Capture",
+		.cpu_dai_name = "msm-dai-q6.4109",
+		.platform_name = "msm-pcm-routing",
+		.codec_name = "msm-stub-codec.1",
+		.codec_dai_name = "msm-stub-tx",
+		.no_pcm = 1,
+		.be_id = MSM_BACKEND_DAI_SEC_AUXPCM_TX,
+		.be_hw_params_fixup = msm_auxpcm_be_params_fixup,
+		.ops = &msm_sec_auxpcm_be_ops,
+		.ignore_suspend = 1,
+	},
+
 	/* Backend DAI Links */
 	{
 		.name = LPASS_BE_SLIMBUS_0_RX,
@@ -2030,7 +2117,8 @@
 };
 
 static int msm8974_dtparse_auxpcm(struct platform_device *pdev,
-				struct msm8974_asoc_mach_data **pdata)
+				struct msm_auxpcm_ctrl **auxpcm_ctrl,
+				char *msm_auxpcm_gpio_name[][2])
 {
 	int ret = 0;
 	int i = 0;
@@ -2038,7 +2126,7 @@
 	struct msm_auxpcm_ctrl *ctrl;
 	unsigned int gpio_no[NUM_OF_AUXPCM_GPIOS];
 	enum of_gpio_flags flags = OF_GPIO_ACTIVE_LOW;
-	int prim_cnt = 0;
+	int auxpcm_cnt = 0;
 
 	pin_data = devm_kzalloc(&pdev->dev, (ARRAY_SIZE(gpio_no) *
 				sizeof(struct msm_auxpcm_gpio)),
@@ -2056,13 +2144,13 @@
 
 		if (gpio_no[i] > 0) {
 			pin_data[i].gpio_name =
-				msm_auxpcm_gpio_name[prim_cnt][GPIO_NAME_INDEX];
+			     msm_auxpcm_gpio_name[auxpcm_cnt][GPIO_NAME_INDEX];
 			pin_data[i].gpio_no = gpio_no[i];
 			dev_dbg(&pdev->dev, "%s:GPIO gpio[%s] =\n"
 				"0x%x\n", __func__,
 				pin_data[i].gpio_name,
 				pin_data[i].gpio_no);
-			prim_cnt++;
+			auxpcm_cnt++;
 		} else {
 			dev_err(&pdev->dev, "%s:Invalid AUXPCM GPIO[%s]= %x\n",
 				 __func__,
@@ -2082,8 +2170,8 @@
 	}
 
 	ctrl->pin_data = pin_data;
-	ctrl->cnt = prim_cnt;
-	(*pdata)->pri_auxpcm_ctrl = ctrl;
+	ctrl->cnt = auxpcm_cnt;
+	*auxpcm_ctrl = ctrl;
 	return ret;
 
 err:
@@ -2160,10 +2248,21 @@
 		return -ENOMEM;
 	}
 
-	ret = msm8974_dtparse_auxpcm(pdev, &pdata);
+	/* Parse Primary AUXPCM info from DT */
+	ret = msm8974_dtparse_auxpcm(pdev, &pdata->pri_auxpcm_ctrl,
+					msm_prim_auxpcm_gpio_name);
 	if (ret) {
 		dev_err(&pdev->dev,
-		"%s: Auxpcm pin data parse failed\n", __func__);
+		"%s: Primary Auxpcm pin data parse failed\n", __func__);
+		goto err;
+	}
+
+	/* Parse Secondary AUXPCM info from DT */
+	ret = msm8974_dtparse_auxpcm(pdev, &pdata->sec_auxpcm_ctrl,
+					msm_sec_auxpcm_gpio_name);
+	if (ret) {
+		dev_err(&pdev->dev,
+		"%s: Secondary Auxpcm pin data parse failed\n", __func__);
 		goto err;
 	}
 
@@ -2248,7 +2347,8 @@
 			ret);
 
 	mutex_init(&cdc_mclk_mutex);
-	atomic_set(&auxpcm_rsc_ref, 0);
+	atomic_set(&prim_auxpcm_rsc_ref, 0);
+	atomic_set(&sec_auxpcm_rsc_ref, 0);
 	spdev = pdev;
 	ext_spk_amp_regulator = NULL;
 	msm8974_liquid_dock_dev = NULL;
@@ -2266,6 +2366,12 @@
 		ret = -EINVAL;
 		goto err;
 	}
+	lpaif_sec_muxsel_virt_addr = ioremap(LPAIF_SEC_MODE_MUXSEL, 4);
+	if (lpaif_sec_muxsel_virt_addr == NULL) {
+		pr_err("%s Sec muxsel virt addr is null\n", __func__);
+		ret = -EINVAL;
+		goto err;
+	}
 	return 0;
 err:
 	if (pdata->mclk_gpio > 0) {
@@ -2310,6 +2416,7 @@
 	}
 
 	iounmap(lpaif_pri_muxsel_virt_addr);
+	iounmap(lpaif_sec_muxsel_virt_addr);
 	snd_soc_unregister_card(card);
 
 	return 0;
diff --git a/sound/soc/msm/qdsp6v2/Makefile b/sound/soc/msm/qdsp6v2/Makefile
index 391b3da..f3dcf95 100644
--- a/sound/soc/msm/qdsp6v2/Makefile
+++ b/sound/soc/msm/qdsp6v2/Makefile
@@ -5,6 +5,7 @@
 			msm-lsm-client.o
 obj-$(CONFIG_SND_SOC_QDSP6V2) += snd-soc-qdsp6v2.o msm-pcm-dtmf-v2.o \
 				 msm-dai-stub-v2.o
+obj-$(CONFIG_DOLBY_DAP) += msm-dolby-dap-config.o
 obj-y += q6adm.o q6afe.o q6asm.o q6audio-v2.o q6voice.o q6core.o audio_acdb.o \
 	 rtac.o q6lsm.o
 ocmem-audio-objs += audio_ocmem.o
diff --git a/sound/soc/msm/qdsp6v2/audio_acdb.c b/sound/soc/msm/qdsp6v2/audio_acdb.c
index 16d6e81..96da2f1 100644
--- a/sound/soc/msm/qdsp6v2/audio_acdb.c
+++ b/sound/soc/msm/qdsp6v2/audio_acdb.c
@@ -18,6 +18,7 @@
 #include <linux/uaccess.h>
 #include <linux/msm_ion.h>
 #include <linux/mm.h>
+#include <linux/msm_audio_ion.h>
 #include "audio_acdb.h"
 
 
@@ -870,9 +871,7 @@
 			kfree(acdb_data.col_data[i]);
 			acdb_data.col_data[i] = NULL;
 		}
-		ion_unmap_kernel(acdb_data.ion_client, acdb_data.ion_handle);
-		ion_free(acdb_data.ion_client, acdb_data.ion_handle);
-		ion_client_destroy(acdb_data.ion_client);
+		msm_audio_ion_free(acdb_data.ion_client, acdb_data.ion_handle);
 		mutex_unlock(&acdb_data.acdb_mutex);
 	}
 	return 0;
@@ -894,34 +893,16 @@
 			(uint32_t)acdb_data.col_data[i]);
 	}
 
-	acdb_data.ion_client =
-		msm_ion_client_create(UINT_MAX, "audio_acdb_client");
-	if (IS_ERR_OR_NULL(acdb_data.ion_client)) {
-		pr_err("%s: Could not register ION client!!!\n", __func__);
+	result = msm_audio_ion_import("audio_acdb_client",
+				&acdb_data.ion_client,
+				&acdb_data.ion_handle,
+				atomic_read(&acdb_data.map_handle),
+				NULL, 0,
+				&paddr, (size_t *)&mem_len, &kvptr);
+	if (result) {
+		pr_err("%s: audio ION alloc failed, rc = %d\n",
+			__func__, result);
 		result = PTR_ERR(acdb_data.ion_client);
-		goto err;
-	}
-
-	acdb_data.ion_handle = ion_import_dma_buf(acdb_data.ion_client,
-		atomic_read(&acdb_data.map_handle));
-	if (IS_ERR_OR_NULL(acdb_data.ion_handle)) {
-		pr_err("%s: Could not import map handle!!!\n", __func__);
-		result = PTR_ERR(acdb_data.ion_handle);
-		goto err_ion_client;
-	}
-
-	result = ion_phys(acdb_data.ion_client, acdb_data.ion_handle,
-				&paddr, (size_t *)&mem_len);
-	if (result != 0) {
-		pr_err("%s: Could not get phys addr!!!\n", __func__);
-		goto err_ion_handle;
-	}
-
-	kvptr = ion_map_kernel(acdb_data.ion_client,
-		acdb_data.ion_handle);
-	if (IS_ERR_OR_NULL(kvptr)) {
-		pr_err("%s: Could not get kernel virt addr!!!\n", __func__);
-		result = PTR_ERR(kvptr);
 		goto err_ion_handle;
 	}
 	kvaddr = (unsigned long)kvptr;
@@ -938,10 +919,8 @@
 
 	return result;
 err_ion_handle:
-	ion_free(acdb_data.ion_client, acdb_data.ion_handle);
-err_ion_client:
-	ion_client_destroy(acdb_data.ion_client);
-err:
+	msm_audio_ion_free(acdb_data.ion_client, acdb_data.ion_handle);
+
 	atomic64_set(&acdb_data.mem_len, 0);
 	mutex_unlock(&acdb_data.acdb_mutex);
 	return result;
diff --git a/sound/soc/msm/qdsp6v2/msm-compr-q6-v2.c b/sound/soc/msm/qdsp6v2/msm-compr-q6-v2.c
index 5dc5f96..9359ed7 100644
--- a/sound/soc/msm/qdsp6v2/msm-compr-q6-v2.c
+++ b/sound/soc/msm/qdsp6v2/msm-compr-q6-v2.c
@@ -321,6 +321,23 @@
 	}
 }
 
+static int msm_compr_send_ddp_cfg(struct audio_client *ac,
+					struct snd_dec_ddp *ddp)
+{
+	int i, rc;
+	pr_debug("%s\n", __func__);
+	for (i = 0; i < ddp->params_length/2; i++) {
+		rc = q6asm_ds1_set_endp_params(ac, ddp->params_id[i],
+						ddp->params_value[i]);
+		if (rc) {
+			pr_err("sending params_id: %d failed\n",
+				ddp->params_id[i]);
+			return rc;
+		}
+	}
+	return 0;
+}
+
 static int msm_compr_playback_prepare(struct snd_pcm_substream *substream)
 {
 	struct snd_pcm_runtime *runtime = substream->runtime;
@@ -358,6 +375,24 @@
 		if (ret < 0)
 			pr_err("%s: CMD Format block failed\n", __func__);
 		break;
+	case SND_AUDIOCODEC_AC3: {
+		struct snd_dec_ddp *ddp =
+				&compr->info.codec_param.codec.options.ddp;
+		pr_debug("%s: SND_AUDIOCODEC_AC3\n", __func__);
+		ret = msm_compr_send_ddp_cfg(prtd->audio_client, ddp);
+		if (ret < 0)
+			pr_err("%s: DDP CMD CFG failed\n", __func__);
+		break;
+	}
+	case SND_AUDIOCODEC_EAC3: {
+		struct snd_dec_ddp *ddp =
+				&compr->info.codec_param.codec.options.ddp;
+		pr_debug("%s: SND_AUDIOCODEC_EAC3\n", __func__);
+		ret = msm_compr_send_ddp_cfg(prtd->audio_client, ddp);
+		if (ret < 0)
+			pr_err("%s: DDP CMD CFG failed\n", __func__);
+		break;
+	}
 	default:
 		return -EINVAL;
 	}
@@ -511,13 +546,15 @@
 {
 	pr_debug("%s\n", __func__);
 	/* MP3 Block */
-	compr->info.compr_cap.num_codecs = 2;
+	compr->info.compr_cap.num_codecs = 4;
 	compr->info.compr_cap.min_fragment_size = runtime->hw.period_bytes_min;
 	compr->info.compr_cap.max_fragment_size = runtime->hw.period_bytes_max;
 	compr->info.compr_cap.min_fragments = runtime->hw.periods_min;
 	compr->info.compr_cap.max_fragments = runtime->hw.periods_max;
 	compr->info.compr_cap.codecs[0] = SND_AUDIOCODEC_MP3;
 	compr->info.compr_cap.codecs[1] = SND_AUDIOCODEC_AAC;
+	compr->info.compr_cap.codecs[2] = SND_AUDIOCODEC_AC3;
+	compr->info.compr_cap.codecs[3] = SND_AUDIOCODEC_EAC3;
 	/* Add new codecs here */
 }
 
@@ -897,7 +934,7 @@
 		}
 		return 0;
 	case SNDRV_COMPRESS_SET_PARAMS:
-		pr_debug("SNDRV_COMPRESS_SET_PARAMS: ");
+		pr_debug("SNDRV_COMPRESS_SET_PARAMS:\n");
 		if (copy_from_user(&compr->info.codec_param, (void *) arg,
 			sizeof(struct snd_compr_params))) {
 			rc = -EFAULT;
@@ -914,6 +951,68 @@
 			pr_debug("SND_AUDIOCODEC_AAC\n");
 			compr->codec = FORMAT_MPEG4_AAC;
 			break;
+		case SND_AUDIOCODEC_AC3: {
+			char params_value[18*2*sizeof(int)];
+			int *params_value_data = (int *)params_value;
+			/* 36 is the max param length for ddp */
+			int i;
+			struct snd_dec_ddp *ddp =
+				&compr->info.codec_param.codec.options.ddp;
+			int params_length = ddp->params_length*sizeof(int);
+			pr_debug("SND_AUDIOCODEC_AC3\n");
+			compr->codec = FORMAT_AC3;
+			if (copy_from_user(params_value, (void *)ddp->params,
+					params_length))
+				pr_err("%s: ERROR: copy ddp params value\n",
+					__func__);
+			pr_debug("params_length: %d\n", ddp->params_length);
+			for (i = 0; i < params_length; i++)
+				pr_debug("params_value[%d]: %x\n", i,
+					params_value_data[i]);
+			for (i = 0; i < ddp->params_length/2; i++) {
+				ddp->params_id[i] = params_value_data[2*i];
+				ddp->params_value[i] = params_value_data[2*i+1];
+			}
+			if (atomic_read(&prtd->start)) {
+				rc = msm_compr_send_ddp_cfg(prtd->audio_client,
+								ddp);
+				if (rc < 0)
+					pr_err("%s: DDP CMD CFG failed\n",
+						__func__);
+			}
+			break;
+		}
+		case SND_AUDIOCODEC_EAC3: {
+			char params_value[18*2*sizeof(int)];
+			int *params_value_data = (int *)params_value;
+			/* 36 is the max param length for ddp */
+			int i;
+			struct snd_dec_ddp *ddp =
+				&compr->info.codec_param.codec.options.ddp;
+			int params_length = ddp->params_length*sizeof(int);
+			pr_debug("SND_AUDIOCODEC_EAC3\n");
+			compr->codec = FORMAT_EAC3;
+			if (copy_from_user(params_value, (void *)ddp->params,
+					params_length))
+				pr_err("%s: ERROR: copy ddp params value\n",
+					__func__);
+			pr_debug("params_length: %d\n", ddp->params_length);
+			for (i = 0; i < ddp->params_length; i++)
+				pr_debug("params_value[%d]: %x\n", i,
+					params_value_data[i]);
+			for (i = 0; i < ddp->params_length/2; i++) {
+				ddp->params_id[i] = params_value_data[2*i];
+				ddp->params_value[i] = params_value_data[2*i+1];
+			}
+			if (atomic_read(&prtd->start)) {
+				rc = msm_compr_send_ddp_cfg(prtd->audio_client,
+								ddp);
+				if (rc < 0)
+					pr_err("%s: DDP CMD CFG failed\n",
+						__func__);
+			}
+			break;
+		}
 		default:
 			pr_debug("FORMAT_LINEAR_PCM\n");
 			compr->codec = FORMAT_LINEAR_PCM;
diff --git a/sound/soc/msm/qdsp6v2/msm-dai-q6-v2.c b/sound/soc/msm/qdsp6v2/msm-dai-q6-v2.c
index d23eea5..8bb3eaf 100644
--- a/sound/soc/msm/qdsp6v2/msm-dai-q6-v2.c
+++ b/sound/soc/msm/qdsp6v2/msm-dai-q6-v2.c
@@ -155,6 +155,8 @@
 	struct afe_clk_cfg *lpass_pcm_src_clk = NULL;
 	struct afe_clk_cfg lpass_pcm_oe_clk;
 	struct msm_dai_auxpcm_pdata *auxpcm_pdata = NULL;
+	unsigned int rx_port = 0;
+	unsigned int tx_port = 0;
 
 	mutex_lock(&aux_pcm_mutex);
 
@@ -186,22 +188,32 @@
 	auxpcm_pdata = (struct msm_dai_auxpcm_pdata *)dai->dev->platform_data;
 	lpass_pcm_src_clk = (struct afe_clk_cfg *)auxpcm_pdata->clk_cfg;
 
-	rc = afe_close(PCM_RX); /* can block */
+	if (dai->id == AFE_PORT_ID_PRIMARY_PCM_RX
+			|| dai->id == AFE_PORT_ID_PRIMARY_PCM_TX) {
+		rx_port = PCM_RX;
+		tx_port = PCM_TX;
+	} else if (dai->id == AFE_PORT_ID_SECONDARY_PCM_RX
+			|| dai->id == AFE_PORT_ID_SECONDARY_PCM_TX) {
+		rx_port = AFE_PORT_ID_SECONDARY_PCM_RX;
+		tx_port = AFE_PORT_ID_SECONDARY_PCM_TX;
+	}
+
+	rc = afe_close(rx_port); /* can block */
 	if (IS_ERR_VALUE(rc))
 		dev_err(dai->dev, "fail to close PCM_RX  AFE port\n");
 
-	rc = afe_close(PCM_TX);
+	rc = afe_close(tx_port);
 	if (IS_ERR_VALUE(rc))
 		dev_err(dai->dev, "fail to close AUX PCM TX port\n");
 
 	lpass_pcm_src_clk->clk_val1 = 0;
-	afe_set_lpass_clock(PCM_TX, lpass_pcm_src_clk);
-	afe_set_lpass_clock(PCM_RX, lpass_pcm_src_clk);
+	afe_set_lpass_clock(tx_port, lpass_pcm_src_clk);
+	afe_set_lpass_clock(rx_port, lpass_pcm_src_clk);
 
 	memcpy(&lpass_pcm_oe_clk, &lpass_clk_cfg_default,
 			 sizeof(struct afe_clk_cfg));
 	lpass_pcm_oe_clk.clk_val1 = 0;
-	afe_set_lpass_clock(PCM_RX, &lpass_pcm_oe_clk);
+	afe_set_lpass_clock(rx_port, &lpass_pcm_oe_clk);
 
 	mutex_unlock(&aux_pcm_mutex);
 }
@@ -215,6 +227,8 @@
 	unsigned long pcm_clk_rate;
 	struct afe_clk_cfg lpass_pcm_oe_clk;
 	struct afe_clk_cfg *lpass_pcm_src_clk = NULL;
+	unsigned int rx_port = 0;
+	unsigned int tx_port = 0;
 
 	auxpcm_pdata = dai->dev->platform_data;
 	lpass_pcm_src_clk = (struct afe_clk_cfg *)auxpcm_pdata->clk_cfg;
@@ -279,30 +293,39 @@
 			sizeof(struct afe_clk_cfg));
 	lpass_pcm_oe_clk.clk_val1 = Q6AFE_LPASS_OSR_CLK_12_P288_MHZ;
 
-	rc = afe_set_lpass_clock(PCM_RX, lpass_pcm_src_clk);
+	if (dai->id == AFE_PORT_ID_PRIMARY_PCM_RX ||
+			dai->id == AFE_PORT_ID_PRIMARY_PCM_TX) {
+		rx_port = PCM_RX;
+		tx_port = PCM_TX;
+	} else if (dai->id == AFE_PORT_ID_SECONDARY_PCM_RX ||
+			dai->id == AFE_PORT_ID_SECONDARY_PCM_TX) {
+		rx_port = AFE_PORT_ID_SECONDARY_PCM_RX;
+		tx_port = AFE_PORT_ID_SECONDARY_PCM_TX;
+	}
+
+	rc = afe_set_lpass_clock(rx_port, lpass_pcm_src_clk);
 	if (rc < 0) {
 		pr_err("%s:afe_set_lpass_clock on RX pcm_src_clk failed\n",
 							__func__);
 		goto fail;
 	}
 
-	rc = afe_set_lpass_clock(PCM_TX, lpass_pcm_src_clk);
+	rc = afe_set_lpass_clock(tx_port, lpass_pcm_src_clk);
 	if (rc < 0) {
 		pr_err("%s:afe_set_lpass_clock on TX pcm_src_clk failed\n",
 							__func__);
 		goto fail;
 	}
 
-	rc = afe_set_lpass_clock(PCM_RX, &lpass_pcm_oe_clk);
+	rc = afe_set_lpass_clock(rx_port, &lpass_pcm_oe_clk);
 	if (rc < 0) {
 		pr_err("%s:afe_set_lpass_clock on pcm_oe_clk failed\n",
 							__func__);
 		goto fail;
 	}
 
-	afe_open(PCM_RX, &dai_data->port_config, dai_data->rate);
-
-	afe_open(PCM_TX, &dai_data->port_config, dai_data->rate);
+	afe_open(rx_port, &dai_data->port_config, dai_data->rate);
+	afe_open(tx_port, &dai_data->port_config, dai_data->rate);
 
 fail:
 	mutex_unlock(&aux_pcm_mutex);
@@ -314,7 +337,7 @@
 {
 	int rc = 0;
 
-	pr_debug("%s:port:%d  cmd:%d  aux_pcm_count= %d",
+	pr_debug("%s:port:%d  cmd:%d  aux_pcm_count= %d\n",
 		__func__, dai->id, cmd, aux_pcm_count);
 
 	switch (cmd) {
@@ -359,7 +382,7 @@
 	} else
 		dev_set_drvdata(dai->dev, dai_data);
 
-	pr_err("%s : probe done for dai->id %d\n", __func__, dai->id);
+	pr_debug("%s : probe done for dai->id %d\n", __func__, dai->id);
 	return rc;
 }
 
@@ -367,6 +390,8 @@
 {
 	struct msm_dai_q6_dai_data *dai_data;
 	int rc;
+	unsigned int rx_port = 0;
+	unsigned int tx_port = 0;
 
 	dai_data = dev_get_drvdata(dai->dev);
 
@@ -393,14 +418,22 @@
 	dev_dbg(dai->dev, "%s(): dai->id %d aux_pcm_count = %d.closing afe\n",
 		__func__, dai->id, aux_pcm_count);
 
-	rc = afe_close(PCM_RX); /* can block */
+	if (dai->id == AFE_PORT_ID_PRIMARY_PCM_RX ||
+			dai->id == AFE_PORT_ID_PRIMARY_PCM_TX) {
+		rx_port = PCM_RX;
+		tx_port = PCM_TX;
+	} else if (dai->id == AFE_PORT_ID_SECONDARY_PCM_RX ||
+			dai->id == AFE_PORT_ID_SECONDARY_PCM_TX) {
+		rx_port = AFE_PORT_ID_SECONDARY_PCM_RX;
+		tx_port = AFE_PORT_ID_SECONDARY_PCM_TX;
+	}
+	rc = afe_close(rx_port); /* can block */
 	if (IS_ERR_VALUE(rc))
 		dev_err(dai->dev, "fail to close AUX PCM RX AFE port\n");
 
-	rc = afe_close(PCM_TX);
+	rc = afe_close(tx_port);
 	if (IS_ERR_VALUE(rc))
 		dev_err(dai->dev, "fail to close AUX PCM TX AFE port\n");
-
 done:
 	kfree(dai_data);
 	snd_soc_unregister_dai(dai->dev);
@@ -941,12 +974,13 @@
 static struct snd_soc_dai_driver msm_dai_q6_slimbus_1_rx_dai = {
 	.playback = {
 		.rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 |
-		SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_96000,
+		SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_96000 |
+		SNDRV_PCM_RATE_192000,
 		.formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE,
 		.channels_min = 1,
 		.channels_max = 2,
 		.rate_min = 8000,
-		.rate_max = 96000,
+		.rate_max = 192000,
 	},
 	.ops = &msm_dai_q6_ops,
 	.probe = msm_dai_q6_dai_probe,
@@ -1084,10 +1118,12 @@
 
 	switch (id) {
 	case AFE_PORT_ID_PRIMARY_PCM_RX:
+	case AFE_PORT_ID_SECONDARY_PCM_RX:
 		rc = snd_soc_register_dai(&pdev->dev,
 					&msm_dai_q6_aux_pcm_rx_dai);
 		break;
 	case AFE_PORT_ID_PRIMARY_PCM_TX:
+	case AFE_PORT_ID_SECONDARY_PCM_TX:
 		rc = snd_soc_register_dai(&pdev->dev,
 					&msm_dai_q6_aux_pcm_tx_dai);
 		break;
@@ -1873,25 +1909,26 @@
 	u32  rx_line = 0;
 	u32 mi2s_intf = 0;
 	struct msm_mi2s_pdata *mi2s_pdata;
-	int rc = 0;
-
+	int rc;
+	struct snd_soc_dai_driver *mi2s_dai;
 
 	rc = of_property_read_u32(pdev->dev.of_node, q6_mi2s_dev_id,
 				  &mi2s_intf);
 	if (rc) {
 		dev_err(&pdev->dev,
 			"%s: missing %x in dt node\n", __func__, mi2s_intf);
-		return rc;
+		goto rtn;
 	}
 
 	dev_dbg(&pdev->dev, "dev name %s dev id %x\n", dev_name(&pdev->dev),
-			     mi2s_intf);
+		mi2s_intf);
 
 	if (mi2s_intf < MSM_PRIM_MI2S || mi2s_intf > MSM_QUAT_MI2S) {
 		dev_err(&pdev->dev,
 			"%s: Invalid MI2S ID %u from Device Tree\n",
 			__func__, mi2s_intf);
-		return -ENXIO;
+		rc = -ENXIO;
+		goto rtn;
 	}
 
 	dev_set_name(&pdev->dev, "%s.%d", "msm-dai-q6-mi2s", mi2s_intf);
@@ -1909,7 +1946,7 @@
 	if (rc) {
 		dev_err(&pdev->dev, "%s: Rx line from DT file %s\n", __func__,
 			"qcom,msm-mi2s-rx-lines");
-		goto rtn;
+		goto free_pdata;
 	}
 
 	rc = of_property_read_u32(pdev->dev.of_node, "qcom,msm-mi2s-tx-lines",
@@ -1917,36 +1954,53 @@
 	if (rc) {
 		dev_err(&pdev->dev, "%s: Tx line from DT file %s\n", __func__,
 			"qcom,msm-mi2s-tx-lines");
-		goto rtn;
+		goto free_pdata;
 	}
 	dev_dbg(&pdev->dev, "dev name %s Rx line %x , Tx ine %x\n",
 		dev_name(&pdev->dev), rx_line, tx_line);
 	mi2s_pdata->rx_sd_lines = rx_line;
 	mi2s_pdata->tx_sd_lines = tx_line;
+
 	dai_data = kzalloc(sizeof(struct msm_dai_q6_mi2s_dai_data),
-				GFP_KERNEL);
+			   GFP_KERNEL);
 	if (!dai_data) {
 		dev_err(&pdev->dev, "fail to allocate dai data\n");
 		rc = -ENOMEM;
-		goto rtn;
+		goto free_pdata;
 	} else
 		dev_set_drvdata(&pdev->dev, dai_data);
+
 	pdev->dev.platform_data = mi2s_pdata;
-	rc = msm_dai_q6_mi2s_platform_data_validation(pdev,
-					&msm_dai_q6_mi2s_dai);
+
+	mi2s_dai = kzalloc(sizeof(struct snd_soc_dai_driver), GFP_KERNEL);
+	if (!mi2s_dai) {
+		dev_err(&pdev->dev, "fail to allocate for mi2s_dai\n");
+		rc = -ENOMEM;
+		goto free_dai_data;
+	}
+
+	memcpy(mi2s_dai, &msm_dai_q6_mi2s_dai,
+	       sizeof(struct snd_soc_dai_driver));
+	rc = msm_dai_q6_mi2s_platform_data_validation(pdev, mi2s_dai);
 	if (IS_ERR_VALUE(rc))
-		goto err_pdata;
+		goto free_dai;
+
 	dai_data->rate_constraint.count = 1;
 	dai_data->bitwidth_constraint.count = 1;
-	rc = snd_soc_register_dai(&pdev->dev, &msm_dai_q6_mi2s_dai);
+	rc = snd_soc_register_dai(&pdev->dev, mi2s_dai);
 	if (IS_ERR_VALUE(rc))
-		goto err_pdata;
+		goto err_register;
 	return 0;
-err_pdata:
+
+err_register:
 	dev_err(&pdev->dev, "fail to msm_dai_q6_mi2s_dev_probe\n");
+free_dai:
+	kfree(mi2s_dai);
+free_dai_data:
 	kfree(dai_data);
-rtn:
+free_pdata:
 	kfree(mi2s_pdata);
+rtn:
 	return rc;
 }
 
diff --git a/sound/soc/msm/qdsp6v2/msm-dolby-dap-config.c b/sound/soc/msm/qdsp6v2/msm-dolby-dap-config.c
new file mode 100644
index 0000000..b43c3bd
--- /dev/null
+++ b/sound/soc/msm/qdsp6v2/msm-dolby-dap-config.c
@@ -0,0 +1,707 @@
+/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License version 2 and
+* only version 2 as published by the Free Software Foundation.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+* GNU General Public License for more details.
+*/
+
+#include <linux/init.h>
+#include <linux/err.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/platform_device.h>
+#include <linux/bitops.h>
+#include <linux/mutex.h>
+#include <linux/of_device.h>
+#include <linux/slab.h>
+#include <sound/core.h>
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+#include <sound/pcm.h>
+#include <sound/initval.h>
+#include <sound/control.h>
+#include <sound/q6adm-v2.h>
+#include <sound/q6asm-v2.h>
+#include <sound/q6afe-v2.h>
+
+#include "msm-dolby-dap-config.h"
+
+/* dolby endp based parameters */
+struct dolby_dap_endp_params_s {
+	int device;
+	int device_ch_caps;
+	int dap_device;
+	int params_id[DOLBY_NUM_ENDP_DEPENDENT_PARAMS];
+	int params_len[DOLBY_NUM_ENDP_DEPENDENT_PARAMS];
+	int params_offset[DOLBY_NUM_ENDP_DEPENDENT_PARAMS];
+	int params_val[DOLBY_ENDDEP_PARAM_LENGTH];
+};
+
+const struct dolby_dap_endp_params_s
+			dolby_dap_endp_params[NUM_DOLBY_ENDP_DEVICE] = {
+	{EARPIECE,			2, DOLBY_ENDP_EXT_SPEAKERS,
+		{DOLBY_PARAM_ID_DVLO}, {DOLBY_ENDDEP_PARAM_DVLO_LENGTH},
+		{DOLBY_ENDDEP_PARAM_DVLO_OFFSET}, {-320} },
+	{SPEAKER,			2, DOLBY_ENDP_INT_SPEAKERS,
+		{DOLBY_PARAM_ID_DVLO}, {DOLBY_ENDDEP_PARAM_DVLO_LENGTH},
+		{DOLBY_ENDDEP_PARAM_DVLO_OFFSET}, {-320} },
+	{WIRED_HEADSET,			2, DOLBY_ENDP_HEADPHONES,
+		{DOLBY_PARAM_ID_DVLO}, {DOLBY_ENDDEP_PARAM_DVLO_LENGTH},
+		{DOLBY_ENDDEP_PARAM_DVLO_OFFSET}, {-320} },
+	{WIRED_HEADPHONE,		2, DOLBY_ENDP_HEADPHONES,
+		{DOLBY_PARAM_ID_DVLO}, {DOLBY_ENDDEP_PARAM_DVLO_LENGTH},
+		{DOLBY_ENDDEP_PARAM_DVLO_OFFSET}, {-320} },
+	{BLUETOOTH_SCO,			2, DOLBY_ENDP_EXT_SPEAKERS,
+		{DOLBY_PARAM_ID_DVLO}, {DOLBY_ENDDEP_PARAM_DVLO_LENGTH},
+		{DOLBY_ENDDEP_PARAM_DVLO_OFFSET}, {-320} },
+	{BLUETOOTH_SCO_HEADSET,		2, DOLBY_ENDP_EXT_SPEAKERS,
+		{DOLBY_PARAM_ID_DVLO}, {DOLBY_ENDDEP_PARAM_DVLO_LENGTH},
+		{DOLBY_ENDDEP_PARAM_DVLO_OFFSET}, {-320} },
+	{BLUETOOTH_SCO_CARKIT,		2, DOLBY_ENDP_EXT_SPEAKERS,
+		{DOLBY_PARAM_ID_DVLO}, {DOLBY_ENDDEP_PARAM_DVLO_LENGTH},
+		{DOLBY_ENDDEP_PARAM_DVLO_OFFSET}, {-320} },
+	{BLUETOOTH_A2DP,		2, DOLBY_ENDP_EXT_SPEAKERS,
+		{DOLBY_PARAM_ID_DVLO}, {DOLBY_ENDDEP_PARAM_DVLO_LENGTH},
+		{DOLBY_ENDDEP_PARAM_DVLO_OFFSET}, {-320} },
+	{BLUETOOTH_A2DP_HEADPHONES,	2, DOLBY_ENDP_HEADPHONES,
+		{DOLBY_PARAM_ID_DVLO}, {DOLBY_ENDDEP_PARAM_DVLO_LENGTH},
+		{DOLBY_ENDDEP_PARAM_DVLO_OFFSET}, {-320} },
+	{BLUETOOTH_A2DP_SPEAKER,	2, DOLBY_ENDP_EXT_SPEAKERS,
+		{DOLBY_PARAM_ID_DVLO}, {DOLBY_ENDDEP_PARAM_DVLO_LENGTH},
+		{DOLBY_ENDDEP_PARAM_DVLO_OFFSET}, {-320} },
+	{AUX_DIGITAL,			2, DOLBY_ENDP_HDMI,
+		{DOLBY_PARAM_ID_DVLO}, {DOLBY_ENDDEP_PARAM_DVLO_LENGTH},
+		{DOLBY_ENDDEP_PARAM_DVLO_OFFSET}, {-640} },
+	{AUX_DIGITAL,			6, DOLBY_ENDP_HDMI,
+		{DOLBY_PARAM_ID_DVLO}, {DOLBY_ENDDEP_PARAM_DVLO_LENGTH},
+		{DOLBY_ENDDEP_PARAM_DVLO_OFFSET}, {-640} },
+	{AUX_DIGITAL,			8, DOLBY_ENDP_HDMI,
+		{DOLBY_PARAM_ID_DVLO}, {DOLBY_ENDDEP_PARAM_DVLO_LENGTH},
+		{DOLBY_ENDDEP_PARAM_DVLO_OFFSET}, {-640} },
+	{ANLG_DOCK_HEADSET,		2, DOLBY_ENDP_HEADPHONES,
+		{DOLBY_PARAM_ID_DVLO}, {DOLBY_ENDDEP_PARAM_DVLO_LENGTH},
+		{DOLBY_ENDDEP_PARAM_DVLO_OFFSET}, {-320} },
+	{DGTL_DOCK_HEADSET,		2, DOLBY_ENDP_HEADPHONES,
+		{DOLBY_PARAM_ID_DVLO}, {DOLBY_ENDDEP_PARAM_DVLO_LENGTH},
+		{DOLBY_ENDDEP_PARAM_DVLO_OFFSET}, {-320} },
+	{USB_ACCESSORY,			2, DOLBY_ENDP_EXT_SPEAKERS,
+		{DOLBY_PARAM_ID_DVLO}, {DOLBY_ENDDEP_PARAM_DVLO_LENGTH},
+		{DOLBY_ENDDEP_PARAM_DVLO_OFFSET}, {-320} },
+	{USB_DEVICE,			2, DOLBY_ENDP_EXT_SPEAKERS,
+		{DOLBY_PARAM_ID_DVLO}, {DOLBY_ENDDEP_PARAM_DVLO_LENGTH},
+		{DOLBY_ENDDEP_PARAM_DVLO_OFFSET}, {-320} },
+	{REMOTE_SUBMIX,			2, DOLBY_ENDP_EXT_SPEAKERS,
+		{DOLBY_PARAM_ID_DVLO}, {DOLBY_ENDDEP_PARAM_DVLO_LENGTH},
+		{DOLBY_ENDDEP_PARAM_DVLO_OFFSET}, {-320} },
+	{ANC_HEADSET,			2, DOLBY_ENDP_HEADPHONES,
+		{DOLBY_PARAM_ID_DVLO}, {DOLBY_ENDDEP_PARAM_DVLO_LENGTH},
+		{DOLBY_ENDDEP_PARAM_DVLO_OFFSET}, {-320} },
+	{ANC_HEADPHONE,			2, DOLBY_ENDP_HEADPHONES,
+		{DOLBY_PARAM_ID_DVLO}, {DOLBY_ENDDEP_PARAM_DVLO_LENGTH},
+		{DOLBY_ENDDEP_PARAM_DVLO_OFFSET}, {-320} },
+	{PROXY,				2, DOLBY_ENDP_EXT_SPEAKERS,
+		{DOLBY_PARAM_ID_DVLO}, {DOLBY_ENDDEP_PARAM_DVLO_LENGTH},
+		{DOLBY_ENDDEP_PARAM_DVLO_OFFSET}, {-320} },
+	{FM,				2, DOLBY_ENDP_EXT_SPEAKERS,
+		{DOLBY_PARAM_ID_DVLO}, {DOLBY_ENDDEP_PARAM_DVLO_LENGTH},
+		{DOLBY_ENDDEP_PARAM_DVLO_OFFSET}, {-320} },
+	{FM_TX,				2, DOLBY_ENDP_EXT_SPEAKERS,
+		{DOLBY_PARAM_ID_DVLO}, {DOLBY_ENDDEP_PARAM_DVLO_LENGTH},
+		{DOLBY_ENDDEP_PARAM_DVLO_OFFSET}, {-320} },
+};
+
+/* dolby param ids to/from dsp */
+static uint32_t	dolby_dap_params_id[ALL_DOLBY_PARAMS] = {
+	DOLBY_PARAM_ID_VDHE, DOLBY_PARAM_ID_VSPE, DOLBY_PARAM_ID_DSSF,
+	DOLBY_PARAM_ID_DVLI, DOLBY_PARAM_ID_DVLO, DOLBY_PARAM_ID_DVLE,
+	DOLBY_PARAM_ID_DVMC, DOLBY_PARAM_ID_DVME, DOLBY_PARAM_ID_IENB,
+	DOLBY_PARAM_ID_IEBF, DOLBY_PARAM_ID_IEON, DOLBY_PARAM_ID_DEON,
+	DOLBY_PARAM_ID_NGON, DOLBY_PARAM_ID_GEON, DOLBY_PARAM_ID_GENB,
+	DOLBY_PARAM_ID_GEBF, DOLBY_PARAM_ID_AONB, DOLBY_PARAM_ID_AOBF,
+	DOLBY_PARAM_ID_AOBG, DOLBY_PARAM_ID_AOON, DOLBY_PARAM_ID_ARNB,
+	DOLBY_PARAM_ID_ARBF, DOLBY_PARAM_ID_PLB,  DOLBY_PARAM_ID_PLMD,
+	DOLBY_PARAM_ID_DHSB, DOLBY_PARAM_ID_DHRG, DOLBY_PARAM_ID_DSSB,
+	DOLBY_PARAM_ID_DSSA, DOLBY_PARAM_ID_DVLA, DOLBY_PARAM_ID_IEBT,
+	DOLBY_PARAM_ID_IEA,  DOLBY_PARAM_ID_DEA,  DOLBY_PARAM_ID_DED,
+	DOLBY_PARAM_ID_GEBG, DOLBY_PARAM_ID_AOCC, DOLBY_PARAM_ID_ARBI,
+	DOLBY_PARAM_ID_ARBL, DOLBY_PARAM_ID_ARBH, DOLBY_PARAM_ID_AROD,
+	DOLBY_PARAM_ID_ARTP, DOLBY_PARAM_ID_VMON, DOLBY_PARAM_ID_VMB,
+	DOLBY_PARAM_ID_VCNB, DOLBY_PARAM_ID_VCBF, DOLBY_PARAM_ID_PREG,
+	DOLBY_PARAM_ID_VEN,  DOLBY_PARAM_ID_PSTG, DOLBY_COMMIT_ALL_TO_DSP,
+	DOLBY_COMMIT_TO_DSP, DOLBY_USE_CACHE, DOLBY_AUTO_ENDP,
+	DOLBY_AUTO_ENDDEP_PARAMS
+};
+
+/* modifed state:	0x00000000 - Not updated
+*			> 0x00000000 && < 0x00010000
+*				Updated and not commited to DSP
+*			0x00010001 - Updated and commited to DSP
+*			> 0x00010001 - Modified the commited value
+*/
+static int dolby_dap_params_modified[MAX_DOLBY_PARAMS] = { 0 };
+/* param offset */
+static uint32_t	dolby_dap_params_offset[MAX_DOLBY_PARAMS] = {
+	DOLBY_PARAM_VDHE_OFFSET, DOLBY_PARAM_VSPE_OFFSET,
+	DOLBY_PARAM_DSSF_OFFSET, DOLBY_PARAM_DVLI_OFFSET,
+	DOLBY_PARAM_DVLO_OFFSET, DOLBY_PARAM_DVLE_OFFSET,
+	DOLBY_PARAM_DVMC_OFFSET, DOLBY_PARAM_DVME_OFFSET,
+	DOLBY_PARAM_IENB_OFFSET, DOLBY_PARAM_IEBF_OFFSET,
+	DOLBY_PARAM_IEON_OFFSET, DOLBY_PARAM_DEON_OFFSET,
+	DOLBY_PARAM_NGON_OFFSET, DOLBY_PARAM_GEON_OFFSET,
+	DOLBY_PARAM_GENB_OFFSET, DOLBY_PARAM_GEBF_OFFSET,
+	DOLBY_PARAM_AONB_OFFSET, DOLBY_PARAM_AOBF_OFFSET,
+	DOLBY_PARAM_AOBG_OFFSET, DOLBY_PARAM_AOON_OFFSET,
+	DOLBY_PARAM_ARNB_OFFSET, DOLBY_PARAM_ARBF_OFFSET,
+	DOLBY_PARAM_PLB_OFFSET,  DOLBY_PARAM_PLMD_OFFSET,
+	DOLBY_PARAM_DHSB_OFFSET, DOLBY_PARAM_DHRG_OFFSET,
+	DOLBY_PARAM_DSSB_OFFSET, DOLBY_PARAM_DSSA_OFFSET,
+	DOLBY_PARAM_DVLA_OFFSET, DOLBY_PARAM_IEBT_OFFSET,
+	DOLBY_PARAM_IEA_OFFSET,  DOLBY_PARAM_DEA_OFFSET,
+	DOLBY_PARAM_DED_OFFSET,  DOLBY_PARAM_GEBG_OFFSET,
+	DOLBY_PARAM_AOCC_OFFSET, DOLBY_PARAM_ARBI_OFFSET,
+	DOLBY_PARAM_ARBL_OFFSET, DOLBY_PARAM_ARBH_OFFSET,
+	DOLBY_PARAM_AROD_OFFSET, DOLBY_PARAM_ARTP_OFFSET,
+	DOLBY_PARAM_VMON_OFFSET, DOLBY_PARAM_VMB_OFFSET,
+	DOLBY_PARAM_VCNB_OFFSET, DOLBY_PARAM_VCBF_OFFSET,
+	DOLBY_PARAM_PREG_OFFSET, DOLBY_PARAM_VEN_OFFSET,
+	DOLBY_PARAM_PSTG_OFFSET
+};
+/* param_length */
+static uint32_t	dolby_dap_params_length[MAX_DOLBY_PARAMS] = {
+	DOLBY_PARAM_VDHE_LENGTH, DOLBY_PARAM_VSPE_LENGTH,
+	DOLBY_PARAM_DSSF_LENGTH, DOLBY_PARAM_DVLI_LENGTH,
+	DOLBY_PARAM_DVLO_LENGTH, DOLBY_PARAM_DVLE_LENGTH,
+	DOLBY_PARAM_DVMC_LENGTH, DOLBY_PARAM_DVME_LENGTH,
+	DOLBY_PARAM_IENB_LENGTH, DOLBY_PARAM_IEBF_LENGTH,
+	DOLBY_PARAM_IEON_LENGTH, DOLBY_PARAM_DEON_LENGTH,
+	DOLBY_PARAM_NGON_LENGTH, DOLBY_PARAM_GEON_LENGTH,
+	DOLBY_PARAM_GENB_LENGTH, DOLBY_PARAM_GEBF_LENGTH,
+	DOLBY_PARAM_AONB_LENGTH, DOLBY_PARAM_AOBF_LENGTH,
+	DOLBY_PARAM_AOBG_LENGTH, DOLBY_PARAM_AOON_LENGTH,
+	DOLBY_PARAM_ARNB_LENGTH, DOLBY_PARAM_ARBF_LENGTH,
+	DOLBY_PARAM_PLB_LENGTH,  DOLBY_PARAM_PLMD_LENGTH,
+	DOLBY_PARAM_DHSB_LENGTH, DOLBY_PARAM_DHRG_LENGTH,
+	DOLBY_PARAM_DSSB_LENGTH, DOLBY_PARAM_DSSA_LENGTH,
+	DOLBY_PARAM_DVLA_LENGTH, DOLBY_PARAM_IEBT_LENGTH,
+	DOLBY_PARAM_IEA_LENGTH,  DOLBY_PARAM_DEA_LENGTH,
+	DOLBY_PARAM_DED_LENGTH,  DOLBY_PARAM_GEBG_LENGTH,
+	DOLBY_PARAM_AOCC_LENGTH, DOLBY_PARAM_ARBI_LENGTH,
+	DOLBY_PARAM_ARBL_LENGTH, DOLBY_PARAM_ARBH_LENGTH,
+	DOLBY_PARAM_AROD_LENGTH, DOLBY_PARAM_ARTP_LENGTH,
+	DOLBY_PARAM_VMON_LENGTH, DOLBY_PARAM_VMB_LENGTH,
+	DOLBY_PARAM_VCNB_LENGTH, DOLBY_PARAM_VCBF_LENGTH,
+	DOLBY_PARAM_PREG_LENGTH, DOLBY_PARAM_VEN_LENGTH,
+	DOLBY_PARAM_PSTG_LENGTH
+};
+
+/* param_value */
+static uint32_t	dolby_dap_params_value[TOTAL_LENGTH_DOLBY_PARAM] = {0};
+
+struct dolby_dap_params_get_s {
+	int32_t  port_id;
+	uint32_t device_id;
+	uint32_t param_id;
+	uint32_t offset;
+	uint32_t length;
+};
+
+struct dolby_dap_params_states_s {
+	bool use_cache;
+	bool auto_endp;
+	bool enddep_params;
+	int  port_id;
+	int  port_open_count;
+	int  port_ids_dolby_can_be_enabled;
+	int  device;
+};
+
+static struct dolby_dap_params_get_s dolby_dap_params_get = {-1, DEVICE_OUT_ALL,
+								 0, 0, 0};
+static struct dolby_dap_params_states_s dolby_dap_params_states = { true, true,
+						true, DOLBY_INVALID_PORT_ID,
+						0, DEVICE_OUT_ALL, 0 };
+/*
+port_ids_dolby_can_be_enabled is set to 0x7FFFFFFF.
+this needs to be removed after interface validation
+*/
+
+static int map_device_to_dolby_endpoint(int device)
+{
+	int i, dolby_dap_device = DOLBY_ENDP_INT_SPEAKERS;
+	for (i = 0; i < NUM_DOLBY_ENDP_DEVICE; i++) {
+		if (dolby_dap_endp_params[i].device == device) {
+			dolby_dap_device = dolby_dap_endp_params[i].dap_device;
+			break;
+		}
+	}
+	/* default the endpoint to speaker if corresponding device entry */
+	/* not found */
+	if (i >= NUM_DOLBY_ENDP_DEVICE)
+		dolby_dap_params_states.device = SPEAKER;
+	return dolby_dap_device;
+}
+
+static int dolby_dap_send_end_point(int port_id)
+{
+	int rc = 0;
+	char *params_value;
+	int *update_params_value;
+	uint32_t params_length = (DOLBY_PARAM_INT_ENDP_LENGTH +
+				DOLBY_PARAM_PAYLOAD_SIZE) * sizeof(uint32_t);
+
+	pr_debug("%s\n", __func__);
+	params_value = kzalloc(params_length, GFP_KERNEL);
+	if (!params_value) {
+		pr_err("%s, params memory alloc failed", __func__);
+		return -ENOMEM;
+	}
+	update_params_value = (int *)params_value;
+	*update_params_value++ = DOLBY_BUNDLE_MODULE_ID;
+	*update_params_value++ = DOLBY_PARAM_ID_INIT_ENDP;
+	*update_params_value++ = DOLBY_PARAM_INT_ENDP_LENGTH * sizeof(uint32_t);
+	*update_params_value++ =
+		 map_device_to_dolby_endpoint(dolby_dap_params_states.device);
+	rc = adm_dolby_dap_send_params(port_id, params_value, params_length);
+	if (rc) {
+		pr_err("%s: send dolby params failed\n", __func__);
+		rc = -EINVAL;
+	}
+	kfree(params_value);
+	return rc;
+}
+
+static int dolby_dap_send_enddep_params(int port_id, int device_channels)
+{
+	int i, j, rc = 0, idx, offset;
+	char *params_value;
+	int *update_params_value;
+	uint32_t params_length = (DOLBY_ENDDEP_PARAM_LENGTH +
+					DOLBY_NUM_ENDP_DEPENDENT_PARAMS *
+					DOLBY_PARAM_PAYLOAD_SIZE) *
+				sizeof(uint32_t);
+
+	pr_debug("%s\n", __func__);
+	params_value = kzalloc(params_length, GFP_KERNEL);
+	if (!params_value) {
+		pr_err("%s, params memory alloc failed", __func__);
+		return -ENOMEM;
+	}
+	update_params_value = (int *)params_value;
+	for (idx = 0; idx < NUM_DOLBY_ENDP_DEVICE; idx++) {
+		if (dolby_dap_endp_params[idx].device ==
+			dolby_dap_params_states.device) {
+			if (dolby_dap_params_states.device == AUX_DIGITAL) {
+				if (dolby_dap_endp_params[idx].device_ch_caps ==
+					device_channels)
+					break;
+			} else {
+				break;
+			}
+		}
+	}
+	if (idx >= NUM_DOLBY_ENDP_DEVICE) {
+		pr_err("%s: device is not set accordingly\n", __func__);
+		return -EINVAL;
+	}
+	for (i = 0; i < DOLBY_ENDDEP_PARAM_LENGTH; i++) {
+		*update_params_value++ = DOLBY_BUNDLE_MODULE_ID;
+		*update_params_value++ =
+				dolby_dap_endp_params[idx].params_id[i];
+		*update_params_value++ =
+			dolby_dap_endp_params[idx].params_len[i] *
+				sizeof(uint32_t);
+		offset = dolby_dap_endp_params[idx].params_offset[i];
+		for (j = 0; j < dolby_dap_endp_params[idx].params_len[i]; j++)
+			*update_params_value++ =
+				dolby_dap_endp_params[idx].params_val[offset+j];
+	}
+	rc = adm_dolby_dap_send_params(port_id, params_value, params_length);
+	if (rc) {
+		pr_err("%s: send dolby params failed\n", __func__);
+		rc = -EINVAL;
+	}
+	kfree(params_value);
+	return rc;
+}
+
+static int dolby_dap_send_cached_params(int port_id, int commit)
+{
+	char *params_value;
+	int *update_params_value, rc = 0;
+	uint32_t index_offset, i, j;
+	uint32_t params_length = (TOTAL_LENGTH_DOLBY_PARAM +
+				MAX_DOLBY_PARAMS * DOLBY_PARAM_PAYLOAD_SIZE) *
+				sizeof(uint32_t);
+
+	params_value = kzalloc(params_length, GFP_KERNEL);
+	if (!params_value) {
+		pr_err("%s, params memory alloc failed\n", __func__);
+		return -ENOMEM;
+	}
+	update_params_value = (int *)params_value;
+	params_length = 0;
+	for (i = 0; i < MAX_DOLBY_PARAMS; i++) {
+		if ((dolby_dap_params_modified[i] == 0) ||
+		    ((commit) &&
+		     ((dolby_dap_params_modified[i] & 0x00010000) &&
+		     ((dolby_dap_params_modified[i] & 0x0000FFFF) <= 1))))
+			continue;
+		*update_params_value++ = DOLBY_BUNDLE_MODULE_ID;
+		*update_params_value++ = dolby_dap_params_id[i];
+		*update_params_value++ = dolby_dap_params_length[i] *
+						sizeof(uint32_t);
+		index_offset = dolby_dap_params_offset[i];
+		for (j = 0; j < dolby_dap_params_length[i]; j++)
+			*update_params_value++ =
+				dolby_dap_params_value[index_offset+j];
+		params_length += (DOLBY_PARAM_PAYLOAD_SIZE +
+				dolby_dap_params_length[i]) * sizeof(uint32_t);
+	}
+	pr_debug("%s, valid param length: %d", __func__, params_length);
+	if (params_length) {
+		rc = adm_dolby_dap_send_params(port_id, params_value,
+						params_length);
+		if (rc) {
+			pr_err("%s: send dolby params failed\n", __func__);
+			return -EINVAL;
+		}
+		for (i = 0; i < MAX_DOLBY_PARAMS; i++) {
+			if ((dolby_dap_params_modified[i] == 0) ||
+			    ((commit) &&
+			     ((dolby_dap_params_modified[i] & 0x00010000) &&
+			     ((dolby_dap_params_modified[i] & 0x0000FFFF) <= 1))
+			    ))
+				continue;
+			dolby_dap_params_modified[i] = 0x00010001;
+		}
+	}
+	kfree(params_value);
+	return 0;
+}
+
+int dolby_dap_init(int port_id, int channels)
+{
+	int ret = 0;
+	if ((port_id != DOLBY_INVALID_PORT_ID) &&
+		(port_id &
+		 dolby_dap_params_states.port_ids_dolby_can_be_enabled)) {
+		dolby_dap_params_states.port_id = port_id;
+		dolby_dap_params_states.port_open_count++;
+		if (dolby_dap_params_states.auto_endp) {
+			ret = dolby_dap_send_end_point(port_id);
+			if (ret) {
+				pr_err("%s: err sending endppoint\n", __func__);
+				return ret;
+			}
+		}
+		if (dolby_dap_params_states.use_cache) {
+			ret = dolby_dap_send_cached_params(port_id, 0);
+			if (ret) {
+				pr_err("%s: err sending cached params\n",
+					__func__);
+				return ret;
+			}
+		}
+		if (dolby_dap_params_states.enddep_params) {
+			dolby_dap_send_enddep_params(port_id,
+				channels);
+			if (ret) {
+				pr_err("%s: err sending endp dependent params\n",
+					__func__);
+				return ret;
+			}
+		}
+	}
+	return ret;
+}
+
+void dolby_dap_deinit(int port_id)
+{
+	dolby_dap_params_states.port_open_count--;
+	if ((dolby_dap_params_states.port_id == port_id) &&
+		(!dolby_dap_params_states.port_open_count))
+		dolby_dap_params_states.port_id = DOLBY_INVALID_PORT_ID;
+}
+
+static int map_device_to_port_id(int device)
+{
+	int port_id = SLIMBUS_0_RX;
+	device = DEVICE_OUT_ALL;
+	/*update the device when single stream to multiple device is handled*/
+	if (device == DEVICE_OUT_ALL) {
+		port_id = PRIMARY_I2S_RX | SLIMBUS_0_RX | HDMI_RX |
+				INT_BT_SCO_RX | INT_FM_RX |
+				RT_PROXY_PORT_001_RX | PCM_RX |
+				MI2S_RX | SECONDARY_I2S_RX |
+				SLIMBUS_1_RX | SLIMBUS_4_RX | SLIMBUS_3_RX |
+				AFE_PORT_ID_SECONDARY_MI2S_RX;
+	} else {
+		/* update port_id based on the device */
+	}
+	return port_id;
+}
+
+int msm_routing_get_dolby_dap_param_to_set_control(
+		struct snd_kcontrol *kcontrol,
+		struct snd_ctl_elem_value *ucontrol) {
+	/* not used while setting the parameters */
+	return 0;
+}
+
+int msm_routing_put_dolby_dap_param_to_set_control(
+		struct snd_kcontrol *kcontrol,
+		struct snd_ctl_elem_value *ucontrol) {
+	int rc = 0;
+	uint32_t idx, j;
+	uint32_t device = ucontrol->value.integer.value[0];
+	uint32_t param_id = ucontrol->value.integer.value[1];
+	uint32_t offset = ucontrol->value.integer.value[2];
+	uint32_t length = ucontrol->value.integer.value[3];
+
+	int port_id = dolby_dap_params_states.port_id;
+
+	dolby_dap_params_states.port_ids_dolby_can_be_enabled =
+						map_device_to_port_id(device);
+	for (idx = 0; idx < ALL_DOLBY_PARAMS; idx++) {
+		/*paramid from user space*/
+		if (param_id == dolby_dap_params_id[idx])
+			break;
+	}
+	if (idx > ALL_DOLBY_PARAMS-1) {
+		pr_err("%s: invalid param id 0x%x to set\n", __func__,
+			param_id);
+		return -EINVAL;
+	}
+	switch (idx) {
+		case DOLBY_COMMIT_ALL_IDX: {
+			/* COMIIT ALL: Send all parameters to DSP */
+			pr_debug("%s: COMMIT_ALL recvd\n", __func__);
+			if (port_id != DOLBY_INVALID_PORT_ID)
+				rc = dolby_dap_send_cached_params(port_id, 0);
+		}
+		break;
+		case DOLBY_COMMIT_IDX: {
+			pr_debug("%s: COMMIT recvd\n", __func__);
+			/* COMMIT: Send only modified paramters to DSP */
+			if (port_id != DOLBY_INVALID_PORT_ID)
+				rc = dolby_dap_send_cached_params(port_id, 1);
+		}
+		break;
+		case DOLBY_USE_CACHE_IDX: {
+			pr_debug("%s: USE CACHE recvd val: %ld\n", __func__,
+				ucontrol->value.integer.value[4]);
+			dolby_dap_params_states.use_cache =
+				ucontrol->value.integer.value[4];
+		}
+		break;
+		case DOLBY_AUTO_ENDP_IDX: {
+			pr_debug("%s: AUTO_ENDP recvd val: %ld\n", __func__,
+				ucontrol->value.integer.value[4]);
+			dolby_dap_params_states.auto_endp =
+				ucontrol->value.integer.value[4];
+		}
+		break;
+		case DOLBY_AUTO_ENDDEP_IDX: {
+			pr_debug("%s: USE_ENDDEP_PARAMS recvd val: %ld\n",
+				__func__, ucontrol->value.integer.value[4]);
+			dolby_dap_params_states.enddep_params =
+				ucontrol->value.integer.value[4];
+		}
+		break;
+		default: {
+			/* cache the parameters */
+			dolby_dap_params_modified[idx] += 1;
+			dolby_dap_params_length[idx] = length;
+			pr_debug("%s: param recvd deviceId=0x%x paramId=0x%x offset=%d length=%d\n",
+				__func__, device, param_id, offset, length);
+			for (j = 0; j < length; j++) {
+				dolby_dap_params_value[
+					dolby_dap_params_offset[idx] +
+					offset + j]
+				= ucontrol->value.integer.value[4+j];
+				pr_debug("value[%d]: %ld\n", j,
+					ucontrol->value.integer.value[4+j]);
+			}
+		}
+	}
+
+	return rc;
+}
+
+int msm_routing_get_dolby_dap_param_to_get_control(
+		struct snd_kcontrol *kcontrol,
+		struct snd_ctl_elem_value *ucontrol) {
+	int rc = 0, i;
+	char *params_value;
+	int *update_params_value;
+	uint32_t params_length = DOLBY_MAX_LENGTH_INDIVIDUAL_PARAM *
+					sizeof(uint32_t);
+	uint32_t param_payload_len =
+			DOLBY_PARAM_PAYLOAD_SIZE * sizeof(uint32_t);
+	int port_id = dolby_dap_params_states.port_id;
+
+	if (port_id == DOLBY_INVALID_PORT_ID) {
+		pr_err("%s, port_id not set, returning error", __func__);
+		return -EINVAL;
+	}
+	params_value = kzalloc(params_length, GFP_KERNEL);
+	if (!params_value) {
+		pr_err("%s, params memory alloc failed\n", __func__);
+		return -ENOMEM;
+	}
+	if (DOLBY_PARAM_ID_VER == dolby_dap_params_get.param_id) {
+		rc = adm_dolby_dap_get_params(dolby_dap_params_get.port_id,
+						DOLBY_BUNDLE_MODULE_ID,
+						DOLBY_PARAM_ID_VER,
+						params_length +
+							param_payload_len,
+						params_value);
+	} else {
+		for (i = 0; i < MAX_DOLBY_PARAMS; i++)
+			if (dolby_dap_params_id[i] ==
+				dolby_dap_params_get.param_id)
+				break;
+		if (i > MAX_DOLBY_PARAMS-1) {
+			pr_err("%s: invalid param id to set", __func__);
+			rc = -EINVAL;
+		} else {
+			params_length = (dolby_dap_params_length[i] +
+						DOLBY_PARAM_PAYLOAD_SIZE) *
+						sizeof(uint32_t);
+			rc = adm_dolby_dap_get_params(
+						dolby_dap_params_get.port_id,
+						DOLBY_BUNDLE_MODULE_ID,
+						dolby_dap_params_id[i],
+						params_length +
+						 param_payload_len,
+						params_value);
+		}
+	}
+	if (rc) {
+		pr_err("%s: get parameters failed\n", __func__);
+		kfree(params_value);
+		rc = -EINVAL;
+	}
+	update_params_value = (int *)params_value;
+	ucontrol->value.integer.value[0] = dolby_dap_params_get.device_id;
+	ucontrol->value.integer.value[1] = dolby_dap_params_get.param_id;
+	ucontrol->value.integer.value[2] = dolby_dap_params_get.offset;
+	ucontrol->value.integer.value[3] = dolby_dap_params_get.length;
+
+	pr_debug("%s: FROM DSP value[0] 0x%x value[1] %d value[2] 0x%x\n",
+			__func__, update_params_value[0],
+			update_params_value[1], update_params_value[2]);
+	for (i = 0; i < dolby_dap_params_get.length; i++) {
+		ucontrol->value.integer.value[DOLBY_PARAM_PAYLOAD_SIZE+i] =
+			update_params_value[i];
+		pr_debug("value[%d]:%d\n", i, update_params_value[i]);
+	}
+	pr_debug("%s: Returning param_id=0x%x offset=%d length=%d\n",
+			__func__, dolby_dap_params_get.param_id,
+			dolby_dap_params_get.offset,
+			dolby_dap_params_get.length);
+	kfree(params_value);
+	return 0;
+}
+
+int msm_routing_put_dolby_dap_param_to_get_control(
+					struct snd_kcontrol *kcontrol,
+					struct snd_ctl_elem_value *ucontrol) {
+	dolby_dap_params_get.device_id = ucontrol->value.integer.value[0];
+	dolby_dap_params_get.port_id =
+			(dolby_dap_params_get.device_id == DEVICE_OUT_ALL) ?
+			dolby_dap_params_states.port_id :
+			map_device_to_port_id(dolby_dap_params_get.device_id);
+	dolby_dap_params_get.param_id = ucontrol->value.integer.value[1];
+	dolby_dap_params_get.offset = ucontrol->value.integer.value[2];
+	dolby_dap_params_get.length = ucontrol->value.integer.value[3];
+	pr_debug("%s: param_id=0x%x offset=%d length=%d\n", __func__,
+		dolby_dap_params_get.param_id, dolby_dap_params_get.offset,
+		dolby_dap_params_get.length);
+	return 0;
+}
+
+int msm_routing_get_dolby_dap_param_visualizer_control(
+		struct snd_kcontrol *kcontrol,
+		struct snd_ctl_elem_value *ucontrol) {
+	uint32_t length = dolby_dap_params_value[DOLBY_PARAM_VCNB_OFFSET];
+	char *visualizer_data;
+	int i, rc;
+	int *update_visualizer_data;
+	uint32_t offset, params_length =
+		(2*length + DOLBY_VIS_PARAM_HEADER_SIZE)*sizeof(uint32_t);
+	uint32_t param_payload_len =
+		DOLBY_PARAM_PAYLOAD_SIZE * sizeof(uint32_t);
+	int port_id = dolby_dap_params_states.port_id;
+	if (port_id == DOLBY_INVALID_PORT_ID) {
+		pr_err("%s, port_id not set, returning error", __func__);
+		ucontrol->value.integer.value[0] = 0;
+		return -EINVAL;
+	}
+	visualizer_data = kzalloc(params_length, GFP_KERNEL);
+	if (!visualizer_data) {
+		pr_err("%s, params memory alloc failed\n", __func__);
+		return -ENOMEM;
+	}
+	offset = 0;
+	params_length = length * sizeof(uint32_t);
+	rc = adm_dolby_dap_get_params(dolby_dap_params_states.port_id,
+					DOLBY_BUNDLE_MODULE_ID,
+					DOLBY_PARAM_ID_VCBG,
+					params_length + param_payload_len,
+					visualizer_data + offset);
+	if (rc) {
+		pr_err("%s: get parameters failed\n", __func__);
+		kfree(visualizer_data);
+		return -EINVAL;
+	}
+
+	offset = length * sizeof(uint32_t);
+	rc = adm_dolby_dap_get_params(dolby_dap_params_states.port_id,
+					DOLBY_BUNDLE_MODULE_ID,
+					DOLBY_PARAM_ID_VCBE,
+					params_length + param_payload_len,
+					visualizer_data + offset);
+	if (rc) {
+		pr_err("%s: get parameters failed\n", __func__);
+		kfree(visualizer_data);
+		return -EINVAL;
+	}
+
+	ucontrol->value.integer.value[0] = 2*length;
+	pr_debug("%s: visualizer data length %ld\n", __func__,
+			ucontrol->value.integer.value[0]);
+	update_visualizer_data = (int *)visualizer_data;
+	for (i = 0; i < 2*length; i++) {
+		ucontrol->value.integer.value[1+i] = update_visualizer_data[i];
+		pr_debug("value[%d] %d\n", i, update_visualizer_data[i]);
+	}
+	kfree(visualizer_data);
+	return 0;
+}
+
+int msm_routing_put_dolby_dap_param_visualizer_control(
+		struct snd_kcontrol *kcontrol,
+		struct snd_ctl_elem_value *ucontrol) {
+	/* not used while getting the visualizer data */
+	return 0;
+}
+
+int msm_routing_get_dolby_dap_endpoint_control(
+		struct snd_kcontrol *kcontrol,
+		struct snd_ctl_elem_value *ucontrol) {
+	/* not used while setting the endpoint */
+	return 0;
+}
+
+int msm_routing_put_dolby_dap_endpoint_control(
+		struct snd_kcontrol *kcontrol,
+		struct snd_ctl_elem_value *ucontrol) {
+	int device = ucontrol->value.integer.value[0];
+	dolby_dap_params_states.device = device;
+	return 0;
+}
diff --git a/sound/soc/msm/qdsp6v2/msm-dolby-dap-config.h b/sound/soc/msm/qdsp6v2/msm-dolby-dap-config.h
new file mode 100644
index 0000000..58ea36d
--- /dev/null
+++ b/sound/soc/msm/qdsp6v2/msm-dolby-dap-config.h
@@ -0,0 +1,348 @@
+/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License version 2 and
+* only version 2 as published by the Free Software Foundation.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+* GNU General Public License for more details.
+*/
+
+#ifndef _MSM_DOLBY_DAP_CONFIG_H_
+#define _MSM_DOLBY_DAP_CONFIG_H_
+
+#ifdef CONFIG_DOLBY_DAP
+/* DOLBY DOLBY GUIDS */
+#define DOLBY_ADM_COPP_TOPOLOGY_ID	0x0001033B
+#define DOLBY_BUNDLE_MODULE_ID		0x00010723
+#define DOLBY_VISUALIZER_MODULE_ID	0x0001072B
+
+#define DOLBY_PARAM_ID_VDHE		0x0001074D
+#define DOLBY_PARAM_ID_VSPE		0x00010750
+#define DOLBY_PARAM_ID_DSSF		0x00010753
+#define DOLBY_PARAM_ID_DVLI		0x0001073E
+#define DOLBY_PARAM_ID_DVLO		0x0001073F
+#define DOLBY_PARAM_ID_DVLE		0x0001073C
+#define DOLBY_PARAM_ID_DVMC		0x00010741
+#define DOLBY_PARAM_ID_DVME		0x00010740
+#define DOLBY_PARAM_ID_IENB		0x00010744
+#define DOLBY_PARAM_ID_IEBF		0x00010745
+#define DOLBY_PARAM_ID_IEON		0x00010743
+#define DOLBY_PARAM_ID_DEON		0x00010738
+#define DOLBY_PARAM_ID_NGON		0x00010736
+#define DOLBY_PARAM_ID_GEON		0x00010748
+#define DOLBY_PARAM_ID_GENB		0x00010749
+#define DOLBY_PARAM_ID_GEBF		0x0001074A
+#define DOLBY_PARAM_ID_AONB		0x0001075B
+#define DOLBY_PARAM_ID_AOBF		0x0001075C
+#define DOLBY_PARAM_ID_AOBG		0x0001075D
+#define DOLBY_PARAM_ID_AOON		0x00010759
+#define DOLBY_PARAM_ID_ARNB		0x0001075F
+#define DOLBY_PARAM_ID_ARBF		0x00010760
+#define DOLBY_PARAM_ID_PLB		0x00010768
+#define DOLBY_PARAM_ID_PLMD		0x00010767
+#define DOLBY_PARAM_ID_DHSB		0x0001074E
+#define DOLBY_PARAM_ID_DHRG		0x0001074F
+#define DOLBY_PARAM_ID_DSSB		0x00010751
+#define DOLBY_PARAM_ID_DSSA		0x00010752
+#define DOLBY_PARAM_ID_DVLA		0x0001073D
+#define DOLBY_PARAM_ID_IEBT		0x00010746
+#define DOLBY_PARAM_ID_IEA		0x0001076A
+#define DOLBY_PARAM_ID_DEA		0x00010739
+#define DOLBY_PARAM_ID_DED		0x0001073A
+#define DOLBY_PARAM_ID_GEBG		0x0001074B
+#define DOLBY_PARAM_ID_AOCC		0x0001075A
+#define DOLBY_PARAM_ID_ARBI		0x00010761
+#define DOLBY_PARAM_ID_ARBL		0x00010762
+#define DOLBY_PARAM_ID_ARBH		0x00010763
+#define DOLBY_PARAM_ID_AROD		0x00010764
+#define DOLBY_PARAM_ID_ARTP		0x00010765
+#define DOLBY_PARAM_ID_VMON		0x00010756
+#define DOLBY_PARAM_ID_VMB		0x00010757
+#define DOLBY_PARAM_ID_VCNB		0x00010733
+#define DOLBY_PARAM_ID_VCBF		0x00010734
+#define DOLBY_PARAM_ID_PREG		0x00010728
+#define DOLBY_PARAM_ID_VEN		0x00010732
+#define DOLBY_PARAM_ID_PSTG		0x00010729
+#define DOLBY_PARAM_ID_INIT_ENDP		0x00010727
+
+/* Not Used with Set Param kcontrol, only to query using Get Param */
+#define DOLBY_PARAM_ID_VER                0x00010726
+
+#define DOLBY_PARAM_ID_VCBG		0x00010730
+#define DOLBY_PARAM_ID_VCBE		0x00010731
+
+/* DOLBY DAP control params */
+#define DOLBY_COMMIT_ALL_TO_DSP		0x70000001
+#define DOLBY_COMMIT_TO_DSP		0x70000002
+#define DOLBY_USE_CACHE			0x70000003
+#define DOLBY_AUTO_ENDP			0x70000004
+#define DOLBY_AUTO_ENDDEP_PARAMS		0x70000005
+
+/* DOLBY DAP offsets start */
+#define DOLBY_PARAM_VDHE_LENGTH   1
+#define DOLBY_PARAM_VDHE_OFFSET   0
+#define DOLBY_PARAM_VSPE_LENGTH   1
+#define DOLBY_PARAM_VSPE_OFFSET   (DOLBY_PARAM_VDHE_OFFSET + \
+					DOLBY_PARAM_VDHE_LENGTH)
+#define DOLBY_PARAM_DSSF_LENGTH   1
+#define DOLBY_PARAM_DSSF_OFFSET   (DOLBY_PARAM_VSPE_OFFSET + \
+					DOLBY_PARAM_VSPE_LENGTH)
+#define DOLBY_PARAM_DVLI_LENGTH   1
+#define DOLBY_PARAM_DVLI_OFFSET   (DOLBY_PARAM_DSSF_OFFSET + \
+					DOLBY_PARAM_DSSF_LENGTH)
+#define DOLBY_PARAM_DVLO_LENGTH   1
+#define DOLBY_PARAM_DVLO_OFFSET   (DOLBY_PARAM_DVLI_OFFSET + \
+					DOLBY_PARAM_DVLI_LENGTH)
+#define DOLBY_PARAM_DVLE_LENGTH   1
+#define DOLBY_PARAM_DVLE_OFFSET   (DOLBY_PARAM_DVLO_OFFSET + \
+					DOLBY_PARAM_DVLO_LENGTH)
+#define DOLBY_PARAM_DVMC_LENGTH   1
+#define DOLBY_PARAM_DVMC_OFFSET   (DOLBY_PARAM_DVLE_OFFSET + \
+					DOLBY_PARAM_DVLE_LENGTH)
+#define DOLBY_PARAM_DVME_LENGTH   1
+#define DOLBY_PARAM_DVME_OFFSET   (DOLBY_PARAM_DVMC_OFFSET + \
+					DOLBY_PARAM_DVMC_LENGTH)
+#define DOLBY_PARAM_IENB_LENGTH   1
+#define DOLBY_PARAM_IENB_OFFSET   (DOLBY_PARAM_DVME_OFFSET + \
+					DOLBY_PARAM_DVME_LENGTH)
+#define DOLBY_PARAM_IEBF_LENGTH   40
+#define DOLBY_PARAM_IEBF_OFFSET   (DOLBY_PARAM_IENB_OFFSET + \
+					DOLBY_PARAM_IENB_LENGTH)
+#define DOLBY_PARAM_IEON_LENGTH   1
+#define DOLBY_PARAM_IEON_OFFSET   (DOLBY_PARAM_IEBF_OFFSET + \
+					DOLBY_PARAM_IEBF_LENGTH)
+#define DOLBY_PARAM_DEON_LENGTH   1
+#define DOLBY_PARAM_DEON_OFFSET   (DOLBY_PARAM_IEON_OFFSET + \
+					DOLBY_PARAM_IEON_LENGTH)
+#define DOLBY_PARAM_NGON_LENGTH   1
+#define DOLBY_PARAM_NGON_OFFSET   (DOLBY_PARAM_DEON_OFFSET + \
+					DOLBY_PARAM_DEON_LENGTH)
+#define DOLBY_PARAM_GEON_LENGTH   1
+#define DOLBY_PARAM_GEON_OFFSET   (DOLBY_PARAM_NGON_OFFSET + \
+					DOLBY_PARAM_NGON_LENGTH)
+#define DOLBY_PARAM_GENB_LENGTH   1
+#define DOLBY_PARAM_GENB_OFFSET   (DOLBY_PARAM_GEON_OFFSET + \
+					DOLBY_PARAM_GEON_LENGTH)
+#define DOLBY_PARAM_GEBF_LENGTH   40
+#define DOLBY_PARAM_GEBF_OFFSET   (DOLBY_PARAM_GENB_OFFSET + \
+					DOLBY_PARAM_GENB_LENGTH)
+#define DOLBY_PARAM_AONB_LENGTH   1
+#define DOLBY_PARAM_AONB_OFFSET   (DOLBY_PARAM_GEBF_OFFSET + \
+					DOLBY_PARAM_GEBF_LENGTH)
+#define DOLBY_PARAM_AOBF_LENGTH   40
+#define DOLBY_PARAM_AOBF_OFFSET   (DOLBY_PARAM_AONB_OFFSET + \
+					DOLBY_PARAM_AONB_LENGTH)
+#define DOLBY_PARAM_AOBG_LENGTH   329
+#define DOLBY_PARAM_AOBG_OFFSET   (DOLBY_PARAM_AOBF_OFFSET + \
+					DOLBY_PARAM_AOBF_LENGTH)
+#define DOLBY_PARAM_AOON_LENGTH   1
+#define DOLBY_PARAM_AOON_OFFSET   (DOLBY_PARAM_AOBG_OFFSET + \
+					DOLBY_PARAM_AOBG_LENGTH)
+#define DOLBY_PARAM_ARNB_LENGTH   1
+#define DOLBY_PARAM_ARNB_OFFSET   (DOLBY_PARAM_AOON_OFFSET + \
+					DOLBY_PARAM_AOON_LENGTH)
+#define DOLBY_PARAM_ARBF_LENGTH   40
+#define DOLBY_PARAM_ARBF_OFFSET   (DOLBY_PARAM_ARNB_OFFSET + \
+					DOLBY_PARAM_ARNB_LENGTH)
+#define DOLBY_PARAM_PLB_LENGTH    1
+#define DOLBY_PARAM_PLB_OFFSET    (DOLBY_PARAM_ARBF_OFFSET + \
+					DOLBY_PARAM_ARBF_LENGTH)
+#define DOLBY_PARAM_PLMD_LENGTH   1
+#define DOLBY_PARAM_PLMD_OFFSET   (DOLBY_PARAM_PLB_OFFSET + \
+					DOLBY_PARAM_PLB_LENGTH)
+#define DOLBY_PARAM_DHSB_LENGTH   1
+#define DOLBY_PARAM_DHSB_OFFSET   (DOLBY_PARAM_PLMD_OFFSET + \
+					DOLBY_PARAM_PLMD_LENGTH)
+#define DOLBY_PARAM_DHRG_LENGTH   1
+#define DOLBY_PARAM_DHRG_OFFSET   (DOLBY_PARAM_DHSB_OFFSET + \
+					DOLBY_PARAM_DHSB_LENGTH)
+#define DOLBY_PARAM_DSSB_LENGTH   1
+#define DOLBY_PARAM_DSSB_OFFSET   (DOLBY_PARAM_DHRG_OFFSET + \
+					DOLBY_PARAM_DHRG_LENGTH)
+#define DOLBY_PARAM_DSSA_LENGTH   1
+#define DOLBY_PARAM_DSSA_OFFSET   (DOLBY_PARAM_DSSB_OFFSET + \
+					DOLBY_PARAM_DSSB_LENGTH)
+#define DOLBY_PARAM_DVLA_LENGTH   1
+#define DOLBY_PARAM_DVLA_OFFSET   (DOLBY_PARAM_DSSA_OFFSET + \
+					DOLBY_PARAM_DSSA_LENGTH)
+#define DOLBY_PARAM_IEBT_LENGTH   40
+#define DOLBY_PARAM_IEBT_OFFSET   (DOLBY_PARAM_DVLA_OFFSET + \
+					DOLBY_PARAM_DVLA_LENGTH)
+#define DOLBY_PARAM_IEA_LENGTH    1
+#define DOLBY_PARAM_IEA_OFFSET    (DOLBY_PARAM_IEBT_OFFSET + \
+					DOLBY_PARAM_IEBT_LENGTH)
+#define DOLBY_PARAM_DEA_LENGTH    1
+#define DOLBY_PARAM_DEA_OFFSET    (DOLBY_PARAM_IEA_OFFSET + \
+					DOLBY_PARAM_IEA_LENGTH)
+#define DOLBY_PARAM_DED_LENGTH    1
+#define DOLBY_PARAM_DED_OFFSET    (DOLBY_PARAM_DEA_OFFSET + \
+					DOLBY_PARAM_DEA_LENGTH)
+#define DOLBY_PARAM_GEBG_LENGTH   40
+#define DOLBY_PARAM_GEBG_OFFSET   (DOLBY_PARAM_DED_OFFSET + \
+					DOLBY_PARAM_DED_LENGTH)
+#define DOLBY_PARAM_AOCC_LENGTH   1
+#define DOLBY_PARAM_AOCC_OFFSET   (DOLBY_PARAM_GEBG_OFFSET + \
+					DOLBY_PARAM_GEBG_LENGTH)
+#define DOLBY_PARAM_ARBI_LENGTH   40
+#define DOLBY_PARAM_ARBI_OFFSET   (DOLBY_PARAM_AOCC_OFFSET + \
+					DOLBY_PARAM_AOCC_LENGTH)
+#define DOLBY_PARAM_ARBL_LENGTH   40
+#define DOLBY_PARAM_ARBL_OFFSET   (DOLBY_PARAM_ARBI_OFFSET + \
+					DOLBY_PARAM_ARBI_LENGTH)
+#define DOLBY_PARAM_ARBH_LENGTH   40
+#define DOLBY_PARAM_ARBH_OFFSET   (DOLBY_PARAM_ARBL_OFFSET + \
+					DOLBY_PARAM_ARBL_LENGTH)
+#define DOLBY_PARAM_AROD_LENGTH   1
+#define DOLBY_PARAM_AROD_OFFSET   (DOLBY_PARAM_ARBH_OFFSET + \
+					DOLBY_PARAM_ARBH_LENGTH)
+#define DOLBY_PARAM_ARTP_LENGTH   1
+#define DOLBY_PARAM_ARTP_OFFSET   (DOLBY_PARAM_AROD_OFFSET + \
+					DOLBY_PARAM_AROD_LENGTH)
+#define DOLBY_PARAM_VMON_LENGTH   1
+#define DOLBY_PARAM_VMON_OFFSET   (DOLBY_PARAM_ARTP_OFFSET + \
+					DOLBY_PARAM_ARTP_LENGTH)
+#define DOLBY_PARAM_VMB_LENGTH    1
+#define DOLBY_PARAM_VMB_OFFSET    (DOLBY_PARAM_VMON_OFFSET + \
+					DOLBY_PARAM_VMON_LENGTH)
+#define DOLBY_PARAM_VCNB_LENGTH   1
+#define DOLBY_PARAM_VCNB_OFFSET   (DOLBY_PARAM_VMB_OFFSET + \
+					DOLBY_PARAM_VMB_LENGTH)
+#define DOLBY_PARAM_VCBF_LENGTH   20
+#define DOLBY_PARAM_VCBF_OFFSET   (DOLBY_PARAM_VCNB_OFFSET + \
+					DOLBY_PARAM_VCNB_LENGTH)
+#define DOLBY_PARAM_PREG_LENGTH   1
+#define DOLBY_PARAM_PREG_OFFSET   (DOLBY_PARAM_VCBF_OFFSET + \
+					DOLBY_PARAM_VCBF_LENGTH)
+#define DOLBY_PARAM_VEN_LENGTH    1
+#define DOLBY_PARAM_VEN_OFFSET    (DOLBY_PARAM_PREG_OFFSET + \
+					DOLBY_PARAM_PREG_LENGTH)
+#define DOLBY_PARAM_PSTG_LENGTH   1
+#define DOLBY_PARAM_PSTG_OFFSET   (DOLBY_PARAM_VEN_OFFSET + \
+					DOLBY_PARAM_VEN_LENGTH)
+
+#define DOLBY_PARAM_INT_ENDP_LENGTH		1
+#define DOLBY_PARAM_PAYLOAD_SIZE		4
+#define DOLBY_MAX_LENGTH_INDIVIDUAL_PARAM	329
+
+#define DOLBY_NUM_ENDP_DEPENDENT_PARAMS		1
+#define DOLBY_ENDDEP_PARAM_DVLO_OFFSET		0
+#define DOLBY_ENDDEP_PARAM_DVLO_LENGTH		1
+#define DOLBY_ENDDEP_PARAM_LENGTH		DOLBY_ENDDEP_PARAM_DVLO_LENGTH
+
+#define MAX_DOLBY_PARAMS			47
+#define MAX_DOLBY_CTRL_PARAMS			5
+#define ALL_DOLBY_PARAMS			(MAX_DOLBY_PARAMS + \
+							MAX_DOLBY_CTRL_PARAMS)
+#define DOLBY_COMMIT_ALL_IDX			MAX_DOLBY_PARAMS
+#define DOLBY_COMMIT_IDX			(MAX_DOLBY_PARAMS+1)
+#define DOLBY_USE_CACHE_IDX			(MAX_DOLBY_PARAMS+2)
+#define DOLBY_AUTO_ENDP_IDX			(MAX_DOLBY_PARAMS+3)
+#define DOLBY_AUTO_ENDDEP_IDX			(MAX_DOLBY_PARAMS+4)
+
+#define TOTAL_LENGTH_DOLBY_PARAM		745
+#define NUM_DOLBY_ENDP_DEVICE			23
+#define DOLBY_VIS_PARAM_HEADER_SIZE		 25
+
+#define DOLBY_INVALID_PORT_ID			-1
+/* DOLBY device definitions */
+enum {
+	DOLBY_ENDP_INT_SPEAKERS = 0,
+	DOLBY_ENDP_EXT_SPEAKERS,
+	DOLBY_ENDP_HEADPHONES,
+	DOLBY_ENDP_HDMI,
+	DOLBY_ENDP_SPDIF,
+	DOLBY_ENDP_DLNA,
+	DOLBY_ENDP_ANALOG,
+};
+
+enum {
+	DEVICE_NONE			= 0x0,
+	/* output devices */
+	EARPIECE			= 0x1,
+	SPEAKER				= 0x2,
+	WIRED_HEADSET			= 0x4,
+	WIRED_HEADPHONE			= 0x8,
+	BLUETOOTH_SCO			= 0x10,
+	BLUETOOTH_SCO_HEADSET		= 0x20,
+	BLUETOOTH_SCO_CARKIT		= 0x40,
+	BLUETOOTH_A2DP			= 0x80,
+	BLUETOOTH_A2DP_HEADPHONES	= 0x100,
+	BLUETOOTH_A2DP_SPEAKER		= 0x200,
+	AUX_DIGITAL			= 0x400,
+	ANLG_DOCK_HEADSET		= 0x800,
+	DGTL_DOCK_HEADSET		= 0x1000,
+	USB_ACCESSORY			= 0x2000,
+	USB_DEVICE			= 0x4000,
+	REMOTE_SUBMIX			= 0x8000,
+	ANC_HEADSET			= 0x10000,
+	ANC_HEADPHONE			= 0x20000,
+	PROXY				= 0x40000,
+	FM				= 0x80000,
+	FM_TX				= 0x100000,
+	DEVICE_OUT_ALL			= 0x7FFFFFFF,
+};
+/* DOLBY device definitions end */
+
+struct dolby_dap_params {
+	uint32_t value[TOTAL_LENGTH_DOLBY_PARAM + MAX_DOLBY_PARAMS];
+} __packed;
+int dolby_dap_init(int port_id, int channels);
+int msm_routing_get_dolby_dap_param_to_set_control(
+			struct snd_kcontrol *kcontrol,
+			struct snd_ctl_elem_value *ucontrol);
+int msm_routing_put_dolby_dap_param_to_set_control(
+			struct snd_kcontrol *kcontrol,
+			struct snd_ctl_elem_value *ucontrol);
+int msm_routing_get_dolby_dap_param_to_get_control(
+			struct snd_kcontrol *kcontrol,
+			struct snd_ctl_elem_value *ucontrol);
+int msm_routing_put_dolby_dap_param_to_get_control(
+			struct snd_kcontrol *kcontrol,
+			struct snd_ctl_elem_value *ucontrol);
+int msm_routing_get_dolby_dap_param_visualizer_control(
+			struct snd_kcontrol *kcontrol,
+			struct snd_ctl_elem_value *ucontrol);
+int msm_routing_put_dolby_dap_param_visualizer_control(
+			struct snd_kcontrol *kcontrol,
+			struct snd_ctl_elem_value *ucontrol);
+int msm_routing_get_dolby_dap_endpoint_control(
+			struct snd_kcontrol *kcontrol,
+			struct snd_ctl_elem_value *ucontrol);
+int msm_routing_put_dolby_dap_endpoint_control(
+			struct snd_kcontrol *kcontrol,
+			struct snd_ctl_elem_value *ucontrol);
+void dolby_dap_deinit(int port_id);
+/* Dolby DOLBY end */
+#else
+int dolby_dap_init(int port_id, int channels) { return 0; }
+int msm_routing_get_dolby_dap_param_to_set_control(
+			struct snd_kcontrol *kcontrol,
+			struct snd_ctl_elem_value *ucontrol) { return 0; }
+int msm_routing_put_dolby_dap_param_to_set_control(
+			struct snd_kcontrol *kcontrol,
+			struct snd_ctl_elem_value *ucontrol) { return 0; }
+int msm_routing_get_dolby_dap_param_to_get_control(
+			struct snd_kcontrol *kcontrol,
+			struct snd_ctl_elem_value *ucontrol) { return 0; }
+int msm_routing_put_dolby_dap_param_to_get_control(
+			struct snd_kcontrol *kcontrol,
+			struct snd_ctl_elem_value *ucontrol) { return 0; }
+int msm_routing_get_dolby_dap_param_visualizer_control(
+			struct snd_kcontrol *kcontrol,
+			struct snd_ctl_elem_value *ucontrol) { return 0; }
+int msm_routing_put_dolby_dap_param_visualizer_control(
+			struct snd_kcontrol *kcontrol,
+			struct snd_ctl_elem_value *ucontrol) { return 0; }
+int msm_routing_get_dolby_dap_endpoint_control(
+			struct snd_kcontrol *kcontrol,
+			struct snd_ctl_elem_value *ucontrol) { return 0; }
+int msm_routing_put_dolby_dap_endpoint_control(
+			struct snd_kcontrol *kcontrol,
+			struct snd_ctl_elem_value *ucontrol) { return 0; }
+void dolby_dap_deinit(int port_id) { return; }
+#endif
+
+#endif
+
diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-afe-v2.c b/sound/soc/msm/qdsp6v2/msm-pcm-afe-v2.c
index e4f3f94..96ddcf6 100644
--- a/sound/soc/msm/qdsp6v2/msm-pcm-afe-v2.c
+++ b/sound/soc/msm/qdsp6v2/msm-pcm-afe-v2.c
@@ -30,7 +30,6 @@
 #include <sound/q6adm-v2.h>
 #include <asm/dma.h>
 #include <linux/memory_alloc.h>
-#include <mach/msm_subsystem_map.h>
 #include "msm-pcm-afe-v2.h"
 
 #define MIN_PERIOD_SIZE (128 * 2)
diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.c b/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.c
index ca91fe5..717e63b 100644
--- a/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.c
+++ b/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.c
@@ -82,9 +82,9 @@
 				SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME),
 	.formats =              (SNDRV_PCM_FMTBIT_S16_LE |
 				SNDRV_PCM_FMTBIT_S24_LE),
-	.rates =                SNDRV_PCM_RATE_8000_96000,
+	.rates =                SNDRV_PCM_RATE_8000_192000,
 	.rate_min =             8000,
-	.rate_max =             96000,
+	.rate_max =             192000,
 	.channels_min =         1,
 	.channels_max =         8,
 	.buffer_bytes_max =     PLAYBACK_NUM_PERIODS * PLAYBACK_MAX_PERIOD_SIZE,
@@ -98,7 +98,7 @@
 /* Conventional and unconventional sample rate supported */
 static unsigned int supported_sample_rates[] = {
 	8000, 11025, 12000, 16000, 22050, 24000, 32000, 44100, 48000,
-	96000
+	96000, 192000
 };
 
 static uint32_t in_frame_info[CAPTURE_NUM_PERIODS][2];
diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c b/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c
index d8f2759..8257023 100644
--- a/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c
+++ b/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c
@@ -10,7 +10,6 @@
  * GNU General Public License for more details.
  */
 
-
 #include <linux/init.h>
 #include <linux/err.h>
 #include <linux/module.h>
@@ -31,8 +30,10 @@
 #include <sound/tlv.h>
 #include <sound/asound.h>
 #include <sound/pcm_params.h>
+#include <mach/qdsp6v2/q6core.h>
 
 #include "msm-pcm-routing-v2.h"
+#include "msm-dolby-dap-config.h"
 #include "q6voice.h"
 
 struct msm_pcm_routing_bdai_data {
@@ -185,6 +186,20 @@
 	(void *)&msm_srs_trumedia_params[param_block_idx].srs_params.global);
 }
 
+int get_topology(int path_type)
+{
+	int topology_id = 0;
+	if (path_type == ADM_PATH_PLAYBACK)
+		topology_id = get_adm_rx_topology();
+	else
+		topology_id = get_adm_tx_topology();
+
+	if (topology_id  == 0)
+		topology_id = DEFAULT_COPP_TOPOLOGY;
+
+	return topology_id;
+}
+
 #define SLIMBUS_EXTPROC_RX AFE_PORT_INVALID
 static struct msm_pcm_routing_bdai_data msm_bedais[MSM_BACKEND_DAI_MAX] = {
 	{ PRIMARY_I2S_RX, 0, 0, 0, 0, 0},
@@ -225,6 +240,8 @@
 	{ AFE_PORT_ID_TERTIARY_MI2S_RX,   0, 0, 0, 0, 0},
 	{ AFE_PORT_ID_TERTIARY_MI2S_TX,   0, 0, 0, 0, 0},
 	{ AUDIO_PORT_ID_I2S_RX,           0, 0, 0, 0, 0},
+	{ AFE_PORT_ID_SECONDARY_PCM_RX,	  0, 0, 0, 0, 0},
+	{ AFE_PORT_ID_SECONDARY_PCM_TX,   0, 0, 0, 0, 0},
 };
 
 
@@ -318,7 +335,7 @@
 void msm_pcm_routing_reg_phy_stream(int fedai_id, bool perf_mode,
 					int dspst_id, int stream_type)
 {
-	int i, session_type, path_type, port_type;
+	int i, session_type, path_type, port_type, port_id, topology;
 	struct route_payload payload;
 	u32 channels;
 	uint16_t bits_per_sample = 16;
@@ -346,6 +363,7 @@
 	/* 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))
 			msm_bedais[i].perf_mode = perf_mode;
@@ -361,27 +379,31 @@
 			else if (msm_bedais[i].format ==
 						SNDRV_PCM_FORMAT_S24_LE)
 				bits_per_sample = 24;
-
 			if ((stream_type == SNDRV_PCM_STREAM_PLAYBACK) &&
 				(channels > 0))
 				adm_multi_ch_copp_open(msm_bedais[i].port_id,
 				path_type,
 				msm_bedais[i].sample_rate,
 				msm_bedais[i].channel,
-				DEFAULT_COPP_TOPOLOGY, msm_bedais[i].perf_mode,
+				topology, msm_bedais[i].perf_mode,
 				bits_per_sample);
 			else
 				adm_open(msm_bedais[i].port_id,
 				path_type,
 				msm_bedais[i].sample_rate,
 				msm_bedais[i].channel,
-				DEFAULT_COPP_TOPOLOGY, false,
+				topology, false,
 				bits_per_sample);
 
 			payload.copp_ids[payload.num_copps++] =
 				msm_bedais[i].port_id;
-			srs_port_id = msm_bedais[i].port_id;
+			port_id = srs_port_id = msm_bedais[i].port_id;
 			srs_send_params(srs_port_id, 1, 0);
+			if (DOLBY_ADM_COPP_TOPOLOGY_ID == topology)
+				if (dolby_dap_init(port_id,
+						msm_bedais[i].channel) < 0)
+					pr_err("%s: Err init dolby dap\n",
+						__func__);
 		}
 	}
 	if (payload.num_copps)
@@ -393,7 +415,7 @@
 
 void msm_pcm_routing_dereg_phy_stream(int fedai_id, int stream_type)
 {
-	int i, port_type, session_type;
+	int i, port_type, session_type, path_type, topology;
 
 	if (fedai_id > MSM_FRONTEND_DAI_MM_MAX_ID) {
 		/* bad ID assigned in machine driver */
@@ -404,19 +426,24 @@
 	if (stream_type == SNDRV_PCM_STREAM_PLAYBACK) {
 		port_type = MSM_AFE_PORT_TYPE_RX;
 		session_type = SESSION_TYPE_RX;
+		path_type = ADM_PATH_PLAYBACK;
 	} else {
 		port_type = MSM_AFE_PORT_TYPE_TX;
 		session_type = SESSION_TYPE_TX;
+		path_type = ADM_PATH_LIVE_REC;
 	}
 
 	mutex_lock(&routing_lock);
-
+	topology = get_topology(path_type);
 	for (i = 0; i < MSM_BACKEND_DAI_MAX; i++) {
 		if (!is_be_dai_extproc(i) &&
 		   (afe_get_port_type(msm_bedais[i].port_id) == port_type) &&
 		   (msm_bedais[i].active) &&
-		   (test_bit(fedai_id, &msm_bedais[i].fe_sessions)))
+		   (test_bit(fedai_id, &msm_bedais[i].fe_sessions))) {
 			adm_close(msm_bedais[i].port_id);
+			if (DOLBY_ADM_COPP_TOPOLOGY_ID == topology)
+				dolby_dap_deinit(msm_bedais[i].port_id);
+		}
 	}
 
 	fe_dai_map[fedai_id][session_type] = INVALID_SESSION;
@@ -443,7 +470,7 @@
 
 static void msm_pcm_routing_process_audio(u16 reg, u16 val, int set)
 {
-	int session_type, path_type;
+	int session_type, path_type, port_id, topology;
 	u32 channels;
 	uint16_t bits_per_sample = 16;
 
@@ -465,7 +492,7 @@
 	}
 
 	mutex_lock(&routing_lock);
-
+	topology = get_topology(path_type);
 	if (set) {
 		if (!test_bit(val, &msm_bedais[reg].fe_sessions) &&
 			(msm_bedais[reg].port_id == VOICE_PLAYBACK_TX))
@@ -484,19 +511,23 @@
 				path_type,
 				msm_bedais[reg].sample_rate,
 				channels,
-				DEFAULT_COPP_TOPOLOGY,
+				topology,
 				msm_bedais[reg].perf_mode,
 				bits_per_sample);
 			} else
 				adm_open(msm_bedais[reg].port_id,
 				path_type,
 				msm_bedais[reg].sample_rate, channels,
-				DEFAULT_COPP_TOPOLOGY, false, bits_per_sample);
+				topology, false, bits_per_sample);
 
 			msm_pcm_routing_build_matrix(val,
 				fe_dai_map[val][session_type], path_type);
-			srs_port_id = msm_bedais[reg].port_id;
+			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)
+				if (dolby_dap_init(port_id, channels) < 0)
+					pr_err("%s: Err init dolby dap\n",
+						__func__);
 		}
 	} else {
 		if (test_bit(val, &msm_bedais[reg].fe_sessions) &&
@@ -506,6 +537,8 @@
 		if (msm_bedais[reg].active && fe_dai_map[val][session_type] !=
 			INVALID_SESSION) {
 			adm_close(msm_bedais[reg].port_id);
+			if (DOLBY_ADM_COPP_TOPOLOGY_ID == topology)
+				dolby_dap_deinit(msm_bedais[reg].port_id);
 			msm_pcm_routing_build_matrix(val,
 				fe_dai_map[val][session_type], path_type);
 		}
@@ -1513,6 +1546,24 @@
 	msm_routing_put_audio_mixer),
 };
 
+static const struct snd_kcontrol_new sec_auxpcm_rx_mixer_controls[] = {
+	SOC_SINGLE_EXT("MultiMedia1", MSM_BACKEND_DAI_SEC_AUXPCM_RX,
+	MSM_FRONTEND_DAI_MULTIMEDIA1, 1, 0, msm_routing_get_audio_mixer,
+	msm_routing_put_audio_mixer),
+	SOC_SINGLE_EXT("MultiMedia2", MSM_BACKEND_DAI_SEC_AUXPCM_RX,
+	MSM_FRONTEND_DAI_MULTIMEDIA2, 1, 0, msm_routing_get_audio_mixer,
+	msm_routing_put_audio_mixer),
+	SOC_SINGLE_EXT("MultiMedia3", MSM_BACKEND_DAI_SEC_AUXPCM_RX,
+	MSM_FRONTEND_DAI_MULTIMEDIA3, 1, 0, msm_routing_get_audio_mixer,
+	msm_routing_put_audio_mixer),
+	SOC_SINGLE_EXT("MultiMedia4", MSM_BACKEND_DAI_SEC_AUXPCM_RX,
+	MSM_FRONTEND_DAI_MULTIMEDIA4, 1, 0, msm_routing_get_audio_mixer,
+	msm_routing_put_audio_mixer),
+	SOC_SINGLE_EXT("MultiMedia5", MSM_BACKEND_DAI_SEC_AUXPCM_RX,
+	MSM_FRONTEND_DAI_MULTIMEDIA5, 1, 0, msm_routing_get_audio_mixer,
+	msm_routing_put_audio_mixer),
+};
+
 static const struct snd_kcontrol_new mmul1_mixer_controls[] = {
 	SOC_SINGLE_EXT("PRI_TX", MSM_BACKEND_DAI_PRI_I2S_TX,
 		MSM_FRONTEND_DAI_MULTIMEDIA1, 1, 0, msm_routing_get_audio_mixer,
@@ -1532,6 +1583,9 @@
 	SOC_SINGLE_EXT("AUX_PCM_UL_TX", MSM_BACKEND_DAI_AUXPCM_TX,
 		MSM_FRONTEND_DAI_MULTIMEDIA1, 1, 0, msm_routing_get_audio_mixer,
 		msm_routing_put_audio_mixer),
+	SOC_SINGLE_EXT("SEC_AUX_PCM_UL_TX", MSM_BACKEND_DAI_SEC_AUXPCM_TX,
+		MSM_FRONTEND_DAI_MULTIMEDIA1, 1, 0, msm_routing_get_audio_mixer,
+		msm_routing_put_audio_mixer),
 	SOC_SINGLE_EXT("INTERNAL_BT_SCO_TX", MSM_BACKEND_DAI_INT_BT_SCO_TX,
 		MSM_FRONTEND_DAI_MULTIMEDIA1, 1, 0, msm_routing_get_audio_mixer,
 		msm_routing_put_audio_mixer),
@@ -1583,6 +1637,9 @@
 	SOC_SINGLE_EXT("AUX_PCM_TX", MSM_BACKEND_DAI_AUXPCM_TX,
 	MSM_FRONTEND_DAI_MULTIMEDIA5, 1, 0, msm_routing_get_audio_mixer,
 	msm_routing_put_audio_mixer),
+	SOC_SINGLE_EXT("SEC_AUX_PCM_TX", MSM_BACKEND_DAI_SEC_AUXPCM_TX,
+	MSM_FRONTEND_DAI_MULTIMEDIA5, 1, 0, msm_routing_get_audio_mixer,
+	msm_routing_put_audio_mixer),
 };
 
 static const struct snd_kcontrol_new pri_rx_voice_mixer_controls[] = {
@@ -1723,6 +1780,24 @@
 	msm_routing_put_voice_mixer),
 };
 
+static const struct snd_kcontrol_new sec_aux_pcm_rx_voice_mixer_controls[] = {
+	SOC_SINGLE_EXT("CSVoice", MSM_BACKEND_DAI_SEC_AUXPCM_RX,
+	MSM_FRONTEND_DAI_CS_VOICE, 1, 0, msm_routing_get_voice_mixer,
+	msm_routing_put_voice_mixer),
+	SOC_SINGLE_EXT("Voip", MSM_BACKEND_DAI_SEC_AUXPCM_RX,
+	MSM_FRONTEND_DAI_VOIP, 1, 0, msm_routing_get_voice_mixer,
+	msm_routing_put_voice_mixer),
+	SOC_SINGLE_EXT("Voice Stub", MSM_BACKEND_DAI_SEC_AUXPCM_RX,
+	MSM_FRONTEND_DAI_VOICE_STUB, 1, 0, msm_routing_get_voice_stub_mixer,
+	msm_routing_put_voice_stub_mixer),
+	SOC_SINGLE_EXT("VoLTE", MSM_BACKEND_DAI_SEC_AUXPCM_RX,
+	MSM_FRONTEND_DAI_VOLTE, 1, 0, msm_routing_get_voice_mixer,
+	msm_routing_put_voice_mixer),
+	SOC_SINGLE_EXT("DTMF", MSM_BACKEND_DAI_SEC_AUXPCM_RX,
+	MSM_FRONTEND_DAI_DTMF_RX, 1, 0, msm_routing_get_voice_mixer,
+	msm_routing_put_voice_mixer),
+};
+
 static const struct snd_kcontrol_new hdmi_rx_voice_mixer_controls[] = {
 	SOC_SINGLE_EXT("CSVoice", MSM_BACKEND_DAI_HDMI_RX,
 	MSM_FRONTEND_DAI_CS_VOICE, 1, 0, msm_routing_get_voice_mixer,
@@ -1781,6 +1856,9 @@
 	SOC_SINGLE_EXT("AUX_PCM_TX_Voice", MSM_BACKEND_DAI_AUXPCM_TX,
 	MSM_FRONTEND_DAI_CS_VOICE, 1, 0, msm_routing_get_voice_mixer,
 	msm_routing_put_voice_mixer),
+	SOC_SINGLE_EXT("SEC_AUX_PCM_TX_Voice", MSM_BACKEND_DAI_SEC_AUXPCM_TX,
+	MSM_FRONTEND_DAI_CS_VOICE, 1, 0, msm_routing_get_voice_mixer,
+	msm_routing_put_voice_mixer),
 };
 
 static const struct snd_kcontrol_new tx_voice2_mixer_controls[] = {
@@ -1820,6 +1898,9 @@
 	SOC_SINGLE_EXT("AUX_PCM_TX_VoLTE", MSM_BACKEND_DAI_AUXPCM_TX,
 	MSM_FRONTEND_DAI_VOLTE, 1, 0, msm_routing_get_voice_mixer,
 	msm_routing_put_voice_mixer),
+	SOC_SINGLE_EXT("SEC_AUX_PCM_TX_VoLTE", MSM_BACKEND_DAI_SEC_AUXPCM_TX,
+	MSM_FRONTEND_DAI_VOLTE, 1, 0, msm_routing_get_voice_mixer,
+	msm_routing_put_voice_mixer),
 	SOC_SINGLE_EXT("MI2S_TX_VoLTE", MSM_BACKEND_DAI_MI2S_TX,
 	MSM_FRONTEND_DAI_VOLTE, 1, 0, msm_routing_get_voice_mixer,
 	msm_routing_put_voice_mixer),
@@ -1844,6 +1925,9 @@
 	SOC_SINGLE_EXT("AUX_PCM_TX_Voip", MSM_BACKEND_DAI_AUXPCM_TX,
 	MSM_FRONTEND_DAI_VOIP, 1, 0, msm_routing_get_voice_mixer,
 	msm_routing_put_voice_mixer),
+	SOC_SINGLE_EXT("SEC_AUX_PCM_TX_Voip", MSM_BACKEND_DAI_SEC_AUXPCM_TX,
+	MSM_FRONTEND_DAI_VOIP, 1, 0, msm_routing_get_voice_mixer,
+	msm_routing_put_voice_mixer),
 };
 
 static const struct snd_kcontrol_new tx_voice_stub_mixer_controls[] = {
@@ -1874,6 +1958,9 @@
 	SOC_SINGLE_EXT("AUX_PCM_UL_TX", MSM_BACKEND_DAI_SLIMBUS_0_RX,
 	MSM_BACKEND_DAI_AUXPCM_TX, 1, 0, msm_routing_get_port_mixer,
 	msm_routing_put_port_mixer),
+	SOC_SINGLE_EXT("SEC_AUX_PCM_UL_TX", MSM_BACKEND_DAI_SLIMBUS_0_RX,
+	MSM_BACKEND_DAI_SEC_AUXPCM_TX, 1, 0, msm_routing_get_port_mixer,
+	msm_routing_put_port_mixer),
 	SOC_SINGLE_EXT("MI2S_TX", MSM_BACKEND_DAI_SLIMBUS_0_RX,
 	MSM_BACKEND_DAI_MI2S_TX, 1, 0, msm_routing_get_port_mixer,
 	msm_routing_put_port_mixer),
@@ -1888,6 +1975,15 @@
 	msm_routing_put_port_mixer),
 };
 
+static const struct snd_kcontrol_new sec_auxpcm_rx_port_mixer_controls[] = {
+	SOC_SINGLE_EXT("SEC_AUX_PCM_UL_TX", MSM_BACKEND_DAI_SEC_AUXPCM_RX,
+	MSM_BACKEND_DAI_SEC_AUXPCM_TX, 1, 0, msm_routing_get_port_mixer,
+	msm_routing_put_port_mixer),
+	SOC_SINGLE_EXT("SLIM_0_TX", MSM_BACKEND_DAI_SEC_AUXPCM_RX,
+	MSM_BACKEND_DAI_SLIMBUS_0_TX, 1, 0, msm_routing_get_port_mixer,
+	msm_routing_put_port_mixer),
+};
+
 static const struct snd_kcontrol_new sbus_1_rx_port_mixer_controls[] = {
 	SOC_SINGLE_EXT("INTERNAL_BT_SCO_TX", MSM_BACKEND_DAI_SLIMBUS_1_RX,
 	MSM_BACKEND_DAI_INT_BT_SCO_TX, 1, 0, msm_routing_get_port_mixer,
@@ -2090,6 +2186,51 @@
 	}
 };
 
+int msm_routing_get_dolby_security_control(
+		struct snd_kcontrol *kcontrol,
+		struct snd_ctl_elem_value *ucontrol) {
+	/* not used while setting the manfr id*/
+	return 0;
+}
+
+int msm_routing_put_dolby_security_control(
+		struct snd_kcontrol *kcontrol,
+		struct snd_ctl_elem_value *ucontrol) {
+	int manufacturer_id = ucontrol->value.integer.value[0];
+	core_set_dolby_manufacturer_id(manufacturer_id);
+	return 0;
+}
+
+static const struct snd_kcontrol_new dolby_security_controls[] = {
+	SOC_SINGLE_MULTI_EXT("DS1 Security", SND_SOC_NOPM, 0,
+	0xFFFFFFFF, 0, 1, msm_routing_get_dolby_security_control,
+	msm_routing_put_dolby_security_control),
+};
+
+static const struct snd_kcontrol_new dolby_dap_param_to_set_controls[] = {
+	SOC_SINGLE_MULTI_EXT("DS1 DAP Set Param", SND_SOC_NOPM, 0, 0xFFFFFFFF,
+	0, 128, msm_routing_get_dolby_dap_param_to_set_control,
+	msm_routing_put_dolby_dap_param_to_set_control),
+};
+
+static const struct snd_kcontrol_new dolby_dap_param_to_get_controls[] = {
+	SOC_SINGLE_MULTI_EXT("DS1 DAP Get Param", SND_SOC_NOPM, 0, 0xFFFFFFFF,
+	0, 128, msm_routing_get_dolby_dap_param_to_get_control,
+	msm_routing_put_dolby_dap_param_to_get_control),
+};
+
+static const struct snd_kcontrol_new dolby_dap_param_visualizer_controls[] = {
+	SOC_SINGLE_MULTI_EXT("DS1 DAP Get Visualizer", SND_SOC_NOPM, 0,
+	0xFFFFFFFF, 0, 41, msm_routing_get_dolby_dap_param_visualizer_control,
+	msm_routing_put_dolby_dap_param_visualizer_control),
+};
+
+static const struct snd_kcontrol_new dolby_dap_param_end_point_controls[] = {
+	SOC_SINGLE_MULTI_EXT("DS1 DAP Endpoint", SND_SOC_NOPM, 0,
+	0xFFFFFFFF, 0, 1, msm_routing_get_dolby_dap_endpoint_control,
+	msm_routing_put_dolby_dap_endpoint_control),
+};
+
 static const struct snd_kcontrol_new eq_enable_mixer_controls[] = {
 	SOC_SINGLE_EXT("MultiMedia1 EQ Enable", SND_SOC_NOPM,
 	MSM_FRONTEND_DAI_MULTIMEDIA1, 1, 0, msm_routing_get_eq_enable_mixer,
@@ -2425,6 +2566,10 @@
 
 	SND_SOC_DAPM_AIF_OUT("AUX_PCM_RX", "AUX PCM Playback", 0, 0, 0, 0),
 	SND_SOC_DAPM_AIF_IN("AUX_PCM_TX", "AUX PCM Capture", 0, 0, 0, 0),
+	SND_SOC_DAPM_AIF_OUT("SEC_AUX_PCM_RX", "Sec AUX PCM Playback",
+				0, 0, 0, 0),
+	SND_SOC_DAPM_AIF_IN("SEC_AUX_PCM_TX", "Sec AUX PCM Capture",
+				0, 0, 0, 0),
 	SND_SOC_DAPM_AIF_IN("VOICE_STUB_DL", "VOICE_STUB Playback", 0, 0, 0, 0),
 	SND_SOC_DAPM_AIF_OUT("VOICE_STUB_UL", "VOICE_STUB Capture", 0, 0, 0, 0),
 	SND_SOC_DAPM_AIF_OUT("STUB_RX", "Stub Playback", 0, 0, 0, 0),
@@ -2480,6 +2625,8 @@
 	mmul5_mixer_controls, ARRAY_SIZE(mmul5_mixer_controls)),
 	SND_SOC_DAPM_MIXER("AUX_PCM_RX Audio Mixer", SND_SOC_NOPM, 0, 0,
 	auxpcm_rx_mixer_controls, ARRAY_SIZE(auxpcm_rx_mixer_controls)),
+	SND_SOC_DAPM_MIXER("SEC_AUX_PCM_RX Audio Mixer", SND_SOC_NOPM, 0, 0,
+	sec_auxpcm_rx_mixer_controls, ARRAY_SIZE(sec_auxpcm_rx_mixer_controls)),
 	/* incall */
 	SND_SOC_DAPM_MIXER("Incall_Music Audio Mixer", SND_SOC_NOPM, 0, 0,
 			incall_music_delivery_mixer_controls,
@@ -2511,6 +2658,10 @@
 				SND_SOC_NOPM, 0, 0,
 				aux_pcm_rx_voice_mixer_controls,
 				ARRAY_SIZE(aux_pcm_rx_voice_mixer_controls)),
+	SND_SOC_DAPM_MIXER("SEC_AUX_PCM_RX_Voice Mixer",
+			      SND_SOC_NOPM, 0, 0,
+			      sec_aux_pcm_rx_voice_mixer_controls,
+			      ARRAY_SIZE(sec_aux_pcm_rx_voice_mixer_controls)),
 	SND_SOC_DAPM_MIXER("HDMI_RX_Voice Mixer",
 				SND_SOC_NOPM, 0, 0,
 				hdmi_rx_voice_mixer_controls,
@@ -2551,6 +2702,9 @@
 	SND_SOC_DAPM_MIXER("AUXPCM_RX Port Mixer",
 	SND_SOC_NOPM, 0, 0, auxpcm_rx_port_mixer_controls,
 	ARRAY_SIZE(auxpcm_rx_port_mixer_controls)),
+	SND_SOC_DAPM_MIXER("SEC_AUXPCM_RX Port Mixer",
+	SND_SOC_NOPM, 0, 0, sec_auxpcm_rx_port_mixer_controls,
+	ARRAY_SIZE(sec_auxpcm_rx_port_mixer_controls)),
 	SND_SOC_DAPM_MIXER("SLIMBUS_1_RX Port Mixer", SND_SOC_NOPM, 0, 0,
 	sbus_1_rx_port_mixer_controls,
 	ARRAY_SIZE(sbus_1_rx_port_mixer_controls)),
@@ -2657,6 +2811,8 @@
 	{"MultiMedia1 Mixer", "SLIM_0_TX", "SLIMBUS_0_TX"},
 	{"MultiMedia1 Mixer", "AUX_PCM_UL_TX", "AUX_PCM_TX"},
 	{"MultiMedia5 Mixer", "AUX_PCM_TX", "AUX_PCM_TX"},
+	{"MultiMedia1 Mixer", "SEC_AUX_PCM_UL_TX", "SEC_AUX_PCM_TX"},
+	{"MultiMedia5 Mixer", "SEC_AUX_PCM_TX", "SEC_AUX_PCM_TX"},
 	{"MultiMedia2 Mixer", "SLIM_0_TX", "SLIMBUS_0_TX"},
 	{"MultiMedia1 Mixer", "SEC_MI2S_TX", "SEC_MI2S_TX"},
 
@@ -2700,6 +2856,13 @@
 	{"AUX_PCM_RX Audio Mixer", "MultiMedia5", "MM_DL5"},
 	{"AUX_PCM_RX", NULL, "AUX_PCM_RX Audio Mixer"},
 
+	{"SEC_AUX_PCM_RX Audio Mixer", "MultiMedia1", "MM_DL1"},
+	{"SEC_AUX_PCM_RX Audio Mixer", "MultiMedia2", "MM_DL2"},
+	{"SEC_AUX_PCM_RX Audio Mixer", "MultiMedia3", "MM_DL3"},
+	{"SEC_AUX_PCM_RX Audio Mixer", "MultiMedia4", "MM_DL4"},
+	{"SEC_AUX_PCM_RX Audio Mixer", "MultiMedia5", "MM_DL5"},
+	{"SEC_AUX_PCM_RX", NULL, "SEC_AUX_PCM_RX Audio Mixer"},
+
 	{"MI2S_RX_Voice Mixer", "CSVoice", "CS-VOICE_DL1"},
 	{"MI2S_RX_Voice Mixer", "Voice2", "VOICE2_DL"},
 	{"MI2S_RX_Voice Mixer", "Voip", "VOIP_DL"},
@@ -2749,6 +2912,12 @@
 	{"AUX_PCM_RX_Voice Mixer", "DTMF", "DTMF_DL_HL"},
 	{"AUX_PCM_RX", NULL, "AUX_PCM_RX_Voice Mixer"},
 
+	{"SEC_AUX_PCM_RX_Voice Mixer", "CSVoice", "CS-VOICE_DL1"},
+	{"SEC_AUX_PCM_RX_Voice Mixer", "VoLTE", "VoLTE_DL"},
+	{"SEC_AUX_PCM_RX_Voice Mixer", "Voip", "VOIP_DL"},
+	{"SEC_AUX_PCM_RX_Voice Mixer", "DTMF", "DTMF_DL_HL"},
+	{"SEC_AUX_PCM_RX", NULL, "SEC_AUX_PCM_RX_Voice Mixer"},
+
 	{"HDMI_RX_Voice Mixer", "CSVoice", "CS-VOICE_DL1"},
 	{"HDMI_RX_Voice Mixer", "Voice2", "VOICE2_DL"},
 	{"HDMI_RX_Voice Mixer", "VoLTE", "VoLTE_DL"},
@@ -2770,6 +2939,7 @@
 	{"Voice_Tx Mixer", "INTERNAL_BT_SCO_TX_Voice", "INT_BT_SCO_TX"},
 	{"Voice_Tx Mixer", "AFE_PCM_TX_Voice", "PCM_TX"},
 	{"Voice_Tx Mixer", "AUX_PCM_TX_Voice", "AUX_PCM_TX"},
+	{"Voice_Tx Mixer", "SEC_AUX_PCM_TX_Voice", "SEC_AUX_PCM_TX"},
 	{"CS-VOICE_UL1", NULL, "Voice_Tx Mixer"},
 
 	{"Voice2_Tx Mixer", "PRI_TX_Voice2", "PRI_I2S_TX"},
@@ -2785,6 +2955,7 @@
 	{"VoLTE_Tx Mixer", "INTERNAL_BT_SCO_TX_VoLTE", "INT_BT_SCO_TX"},
 	{"VoLTE_Tx Mixer", "AFE_PCM_TX_VoLTE", "PCM_TX"},
 	{"VoLTE_Tx Mixer", "AUX_PCM_TX_VoLTE", "AUX_PCM_TX"},
+	{"VoLTE_Tx Mixer", "SEC_AUX_PCM_TX_VoLTE", "SEC_AUX_PCM_TX"},
 	{"VoLTE_Tx Mixer", "MI2S_TX_VoLTE", "MI2S_TX"},
 	{"VoLTE_UL", NULL, "VoLTE_Tx Mixer"},
 	{"Voip_Tx Mixer", "PRI_TX_Voip", "PRI_I2S_TX"},
@@ -2793,6 +2964,7 @@
 	{"Voip_Tx Mixer", "INTERNAL_BT_SCO_TX_Voip", "INT_BT_SCO_TX"},
 	{"Voip_Tx Mixer", "AFE_PCM_TX_Voip", "PCM_TX"},
 	{"Voip_Tx Mixer", "AUX_PCM_TX_Voip", "AUX_PCM_TX"},
+	{"Voip_Tx Mixer", "SEC_AUX_PCM_TX_Voip", "SEC_AUX_PCM_TX"},
 
 	{"VOIP_UL", NULL, "Voip_Tx Mixer"},
 	{"SLIMBUS_DL_HL", "Switch", "SLIM0_DL_HL"},
@@ -2828,6 +3000,7 @@
 	{"SLIMBUS_0_RX Port Mixer", "INTERNAL_FM_TX", "INT_FM_TX"},
 	{"SLIMBUS_0_RX Port Mixer", "SLIM_0_TX", "SLIMBUS_0_TX"},
 	{"SLIMBUS_0_RX Port Mixer", "AUX_PCM_UL_TX", "AUX_PCM_TX"},
+	{"SLIMBUS_0_RX Port Mixer", "SEC_AUX_PCM_UL_TX", "SEC_AUX_PCM_TX"},
 	{"SLIMBUS_0_RX Port Mixer", "MI2S_TX", "MI2S_TX"},
 	{"SLIMBUS_0_RX", NULL, "SLIMBUS_0_RX Port Mixer"},
 	{"AFE_PCM_RX Port Mixer", "INTERNAL_FM_TX", "INT_FM_TX"},
@@ -2837,6 +3010,10 @@
 	{"AUXPCM_RX Port Mixer", "SLIM_0_TX", "SLIMBUS_0_TX"},
 	{"AUX_PCM_RX", NULL, "AUXPCM_RX Port Mixer"},
 
+	{"SEC_AUXPCM_RX Port Mixer", "SEC_AUX_PCM_UL_TX", "SEC_AUX_PCM_TX"},
+	{"SEC_AUXPCM_RX Port Mixer", "SLIM_0_TX", "SLIMBUS_0_TX"},
+	{"SEC_AUX_PCM_RX", NULL, "SEC_AUXPCM_RX Port Mixer"},
+
 	{"Voice Stub Tx Mixer", "STUB_TX_HL", "STUB_TX"},
 	{"Voice Stub Tx Mixer", "SLIM_1_TX", "SLIMBUS_1_TX"},
 	{"Voice Stub Tx Mixer", "INTERNAL_BT_SCO_TX", "INT_BT_SCO_TX"},
@@ -2892,6 +3069,7 @@
 	{"BE_OUT", NULL, "PCM_RX"},
 	{"BE_OUT", NULL, "SLIMBUS_3_RX"},
 	{"BE_OUT", NULL, "AUX_PCM_RX"},
+	{"BE_OUT", NULL, "SEC_AUX_PCM_RX"},
 
 	{"PRI_I2S_TX", NULL, "BE_IN"},
 	{"MI2S_TX", NULL, "BE_IN"},
@@ -2911,6 +3089,8 @@
 	{"BE_OUT", NULL, "SLIMBUS_3_RX"},
 	{"BE_OUT", NULL, "AUX_PCM_RX"},
 	{"AUX_PCM_TX", NULL, "BE_IN"},
+	{"BE_OUT", NULL, "SEC_AUX_PCM_RX"},
+	{"SEC_AUX_PCM_TX", NULL, "BE_IN"},
 	{"INCALL_RECORD_TX", NULL, "BE_IN"},
 	{"INCALL_RECORD_RX", NULL, "BE_IN"},
 	{"BE_OUT", NULL, "VOICE_PLAYBACK_TX"},
@@ -2941,7 +3121,7 @@
 {
 	struct snd_soc_pcm_runtime *rtd = substream->private_data;
 	unsigned int be_id = rtd->dai_link->be_id;
-	int i, session_type;
+	int i, session_type, path_type, topology;
 	struct msm_pcm_routing_bdai_data *bedai;
 
 	if (be_id >= MSM_BACKEND_DAI_MAX) {
@@ -2952,13 +3132,20 @@
 	bedai = &msm_bedais[be_id];
 	session_type = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK ?
 		0 : 1);
+	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+		path_type = ADM_PATH_PLAYBACK;
+	else
+		path_type = ADM_PATH_LIVE_REC;
 
 	mutex_lock(&routing_lock);
-
+	topology = get_topology(path_type);
 	for_each_set_bit(i, &bedai->fe_sessions, MSM_FRONTEND_DAI_MM_SIZE) {
-		if (fe_dai_map[i][session_type] != INVALID_SESSION)
+		if (fe_dai_map[i][session_type] != INVALID_SESSION) {
 			adm_close(bedai->port_id);
 			srs_port_id = -1;
+			if (DOLBY_ADM_COPP_TOPOLOGY_ID == topology)
+				dolby_dap_deinit(bedai->port_id);
+		}
 	}
 
 	bedai->active = 0;
@@ -2974,7 +3161,7 @@
 {
 	struct snd_soc_pcm_runtime *rtd = substream->private_data;
 	unsigned int be_id = rtd->dai_link->be_id;
-	int i, path_type, session_type;
+	int i, path_type, session_type, port_id, topology;
 	struct msm_pcm_routing_bdai_data *bedai;
 	u32 channels;
 	bool playback, capture;
@@ -2996,7 +3183,7 @@
 	}
 
 	mutex_lock(&routing_lock);
-
+	topology = get_topology(path_type);
 	if (bedai->active == 1)
 		goto done; /* Ignore prepare if back-end already active */
 
@@ -3021,21 +3208,25 @@
 					path_type,
 					bedai->sample_rate,
 					channels,
-					DEFAULT_COPP_TOPOLOGY, bedai->perf_mode,
+					topology, bedai->perf_mode,
 					bits_per_sample);
 			} else if (capture) {
 				adm_open(bedai->port_id,
 				path_type,
 				bedai->sample_rate,
 				channels,
-				DEFAULT_COPP_TOPOLOGY, false,
+				topology, false,
 				bits_per_sample);
 			}
 
 			msm_pcm_routing_build_matrix(i,
 				fe_dai_map[i][session_type], path_type);
-			srs_port_id = bedai->port_id;
+			port_id = srs_port_id = bedai->port_id;
 			srs_send_params(srs_port_id, 1, 0);
+			if (DOLBY_ADM_COPP_TOPOLOGY_ID == topology)
+				if (dolby_dap_init(port_id, channels) < 0)
+					pr_err("%s: Err init dolby dap\n",
+						__func__);
 		}
 	}
 
@@ -3130,6 +3321,27 @@
 	snd_soc_add_platform_controls(platform,
 				aanc_slim_0_rx_mux,
 				ARRAY_SIZE(aanc_slim_0_rx_mux));
+
+	snd_soc_add_platform_controls(platform,
+				dolby_security_controls,
+			ARRAY_SIZE(dolby_security_controls));
+
+	snd_soc_add_platform_controls(platform,
+				dolby_dap_param_to_set_controls,
+			ARRAY_SIZE(dolby_dap_param_to_set_controls));
+
+	snd_soc_add_platform_controls(platform,
+				dolby_dap_param_to_get_controls,
+			ARRAY_SIZE(dolby_dap_param_to_get_controls));
+
+	snd_soc_add_platform_controls(platform,
+				dolby_dap_param_visualizer_controls,
+			ARRAY_SIZE(dolby_dap_param_visualizer_controls));
+
+	snd_soc_add_platform_controls(platform,
+				dolby_dap_param_end_point_controls,
+			ARRAY_SIZE(dolby_dap_param_end_point_controls));
+
 	return 0;
 }
 
diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.h b/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.h
index 1c1029c..4a58369 100644
--- a/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.h
+++ b/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.h
@@ -26,6 +26,8 @@
 #define LPASS_BE_AFE_PCM_TX "RT_PROXY_DAI_002_TX"
 #define LPASS_BE_AUXPCM_RX "AUX_PCM_RX"
 #define LPASS_BE_AUXPCM_TX "AUX_PCM_TX"
+#define LPASS_BE_SEC_AUXPCM_RX "SEC_AUX_PCM_RX"
+#define LPASS_BE_SEC_AUXPCM_TX "SEC_AUX_PCM_TX"
 #define LPASS_BE_VOICE_PLAYBACK_TX "VOICE_PLAYBACK_TX"
 #define LPASS_BE_INCALL_RECORD_RX "INCALL_RECORD_TX"
 #define LPASS_BE_INCALL_RECORD_TX "INCALL_RECORD_RX"
@@ -119,6 +121,8 @@
 	MSM_BACKEND_DAI_TERTIARY_MI2S_RX,
 	MSM_BACKEND_DAI_TERTIARY_MI2S_TX,
 	MSM_BACKEND_DAI_AUDIO_I2S_RX,
+	MSM_BACKEND_DAI_SEC_AUXPCM_RX,
+	MSM_BACKEND_DAI_SEC_AUXPCM_TX,
 	MSM_BACKEND_DAI_MAX,
 };
 
@@ -141,4 +145,7 @@
 
 int compressed_set_volume(unsigned volume);
 
+uint32_t get_adm_rx_topology(void);
+
+uint32_t get_adm_tx_topology(void);
 #endif /*_MSM_PCM_H*/
diff --git a/sound/soc/msm/qdsp6v2/q6adm.c b/sound/soc/msm/qdsp6v2/q6adm.c
index b1db277..1bd3eac 100644
--- a/sound/soc/msm/qdsp6v2/q6adm.c
+++ b/sound/soc/msm/qdsp6v2/q6adm.c
@@ -33,6 +33,7 @@
 
 #define RESET_COPP_ID 99
 #define INVALID_COPP_ID 0xFF
+#define ADM_GET_PARAMETER_LENGTH 350
 
 struct adm_ctl {
 	void *apr;
@@ -64,6 +65,8 @@
 						{0, 0, 0, 0, 0, 0, 0, 0}
 					      };
 
+static int adm_dolby_get_parameters[ADM_GET_PARAMETER_LENGTH];
+
 int srs_trumedia_open(int port_id, int srs_tech_id, void *srs_params)
 {
 	struct adm_cmd_set_pp_params_inband_v5 *adm_params = NULL;
@@ -266,6 +269,134 @@
 	return ret;
 }
 
+int adm_dolby_dap_send_params(int port_id, char *params, uint32_t params_length)
+{
+	struct adm_cmd_set_pp_params_v5	*adm_params = NULL;
+	int sz, rc = 0, index = afe_get_port_index(port_id);
+
+	pr_debug("%s\n", __func__);
+	if (index < 0 || index >= AFE_MAX_PORTS) {
+		pr_err("%s: invalid port idx %d portid %#x\n",
+			__func__, index, port_id);
+		return -EINVAL;
+	}
+	sz = sizeof(struct adm_cmd_set_pp_params_v5) + params_length;
+	adm_params = kzalloc(sz, GFP_KERNEL);
+	if (!adm_params) {
+		pr_err("%s, adm params memory alloc failed", __func__);
+		return -ENOMEM;
+	}
+
+	memcpy(((u8 *)adm_params + sizeof(struct adm_cmd_set_pp_params_v5)),
+			params, params_length);
+	adm_params->hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
+				APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
+	adm_params->hdr.pkt_size = sz;
+	adm_params->hdr.src_svc = APR_SVC_ADM;
+	adm_params->hdr.src_domain = APR_DOMAIN_APPS;
+	adm_params->hdr.src_port = port_id;
+	adm_params->hdr.dest_svc = APR_SVC_ADM;
+	adm_params->hdr.dest_domain = APR_DOMAIN_ADSP;
+	adm_params->hdr.dest_port = atomic_read(&this_adm.copp_id[index]);
+	adm_params->hdr.token = port_id;
+	adm_params->hdr.opcode = ADM_CMD_SET_PP_PARAMS_V5;
+	adm_params->payload_addr_lsw = 0;
+	adm_params->payload_addr_msw = 0;
+	adm_params->mem_map_handle = 0;
+	adm_params->payload_size = params_length;
+
+	atomic_set(&this_adm.copp_stat[index], 0);
+	rc = apr_send_pkt(this_adm.apr, (uint32_t *)adm_params);
+	if (rc < 0) {
+		pr_err("%s: Set params failed port = %#x\n",
+			__func__, port_id);
+		rc = -EINVAL;
+		goto dolby_dap_send_param_return;
+	}
+	/* Wait for the callback */
+	rc = wait_event_timeout(this_adm.wait[index],
+		atomic_read(&this_adm.copp_stat[index]),
+		msecs_to_jiffies(TIMEOUT_MS));
+	if (!rc) {
+		pr_err("%s: Set params timed out port = %#x\n",
+			 __func__, port_id);
+		rc = -EINVAL;
+		goto dolby_dap_send_param_return;
+	}
+	rc = 0;
+dolby_dap_send_param_return:
+	kfree(adm_params);
+	return rc;
+}
+
+int adm_dolby_dap_get_params(int port_id, uint32_t module_id, uint32_t param_id,
+				uint32_t params_length, char *params)
+{
+	struct adm_cmd_get_pp_params_v5	*adm_params = NULL;
+	int sz, rc = 0, i = 0, index = afe_get_port_index(port_id);
+	int *params_data = (int *)params;
+
+	if (index < 0 || index >= AFE_MAX_PORTS) {
+		pr_err("%s: invalid port idx %d portid %#x\n",
+			__func__, index, port_id);
+		return -EINVAL;
+	}
+	sz = sizeof(struct adm_cmd_set_pp_params_v5) + params_length;
+	adm_params = kzalloc(sz, GFP_KERNEL);
+	if (!adm_params) {
+		pr_err("%s, adm params memory alloc failed", __func__);
+		return -ENOMEM;
+	}
+
+	memcpy(((u8 *)adm_params + sizeof(struct adm_cmd_set_pp_params_v5)),
+			params, params_length);
+	adm_params->hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
+				APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
+	adm_params->hdr.pkt_size = sz;
+	adm_params->hdr.src_svc = APR_SVC_ADM;
+	adm_params->hdr.src_domain = APR_DOMAIN_APPS;
+	adm_params->hdr.src_port = port_id;
+	adm_params->hdr.dest_svc = APR_SVC_ADM;
+	adm_params->hdr.dest_domain = APR_DOMAIN_ADSP;
+	adm_params->hdr.dest_port = atomic_read(&this_adm.copp_id[index]);
+	adm_params->hdr.token = port_id;
+	adm_params->hdr.opcode = ADM_CMD_GET_PP_PARAMS_V5;
+	adm_params->data_payload_addr_lsw = 0;
+	adm_params->data_payload_addr_msw = 0;
+	adm_params->mem_map_handle = 0;
+	adm_params->module_id = module_id;
+	adm_params->param_id = param_id;
+	adm_params->param_max_size = params_length;
+	adm_params->reserved = 0;
+
+	atomic_set(&this_adm.copp_stat[index], 0);
+	rc = apr_send_pkt(this_adm.apr, (uint32_t *)adm_params);
+	if (rc < 0) {
+		pr_err("%s: Failed to Get DOLBY Params on port %d\n", __func__,
+			port_id);
+		rc = -EINVAL;
+		goto dolby_dap_get_param_return;
+	}
+	/* Wait for the callback with copp id */
+	rc = wait_event_timeout(this_adm.wait[index],
+			atomic_read(&this_adm.copp_stat[index]),
+			msecs_to_jiffies(TIMEOUT_MS));
+	if (!rc) {
+		pr_err("%s: DOLBY get params timed out port = %d\n", __func__,
+			port_id);
+		rc = -EINVAL;
+		goto dolby_dap_get_param_return;
+	}
+	if (params_data) {
+		for (i = 0; i < adm_dolby_get_parameters[0]; i++)
+			params_data[i] = adm_dolby_get_parameters[1+i];
+	}
+	rc = 0;
+dolby_dap_get_param_return:
+	kfree(adm_params);
+	return rc;
+}
+
 static void adm_callback_debug_print(struct apr_client_data *data)
 {
 	uint32_t *payload;
@@ -428,6 +559,13 @@
 					__func__, payload[0]);
 			rtac_make_adm_callback(payload,
 				data->payload_size);
+			adm_dolby_get_parameters[0] = payload[3];
+			pr_debug("GET_PP PARAM:received parameter length: %x\n",
+					adm_dolby_get_parameters[0]);
+			for (i = 0; i < payload[3]; i++)
+				adm_dolby_get_parameters[1+i] = payload[4+i];
+			atomic_set(&this_adm.copp_stat[index], 1);
+			wake_up(&this_adm.wait[index]);
 			break;
 		case ADM_CMDRSP_SHARED_MEM_MAP_REGIONS:
 			pr_debug("%s: ADM_CMDRSP_SHARED_MEM_MAP_REGIONS\n",
@@ -807,20 +945,10 @@
 		open.endpoint_id_1 = tmp_port;
 		open.endpoint_id_2 = 0xFFFF;
 
-		/* convert path to acdb path */
-		if (path == ADM_PATH_PLAYBACK)
-			open.topology_id = get_adm_rx_topology();
-		else {
-			open.topology_id = get_adm_tx_topology();
-			if ((open.topology_id ==
-				VPM_TX_SM_ECNS_COPP_TOPOLOGY) ||
-			    (open.topology_id ==
-				VPM_TX_DM_FLUENCE_COPP_TOPOLOGY))
+		open.topology_id = topology;
+		if ((open.topology_id == VPM_TX_SM_ECNS_COPP_TOPOLOGY) ||
+			(open.topology_id == VPM_TX_DM_FLUENCE_COPP_TOPOLOGY))
 				rate = 16000;
-		}
-
-		if (open.topology_id  == 0)
-			open.topology_id = topology;
 
 		open.dev_num_channel = channel_mode & 0x00FF;
 		open.bit_width = bits_per_sample;
diff --git a/sound/soc/msm/qdsp6v2/q6afe.c b/sound/soc/msm/qdsp6v2/q6afe.c
index fed0d81..09d6a0f 100644
--- a/sound/soc/msm/qdsp6v2/q6afe.c
+++ b/sound/soc/msm/qdsp6v2/q6afe.c
@@ -17,7 +17,7 @@
 #include <linux/wait.h>
 #include <linux/jiffies.h>
 #include <linux/sched.h>
-#include <linux/msm_ion.h>
+#include <linux/msm_audio_ion.h>
 #include <sound/apr_audio-v2.h>
 #include <sound/q6afe-v2.h>
 #include <sound/q6audio-v2.h>
@@ -224,6 +224,7 @@
 	case AFE_PORT_ID_SECONDARY_MI2S_RX:
 	case AFE_PORT_ID_TERTIARY_MI2S_RX:
 	case AFE_PORT_ID_QUATERNARY_MI2S_RX:
+	case AFE_PORT_ID_SECONDARY_PCM_RX:
 		ret = MSM_AFE_PORT_TYPE_RX;
 		break;
 
@@ -247,6 +248,7 @@
 	case AFE_PORT_ID_SECONDARY_MI2S_TX:
 	case AFE_PORT_ID_TERTIARY_MI2S_TX:
 	case AFE_PORT_ID_QUATERNARY_MI2S_TX:
+	case AFE_PORT_ID_SECONDARY_PCM_TX:
 		ret = MSM_AFE_PORT_TYPE_TX;
 		break;
 
@@ -295,6 +297,8 @@
 		break;
 	case PCM_RX:
 	case PCM_TX:
+	case AFE_PORT_ID_SECONDARY_PCM_RX:
+	case AFE_PORT_ID_SECONDARY_PCM_TX:
 	default:
 		ret_size = SIZEOF_CFG_CMD(afe_param_id_pcm_cfg);
 		break;
@@ -1120,7 +1124,9 @@
 		break;
 	case PCM_RX:
 	case PCM_TX:
-		cfg_type = AFE_PARAM_ID_HDMI_CONFIG;
+	case AFE_PORT_ID_SECONDARY_PCM_RX:
+	case AFE_PORT_ID_SECONDARY_PCM_TX:
+		cfg_type = AFE_PARAM_ID_PCM_CONFIG;
 		break;
 	case SECONDARY_I2S_RX:
 	case SECONDARY_I2S_TX:
@@ -1215,6 +1221,10 @@
 	case PRIMARY_I2S_TX: return IDX_PRIMARY_I2S_TX;
 	case PCM_RX: return IDX_PCM_RX;
 	case PCM_TX: return IDX_PCM_TX;
+	case AFE_PORT_ID_SECONDARY_PCM_RX:
+		return IDX_AFE_PORT_ID_SECONDARY_PCM_RX;
+	case AFE_PORT_ID_SECONDARY_PCM_TX:
+		return IDX_AFE_PORT_ID_SECONDARY_PCM_TX;
 	case SECONDARY_I2S_RX: return IDX_SECONDARY_I2S_RX;
 	case SECONDARY_I2S_TX: return IDX_SECONDARY_I2S_TX;
 	case MI2S_RX: return IDX_MI2S_RX;
@@ -1310,6 +1320,8 @@
 		break;
 	case PCM_RX:
 	case PCM_TX:
+	case AFE_PORT_ID_SECONDARY_PCM_RX:
+	case AFE_PORT_ID_SECONDARY_PCM_TX:
 		cfg_type = AFE_PARAM_ID_PCM_CONFIG;
 		break;
 	case SECONDARY_I2S_RX:
@@ -1707,35 +1719,13 @@
 
 	ac->port[dir].buf = buf;
 
-	buf[0].client = msm_ion_client_create(UINT_MAX, "audio_client");
-	if (IS_ERR_OR_NULL((void *)buf[0].client)) {
-		pr_err("%s: ION create client for AUDIO failed\n", __func__);
-		goto fail;
-	}
-	buf[0].handle = ion_alloc(buf[0].client, bufsz * bufcnt, SZ_4K,
-				  (0x1 << ION_AUDIO_HEAP_ID), 0);
-	if (IS_ERR_OR_NULL((void *) buf[0].handle)) {
-		pr_err("%s: ION memory allocation for AUDIO failed\n",
-			__func__);
-		goto fail;
-	}
-
-	rc = ion_phys(buf[0].client, buf[0].handle,
-		  (ion_phys_addr_t *)&buf[0].phys, (size_t *)&len);
+	rc = msm_audio_ion_alloc("audio_client", &buf[0].client,
+				&buf[0].handle, bufsz*bufcnt,
+				(ion_phys_addr_t *)&buf[0].phys, (size_t *)&len,
+				&buf[0].data);
 	if (rc) {
-		pr_err("%s: ION Get Physical for AUDIO failed, rc = %d\n",
+		pr_err("%s: audio ION alloc failed, rc = %d\n",
 			__func__, rc);
-		goto fail;
-	}
-
-	buf[0].data = ion_map_kernel(buf[0].client, buf[0].handle);
-	if (IS_ERR_OR_NULL((void *) buf[0].data)) {
-		pr_err("%s: ION memory mapping for AUDIO failed\n", __func__);
-		goto fail;
-	}
-	memset((void *)buf[0].data, 0, (bufsz * bufcnt));
-	if (!buf[0].data) {
-		pr_err("%s:invalid vaddr, iomap failed\n", __func__);
 		mutex_unlock(&ac->cmd_lock);
 		goto fail;
 	}
@@ -1944,9 +1934,7 @@
 	cnt = port->max_buf_cnt - 1;
 
 	if (port->buf[0].data) {
-		ion_unmap_kernel(port->buf[0].client, port->buf[0].handle);
-		ion_free(port->buf[0].client, port->buf[0].handle);
-		ion_client_destroy(port->buf[0].client);
+		msm_audio_ion_free(port->buf[0].client, port->buf[0].handle);
 		pr_debug("%s:data[%p]phys[%p][%p] , client[%p] handle[%p]\n",
 			__func__,
 			(void *)port->buf[0].data,
@@ -2521,6 +2509,8 @@
 	case PRIMARY_I2S_TX:
 	case PCM_RX:
 	case PCM_TX:
+	case AFE_PORT_ID_SECONDARY_PCM_RX:
+	case AFE_PORT_ID_SECONDARY_PCM_TX:
 	case SECONDARY_I2S_RX:
 	case SECONDARY_I2S_TX:
 	case MI2S_RX:
diff --git a/sound/soc/msm/qdsp6v2/q6asm.c b/sound/soc/msm/qdsp6v2/q6asm.c
index 49b6d03..fffd0b3 100644
--- a/sound/soc/msm/qdsp6v2/q6asm.c
+++ b/sound/soc/msm/qdsp6v2/q6asm.c
@@ -29,13 +29,13 @@
 #include <linux/debugfs.h>
 #include <linux/time.h>
 #include <linux/atomic.h>
+#include <linux/msm_audio_ion.h>
 
 #include <asm/ioctls.h>
 
 #include <mach/memory.h>
 #include <mach/debug_mm.h>
 #include <mach/qdsp6v2/rtac.h>
-#include <mach/msm_subsystem_map.h>
 
 #include <sound/apr_audio-v2.h>
 #include <sound/q6asm-v2.h>
@@ -456,11 +456,8 @@
 
 		while (cnt >= 0) {
 			if (port->buf[cnt].data) {
-				ion_unmap_kernel(port->buf[cnt].client,
-						port->buf[cnt].handle);
-				ion_free(port->buf[cnt].client,
-						port->buf[cnt].handle);
-				ion_client_destroy(port->buf[cnt].client);
+				msm_audio_ion_free(port->buf[cnt].client,
+						   port->buf[cnt].handle);
 				port->buf[cnt].data = NULL;
 				port->buf[cnt].phys = 0;
 				--(port->max_buf_cnt);
@@ -497,9 +494,7 @@
 	}
 
 	if (port->buf[0].data) {
-		ion_unmap_kernel(port->buf[0].client, port->buf[0].handle);
-		ion_free(port->buf[0].client, port->buf[0].handle);
-		ion_client_destroy(port->buf[0].client);
+		msm_audio_ion_free(port->buf[0].client, port->buf[0].handle);
 		pr_debug("%s:data[%p]phys[%p][%p] , client[%p] handle[%p]\n",
 			__func__,
 			(void *)port->buf[0].data,
@@ -724,44 +719,19 @@
 		while (cnt < bufcnt) {
 			if (bufsz > 0) {
 				if (!buf[cnt].data) {
-					buf[cnt].client = msm_ion_client_create
-						(UINT_MAX, "audio_client");
-					if (IS_ERR_OR_NULL((void *)
-						buf[cnt].client)) {
-						pr_err("%s: ION create client for AUDIO failed\n",
-						__func__);
-						goto fail;
-					}
-					buf[cnt].handle = ion_alloc
-						(buf[cnt].client, bufsz, SZ_4K,
-						(0x1 << ION_AUDIO_HEAP_ID), 0);
-					if (IS_ERR_OR_NULL((void *)
-						buf[cnt].handle)) {
-						pr_err("%s: ION memory allocation for AUDIO failed\n",
-							__func__);
-						goto fail;
-					}
-
-					rc = ion_phys(buf[cnt].client,
-						buf[cnt].handle,
-						(ion_phys_addr_t *)
-						&buf[cnt].phys,
-						(size_t *)&len);
+					msm_audio_ion_alloc("audio_client",
+					&buf[cnt].client, &buf[cnt].handle,
+					      bufsz,
+					      (ion_phys_addr_t *)&buf[cnt].phys,
+					      (size_t *)&len,
+					      &buf[cnt].data);
 					if (rc) {
 						pr_err("%s: ION Get Physical for AUDIO failed, rc = %d\n",
 							__func__, rc);
-						goto fail;
+						mutex_unlock(&ac->cmd_lock);
+					goto fail;
 					}
 
-					buf[cnt].data = ion_map_kernel
-					(buf[cnt].client, buf[cnt].handle);
-					if (IS_ERR_OR_NULL((void *)
-						buf[cnt].data)) {
-						pr_err("%s: ION memory mapping for AUDIO failed\n",
-						 __func__);
-						goto fail;
-					}
-					memset((void *)buf[cnt].data, 0, bufsz);
 					buf[cnt].used = 1;
 					buf[cnt].size = bufsz;
 					buf[cnt].actual_size = bufsz;
@@ -824,35 +794,13 @@
 
 	ac->port[dir].buf = buf;
 
-	buf[0].client = msm_ion_client_create(UINT_MAX, "audio_client");
-	if (IS_ERR_OR_NULL((void *)buf[0].client)) {
-		pr_err("%s: ION create client for AUDIO failed\n", __func__);
-		goto fail;
-	}
-	buf[0].handle = ion_alloc(buf[0].client, bufsz * bufcnt, SZ_4K,
-				  (0x1 << ION_AUDIO_HEAP_ID), 0);
-	if (IS_ERR_OR_NULL((void *) buf[0].handle)) {
-		pr_err("%s: ION memory allocation for AUDIO failed\n",
-			__func__);
-		goto fail;
-	}
-
-	rc = ion_phys(buf[0].client, buf[0].handle,
-		  (ion_phys_addr_t *)&buf[0].phys, (size_t *)&len);
+	rc = msm_audio_ion_alloc("audio_client", &buf[0].client, &buf[0].handle,
+		bufsz*bufcnt,
+		(ion_phys_addr_t *)&buf[0].phys, (size_t *)&len,
+		&buf[0].data);
 	if (rc) {
-		pr_err("%s: ION Get Physical for AUDIO failed, rc = %d\n",
+		pr_err("%s: Audio ION alloc is failed, rc = %d\n",
 			__func__, rc);
-		goto fail;
-	}
-
-	buf[0].data = ion_map_kernel(buf[0].client, buf[0].handle);
-	if (IS_ERR_OR_NULL((void *) buf[0].data)) {
-		pr_err("%s: ION memory mapping for AUDIO failed\n", __func__);
-		goto fail;
-	}
-	memset((void *)buf[0].data, 0, (bufsz * bufcnt));
-	if (!buf[0].data) {
-		pr_err("%s:invalid vaddr, iomap failed\n", __func__);
 		mutex_unlock(&ac->cmd_lock);
 		goto fail;
 	}
@@ -1570,6 +1518,12 @@
 	case FORMAT_MP3:
 		open.dec_fmt_id = ASM_MEDIA_FMT_MP3;
 		break;
+	case FORMAT_AC3:
+		open.dec_fmt_id = ASM_MEDIA_FMT_EAC3_DEC;
+		break;
+	case FORMAT_EAC3:
+		open.dec_fmt_id = ASM_MEDIA_FMT_EAC3_DEC;
+		break;
 	default:
 		pr_err("%s: Invalid format[%d]\n", __func__, format);
 		goto fail_cmd;
@@ -2571,6 +2525,40 @@
 	return -EINVAL;
 }
 
+int q6asm_ds1_set_endp_params(struct audio_client *ac,
+				int param_id, int param_value)
+{
+	struct asm_dec_ddp_endp_param_v2 ddp_cfg;
+	int rc = 0;
+
+	pr_debug("%s: session[%d]param_id[%d]param_value[%d]", __func__,
+			ac->session, param_id, param_value);
+	q6asm_add_hdr(ac, &ddp_cfg.hdr, sizeof(ddp_cfg), TRUE);
+	ddp_cfg.hdr.opcode = ASM_STREAM_CMD_SET_ENCDEC_PARAM;
+	ddp_cfg.encdec.param_id = param_id;
+	ddp_cfg.encdec.param_size = sizeof(struct asm_dec_ddp_endp_param_v2) -
+				(sizeof(struct apr_hdr) +
+				sizeof(struct asm_stream_cmd_set_encdec_param));
+	ddp_cfg.endp_param_value = param_value;
+	rc = apr_send_pkt(ac->apr, (uint32_t *) &ddp_cfg);
+	if (rc < 0) {
+		pr_err("%s:Command opcode[0x%x] failed\n",
+			__func__, ASM_STREAM_CMD_SET_ENCDEC_PARAM);
+		goto fail_cmd;
+	}
+	rc = wait_event_timeout(ac->cmd_wait,
+		(atomic_read(&ac->cmd_state) == 0), 5*HZ);
+	if (!rc) {
+		pr_err("%s:timeout opcode[0x%x]\n", __func__,
+			ddp_cfg.hdr.opcode);
+		rc = -ETIMEDOUT;
+		goto fail_cmd;
+	}
+	return 0;
+fail_cmd:
+	return rc;
+}
+
 int q6asm_memory_map(struct audio_client *ac, uint32_t buf_add, int dir,
 				uint32_t bufsz, uint32_t bufcnt)
 {
diff --git a/sound/soc/msm/qdsp6v2/q6audio-v2.c b/sound/soc/msm/qdsp6v2/q6audio-v2.c
index d3d335d..faf5f35 100644
--- a/sound/soc/msm/qdsp6v2/q6audio-v2.c
+++ b/sound/soc/msm/qdsp6v2/q6audio-v2.c
@@ -26,6 +26,10 @@
 	case PRIMARY_I2S_TX: return IDX_PRIMARY_I2S_TX;
 	case PCM_RX: return IDX_PCM_RX;
 	case PCM_TX: return IDX_PCM_TX;
+	case AFE_PORT_ID_SECONDARY_PCM_RX:
+		return IDX_AFE_PORT_ID_SECONDARY_PCM_RX;
+	case AFE_PORT_ID_SECONDARY_PCM_TX:
+		return IDX_AFE_PORT_ID_SECONDARY_PCM_TX;
 	case SECONDARY_I2S_RX: return IDX_SECONDARY_I2S_RX;
 	case SECONDARY_I2S_TX: return IDX_SECONDARY_I2S_TX;
 	case MI2S_RX: return IDX_MI2S_RX;
@@ -74,6 +78,10 @@
 	case PRIMARY_I2S_TX: return AFE_PORT_ID_PRIMARY_MI2S_TX;
 	case PCM_RX: return AFE_PORT_ID_PRIMARY_PCM_RX;
 	case PCM_TX: return AFE_PORT_ID_PRIMARY_PCM_TX;
+	case AFE_PORT_ID_SECONDARY_PCM_RX:
+			return AFE_PORT_ID_SECONDARY_PCM_RX;
+	case AFE_PORT_ID_SECONDARY_PCM_TX:
+			return AFE_PORT_ID_SECONDARY_PCM_TX;
 	case SECONDARY_I2S_RX: return AFE_PORT_ID_SECONDARY_MI2S_RX;
 	case SECONDARY_I2S_TX: return AFE_PORT_ID_SECONDARY_MI2S_TX;
 	case MI2S_RX: return AFE_PORT_ID_PRIMARY_MI2S_RX;
@@ -146,6 +154,8 @@
 	case PRIMARY_I2S_TX:
 	case PCM_RX:
 	case PCM_TX:
+	case AFE_PORT_ID_SECONDARY_PCM_RX:
+	case AFE_PORT_ID_SECONDARY_PCM_TX:
 	case SECONDARY_I2S_RX:
 	case SECONDARY_I2S_TX:
 	case MI2S_RX:
@@ -171,6 +181,8 @@
 	case PRIMARY_I2S_TX:
 	case PCM_RX:
 	case PCM_TX:
+	case AFE_PORT_ID_SECONDARY_PCM_RX:
+	case AFE_PORT_ID_SECONDARY_PCM_TX:
 	case SECONDARY_I2S_RX:
 	case SECONDARY_I2S_TX:
 	case MI2S_RX:
diff --git a/sound/soc/msm/qdsp6v2/q6lsm.c b/sound/soc/msm/qdsp6v2/q6lsm.c
index f2b531a..49e5ede 100644
--- a/sound/soc/msm/qdsp6v2/q6lsm.c
+++ b/sound/soc/msm/qdsp6v2/q6lsm.c
@@ -30,7 +30,6 @@
 #include <asm/ioctls.h>
 #include <mach/memory.h>
 #include <mach/debug_mm.h>
-#include <mach/msm_subsystem_map.h>
 #include "audio_acdb.h"
 
 #define APR_TIMEOUT	(5 * HZ)
diff --git a/sound/soc/msm/qdsp6v2/q6voice.c b/sound/soc/msm/qdsp6v2/q6voice.c
index 754a4fa..a417b26 100644
--- a/sound/soc/msm/qdsp6v2/q6voice.c
+++ b/sound/soc/msm/qdsp6v2/q6voice.c
@@ -16,6 +16,7 @@
 #include <linux/uaccess.h>
 #include <linux/wait.h>
 #include <linux/mutex.h>
+#include <linux/msm_audio_ion.h>
 
 #include <asm/mach-types.h>
 #include <mach/qdsp6v2/rtac.h>
@@ -2532,14 +2533,8 @@
 	mvm_set_voice_timing.hdr.opcode = VSS_ICOMMON_CMD_SET_VOICE_TIMING;
 	mvm_set_voice_timing.timing.mode = 0;
 	mvm_set_voice_timing.timing.enc_offset = 8000;
-	if ((machine_is_apq8064_sim()) || (machine_is_msm8974_sim())) {
-		pr_debug("%s: Machine is MSM8974 sim\n", __func__);
-		mvm_set_voice_timing.timing.dec_req_offset = 0;
-		mvm_set_voice_timing.timing.dec_offset = 18000;
-	} else {
-		mvm_set_voice_timing.timing.dec_req_offset = 3300;
-		mvm_set_voice_timing.timing.dec_offset = 8300;
-	}
+	mvm_set_voice_timing.timing.dec_req_offset = 3300;
+	mvm_set_voice_timing.timing.dec_offset = 8300;
 
 	v->mvm_state = CMD_STATUS_FAIL;
 
@@ -4639,35 +4634,16 @@
 		pr_err("%s: v is NULL\n", __func__);
 		return -EINVAL;
 	}
-	v->shmem_info.sh_buf.client = msm_ion_client_create(UINT_MAX,
-							    "voip_client");
-	if (IS_ERR_OR_NULL((void *)v->shmem_info.sh_buf.client)) {
-		pr_err("%s: ION create client failed\n", __func__);
-		goto err;
-	}
 
-	v->shmem_info.sh_buf.handle = ion_alloc(v->shmem_info.sh_buf.client,
-						bufsz * bufcnt, SZ_4K,
-						(0x1 << ION_AUDIO_HEAP_ID), 0);
-	if (IS_ERR_OR_NULL((void *)v->shmem_info.sh_buf.handle)) {
-		pr_err("%s: ION memory allocation failed\n",
-			__func__);
-		goto err_ion_client;
-	}
-
-	rc = ion_phys(v->shmem_info.sh_buf.client, v->shmem_info.sh_buf.handle,
-		  (ion_phys_addr_t *)&phys, (size_t *)&len);
+	rc = msm_audio_ion_alloc("voip_client", &(v->shmem_info.sh_buf.client),
+			&(v->shmem_info.sh_buf.handle),
+			bufsz*bufcnt,
+			(ion_phys_addr_t *)&phys, (size_t *)&len,
+			&mem_addr);
 	if (rc) {
-		pr_err("%s: ION Get Physical failed, rc = %d\n",
+		pr_err("%s: audio ION alloc failed, rc = %d\n",
 			__func__, rc);
-		goto err_ion_handle;
-	}
-
-	mem_addr = ion_map_kernel(v->shmem_info.sh_buf.client,
-				  v->shmem_info.sh_buf.handle);
-	if (IS_ERR_OR_NULL(mem_addr)) {
-		pr_err("%s: ION memory mapping failed\n", __func__);
-		goto err_ion_handle;
+		return -EINVAL;
 	}
 
 	while (cnt < bufcnt) {
@@ -4691,13 +4667,6 @@
 	memset((void *)v->shmem_info.sh_buf.buf[0].data, 0, (bufsz * bufcnt));
 
 	return 0;
-
-err_ion_handle:
-	ion_free(v->shmem_info.sh_buf.client, v->shmem_info.sh_buf.handle);
-err_ion_client:
-	ion_client_destroy(v->shmem_info.sh_buf.client);
-err:
-	return -EINVAL;
 }
 
 static int voice_alloc_oob_mem_table(void)
@@ -4711,41 +4680,19 @@
 		pr_err("%s: v is NULL\n", __func__);
 		return -EINVAL;
 	}
-	v->shmem_info.memtbl.client = msm_ion_client_create(UINT_MAX,
-							      "voip_client");
-	if (IS_ERR_OR_NULL((void *)v->shmem_info.memtbl.client)) {
-		pr_err("%s: ION create client for memtbl failed\n", __func__);
-		goto err;
-	}
 
-	v->shmem_info.memtbl.handle = ion_alloc(v->shmem_info.memtbl.client,
-				sizeof(struct vss_imemory_table_t), SZ_4K,
-				(0x1 << ION_AUDIO_HEAP_ID), 0);
-	if (IS_ERR_OR_NULL((void *) v->shmem_info.memtbl.handle)) {
-		pr_err("%s: ION memory allocation for memtbl failed\n",
-			__func__);
-		goto err_ion_client;
-	}
-
-	rc = ion_phys(v->shmem_info.memtbl.client, v->shmem_info.memtbl.handle,
-		(ion_phys_addr_t *)&v->shmem_info.memtbl.phys, (size_t *)&len);
+	rc = msm_audio_ion_alloc("voip_client", &(v->shmem_info.memtbl.client),
+				&(v->shmem_info.memtbl.handle),
+				sizeof(struct vss_imemory_table_t),
+				(ion_phys_addr_t *)&v->shmem_info.memtbl.phys,
+				(size_t *)&len,
+				&(v->shmem_info.memtbl.data));
 	if (rc) {
-		pr_err("%s: ION Get Physical for memtbl failed, rc = %d\n",
+		pr_err("%s: audio ION alloc failed, rc = %d\n",
 			__func__, rc);
-		goto err_ion_handle;
+		return -EINVAL;
 	}
 
-	v->shmem_info.memtbl.data = ion_map_kernel(v->shmem_info.memtbl.client,
-						   v->shmem_info.memtbl.handle);
-	if (IS_ERR_OR_NULL((void *)v->shmem_info.memtbl.data)) {
-		pr_err("%s: ION memory mapping for memtbl failed\n",
-				__func__);
-		goto err_ion_handle;
-	}
-
-	memset(v->shmem_info.memtbl.data, 0,
-	       sizeof(struct vss_imemory_table_t));
-
 	v->shmem_info.memtbl.size = sizeof(struct vss_imemory_table_t);
 
 	pr_debug("%s data[%p]phys[%p][%p]\n", __func__,
@@ -4755,12 +4702,6 @@
 
 	return 0;
 
-err_ion_handle:
-	ion_free(v->shmem_info.memtbl.client, v->shmem_info.memtbl.handle);
-err_ion_client:
-	ion_client_destroy(v->shmem_info.memtbl.client);
-err:
-	return -EINVAL;
 }
 
 static int voice_alloc_cal_mem_map_table(void)
@@ -4768,67 +4709,25 @@
 	int ret = 0;
 	int len;
 
-	common.cal_mem_map_table.client = msm_ion_client_create(UINT_MAX,
-								"voc_client");
-
-	if (IS_ERR_OR_NULL((void *) common.cal_mem_map_table.client)) {
-		pr_err("%s: ION create client for cal mem map table failed\n",
-		       __func__);
-
-		goto err;
-	}
-
-	common.cal_mem_map_table.handle =
-				ion_alloc(common.cal_mem_map_table.client,
-					  sizeof(struct vss_imemory_table_t),
-					  SZ_4K, (0x1 << ION_AUDIO_HEAP_ID), 0);
-	if (IS_ERR_OR_NULL((void *) common.cal_mem_map_table.handle)) {
-		pr_err("%s: ION memory alloc for cal mem map table failed\n",
-		       __func__);
-
-		goto err_ion_client;
-	}
-
-	ret = ion_phys(common.cal_mem_map_table.client,
-		      common.cal_mem_map_table.handle,
-		      (ion_phys_addr_t *) &common.cal_mem_map_table.phys,
-		      (size_t *) &len);
+	ret = msm_audio_ion_alloc("voip_client",
+				&(common.cal_mem_map_table.client),
+				&(common.cal_mem_map_table.handle),
+				sizeof(struct vss_imemory_table_t),
+			      (ion_phys_addr_t *)&common.cal_mem_map_table.phys,
+				(size_t *) &len,
+				&(common.cal_mem_map_table.data));
 	if (ret) {
-		pr_err("%s: Phy addr for cal mem map table failed %d\n",
-		       __func__, ret);
-
-		goto err_ion_handle;
+		pr_err("%s: audio ION alloc failed, rc = %d\n",
+			__func__, ret);
+		return -EINVAL;
 	}
 
-	common.cal_mem_map_table.data =
-				ion_map_kernel(common.cal_mem_map_table.client,
-					       common.cal_mem_map_table.handle);
-	if (IS_ERR_OR_NULL((void *) common.cal_mem_map_table.data)) {
-		pr_err("%s: Virtual addr for cal memory map table failed\n",
-		       __func__);
-
-		goto err_ion_handle;
-	}
-
-	memset(common.cal_mem_map_table.data, 0,
-	       sizeof(struct vss_imemory_table_t));
-
 	common.cal_mem_map_table.size = sizeof(struct vss_imemory_table_t);
-
 	pr_debug("%s: data 0x%x phys 0x%x\n", __func__,
 		 (unsigned int) common.cal_mem_map_table.data,
 		 common.cal_mem_map_table.phys);
 
 	return 0;
-
-err_ion_handle:
-	ion_free(common.cal_mem_map_table.client,
-		 common.cal_mem_map_table.handle);
-err_ion_client:
-	ion_client_destroy(common.cal_mem_map_table.client);
-	memset(&common.cal_mem_map_table, 0, sizeof(common.cal_mem_map_table));
-err:
-	return -EINVAL;
 }
 
 static int __init voice_init(void)
diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c
index 915c3c2..40595bf 100644
--- a/sound/soc/soc-pcm.c
+++ b/sound/soc/soc-pcm.c
@@ -1649,9 +1649,11 @@
 		break;
 	case SNDRV_PCM_TRIGGER_STOP:
 	case SNDRV_PCM_TRIGGER_SUSPEND:
-	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
 		fe->dpcm[stream].state = SND_SOC_DPCM_STATE_STOP;
 		break;
+	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
+		fe->dpcm[stream].state = SND_SOC_DPCM_STATE_PAUSED;
+		break;
 	}
 
 out: